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.
19 * use for find view toplevel
21 #define SET_VIEW_LEVEL(wd, view_level)\
22 view_level = wd->level;\
23 while ((!wd->tot_items_count[view_level]) && view_level)\
28 typedef struct _Widget_Data Widget_Data;
30 typedef struct _PlacementPart PlacementPart;
35 Evas_Object *event[2];
36 Evas_Object *bx[2]; // 2 - for now all that's supported
37 Eina_List *items; // 1 list. yes N levels, but only 2 for now and # of items will be small
40 int max_supp_items_count;
41 int tot_items_count[2];
42 int min_obj_height, max_grp_size;
43 int min_1st_level_obj_height;
46 Evas_Coord pwidth, pheight;
48 const char *special_char;
49 Eina_Bool level_active[2];
50 Eina_Bool horizontal : 1;
53 Eina_Bool hide_button : 1;
57 struct _Elm_Index_Item
61 const char *letter, *vis_letter;
64 Eina_Bool selected : 1;
73 static const char *widtype = NULL;
75 static void _del_hook(Evas_Object *obj);
76 static void _theme_hook(Evas_Object *obj);
77 static void _sizing_eval(Evas_Object *obj);
78 static void _index_box_auto_fill(Evas_Object *obj, Evas_Object *box, int level);
79 static void _index_box_clear(Evas_Object *obj, Evas_Object *box, int level);
80 static void _item_free(Elm_Index_Item *it);
81 static void _index_process(Evas_Object *obj);
83 /* Free a block allocated by `malloc', `realloc' or `calloc' one by one*/
85 _del_hook(Evas_Object *obj)
87 Widget_Data *wd = elm_widget_data_get(obj);
89 Eina_List *l, *clear = NULL;
91 _index_box_clear(obj, wd->bx[wd->level], wd->level);
92 _index_box_clear(obj, wd->bx[0], 0);
93 EINA_LIST_FOREACH(wd->items, l, it) clear = eina_list_append(clear, it);
94 EINA_LIST_FREE(clear, it) _item_free(it);
95 if(wd->popup_str[0]) free(wd->popup_str[0]);
96 if(wd->popup_str[1]) free(wd->popup_str[1]);
97 if (wd->delay) ecore_timer_del(wd->delay);
102 _layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data)
104 Widget_Data *wd = data;
106 _els_box_layout(o, priv, wd->horizontal, 0, 0); /* making box layout non homogenous */
110 _theme_hook(Evas_Object *obj)
112 Widget_Data *wd = elm_widget_data_get(obj);
114 _index_box_clear(obj, wd->bx[0], 0);
115 _index_box_clear(obj, wd->bx[1], 1);
117 _elm_theme_object_set(obj, wd->base, "index", "base/horizontal", elm_widget_style_get(obj));
119 _elm_theme_object_set(obj, wd->base, "index", "base/vertical", elm_widget_style_get(obj));
120 edje_object_part_swallow(wd->base, "elm.swallow.event.0", wd->event[0]);
121 edje_object_part_swallow(wd->base, "elm.swallow.index.0", wd->bx[0]);
122 if (edje_object_part_exists(wd->base, "elm.swallow.index.1"))
126 wd->bx[1] = evas_object_box_add(evas_object_evas_get(wd->base));
127 evas_object_box_layout_set(wd->bx[1], _layout, wd, NULL);
128 elm_widget_sub_object_add(obj, wd->bx[1]);
130 edje_object_part_swallow(wd->base, "elm.swallow.index.1", wd->bx[1]);
131 evas_object_show(wd->bx[1]);
135 evas_object_del(wd->bx[1]);
138 if (edje_object_part_exists(wd->base, "elm.swallow.event.1"))
142 Evas_Coord minw = 0, minh = 0;
144 wd->event[1] = evas_object_rectangle_add(evas_object_evas_get(wd->base));
145 evas_object_color_set(wd->event[1], 0, 0, 0, 0);
146 evas_object_size_hint_min_set(wd->event[1], minw, minh);
148 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
149 elm_widget_sub_object_add(obj, wd->event[1]);
151 edje_object_part_swallow(wd->base, "elm.swallow.event.1", wd->event[1]);
153 else if (wd->event[1])
155 evas_object_del(wd->event[1]);
158 edje_object_message_signal_process(wd->base);
159 edje_object_scale_set(wd->base, elm_widget_scale_get(obj) * _elm_config->scale);
161 _index_box_auto_fill(obj, wd->bx[0], 0);
164 _index_box_auto_fill(obj, wd->bx[1], 1);
168 _sizing_eval(Evas_Object *obj)
170 Widget_Data *wd = elm_widget_data_get(obj);
171 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
173 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
174 edje_object_size_min_restricted_calc(wd->base, &minw, &minh, minw, minh);
175 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
176 evas_object_size_hint_min_set(obj, minw, minh);
177 evas_object_size_hint_max_set(obj, maxw, maxh);
180 static Elm_Index_Item *
181 _item_new(Evas_Object *obj, const char *letter, const void *item)
183 Widget_Data *wd = elm_widget_data_get(obj);
185 if (!wd) return NULL;
186 it = calloc(1, sizeof(Elm_Index_Item));
187 if (!it) return NULL;
190 it->level = wd->level;
192 it->size = wd->min_obj_height;
194 it->size = wd->min_1st_level_obj_height;
197 it->letter = eina_stringshare_add(letter);
198 it->vis_letter = eina_stringshare_add(letter);
205 static Elm_Index_Item *
206 _item_find(Evas_Object *obj, const void *item)
208 Widget_Data *wd = elm_widget_data_get(obj);
211 if (!wd) return NULL;
212 EINA_LIST_FOREACH(wd->items, l, it)
213 if (it->data == item) return it;
218 _item_free(Elm_Index_Item *it)
220 Widget_Data *wd = elm_widget_data_get(it->obj);
222 wd->items = eina_list_remove(wd->items, it);
223 if (it->base) evas_object_del(it->base);
224 eina_stringshare_del(it->letter);
225 eina_stringshare_del(it->vis_letter);
229 /* Automatically filling the box with index item*/
231 _index_box_auto_fill(Evas_Object *obj, Evas_Object *box, int level)
233 Widget_Data *wd = elm_widget_data_get(obj);
236 Evas_Coord mw, mh, w, h;
239 if (wd->level_active[level]) return;
240 evas_object_geometry_get(box, NULL, NULL, &w, &h);
241 EINA_LIST_FOREACH(wd->items, l, it)
244 const char *stacking;
246 if (it->level != level) continue;
247 if(i > wd->max_supp_items_count) break;
249 o = edje_object_add(evas_object_evas_get(obj));
252 _elm_theme_object_set(obj, o, "index", "item_odd/vertical", elm_widget_style_get(obj));
254 //_elm_theme_object_set(obj, o, "index", "item/vertical", "default");
255 _elm_theme_object_set(obj, o, "index", "item/vertical", elm_widget_style_get(obj));
256 edje_object_part_text_set(o, "elm.text", it->letter);
257 edje_object_size_min_restricted_calc(o, &mw, &mh, 0, 0);
258 evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
259 evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
260 edje_object_part_text_set(o, "elm.text", it->vis_letter);
261 evas_object_resize(o, mw, it->size);
262 evas_object_size_hint_min_set(o, mw, it->size);
263 evas_object_size_hint_max_set(o, mw, it->size);
264 elm_widget_sub_object_add(obj, o);
265 evas_object_box_append(box, o);
266 stacking = edje_object_data_get(o, "stacking");
269 if (!strcmp(stacking, "below")) evas_object_lower(o);
270 else if (!strcmp(stacking, "above")) evas_object_raise(o);
275 wd->tot_items_count[1] = i;
276 evas_object_smart_calculate(box); // force a calc so we know the size
277 evas_object_size_hint_min_get(box, &mw, &mh);
280 _index_box_clear(obj, box, level);
283 // FIXME: only i objects fit! try again. overflows right now
287 evas_object_smart_calculate(box);
288 wd->level_active[level] = 1;
292 _index_box_clear(Evas_Object *obj, Evas_Object *box __UNUSED__, int level)
294 Widget_Data *wd = elm_widget_data_get(obj);
298 if (!wd->level_active[level]) return;
299 EINA_LIST_FOREACH(wd->items, l, it)
301 if (!it->base) continue;
302 if (it->level != level) continue;
303 evas_object_del(it->base);
306 wd->level_active[level] = 0;
310 _delay_change(void *data)
312 Widget_Data *wd = elm_widget_data_get(data);
315 if (!wd) return ECORE_CALLBACK_CANCEL;
317 SET_VIEW_LEVEL(wd, view_level);
318 d = (void *)elm_index_item_selected_get(data, view_level);
319 if (d) evas_object_smart_callback_call(data, "delay,changed", d);
320 return ECORE_CALLBACK_CANCEL;
324 _sel_eval(Evas_Object *obj, Evas_Coord evx, Evas_Coord evy)
326 Widget_Data *wd = elm_widget_data_get(obj);
327 Elm_Index_Item *it, *it_closest, *it_last;
329 Evas_Coord x, y, w, h, bx, by, bw, bh, xx, yy;
335 Eina_Bool change = EINA_FALSE;
336 char *label = NULL, *last = NULL;
341 SET_VIEW_LEVEL(wd, view_level);
342 for (i = 0; i <= view_level; i++)
347 evas_object_geometry_get(wd->bx[i], &bx, &by, &bw, &bh);
348 dmin = (double)(wd->min_1st_level_obj_height*wd->tot_items_count[1])/(2*(double)bh);
349 dmax = 1.0-dmin-0.08;
350 EINA_LIST_FOREACH(wd->items, l, it)
352 if (!((it->level == i) && (it->base))) continue;
358 evas_object_geometry_get(it->base, &x, &y, &w, &h);
363 x = (x * x) + (y * y);
364 if ((x < dist) || (!it_closest))
367 cdv = (double)(xx - bx) / (double)bw;
369 cdv = (double)(yy - by) / (double)bh;
374 if ((i == 0) && (view_level == 0))
376 if(cdv > dmax || cdv < dmin)
386 edje_object_part_drag_value_set(wd->base, "elm.dragable.index.1", cdv, cdvv);
390 edje_object_part_drag_value_set(wd->base, "elm.dragable.index.1", cdv, cdv);
393 if (it_closest) it_closest->selected = 1;
394 if (it_closest != it_last)
399 const char *stacking, *selectraise;
402 if(view_level == it->level)
403 edje_object_signal_emit(it->base, "elm,state,inactive", "elm");
404 stacking = edje_object_data_get(it->base, "stacking");
405 selectraise = edje_object_data_get(it->base, "selectraise");
406 if ((selectraise) && (!strcmp(selectraise, "on")))
408 if ((stacking) && (!strcmp(stacking, "below")))
409 evas_object_lower(it->base);
414 const char *selectraise;
417 if(view_level == it->level)
418 edje_object_signal_emit(it->base, "elm,state,active", "elm");
419 selectraise = edje_object_data_get(it->base, "selectraise");
420 if ((selectraise) && (!strcmp(selectraise, "on")))
421 evas_object_raise(it->base);
422 evas_object_smart_callback_call((void *)obj, "changed", (void *)it->data);
423 if (wd->delay) ecore_timer_del(wd->delay);
424 wd->delay = ecore_timer_add(0.2, _delay_change, obj);
431 last = strdup(it->letter);
434 if (!label) label = strdup(last);
437 label = realloc(label, strlen(label) + strlen(last) + 1);
441 last = strdup(it->letter);
445 if (!label) label = strdup("");
446 if (!last) last = strdup("");
453 if (wd->popup_str[1]) wd->popup_str[1][0] = '\0';
454 wd->popup_str[0] = (char *)realloc(wd->popup_str[0], (sizeof(char) * strlen(last) + 1));
456 strcpy(wd->popup_str[0], last);
457 edje_object_signal_emit(wd->base, "hide_2nd_level", "");
459 if (view_level == 1 && wd->level_active[1])
461 wd->popup_str[1] = (char *)realloc(wd->popup_str[1], (sizeof(char) * strlen(last) + 1));
463 strcpy(wd->popup_str[1], last);
464 edje_object_signal_emit(wd->base, "hide_first_level", "");
466 popup_text = (char *)malloc(sizeof(char) * (strlen(wd->popup_str[0]) + strlen(wd->popup_str[1]) + 1));
467 sprintf(popup_text, "%s%s", wd->popup_str[0], wd->popup_str[1]);
468 edje_object_part_text_set(wd->base, "elm.text", popup_text);
480 _wheel(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
482 Widget_Data *wd = elm_widget_data_get(data);
487 _mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info)
489 Widget_Data *wd = elm_widget_data_get(data);
490 Evas_Event_Mouse_Down *ev = event_info;
493 if (ev->button != 1) return;
495 evas_object_geometry_get(wd->base, &x, &y, NULL, NULL);
496 wd->dx = ev->canvas.x - x;
497 wd->dy = ev->canvas.y - y;
498 elm_index_active_set(data, 1);
499 _sel_eval(data, ev->canvas.x, ev->canvas.y);
500 edje_object_part_drag_value_set(wd->base, "elm.dragable.pointer", wd->dx, wd->dy);
504 _mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info)
506 Widget_Data *wd = elm_widget_data_get(data);
507 Evas_Event_Mouse_Up *ev = event_info;
514 if (ev->button != 1) return;
515 if (wd->level == 1 && wd->delay) ecore_timer_del(wd->delay);
518 SET_VIEW_LEVEL(wd, view_level);
519 d = (void *)elm_index_item_selected_get(data, view_level);
520 EINA_LIST_FOREACH(wd->items, l, it)
522 edje_object_signal_emit(it->base, "elm,state,inactive", "elm");
524 if (d) evas_object_smart_callback_call(data, "selected", d);
525 elm_index_active_set(data, 0);
526 edje_object_signal_emit(wd->base, "elm,state,level,0", "elm");
530 _mouse_move(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info)
532 Widget_Data *wd = elm_widget_data_get(data);
533 Evas_Event_Mouse_Move *ev = event_info;
534 Evas_Coord minw = 0, minh = 0, x, y, dx, dy, adx, ady;
538 if (!wd->down) return;
539 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
540 evas_object_geometry_get(wd->base, &x, &y, NULL, NULL);
541 x = ev->cur.canvas.x - x;
542 y = ev->cur.canvas.y - y;
545 if (adx < 0) adx = -dx;
548 if (ady < 0) ady = -dy;
549 edje_object_part_drag_value_set(wd->base, "elm.dragable.pointer", x, y);
560 snprintf(buf, sizeof(buf), "elm,state,level,%i", wd->level);
561 edje_object_signal_emit(wd->base, buf, "elm");
562 evas_object_smart_callback_call(data, "level,up", NULL);
570 snprintf(buf, sizeof(buf), "elm,state,level,%i", wd->level);
571 edje_object_signal_emit(wd->base, buf, "elm");
572 d = (void *)elm_index_item_selected_get(data, wd->level);
573 evas_object_smart_callback_call(data, "changed", d);
574 if (wd->delay) ecore_timer_del(wd->delay);
575 wd->delay = ecore_timer_add(0.2, _delay_change, data);
576 evas_object_smart_callback_call(data, "level,down", NULL);
580 _sel_eval(data, ev->cur.canvas.x, ev->cur.canvas.y);
583 _index_box_refill_job(void *data)
585 Widget_Data *wd = elm_widget_data_get((Evas_Object *)data);
591 evas_object_geometry_get(wd->base, NULL, NULL, &pw, &ph);
592 wd->scale_factor = elm_scale_get();
593 if ( wd->scale_factor == 0.0 ) {
594 wd->scale_factor = 1.0;
596 string = edje_object_data_get(wd->base, "min_obj_height");
598 wd->min_obj_height = (int) (atoi(string))*wd->scale_factor;
600 wd->min_obj_height = MIN_OBJ_HEIGHT*wd->scale_factor;
601 if(!wd->min_obj_height) return;
603 wd->max_grp_size = wd->min_obj_height - 2*MIN_GRP_SIZE;
604 wd->items_count = ph/wd->min_obj_height;
605 wd->max_supp_items_count = wd->max_grp_size*(int)((wd->items_count-1)*0.5)+wd->items_count;
607 if(pw != wd->pwidth && ph != wd->pheight)
612 elm_index_active_set(data, 1);
614 _index_box_clear((Evas_Object *)data, wd->bx[0], 0);
615 evas_object_smart_calculate( wd->bx[0]);
616 elm_index_item_go((Evas_Object *)data, wd->level);
622 static void _index_object_resize(void *data, Evas *e, Evas_Object *obj, void *event_info)
626 wd = elm_widget_data_get((Evas_Object *)data);
628 ecore_job_add(_index_box_refill_job, (Evas_Object *)data);
632 * Add a new index to the parent
634 * @param parent The parent object
635 * @return The new object or NULL if it cannot be created
640 elm_index_add(Evas_Object *parent)
646 Evas_Coord minw, minh;
649 wd = ELM_NEW(Widget_Data);
650 e = evas_object_evas_get(parent);
652 obj = elm_widget_add(e);
653 ELM_SET_WIDTYPE(widtype, "index");
654 elm_widget_type_set(obj, "index");
655 elm_widget_sub_object_add(parent, obj);
656 elm_widget_data_set(obj, wd);
657 elm_widget_del_hook_set(obj, _del_hook);
658 elm_widget_theme_hook_set(obj, _theme_hook);
660 wd->horizontal = EINA_FALSE;
661 wd->min_obj_height = 0;
662 wd->max_grp_size = 0;
664 wd->max_supp_items_count = 0;
665 wd->tot_items_count[0] = 0;
666 wd->tot_items_count[1] = 0;
668 wd->special_char = edje_object_data_get(wd->base, "special_char");
669 if(wd->special_char == NULL) wd->special_char = eina_stringshare_add("*");
671 wd->base = edje_object_add(e);
672 _elm_theme_object_set(obj, wd->base, "index", "base/vertical", "default");
673 elm_widget_resize_object_set(obj, wd->base);
675 o = evas_object_rectangle_add(e);
677 evas_object_color_set(o, 0, 0, 0, 0);
679 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
680 evas_object_size_hint_min_set(o, minw, minh);
681 edje_object_part_swallow(wd->base, "elm.swallow.event.0", o);
682 elm_widget_sub_object_add(obj, o);
683 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _index_object_resize, obj);
684 evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_WHEEL, _wheel, obj);
685 evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down, obj);
686 evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_UP, _mouse_up, obj);
687 evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move, obj);
689 if (edje_object_part_exists(wd->base, "elm.swallow.event.1"))
691 o = evas_object_rectangle_add(e);
693 evas_object_color_set(o, 0, 0, 0, 0);
694 evas_object_size_hint_min_set(o, minw, minh);
695 edje_object_part_swallow(wd->base, "elm.swallow.event.1", o);
696 elm_widget_sub_object_add(obj, o);
699 wd->bx[0] = evas_object_box_add(e);
700 evas_object_box_layout_set(wd->bx[0], _layout, wd, NULL);
701 elm_widget_sub_object_add(obj, wd->bx[0]);
702 edje_object_part_swallow(wd->base, "elm.swallow.index.0", wd->bx[0]);
703 evas_object_show(wd->bx[0]);
705 if (edje_object_part_exists(wd->base, "elm.swallow.index.1"))
707 wd->bx[1] = evas_object_box_add(e);
708 evas_object_box_layout_set(wd->bx[1], _layout, wd, NULL);
709 elm_widget_sub_object_add(obj, wd->bx[1]);
710 edje_object_part_swallow(wd->base, "elm.swallow.index.1", wd->bx[1]);
711 evas_object_show(wd->bx[1]);
714 wd->scale_factor = elm_scale_get();
715 if ( wd->scale_factor == 0.0 )
717 wd->scale_factor = 1.0;
719 string = edje_object_data_get(wd->base, "min_1st_level_obj_height");
721 wd->min_1st_level_obj_height = (int) (atoi(string))*wd->scale_factor;
723 wd->min_1st_level_obj_height = MIN_OBJ_HEIGHT*wd->scale_factor;
725 wd->popup_str[0] = calloc(1, sizeof(char) * 1);
726 wd->popup_str[1] = calloc(1, sizeof(char) * 1);
731 _group_count(Evas_Object *obj, int extraIndex, int adj_pos, int vis_pos)
733 Widget_Data *wd = elm_widget_data_get(obj);
735 int group_count = MIN_GRP_SIZE;
736 while(group_count <= wd->max_grp_size)
738 if(extraIndex <= wd->max_grp_size*adj_pos)
740 if(group_count*adj_pos>=extraIndex) return group_count;
743 return wd->max_grp_size;
745 group_count += MIN_GRP_SIZE;
750 _index_process(Evas_Object *obj)
753 int j,i, group_count;
759 Widget_Data *wd = elm_widget_data_get(obj);
762 if (wd->items_count == 0) return;
764 const int adj_pos = (wd->items_count-1)*0.5;
765 if(wd->tot_items_count[wd->level] <= wd->max_supp_items_count)
766 n = wd->tot_items_count[wd->level];
768 n = wd->max_supp_items_count;
769 group_count = MIN_GRP_SIZE;
771 int *indx = (int*)calloc(n, sizeof(int));
774 const int minh = wd->min_obj_height;
775 EINA_LIST_FOREACH(wd->items, l, it)
777 it->vis_letter = eina_stringshare_add(it->letter);
782 int N = wd->items_count;
789 if (extraIndex < 0) return;
791 group_count = _group_count(obj, extraIndex, adj_pos, N);
792 if (group_count <= 0) return;
794 PlacementPart place[adj_pos];
795 remainder = extraIndex%group_count;
796 numberofparts=(extraIndex/group_count)+(remainder == 0? 0: 1);
798 for (i=0;i<numberofparts; i++)
800 place[i].count=group_count+1;
801 count = (int)(((float)(i+1)/(float)(numberofparts+1))*N);
802 place[i].start= count +i*group_count-1;
805 place[numberofparts-1].count=remainder+1;
807 for (i=0;i<numberofparts;i++)
809 for (j=0;j<place[i].count; j++)
811 indx[((place[i].start)+j)]= MIN_PIXEL_VALUE;
813 indx[(place[i].start+(place[i].count)/2)] = minh-place[i].count+1;
816 EINA_LIST_FOREACH(wd->items, l, it)
818 int size = indx[count];
822 it->vis_letter = eina_stringshare_add(it->letter);
827 eina_stringshare_del(it->vis_letter);
828 it->vis_letter = eina_stringshare_add("");
832 eina_stringshare_del(it->vis_letter);
833 it->vis_letter = eina_stringshare_add(wd->special_char);
835 it->size = size*wd->scale_factor;
844 * Set the active state of the index programatically
846 * @param obj The index object
847 * @param active The active starte
852 elm_index_active_set(Evas_Object *obj, Eina_Bool active)
854 ELM_CHECK_WIDTYPE(obj, widtype);
855 Widget_Data *wd = elm_widget_data_get(obj);
857 if (wd->active == active) return;
862 _index_box_clear(obj, wd->bx[1], 1);
864 _index_box_auto_fill(obj, wd->bx[0], 0);
865 edje_object_signal_emit(wd->base, "elm,state,active", "elm");
868 edje_object_signal_emit(wd->base, "elm,state,inactive", "elm");
872 * Sets the level of the item.
874 * @param obj The index object.
875 * @param level To be documented.
880 elm_index_item_level_set(Evas_Object *obj, int level)
882 ELM_CHECK_WIDTYPE(obj, widtype);
883 Widget_Data *wd = elm_widget_data_get(obj);
885 if (wd->level == level) return;
890 * Gets the level of the item.
892 * @param obj The index object
897 elm_index_item_level_get(const Evas_Object *obj)
899 ELM_CHECK_WIDTYPE(obj, widtype) 0;
900 Widget_Data *wd = elm_widget_data_get(obj);
906 * Returns the selected item.
908 * @param obj The index object.
909 * @param level to be documented.
914 elm_index_item_selected_get(const Evas_Object *obj, int level)
916 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
917 Widget_Data *wd = elm_widget_data_get(obj);
920 if (!wd) return NULL;
921 EINA_LIST_FOREACH(wd->items, l, it)
922 if ((it->selected) && (it->level == level)) return it->data;
927 * Appends a new item.
929 * @param obj The index object.
930 * @param letter Letter under which the item should be indexed
931 * @param item The item to put in the index
936 elm_index_item_append(Evas_Object *obj, const char *letter, const void *item)
938 ELM_CHECK_WIDTYPE(obj, widtype);
939 Widget_Data *wd = elm_widget_data_get(obj);
942 it = _item_new(obj, letter, item);
944 wd->items = eina_list_append(wd->items, it);
945 wd->tot_items_count[wd->level]++;
946 _index_box_clear(obj, wd->bx[wd->level], wd->level);
950 * Prepends a new item.
952 * @param obj The index object.
953 * @param letter Letter under which the item should be indexed
954 * @param item The item to put in the index
959 elm_index_item_prepend(Evas_Object *obj, const char *letter, const void *item)
961 ELM_CHECK_WIDTYPE(obj, widtype);
962 Widget_Data *wd = elm_widget_data_get(obj);
966 it = _item_new(obj, letter, item);
968 wd->items = eina_list_prepend(wd->items, it);
969 wd->tot_items_count[wd->level]++;
970 _index_box_clear(obj, wd->bx[wd->level], wd->level);
974 * Append an item after @p relative in letter @p letter.
976 * @param obj The index object
977 * @param letter Letter under which the item should be indexed
978 * @param item The item to put in the index
979 * @param relative The item to put @p item after
984 elm_index_item_append_relative(Evas_Object *obj, const char *letter, const void *item, const void *relative)
986 ELM_CHECK_WIDTYPE(obj, widtype);
987 Widget_Data *wd = elm_widget_data_get(obj);
988 Elm_Index_Item *it, *it_rel;
992 elm_index_item_append(obj, letter, item);
993 wd->tot_items_count[wd->level]++;
996 it = _item_new(obj, letter, item);
997 it_rel = _item_find(obj, relative);
1000 elm_index_item_append(obj, letter, item);
1001 wd->tot_items_count[wd->level]++;
1005 wd->items = eina_list_append_relative(wd->items, it, it_rel);
1006 wd->tot_items_count[wd->level]++;
1007 _index_box_clear(obj, wd->bx[wd->level], wd->level);
1011 * Prepend an item before @p relative in letter @p letter.
1013 * @param obj The index object
1014 * @param letter Letter under which the item should be indexed
1015 * @param item The item to put in the index
1016 * @param relative The item to put @p item before
1021 elm_index_item_prepend_relative(Evas_Object *obj, const char *letter, const void *item, const void *relative)
1023 ELM_CHECK_WIDTYPE(obj, widtype);
1024 Widget_Data *wd = elm_widget_data_get(obj);
1025 Elm_Index_Item *it, *it_rel;
1029 elm_index_item_prepend(obj, letter, item);
1030 wd->tot_items_count[wd->level]++;
1033 it = _item_new(obj, letter, item);
1034 it_rel = _item_find(obj, relative);
1037 elm_index_item_append(obj, letter, item);
1038 wd->tot_items_count[wd->level]++;
1042 wd->items = eina_list_prepend_relative(wd->items, it, it_rel);
1043 wd->tot_items_count[wd->level]++;
1044 _index_box_clear(obj, wd->bx[wd->level], wd->level);
1048 * Insert a new @p item into the sorted index @p obj in @p letter.
1050 * @param obj The index object
1051 * @param letter Letter under which the item should be indexed
1052 * @param item The item to put in the index
1053 * @param cmp_func The function called for the sort of index items.
1054 * @param cmp_data_func The function called for the sort of the data. It will
1055 * be used when cmp_func return 0. It means the index item already exists.
1056 * So, to decide which data item should be pointed by the index item, a function
1057 * to compare them is needed. If this function is not provided, index items
1058 * will be duplicated. If cmp_data_func returns a non-negative value, the
1059 * previous index item data will be replaced by the inserted @p item. So
1060 * if the previous data need to be free, it should be done in this function,
1061 * because the reference will be lost.
1066 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)
1068 ELM_CHECK_WIDTYPE(obj, widtype);
1069 Widget_Data *wd = elm_widget_data_get(obj);
1077 elm_index_item_append(obj, letter, item);
1081 it = _item_new(obj, letter, item);
1084 lnear = eina_list_search_sorted_near_list(wd->items, cmp_func, it, &cmp);
1086 wd->items = eina_list_append_relative_list(wd->items, it, lnear);
1088 wd->items = eina_list_prepend_relative_list(wd->items, it, lnear);
1091 /* If cmp_data_func is not provided, append a duplicated item */
1093 wd->items = eina_list_append_relative_list(wd->items, it, lnear);
1096 Elm_Index_Item *p_it = eina_list_data_get(lnear);
1097 if (cmp_data_func(p_it->data, it->data) >= 0)
1098 p_it->data = it->data;
1103 _index_box_clear(obj, wd->bx[wd->level], wd->level);
1107 * Remove an item from the index.
1109 * @param obj The index object
1110 * @param item The item to remove from the index
1115 elm_index_item_del(Evas_Object *obj, const void *item)
1117 ELM_CHECK_WIDTYPE(obj, widtype);
1118 Widget_Data *wd = elm_widget_data_get(obj);
1121 it = _item_find(obj, item);
1124 wd->tot_items_count[wd->level]--;
1125 _index_box_clear(obj, wd->bx[wd->level], wd->level);
1129 * Find an index item using item data.
1131 * @param obj The index object
1132 * @param item The item pointed by index item
1133 * @return The index item pointing to @p item
1137 EAPI Elm_Index_Item *
1138 elm_index_item_find(Evas_Object *obj, const void *item)
1140 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1141 Widget_Data *wd = elm_widget_data_get(obj);
1142 if (!wd) return NULL;
1143 return _item_find(obj, item);
1147 * Clears an index of its items.
1149 * @param obj The index object.
1154 elm_index_item_clear(Evas_Object *obj)
1156 ELM_CHECK_WIDTYPE(obj, widtype);
1157 Widget_Data *wd = elm_widget_data_get(obj);
1159 Eina_List *l, *clear = NULL;
1161 _index_box_clear(obj, wd->bx[wd->level], wd->level);
1162 EINA_LIST_FOREACH(wd->items, l, it)
1164 if (it->level != wd->level) continue;
1165 clear = eina_list_append(clear, it);
1167 EINA_LIST_FREE(clear, it)
1170 wd->tot_items_count[wd->level]--;
1175 * Go to item at @p level
1177 * @param obj The index object
1178 * @param level The index level
1183 elm_index_item_go(Evas_Object *obj, int level)
1185 ELM_CHECK_WIDTYPE(obj, widtype);
1186 Widget_Data *wd = elm_widget_data_get(obj);
1189 _index_process(obj);
1190 _index_box_auto_fill(obj, wd->bx[0], 0);
1191 if (wd->level == 1) _index_box_auto_fill(obj, wd->bx[1], 1);
1195 * Returns the data associated with the item.
1197 * @param it The list item
1198 * @return The data associated with @p it
1203 elm_index_item_data_get(const Elm_Index_Item *it)
1205 if (!it) return NULL;
1206 return (void *)it->data;
1210 * Set the data item from the index item
1212 * This set a new data value.
1214 * @param it The item
1215 * @param data The new data pointer to set
1220 elm_index_item_data_set(Elm_Index_Item *it, const void *data)
1227 * Gets the letter of the item.
1229 * @param it The list item
1230 * @return The letter of @p it
1235 elm_index_item_letter_get(const Elm_Index_Item *it)
1237 if (!it) return NULL;
1242 * Make the Central Button Image invisible.
1244 * @param obj The Index.
1245 * @param invisible Whether button visible or not.
1251 elm_index_button_image_invisible_set(Evas_Object *obj, Eina_Bool invisible)
1253 ELM_CHECK_WIDTYPE(obj, widtype);
1254 Widget_Data *wd = elm_widget_data_get(obj);
1255 wd->hide_button = invisible;
1257 edje_object_signal_emit(wd->base, "elm,state,button,image,hide", "elm");