Elementary: Added on-the-fly UI-mirroing support to all of the widgets
[framework/uifw/elementary.git] / src / lib / elm_toolbar.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 /**
5  * @defgroup Toolbar Toolbar
6  *
7  * A toolbar is a widget that displays a list of buttons inside
8  * a box.  It is scrollable, and only one item can be selected at a time.
9  */
10
11 typedef struct _Widget_Data Widget_Data;
12
13 struct _Widget_Data
14 {
15    Evas_Object *scr, *bx;
16    Evas_Object *menu_parent;
17    Eina_Inlist *items;
18    Elm_Toolbar_Item *more_item, *selected_item;
19    Elm_Toolbar_Shrink_Mode shrink_mode;
20    Elm_Icon_Lookup_Order lookup_order;
21    int icon_size;
22    double align;
23    Eina_Bool homogeneous : 1;
24    Eina_Bool no_select : 1;
25    Ecore_Job *resize_job;
26 };
27
28 struct _Elm_Toolbar_Item
29 {
30    Elm_Widget_Item base;
31    EINA_INLIST;
32    const char *label;
33    const char *icon_str;
34    Evas_Object *icon;
35    Evas_Object *o_menu;
36    Evas_Smart_Cb func;
37    struct {
38       int priority;
39       Eina_Bool visible : 1;
40    } prio;
41    Eina_Bool selected : 1;
42    Eina_Bool disabled : 1;
43    Eina_Bool separator : 1;
44    Eina_Bool menu : 1;
45    Eina_List *states;
46    Eina_List *current_state;
47 };
48
49 #define ELM_TOOLBAR_ITEM_FROM_INLIST(item)      \
50   ((item) ? EINA_INLIST_CONTAINER_GET(item, Elm_Toolbar_Item) : NULL)
51
52 struct _Elm_Toolbar_Item_State
53 {
54    const char *label;
55    const char *icon_str;
56    Evas_Object *icon;
57    Evas_Smart_Cb func;
58    const void *data;
59 };
60
61 static const char *widtype = NULL;
62 static void _item_show(Elm_Toolbar_Item *it);
63 static void _item_select(Elm_Toolbar_Item *it);
64 static void _item_unselect(Elm_Toolbar_Item *it);
65 static void _item_disable(Elm_Toolbar_Item *it, Eina_Bool disabled);
66 static void _del_pre_hook(Evas_Object *obj);
67 static void _del_hook(Evas_Object *obj);
68 static void _mirrored_set(Evas_Object *obj, Eina_Bool mirrored);
69 static void _mirrored_set_item(Evas_Object *obj, Elm_Toolbar_Item *it, Eina_Bool mirrored);
70 static void _theme_hook(Evas_Object *obj);
71 static void _sizing_eval(Evas_Object *obj);
72 static void _resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
73 static void _menu_move_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
74 static void _menu_hide(void *data, Evas *e, Evas_Object *obj, void *event_info);
75 static void _layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data);
76 static void _elm_toolbar_item_icon_obj_set(Evas_Object *obj, Elm_Toolbar_Item *item, Evas_Object *icon_obj, const char *icon_str, double icon_size, const char *signal);
77 static void _item_label_set(Elm_Toolbar_Item *item, const char *label, const char *signal);
78
79 static Eina_Bool
80 _item_icon_set(Evas_Object *icon_obj, const char *type, const char *icon)
81 {
82    char icon_str[512];
83
84    if ((!type) || (!*type)) goto end;
85    if ((!icon) || (!*icon)) return EINA_FALSE;
86    if ((snprintf(icon_str, sizeof(icon_str), "%s%s", type, icon) > 0)
87        && (elm_icon_standard_set(icon_obj, icon_str)))
88      return EINA_TRUE;
89 end:
90    if (elm_icon_standard_set(icon_obj, icon))
91      return EINA_TRUE;
92    WRN("couldn't find icon definition for '%s'", icon);
93    return EINA_FALSE;
94 }
95
96 static int
97 _elm_toolbar_icon_size_get(Widget_Data *wd)
98 {
99    const char *icon_size = edje_object_data_get(
100       elm_smart_scroller_edje_object_get(wd->scr), "icon_size");
101    if (icon_size)
102       return atoi(icon_size);
103    return _elm_config->icon_size;
104 }
105
106 static void
107 _item_show(Elm_Toolbar_Item *it)
108 {
109    Widget_Data *wd = elm_widget_data_get(it->base.widget);
110    Evas_Coord x, y, w, h, bx, by;
111
112    if (!wd) return;
113    evas_object_geometry_get(wd->bx, &bx, &by, NULL, NULL);
114    evas_object_geometry_get(it->base.view, &x, &y, &w, &h);
115    elm_smart_scroller_child_region_show(wd->scr, x - bx, y - by, w, h);
116 }
117
118 static void
119 _item_unselect(Elm_Toolbar_Item *item)
120 {
121    Widget_Data *wd;
122    if ((!item) || (!item->selected)) return;
123    wd = elm_widget_data_get(item->base.widget);
124    if (!wd) return;
125    item->selected = EINA_FALSE;
126    wd->selected_item = NULL;
127    edje_object_signal_emit(item->base.view, "elm,state,unselected", "elm");
128    elm_widget_signal_emit(item->icon, "elm,state,unselected", "elm");
129 }
130
131 static void
132 _item_select(Elm_Toolbar_Item *it)
133 {
134    Elm_Toolbar_Item *it2;
135    Widget_Data *wd = elm_widget_data_get(it->base.widget);
136    Evas_Object *obj2;
137
138    if (!wd) return;
139    if ((it->selected) || (it->disabled) || (it->separator)) return;
140
141    if (!wd->no_select)
142      {
143         it2 = elm_toolbar_selected_item_get(it->base.widget);
144         _item_unselect(it2);
145
146         it->selected = EINA_TRUE;
147         wd->selected_item = it;
148         edje_object_signal_emit(it->base.view, "elm,state,selected", "elm");
149         elm_widget_signal_emit(it->icon, "elm,state,selected", "elm");
150         _item_show(it);
151      }
152    obj2 = it->base.widget;
153    if (it->menu)
154      {
155         evas_object_show(it->o_menu);
156         evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_RESIZE,
157                                        _menu_move_resize, it);
158         evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_MOVE,
159                                        _menu_move_resize, it);
160
161         _menu_move_resize(it, NULL, NULL, NULL);
162      }
163    if (it->func) it->func((void *)(it->base.data), it->base.widget, it);
164    evas_object_smart_callback_call(obj2, "clicked", it);
165 }
166
167 static void
168 _menu_hide(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
169 {
170    Elm_Toolbar_Item *selected;
171    Elm_Toolbar_Item *it = data;
172    selected = elm_toolbar_selected_item_get(it->base.widget);
173    _item_unselect(selected);
174 }
175
176 static void
177 _menu_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
178 {
179    // avoid hide being emitted during object deletion
180    evas_object_event_callback_del_full
181      (obj, EVAS_CALLBACK_HIDE, _menu_hide, data);
182 }
183
184 static void
185 _menu_move_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
186 {
187     Elm_Toolbar_Item *it = data;
188     Evas_Coord x,y,w,h;
189     Widget_Data *wd = elm_widget_data_get(it->base.widget);
190
191     if ((!wd) || (!wd->menu_parent)) return;
192     evas_object_geometry_get(it->base.view, &x, &y, &w, &h);
193     elm_menu_move(it->o_menu, x, y+h);
194 }
195
196 static void
197 _item_disable(Elm_Toolbar_Item *it, Eina_Bool disabled)
198 {
199    Widget_Data *wd = elm_widget_data_get(it->base.widget);
200
201    if (!wd) return;
202    if (it->disabled == disabled) return;
203    it->disabled = disabled;
204    if (it->disabled)
205      {
206         edje_object_signal_emit(it->base.view, "elm,state,disabled", "elm");
207         elm_widget_signal_emit(it->icon, "elm,state,disabled", "elm");
208      }
209    else
210      {
211         edje_object_signal_emit(it->base.view, "elm,state,enabled", "elm");
212         elm_widget_signal_emit(it->icon, "elm,state,enabled", "elm");
213      }
214 }
215
216 static void
217 _item_del(Elm_Toolbar_Item *it)
218 {
219    Elm_Toolbar_Item_State *it_state;
220    _item_unselect(it);
221    elm_widget_item_pre_notify_del(it);
222    EINA_LIST_FREE(it->states, it_state)
223      {
224         if (it->icon == it_state->icon)
225            it->icon = NULL;
226         eina_stringshare_del(it_state->label);
227         eina_stringshare_del(it_state->icon_str);
228         if (it_state->icon) evas_object_del(it_state->icon);
229         free(it_state);
230      }
231    eina_stringshare_del(it->label);
232    eina_stringshare_del(it->icon_str);
233    if (it->icon) evas_object_del(it->icon);
234    //TODO: See if checking for wd->menu_parent is necessary before deleting menu
235    if (it->o_menu) evas_object_del(it->o_menu);
236    elm_widget_item_del(it);
237 }
238
239 static void
240 _del_pre_hook(Evas_Object *obj)
241 {
242    Widget_Data *wd = elm_widget_data_get(obj);
243    Elm_Toolbar_Item *it, *next;
244
245    if (!wd) return;
246    it = ELM_TOOLBAR_ITEM_FROM_INLIST(wd->items);
247    while(it)
248      {
249         next = ELM_TOOLBAR_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
250         _item_del(it);
251         it = next;
252      }
253    if (wd->more_item)
254       _item_del(wd->more_item);
255 }
256
257 static void
258 _del_hook(Evas_Object *obj)
259 {
260    Widget_Data *wd = elm_widget_data_get(obj);
261
262    if (!wd) return;
263    free(wd);
264 }
265
266
267 static void
268 _mirrored_set_item(Evas_Object *obj __UNUSED__, Elm_Toolbar_Item *it, Eina_Bool mirrored)
269 {
270    edje_object_mirrored_set(it->base.view, mirrored);
271    elm_widget_mirrored_set(it->o_menu, mirrored);
272 }
273
274 static void
275 _theme_hook_item(Evas_Object *obj, Elm_Toolbar_Item *it, double scale, int icon_size)
276 {
277    Evas_Object *view = it->base.view;
278    Evas_Coord mw, mh;
279    const char *style = elm_widget_style_get(obj);
280
281    _mirrored_set_item(obj, it, elm_widget_mirrored_get(obj));
282    edje_object_scale_set(view, scale);
283    if (!it->separator)
284      {
285         _elm_theme_object_set(obj, view, "toolbar", "item", style);
286         if (it->selected)
287           {
288              edje_object_signal_emit(view, "elm,state,selected", "elm");
289              elm_widget_signal_emit(it->icon, "elm,state,selected", "elm");
290           }
291         if (it->disabled)
292           {
293              edje_object_signal_emit(view, "elm,state,disabled", "elm");
294              elm_widget_signal_emit(it->icon, "elm,state,disabled", "elm");
295           }
296         if (it->icon)
297           {
298              int ms = 0;
299
300              ms = ((double)icon_size * scale);
301              evas_object_size_hint_min_set(it->icon, ms, ms);
302              evas_object_size_hint_max_set(it->icon, ms, ms);
303              edje_object_part_swallow(view, "elm.swallow.icon",
304                                       it->icon);
305           }
306         edje_object_part_text_set(view, "elm.text", it->label);
307      }
308    else
309       _elm_theme_object_set(obj, view, "toolbar", "separator", style);
310
311    mw = mh = -1;
312    if (!it->separator)
313       elm_coords_finger_size_adjust(1, &mw, 1, &mh);
314    edje_object_size_min_restricted_calc(view, &mw, &mh, mw, mh);
315    if (!it->separator)
316       elm_coords_finger_size_adjust(1, &mw, 1, &mh);
317    evas_object_size_hint_min_set(view, mw, mh);
318 }
319
320 static void
321 _mirrored_set(Evas_Object *obj, Eina_Bool mirrored)
322 {
323    Widget_Data *wd = elm_widget_data_get(obj);
324    Elm_Toolbar_Item *it;
325
326    EINA_INLIST_FOREACH(wd->items, it)
327       _mirrored_set_item(obj, it, mirrored);
328    if (wd->more_item)
329       _mirrored_set_item(obj, wd->more_item, mirrored);
330 }
331
332 static void
333 _theme_hook(Evas_Object *obj)
334 {
335    Widget_Data *wd = elm_widget_data_get(obj);
336    Elm_Toolbar_Item *it;
337    double scale = 0;
338
339    if (!wd) return;
340    _elm_widget_mirrored_reload(obj);
341    elm_smart_scroller_object_theme_set(obj, wd->scr, "toolbar", "base", elm_widget_style_get(obj));
342    _mirrored_set(obj, elm_widget_mirrored_get(obj));
343    scale = (elm_widget_scale_get(obj) * _elm_config->scale);
344    edje_object_scale_set(wd->scr, scale);
345    wd->icon_size = _elm_toolbar_icon_size_get(wd);
346    EINA_INLIST_FOREACH(wd->items, it)
347       _theme_hook_item(obj, it, scale, wd->icon_size);
348    if (wd->more_item)
349       _theme_hook_item(obj, wd->more_item, scale, wd->icon_size);
350    _sizing_eval(obj);
351 }
352
353 static void
354 _sizing_eval(Evas_Object *obj)
355 {
356    Widget_Data *wd = elm_widget_data_get(obj);
357    Evas_Coord minw = -1, minh = -1, minw_bx;
358    Evas_Coord vw = 0, vh = 0;
359    Evas_Coord w, h;
360
361    if (!wd) return;
362    evas_object_smart_calculate(wd->bx);
363    edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
364                              &minw, &minh);
365    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
366    if (w < minw) w = minw;
367    if (h < minh) h = minh;
368
369    evas_object_resize(wd->scr, w, h);
370
371    evas_object_size_hint_min_get(wd->bx, &minw, &minh);
372    minw_bx = minw;
373    if (w > minw) minw = w;
374    evas_object_resize(wd->bx, minw, minh);
375    elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
376    switch (wd->shrink_mode)
377      {
378        case ELM_TOOLBAR_SHRINK_MENU: /* fallthrough */
379        case ELM_TOOLBAR_SHRINK_HIDE: /* fallthrough */
380        case ELM_TOOLBAR_SHRINK_SCROLL: minw = w - vw; break;
381        case ELM_TOOLBAR_SHRINK_NONE: minw = minw_bx + (w - vw); break;
382      }
383    minh = minh + (h - vh);
384    evas_object_size_hint_min_set(obj, minw, minh);
385    evas_object_size_hint_max_set(obj, -1, -1);
386 }
387
388 static void
389 _item_menu_create(Widget_Data *wd, Elm_Toolbar_Item *item)
390 {
391    item->o_menu = elm_menu_add(item->base.view);
392    if (wd->menu_parent)
393      elm_menu_parent_set(item->o_menu, wd->menu_parent);
394    evas_object_event_callback_add(item->o_menu, EVAS_CALLBACK_HIDE,
395                                   _menu_hide, item);
396    evas_object_event_callback_add(item->o_menu, EVAS_CALLBACK_DEL,
397                                   _menu_del, item);
398 }
399
400 static void
401 _item_menu_destroy(Elm_Toolbar_Item *item)
402 {
403    if (item->o_menu)
404      {
405         evas_object_del(item->o_menu);
406         item->o_menu = NULL;
407      }
408 }
409
410 static int
411 _toolbar_item_prio_compare_cb(const void *i1, const void *i2)
412 {
413    const Elm_Toolbar_Item *eti1 = i1;
414    const Elm_Toolbar_Item *eti2 = i2;
415
416    if (!eti2) return 1;
417    if (!eti1) return -1;
418
419    return eti2->prio.priority - eti1->prio.priority;
420 }
421
422 static void
423 _fix_items_visibility(Widget_Data *wd, Evas_Coord *iw, Evas_Coord vw)
424 {
425    Elm_Toolbar_Item *it;
426    Eina_List *sorted = NULL;
427    Evas_Coord ciw;
428
429    EINA_INLIST_FOREACH(wd->items, it)
430      {
431         sorted = eina_list_sorted_insert(sorted,
432                                          _toolbar_item_prio_compare_cb, it);
433      }
434
435    if (wd->more_item)
436      {
437         evas_object_geometry_get(wd->more_item->base.view, NULL, NULL, &ciw, NULL);
438         *iw += ciw;
439      }
440    EINA_LIST_FREE(sorted, it)
441      {
442         evas_object_geometry_get(it->base.view, NULL, NULL, &ciw, NULL);
443         *iw += ciw;
444         it->prio.visible = (*iw <= vw);
445      }
446 }
447
448 static void
449 _elm_toolbar_item_menu_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
450 {
451    Elm_Toolbar_Item *it = data;
452    if (it->func) it->func((void *)(it->base.data), it->base.widget, it);
453 }
454
455 static void
456 _resize_job(void *data)
457 {
458    Widget_Data *wd = elm_widget_data_get(data);
459    Evas_Coord mw, mh, vw, vh, w, h;
460    Elm_Toolbar_Item *it;
461    Evas_Object *obj = (Evas_Object *) data;
462
463    if (!wd) return;
464    wd->resize_job = NULL;
465    elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
466    evas_object_size_hint_min_get(wd->bx, &mw, &mh);
467    evas_object_geometry_get(wd->bx, NULL, NULL, &w, &h);
468    if (wd->shrink_mode == ELM_TOOLBAR_SHRINK_MENU)
469      {
470         Evas_Coord iw = 0, more_w;
471
472         evas_object_resize(wd->bx, vw, h);
473         _fix_items_visibility(wd, &iw, vw);
474         evas_object_geometry_get(wd->more_item->base.view, NULL, NULL, &more_w, NULL);
475         if (iw - more_w <= vw)
476            iw -= more_w;
477
478         /* All items are removed from the box object, since removing individual
479          * items won't trigger a resize. Items are be readded below. */
480         evas_object_box_remove_all(wd->bx, EINA_FALSE);
481         if (iw > vw)
482           {
483              Evas_Object *menu;
484
485              _item_menu_destroy(wd->more_item);
486              _item_menu_create(wd, wd->more_item);
487              menu = elm_toolbar_item_menu_get(wd->more_item);
488
489              EINA_INLIST_FOREACH(wd->items, it)
490                {
491                  if (!it->prio.visible)
492                     {
493                        if (it->separator)
494                          elm_menu_item_separator_add(menu, NULL);
495                        else
496                          {
497                             Elm_Menu_Item *item;
498                             item = elm_menu_item_add(menu, NULL, it->icon_str, it->label,
499                                                      _elm_toolbar_item_menu_cb, it);
500                             elm_menu_item_disabled_set(item, it->disabled);
501                             if (it->o_menu) elm_menu_clone(it->o_menu, menu, item);
502                          }
503                        evas_object_hide(it->base.view);
504                     }
505                  else
506                     {
507                        evas_object_box_append(wd->bx, it->base.view);
508                        evas_object_show(it->base.view);
509                     }
510                }
511
512              evas_object_box_append(wd->bx, wd->more_item->base.view);
513              evas_object_show(wd->more_item->base.view);
514           }
515         else
516           {
517              /* All items are visible, show them all (except for the "More"
518               * button, of course). */
519              EINA_INLIST_FOREACH(wd->items, it)
520                {
521                   evas_object_show(it->base.view);
522                   evas_object_box_append(wd->bx, it->base.view);
523                }
524              evas_object_hide(wd->more_item->base.view);
525           }
526      }
527    else if (wd->shrink_mode == ELM_TOOLBAR_SHRINK_HIDE)
528      {
529         Evas_Coord iw = 0;
530
531         evas_object_resize(wd->bx, vw, h);
532         _fix_items_visibility(wd, &iw, vw);
533         evas_object_box_remove_all(wd->bx, EINA_FALSE);
534         if (iw > vw)
535           {
536              EINA_INLIST_FOREACH(wd->items, it)
537                {
538                  if (!it->prio.visible)
539                    evas_object_hide(it->base.view);
540                  else
541                    {
542                       evas_object_box_append(wd->bx, it->base.view);
543                       evas_object_show(it->base.view);
544                    }
545                }
546           }
547         else
548           {
549              /* All items are visible, show them all */
550              EINA_INLIST_FOREACH(wd->items, it)
551                {
552                   evas_object_show(it->base.view);
553                   evas_object_box_append(wd->bx, it->base.view);
554                }
555           }
556      }
557    else
558      {
559         if ((vw >= mw) && (w != vw)) evas_object_resize(wd->bx, vw, h);
560         EINA_INLIST_FOREACH(wd->items, it)
561           {
562              if (it->selected)
563                {
564                   _item_show(it);
565                   break;
566                }
567           }
568      }
569
570    _mirrored_set(obj, elm_widget_mirrored_get(obj));
571 }
572
573 static void
574 _resize_item(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
575 {
576    _sizing_eval(data);
577    _resize(data, NULL, NULL, NULL);
578 }
579
580 static void
581 _resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
582 {
583    Widget_Data *wd = elm_widget_data_get(data);
584    if (!wd->resize_job)
585       wd->resize_job = ecore_job_add(_resize_job, data);
586 }
587
588 static void
589 _select(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
590 {
591    _item_select(data);
592 }
593
594 static void
595 _mouse_in(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
596 {
597    Elm_Toolbar_Item *it = data;
598    edje_object_signal_emit(it->base.view, "elm,state,highlighted", "elm");
599    elm_widget_signal_emit(it->icon, "elm,state,highlighted", "elm");
600 }
601
602 static void
603 _mouse_out(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
604 {
605    Elm_Toolbar_Item *it = data;
606    edje_object_signal_emit(it->base.view, "elm,state,unhighlighted", "elm");
607    elm_widget_signal_emit(it->icon, "elm,state,unhighlighted", "elm");
608 }
609
610 static void
611 _layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data)
612 {
613    Evas_Object *obj = (Evas_Object *) data;
614    Widget_Data *wd = elm_widget_data_get(obj);
615    if (!wd) return;
616    _els_box_layout(o, priv, 1, wd->homogeneous, elm_widget_mirrored_get(obj));
617 }
618
619 static Elm_Toolbar_Item *
620 _item_new(Evas_Object *obj, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
621 {
622    Widget_Data *wd = elm_widget_data_get(obj);
623    Evas_Object *icon_obj;
624    Evas_Coord mw, mh;
625    Elm_Toolbar_Item *it;
626
627    icon_obj = elm_icon_add(obj);
628    elm_icon_order_lookup_set(icon_obj, wd->lookup_order);
629    if (!icon_obj) return NULL;
630    it = elm_widget_item_new(obj, Elm_Toolbar_Item);
631    if (!it)
632      {
633         evas_object_del(icon_obj);
634         return NULL;
635      }
636    it->label = eina_stringshare_add(label);
637    it->prio.visible = 1;
638    it->prio.priority = 0;
639    it->func = func;
640    it->separator = EINA_FALSE;
641    it->base.data = data;
642    it->base.view = edje_object_add(evas_object_evas_get(obj));
643    if (_item_icon_set(icon_obj, "toolbar/", icon))
644      {
645         it->icon = icon_obj;
646         it->icon_str = eina_stringshare_add(icon);
647      }
648    else
649      {
650         it->icon = NULL;
651         it->icon_str = NULL;
652         evas_object_del(icon_obj);
653      }
654
655    _elm_theme_object_set(obj, it->base.view, "toolbar", "item",
656                          elm_widget_style_get(obj));
657    edje_object_signal_callback_add(it->base.view, "elm,action,click", "elm",
658                                    _select, it);
659    edje_object_signal_callback_add(it->base.view, "elm,mouse,in", "elm",
660                                    _mouse_in, it);
661    edje_object_signal_callback_add(it->base.view, "elm,mouse,out", "elm",
662                                    _mouse_out, it);
663    elm_widget_sub_object_add(obj, it->base.view);
664    if (it->icon)
665      {
666         int ms = 0;
667
668         ms = ((double)wd->icon_size * _elm_config->scale);
669         evas_object_size_hint_min_set(it->icon, ms, ms);
670         evas_object_size_hint_max_set(it->icon, ms, ms);
671         edje_object_part_swallow(it->base.view, "elm.swallow.icon", it->icon);
672         evas_object_show(it->icon);
673         elm_widget_sub_object_add(obj, it->icon);
674      }
675    edje_object_part_text_set(it->base.view, "elm.text", it->label);
676    mw = mh = -1;
677    elm_coords_finger_size_adjust(1, &mw, 1, &mh);
678    edje_object_size_min_restricted_calc(it->base.view, &mw, &mh, mw, mh);
679    elm_coords_finger_size_adjust(1, &mw, 1, &mh);
680    evas_object_size_hint_weight_set(it->base.view, -1.0, EVAS_HINT_EXPAND);
681    evas_object_size_hint_align_set(it->base.view, 0.5, EVAS_HINT_FILL);
682    evas_object_size_hint_min_set(it->base.view, mw, mh);
683    evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_RESIZE,
684                                   _resize_item, obj);
685    return it;
686 }
687
688 /**
689  * Add a toolbar object to @p parent.
690  *
691  * @param parent The parent object
692  *
693  * @return The created object, or NULL on failure
694  *
695  * @ingroup Toolbar
696  */
697 EAPI Evas_Object *
698 elm_toolbar_add(Evas_Object *parent)
699 {
700    Evas_Object *obj;
701    Evas *e;
702    Widget_Data *wd;
703
704    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
705
706    wd = ELM_NEW(Widget_Data);
707    e = evas_object_evas_get(parent);
708    if (!e) return NULL;
709    obj = elm_widget_add(e);
710    ELM_SET_WIDTYPE(widtype, "toolbar");
711    elm_widget_type_set(obj, "toolbar");
712    elm_widget_sub_object_add(parent, obj);
713    elm_widget_data_set(obj, wd);
714    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
715    elm_widget_del_hook_set(obj, _del_hook);
716    elm_widget_theme_hook_set(obj, _theme_hook);
717    elm_widget_can_focus_set(obj, EINA_FALSE);
718
719    wd->more_item = NULL;
720    wd->selected_item = NULL;
721    wd->scr = elm_smart_scroller_add(e);
722    elm_smart_scroller_widget_set(wd->scr, obj);
723    elm_smart_scroller_object_theme_set(obj, wd->scr, "toolbar", "base", "default");
724    elm_smart_scroller_bounce_allow_set(wd->scr,
725                                        _elm_config->thumbscroll_bounce_enable,
726                                        EINA_FALSE);
727    elm_widget_resize_object_set(obj, wd->scr);
728    elm_smart_scroller_policy_set(wd->scr,
729                                  ELM_SMART_SCROLLER_POLICY_AUTO,
730                                  ELM_SMART_SCROLLER_POLICY_OFF);
731
732
733    wd->icon_size = _elm_toolbar_icon_size_get(wd);
734
735
736    wd->homogeneous = EINA_TRUE;
737    wd->align = 0.5;
738
739    wd->bx = evas_object_box_add(e);
740    evas_object_size_hint_align_set(wd->bx, wd->align, 0.5);
741    evas_object_box_layout_set(wd->bx, _layout, obj, NULL);
742    elm_widget_sub_object_add(obj, wd->bx);
743    elm_smart_scroller_child_set(wd->scr, wd->bx);
744    evas_object_show(wd->bx);
745
746    elm_toolbar_mode_shrink_set(obj, _elm_config->toolbar_shrink_mode);
747    evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_RESIZE, _resize, obj);
748    evas_object_event_callback_add(wd->bx, EVAS_CALLBACK_RESIZE, _resize, obj);
749    elm_toolbar_icon_order_lookup_set(obj, ELM_ICON_LOOKUP_THEME_FDO);
750
751    _sizing_eval(obj);
752    return obj;
753 }
754
755 /**
756  * Set the icon size (in pixels) for the toolbar.
757  *
758  * @param obj The toolbar object
759  * @param icon_size The icon size in pixels
760  *
761  * @ingroup Toolbar
762  */
763 EAPI void
764 elm_toolbar_icon_size_set(Evas_Object *obj, int icon_size)
765 {
766    ELM_CHECK_WIDTYPE(obj, widtype);
767    Widget_Data *wd = elm_widget_data_get(obj);
768    if (!wd) return;
769    if (wd->icon_size == icon_size) return;
770    wd->icon_size = icon_size;
771    _theme_hook(obj);
772 }
773
774 /**
775  * Get the icon size (in pixels) for the toolbar.
776  *
777  * @param obj The toolbar object
778  * @return The icon size in pixels
779  *
780  * @ingroup Toolbar
781  */
782 EAPI int
783 elm_toolbar_icon_size_get(const Evas_Object *obj)
784 {
785    ELM_CHECK_WIDTYPE(obj, widtype) 0;
786    Widget_Data *wd = elm_widget_data_get(obj);
787    if (!wd) return 0;
788    return wd->icon_size;
789 }
790
791 /**
792  * Append item to the toolbar
793  *
794  * @param obj The toolbar object
795  * @param icon A string with icon name or the absolute path of an image file.
796  * @param label The label of the item
797  * @param func The function to call when the item is clicked
798  * @param data The data to associate with the item
799  * @return The toolbar item, or NULL upon failure
800  *
801  * @see elm_toolbar_item_icon_set
802  *
803  * @ingroup Toolbar
804  */
805 EAPI Elm_Toolbar_Item *
806 elm_toolbar_item_append(Evas_Object *obj, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
807 {
808    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
809    Widget_Data *wd = elm_widget_data_get(obj);
810    if (!wd) return NULL;
811
812    Elm_Toolbar_Item *it = _item_new(obj, icon, label, func, data);
813    if (!it) return NULL;
814
815    wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(it));
816    evas_object_box_append(wd->bx, it->base.view);
817    evas_object_show(it->base.view);
818    _sizing_eval(obj);
819
820    return it;
821 }
822
823 static void
824 _elm_toolbar_item_state_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
825 {
826    Elm_Toolbar_Item *it = event_info;
827    Elm_Toolbar_Item_State *it_state;
828
829    it_state = eina_list_data_get(it->current_state);
830    if (it_state->func)
831       it_state->func((void *)it_state->data, obj, event_info);
832 }
833
834 /**
835  * Sets the next @p item state as the current state.
836  *
837  * @param item The item.
838  *
839  * @ingroup Toolbar
840  */
841 EAPI Elm_Toolbar_Item_State *
842 elm_toolbar_item_state_next(Elm_Toolbar_Item *item)
843 {
844    Widget_Data *wd;
845    Evas_Object *obj;
846    Eina_List *next_state;
847    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
848
849    obj = item->base.widget;
850    wd = elm_widget_data_get(obj);
851    if (!wd) return NULL;
852    if (!item->states) return NULL;
853
854    next_state = eina_list_next(item->current_state);
855    if (!next_state)
856       next_state = eina_list_next(item->states);
857    return eina_list_data_get(next_state);
858 }
859
860 /**
861  * Sets the previous @p item state as the current state.
862  *
863  * @param item The item.
864  *
865  * @ingroup Toolbar
866  */
867 EAPI Elm_Toolbar_Item_State *
868 elm_toolbar_item_state_prev(Elm_Toolbar_Item *item)
869 {
870    Widget_Data *wd;
871    Evas_Object *obj;
872    Eina_List *prev_state;
873    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
874
875    obj = item->base.widget;
876    wd = elm_widget_data_get(obj);
877    if (!wd) return NULL;
878    if (!item->states) return NULL;
879
880    prev_state = eina_list_prev(item->current_state);
881    if ((!prev_state) || (prev_state == item->states))
882       prev_state = eina_list_last(item->states);
883    return eina_list_data_get(prev_state);
884 }
885
886 /**
887  * Unset the state of @p it
888  * The default icon and label from this item will be displayed.
889  *
890  * @param it The item.
891  *
892  * @ingroup Toolbar
893  */
894 EAPI void
895 elm_toolbar_item_state_unset(Elm_Toolbar_Item *it)
896 {
897    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
898    elm_toolbar_item_state_set(it, NULL);
899 }
900
901 /**
902  * Sets @p state as the current state of @p it.
903  * If @p state is NULL, it won't select any state and the default icon and
904  * label will be used.
905  *
906  * @param it The item.
907  * @param state The state to use.
908  *
909  * @return True if the state was correctly set.
910  *
911  * @ingroup Toolbar
912  */
913 EAPI Eina_Bool
914 elm_toolbar_item_state_set(Elm_Toolbar_Item *it, Elm_Toolbar_Item_State *state)
915 {
916    Widget_Data *wd;
917    Eina_List *next_state;
918    Elm_Toolbar_Item_State *it_state;
919    Evas_Object *obj;
920    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
921
922    obj = it->base.widget;
923    wd = elm_widget_data_get(obj);
924    if (!wd) return EINA_FALSE;
925    if (!it->states) return EINA_FALSE;
926
927    if (state)
928      {
929         next_state = eina_list_data_find_list(it->states, state);
930         if (!next_state) return EINA_FALSE;
931      }
932    else
933       next_state = it->states;
934
935    if (next_state == it->current_state) return EINA_TRUE;
936
937    it_state = eina_list_data_get(next_state);
938    if (eina_list_data_find(it->current_state, state))
939      {
940         _item_label_set(it, it_state->label, "elm,state,label_set,forward");
941         _elm_toolbar_item_icon_obj_set(obj, it, it_state->icon, it_state->icon_str,
942                                        wd->icon_size, "elm,state,icon_set,forward");
943      }
944    else
945      {
946         _item_label_set(it, it_state->label, "elm,state,label_set,backward");
947         _elm_toolbar_item_icon_obj_set(obj, it, it_state->icon, it_state->icon_str,
948                                        wd->icon_size, "elm,state,icon_set,backward");
949      }
950    if (it->disabled)
951         elm_widget_signal_emit(it->icon, "elm,state,disabled", "elm");
952    else
953         elm_widget_signal_emit(it->icon, "elm,state,enabled", "elm");
954
955    it->current_state = next_state;
956    return EINA_TRUE;
957 }
958
959 /**
960  * Get the current state of @p item.
961  * If no state is selected, returns NULL.
962  *
963  * @param item The item.
964  *
965  * @return The state.
966  *
967  * @ingroup Toolbar
968  */
969 EAPI Elm_Toolbar_Item_State *
970 elm_toolbar_item_state_get(const Elm_Toolbar_Item *it)
971 {
972    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
973    if ((!it->states) || (!it->current_state)) return NULL;
974    if (it->current_state == it->states) return NULL;
975
976    return eina_list_data_get(it->current_state);
977 }
978
979 static Elm_Toolbar_Item_State *
980 _item_state_new(const char *label, const char *icon_str, Evas_Object *icon, Evas_Smart_Cb func, const void *data)
981 {
982    Elm_Toolbar_Item_State *it_state;
983    it_state = ELM_NEW(Elm_Toolbar_Item_State);
984    it_state->label = eina_stringshare_add(label);
985    it_state->icon_str = eina_stringshare_add(icon_str);
986    it_state->icon = icon;
987    it_state->func = func;
988    it_state->data = data;
989    return it_state;
990 }
991
992 /**
993  * Add a new state to @p item
994  *
995  * @param item The item.
996  * @param icon The icon string
997  * @param label The label of the new state
998  * @param func The function to call when the item is clicked when this state is
999  * selected.
1000  * @param data The data to associate with the state
1001  * @return The toolbar item state, or NULL upon failure
1002  *
1003  * @ingroup Toolbar
1004  */
1005 EAPI Elm_Toolbar_Item_State *
1006 elm_toolbar_item_state_add(Elm_Toolbar_Item *item, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
1007 {
1008    Elm_Toolbar_Item_State *it_state;
1009    Evas_Object *icon_obj;
1010    Evas_Object *obj;
1011    Widget_Data *wd;
1012    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
1013    obj = item->base.widget;
1014    wd = elm_widget_data_get(item->base.widget);
1015    if (!wd) return NULL;
1016
1017    if (!item->states)
1018      {
1019         it_state = _item_state_new(item->label, item->icon_str, item->icon,
1020                                    item->func, item->base.data);
1021         item->states = eina_list_append(item->states, it_state);
1022         item->current_state = item->states;
1023      }
1024
1025    icon_obj = elm_icon_add(obj);
1026    elm_icon_order_lookup_set(icon_obj, wd->lookup_order);
1027    if (!icon_obj) goto error_state_add;
1028
1029    if (!_item_icon_set(icon_obj, "toolbar/", icon))
1030      {
1031         evas_object_del(icon_obj);
1032         icon_obj = NULL;
1033         icon = NULL;
1034      }
1035
1036    it_state = _item_state_new(label, icon, icon_obj, func, data);
1037    item->states = eina_list_append(item->states, it_state);
1038    item->func = _elm_toolbar_item_state_cb;
1039    item->base.data = NULL;
1040
1041    return it_state;
1042
1043 error_state_add:
1044    if (item->states && !eina_list_next(item->states))
1045      {
1046         eina_stringshare_del(item->label);
1047         eina_stringshare_del(item->icon_str);
1048         free(eina_list_data_get(item->states));
1049         eina_list_free(item->states);
1050         item->states = NULL;
1051      }
1052    return NULL;
1053 }
1054
1055 EAPI Eina_Bool
1056 elm_toolbar_item_state_del(Elm_Toolbar_Item *item, Elm_Toolbar_Item_State *state)
1057 {
1058    Eina_List *del_state;
1059    Elm_Toolbar_Item_State *it_state;
1060    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
1061
1062    if (!state) return EINA_FALSE;
1063    if (!item->states) return EINA_FALSE;
1064
1065    del_state = eina_list_data_find_list(item->states, state);
1066    if (del_state == item->states) return EINA_FALSE;
1067    if (del_state == item->current_state)
1068       elm_toolbar_item_state_unset(item);
1069
1070    eina_stringshare_del(state->label);
1071    eina_stringshare_del(state->icon_str);
1072    if (state->icon) evas_object_del(state->icon);
1073    free(state);
1074    item->states = eina_list_remove_list(item->states, del_state);
1075    if (item->states && !eina_list_next(item->states))
1076      {
1077         it_state = eina_list_data_get(item->states);
1078         item->base.data = it_state->data;
1079         item->func = it_state->func;
1080         eina_stringshare_del(it_state->label);
1081         eina_stringshare_del(it_state->icon_str);
1082         free(eina_list_data_get(item->states));
1083         eina_list_free(item->states);
1084         item->states = NULL;
1085      }
1086    return EINA_TRUE;
1087 }
1088
1089
1090 /**
1091  * Prepend item to the toolbar
1092  *
1093  * @param obj The toolbar object
1094  * @param icon A string with icon name or the absolute path of an image file.
1095  * @param label The label of the item
1096  * @param func The function to call when the item is clicked
1097  * @param data The data to associate with the item
1098  * @return The toolbar item, or NULL upon failure
1099  *
1100  * @see elm_toolbar_item_icon_set
1101  *
1102  * @ingroup Toolbar
1103  */
1104 EAPI Elm_Toolbar_Item *
1105 elm_toolbar_item_prepend(Evas_Object *obj, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
1106 {
1107    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1108    Widget_Data *wd = elm_widget_data_get(obj);
1109    if (!wd) return NULL;
1110
1111    Elm_Toolbar_Item *it = _item_new(obj, icon, label, func, data);
1112    if (!it) return NULL;
1113
1114    wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(it));
1115    evas_object_box_prepend(wd->bx, it->base.view);
1116    evas_object_show(it->base.view);
1117    _sizing_eval(obj);
1118
1119    return it;
1120 }
1121
1122 /**
1123  * Insert item before another in the toolbar
1124  *
1125  * @param obj The toolbar object
1126  * @param before The item to insert before
1127  * @param icon A string with icon name or the absolute path of an image file.
1128  * @param label The label of the item
1129  * @param func The function to call when the item is clicked
1130  * @param data The data to associate with the item
1131  * @return The toolbar item, or NULL upon failure
1132  *
1133  * @see elm_toolbar_item_icon_set
1134  *
1135  * @ingroup Toolbar
1136  */
1137 EAPI Elm_Toolbar_Item *
1138 elm_toolbar_item_insert_before(Evas_Object *obj, Elm_Toolbar_Item *before, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
1139 {
1140    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1141    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(before, NULL);
1142    Widget_Data *wd = elm_widget_data_get(obj);
1143    if (!wd) return NULL;
1144
1145    Elm_Toolbar_Item *it = _item_new(obj, icon, label, func, data);
1146    if (!it) return NULL;
1147
1148    wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
1149                                             EINA_INLIST_GET(before));
1150    evas_object_box_insert_before(wd->bx, it->base.view, before->base.view);
1151    evas_object_show(it->base.view);
1152    _sizing_eval(obj);
1153
1154    return it;
1155 }
1156
1157 /**
1158  * Insert item after another in the toolbar
1159  *
1160  * @param obj The toolbar object
1161  * @param after The item to insert after
1162  * @param icon A string with icon name or the absolute path of an image file.
1163  * @param label The label of the item
1164  * @param func The function to call when the item is clicked
1165  * @param data The data to associate with the item
1166  * @return The toolbar item, or NULL upon failure
1167  *
1168  * @see elm_toolbar_item_icon_set
1169  *
1170  * @ingroup Toolbar
1171  */
1172 EAPI Elm_Toolbar_Item *
1173 elm_toolbar_item_insert_after(Evas_Object *obj, Elm_Toolbar_Item *after, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
1174 {
1175    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1176    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(after, NULL);
1177    Widget_Data *wd = elm_widget_data_get(obj);
1178    if (!wd) return NULL;
1179
1180    Elm_Toolbar_Item *it = _item_new(obj, icon, label, func, data);
1181    if (!it) return NULL;
1182
1183    wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
1184                                             EINA_INLIST_GET(after));
1185    evas_object_box_insert_after(wd->bx, it->base.view, after->base.view);
1186    evas_object_show(it->base.view);
1187    _sizing_eval(obj);
1188
1189    return it;
1190 }
1191
1192 /**
1193  * Get the first item in the toolbar
1194  *
1195  * @param obj The toolbar object
1196  * @return The first item, or NULL if none
1197  *
1198  * @ingroup Toolbar
1199  */
1200 EAPI Elm_Toolbar_Item *
1201 elm_toolbar_first_item_get(const Evas_Object *obj)
1202 {
1203    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1204    Widget_Data *wd = elm_widget_data_get(obj);
1205    if (!wd || !wd->items) return NULL;
1206    Elm_Toolbar_Item *it = ELM_TOOLBAR_ITEM_FROM_INLIST(wd->items);
1207    return it;
1208 }
1209
1210 /**
1211  * Get the last item in the toolbar
1212  *
1213  * @return The last item, or NULL if none
1214  *
1215  * @ingroup Toolbar
1216  */
1217 EAPI Elm_Toolbar_Item *
1218 elm_toolbar_last_item_get(const Evas_Object *obj)
1219 {
1220    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1221    Widget_Data *wd = elm_widget_data_get(obj);
1222    if (!wd || !wd->items) return NULL;
1223    Elm_Toolbar_Item *it = ELM_TOOLBAR_ITEM_FROM_INLIST(wd->items->last);
1224    return it;
1225 }
1226
1227 /**
1228  * Get the next item in the toolbar
1229  *
1230  * This returns the item after the item @p it.
1231  *
1232  * @param item The item
1233  * @return The item after @p it, or NULL if none
1234  *
1235  * @ingroup Toolbar
1236  */
1237 EAPI Elm_Toolbar_Item *
1238 elm_toolbar_item_next_get(const Elm_Toolbar_Item *item)
1239 {
1240    Elm_Toolbar_Item *next;
1241    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
1242    next = ELM_TOOLBAR_ITEM_FROM_INLIST(EINA_INLIST_GET(item)->next);
1243    return next;
1244 }
1245
1246 /**
1247  * Get the previous item in the toolbar
1248  *
1249  * This returns the item before the item @p it.
1250  *
1251  * @param item The item
1252  * @return The item before @p it, or NULL if none
1253  *
1254  * @ingroup Toolbar
1255  */
1256 EAPI Elm_Toolbar_Item *
1257 elm_toolbar_item_prev_get(const Elm_Toolbar_Item *item)
1258 {
1259    Elm_Toolbar_Item *prev;
1260    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
1261    prev = ELM_TOOLBAR_ITEM_FROM_INLIST(EINA_INLIST_GET(item)->prev);
1262    return prev;
1263 }
1264
1265 /**
1266  * Get the toolbar object from an item
1267  *
1268  * This returns the toolbar object itself that an item belongs to.
1269  *
1270  * @param item The item
1271  * @return The toolbar object
1272  *
1273  * @ingroup Toolbar
1274  */
1275 EAPI Evas_Object *
1276 elm_toolbar_item_toolbar_get(const Elm_Toolbar_Item *item)
1277 {
1278    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
1279    return item->base.widget;
1280 }
1281
1282 /**
1283  * Sets the priority of a toolbar item. This is used only when the toolbar
1284  * shrink mode is set to ELM_TOOLBAR_SHRINK_MENU or ELM_TOOLBAR_SHRINK_HIDE:
1285  * when space is at a premium, items with low priority will be removed from
1286  * the toolbar and added to a dynamically-created menu, while items with
1287  * higher priority will remain on the toolbar, with the same order they were
1288  * added.
1289  *
1290  * @param item The toolbar item.
1291  * @param priority The item priority. The default is zero.
1292  *
1293  * @ingroup Toolbar
1294  */
1295 EAPI void
1296 elm_toolbar_item_priority_set(Elm_Toolbar_Item *item, int priority)
1297 {
1298    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1299     if (item->prio.priority == priority) return;
1300     item->prio.priority = priority;
1301     _resize(item->base.widget, NULL, NULL, NULL);
1302 }
1303
1304 /**
1305  * Gets the priority of a toolbar item.
1306  *
1307  * @param item The toolbar item.
1308  * @return The item priority, or 0 if an error occurred.
1309  *
1310  * @ingroup Toolbar
1311  */
1312 EAPI int
1313 elm_toolbar_item_priority_get(const Elm_Toolbar_Item *item)
1314 {
1315    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, 0);
1316    return item->prio.priority;
1317 }
1318
1319 /**
1320  * Get the string used to set the icon of @p item.
1321  *
1322  * @param item The toolbar item
1323  * @return The string associated with the icon object.
1324  *
1325  * @see elm_toolbar_item_icon_set()
1326  *
1327  * @ingroup Toolbar
1328  */
1329 EAPI const char *
1330 elm_toolbar_item_icon_get(const Elm_Toolbar_Item *item)
1331 {
1332    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
1333    return item->icon_str;
1334 }
1335
1336 /**
1337  * Get the label associated with @p item.
1338  *
1339  * @param item The toolbar item
1340  * @return The label
1341  *
1342  * @ingroup Toolbar
1343  */
1344 EAPI const char *
1345 elm_toolbar_item_label_get(const Elm_Toolbar_Item *item)
1346 {
1347    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
1348    return item->label;
1349 }
1350
1351 static void
1352 _elm_toolbar_item_label_update(Elm_Toolbar_Item *item)
1353 {
1354    Evas_Coord mw = -1, mh = -1;
1355    edje_object_part_text_set(item->base.view, "elm.text", item->label);
1356
1357    elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1358    edje_object_size_min_restricted_calc(item->base.view, &mw, &mh, mw, mh);
1359    elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1360    evas_object_size_hint_weight_set(item->base.view, -1.0, EVAS_HINT_EXPAND);
1361    evas_object_size_hint_align_set(item->base.view, 0.5, EVAS_HINT_FILL);
1362    evas_object_size_hint_min_set(item->base.view, mw, mh);
1363 }
1364
1365 static void
1366 _elm_toolbar_item_label_set_cb (void *data, Evas_Object *obj, const char *emission, const char *source)
1367 {
1368    Elm_Toolbar_Item *item = data;
1369    _elm_toolbar_item_label_update(item);
1370    edje_object_signal_callback_del(obj, emission, source,
1371                                    _elm_toolbar_item_label_set_cb);
1372    edje_object_signal_emit (item->base.view, "elm,state,label,reset", "elm");
1373 }
1374
1375 static void
1376 _item_label_set(Elm_Toolbar_Item *item, const char *label, const char *signal)
1377 {
1378    const char *s;
1379
1380    if ((label) && (item->label) && (!strcmp(label, item->label))) return;
1381
1382    eina_stringshare_replace(&item->label, label);
1383    s = edje_object_data_get(item->base.view, "transition_animation_on");
1384    if ((s) && (atoi(s)))
1385      {
1386         edje_object_part_text_set(item->base.view, "elm.text_new", item->label);
1387         edje_object_signal_emit (item->base.view, signal, "elm");
1388         edje_object_signal_callback_add(item->base.view,
1389                                         "elm,state,label_set,done", "elm",
1390                                         _elm_toolbar_item_label_set_cb, item);
1391      }
1392    else
1393       _elm_toolbar_item_label_update(item);
1394    _resize(item->base.widget, NULL, NULL, NULL);
1395 }
1396
1397 /**
1398  * Set the label associated with @p item.
1399  *
1400  * @param item The toolbar item
1401  * @param label The label of @p item
1402  *
1403  * @ingroup Toolbar
1404  */
1405 EAPI void
1406 elm_toolbar_item_label_set(Elm_Toolbar_Item *item, const char *label)
1407 {
1408    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1409    _item_label_set(item, label, "elm,state,label_set");
1410 }
1411
1412 static void
1413 _elm_toolbar_item_icon_update(Elm_Toolbar_Item *item)
1414 {
1415    Elm_Toolbar_Item_State *it_state;
1416    Eina_List *l;
1417    Evas_Coord mw = -1, mh = -1;
1418    Evas_Object *old_icon = edje_object_part_swallow_get(item->base.view,
1419                                                         "elm.swallow.icon");
1420    elm_widget_sub_object_del(item->base.view, old_icon);
1421    evas_object_hide(old_icon);
1422    edje_object_part_swallow(item->base.view, "elm.swallow.icon", item->icon);
1423    elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1424    edje_object_size_min_restricted_calc(item->base.view, &mw, &mh, mw, mh);
1425    elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1426    evas_object_size_hint_weight_set(item->base.view, -1.0, EVAS_HINT_EXPAND);
1427    evas_object_size_hint_align_set(item->base.view, 0.5, EVAS_HINT_FILL);
1428    evas_object_size_hint_min_set(item->base.view, mw, mh);
1429
1430    EINA_LIST_FOREACH(item->states, l, it_state)
1431       if (it_state->icon == old_icon)
1432          return;
1433    evas_object_del(old_icon);
1434 }
1435
1436 /**
1437  * Get the selected state of @p item.
1438  *
1439  * @param item The toolbar item
1440  * @return If true, the item is selected
1441  *
1442  * @ingroup Toolbar
1443  */
1444 EAPI Eina_Bool
1445 elm_toolbar_item_selected_get(const Elm_Toolbar_Item *item)
1446 {
1447    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
1448    return item->selected;
1449 }
1450
1451 /**
1452  * Set the selected state of an item
1453  *
1454  * This sets the selected state (1 selected, 0 not selected) of the given
1455  * item @p it. If a new item is selected the previosly selected will be
1456  * unselected.
1457  *
1458  * @param item The item
1459  * @param selected The selected state
1460  *
1461  * @ingroup Toolbar
1462  */
1463 EAPI void
1464 elm_toolbar_item_selected_set(Elm_Toolbar_Item *item, Eina_Bool selected)
1465 {
1466    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1467    Widget_Data *wd = elm_widget_data_get(item->base.widget);
1468    if (!wd) return;
1469
1470    if (item->selected == selected) return;
1471
1472    if (selected)
1473      _item_select(item);
1474    else
1475      _item_unselect(item);
1476 }
1477
1478 /**
1479  * Get the selectd item in the toolbar
1480  *
1481  * If no item is selected, NULL is returned.
1482  *
1483  * @param obj The toolbar object
1484  * @return The selected item, or NULL if none.
1485  *
1486  * @ingroup Toolbar
1487  */
1488 EAPI Elm_Toolbar_Item *
1489 elm_toolbar_selected_item_get(const Evas_Object *obj)
1490 {
1491    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1492    Widget_Data *wd = elm_widget_data_get(obj);
1493    if (!wd) return NULL;
1494    return wd->selected_item;
1495 }
1496
1497 static void
1498 _elm_toolbar_item_icon_set_cb (void *data, Evas_Object *obj, const char *emission, const char *source)
1499 {
1500    Elm_Toolbar_Item *item = data;
1501    edje_object_part_unswallow(item->base.view, item->icon);
1502    _elm_toolbar_item_icon_update(item);
1503    edje_object_signal_callback_del(obj, emission, source,
1504                                    _elm_toolbar_item_icon_set_cb);
1505    edje_object_signal_emit (item->base.view, "elm,state,icon,reset", "elm");
1506 }
1507
1508 static void
1509 _elm_toolbar_item_icon_obj_set(Evas_Object *obj, Elm_Toolbar_Item *item, Evas_Object *icon_obj, const char *icon_str, double icon_size, const char *signal)
1510 {
1511    Evas_Object *old_icon;
1512    int ms = 0;
1513    const char *s;
1514
1515    if (icon_str)
1516       eina_stringshare_replace(&item->icon_str, icon_str);
1517    else
1518      {
1519         eina_stringshare_del(item->icon_str);
1520         item->icon_str = NULL;
1521      }
1522    item->icon = icon_obj;
1523    if (icon_obj)
1524      {
1525         ms = (icon_size * _elm_config->scale);
1526         evas_object_size_hint_min_set(item->icon, ms, ms);
1527         evas_object_size_hint_max_set(item->icon, ms, ms);
1528         evas_object_show(item->icon);
1529         elm_widget_sub_object_add(obj, item->icon);
1530      }
1531    s = edje_object_data_get(item->base.view, "transition_animation_on");
1532    if ((s) && (atoi(s)))
1533      {
1534         old_icon = edje_object_part_swallow_get(item->base.view,
1535                                                 "elm.swallow.icon_new");
1536         if (old_icon)
1537           {
1538              elm_widget_sub_object_del(item->base.view, old_icon);
1539              evas_object_hide(old_icon);
1540           }
1541         edje_object_part_swallow(item->base.view, "elm.swallow.icon_new",
1542                                  item->icon);
1543         edje_object_signal_emit (item->base.view, signal, "elm");
1544         edje_object_signal_callback_add(item->base.view,
1545                                         "elm,state,icon_set,done", "elm",
1546                                         _elm_toolbar_item_icon_set_cb, item);
1547      }
1548    else
1549       _elm_toolbar_item_icon_update(item);
1550    _resize(obj, NULL, NULL, NULL);
1551 }
1552
1553 /**
1554  * Set the icon associated with @p item.
1555  *
1556  * Toolbar will load icon image from fdo or current theme.
1557  * This behavior can be set by elm_toolbar_icon_order_lookup_set() function.
1558  * If an absolute path is provided it will load it direct from a file.
1559  *
1560  * @param obj The parent of this item
1561  * @param item The toolbar item
1562  * @param icon A string with icon name or the absolute path of an image file.
1563  *
1564  * @see elm_toolbar_icon_order_lookup_set(), elm_toolbar_icon_order_lookup_get()
1565  *
1566  * @ingroup Toolbar
1567  */
1568 EAPI void
1569 elm_toolbar_item_icon_set(Elm_Toolbar_Item *item, const char *icon)
1570 {
1571    Evas_Object *icon_obj;
1572    Widget_Data *wd;
1573    Evas_Object *obj = item->base.widget;
1574
1575    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1576    wd = elm_widget_data_get(obj);
1577    if (!wd) return;
1578    if ((icon) && (item->icon_str) && (!strcmp(icon, item->icon_str))) return;
1579
1580    icon_obj = elm_icon_add(obj);
1581    if (!icon_obj) return;
1582    if (_item_icon_set(icon_obj, "toolbar/", icon))
1583       _elm_toolbar_item_icon_obj_set(obj, item, icon_obj, icon, wd->icon_size,
1584                                      "elm,state,icon_set");
1585    else
1586      {
1587         _elm_toolbar_item_icon_obj_set(obj, item, NULL, NULL, 0,
1588                                        "elm,state,icon_set");
1589         evas_object_del(icon_obj);
1590      }
1591 }
1592
1593 /**
1594  * Delete a toolbar item.
1595  *
1596  * @param item The toolbar item
1597  *
1598  * @ingroup Toolbar
1599  */
1600 EAPI void
1601 elm_toolbar_item_del(Elm_Toolbar_Item *item)
1602 {
1603    Widget_Data *wd;
1604    Evas_Object *obj2;
1605
1606    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1607    wd = elm_widget_data_get(item->base.widget);
1608    if (!wd) return;
1609    obj2 = item->base.widget;
1610    wd->items = eina_inlist_remove(wd->items, EINA_INLIST_GET(item));
1611    _item_del(item);
1612    _theme_hook(obj2);
1613 }
1614
1615 /**
1616  * Set the function called when a toolbar item is freed.
1617  *
1618  * @param item The item to set the callback on
1619  * @param func The function called
1620  *
1621  * @ingroup Toolbar
1622  */
1623 EAPI void
1624 elm_toolbar_item_del_cb_set(Elm_Toolbar_Item *item, Evas_Smart_Cb func)
1625 {
1626    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1627    elm_widget_item_del_cb_set(item, func);
1628 }
1629
1630 /**
1631  * Get the disabled state of @p item.
1632  *
1633  * @param item The toolbar item
1634  * @return If true, the item is disabled
1635  *
1636  * @ingroup Toolbar
1637  */
1638 EAPI Eina_Bool
1639 elm_toolbar_item_disabled_get(const Elm_Toolbar_Item *item)
1640 {
1641    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
1642    return item->disabled;
1643 }
1644
1645 /**
1646  * Set the disabled state of @p item.
1647  *
1648  * @param item The toolbar item
1649  * @param disabled If true, the item is disabled
1650  *
1651  * @ingroup Toolbar
1652  */
1653 EAPI void
1654 elm_toolbar_item_disabled_set(Elm_Toolbar_Item *item, Eina_Bool disabled)
1655 {
1656    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1657    _item_disable(item, disabled);
1658    _resize(item->base.widget, NULL, NULL, NULL);
1659 }
1660
1661 /**
1662  * Get the separator state of @p item.
1663  *
1664  * @param item The toolbar item
1665  * @param separator If true, the item is a separator
1666  *
1667  * @ingroup Toolbar
1668  */
1669 EAPI void
1670 elm_toolbar_item_separator_set(Elm_Toolbar_Item *item, Eina_Bool separator)
1671 {
1672    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1673    if (item->separator == separator) return;
1674    item->separator = separator;
1675    _theme_hook(item->base.view);
1676 }
1677
1678 /**
1679  * Set the separator state of @p item.
1680  *
1681  * @param item The toolbar item
1682  * @return If true, the item is a separator
1683  *
1684  * @ingroup Toolbar
1685  */
1686 EAPI Eina_Bool
1687 elm_toolbar_item_separator_get(const Elm_Toolbar_Item *item)
1688 {
1689    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
1690    return item->separator;
1691 }
1692
1693 /**
1694  * Set the shrink state of toolbar @p obj.
1695  *
1696  * @param obj The toolbar object
1697  * @param shrink_mode The toolbar won't scroll if ELM_TOOLBAR_SHRINK_NONE,
1698  * but will enforce a minimun size so all the items will fit, won't scroll
1699  * and won't show the items that don't fit if ELM_TOOLBAR_SHRINK_HIDE,
1700  * will scroll if ELM_TOOLBAR_SHRINK_SCROLL, and will create a button to
1701  * pop up excess elements with ELM_TOOLBAR_SHRINK_MENU.
1702  *
1703  * @ingroup Toolbar
1704  */
1705 EAPI void
1706 elm_toolbar_mode_shrink_set(Evas_Object *obj, Elm_Toolbar_Shrink_Mode shrink_mode)
1707 {
1708    ELM_CHECK_WIDTYPE(obj, widtype);
1709    Widget_Data *wd = elm_widget_data_get(obj);
1710    Eina_Bool bounce;
1711
1712    if (!wd) return;
1713    wd->shrink_mode = shrink_mode;
1714    bounce = (_elm_config->thumbscroll_bounce_enable) &&
1715       (shrink_mode == ELM_TOOLBAR_SHRINK_SCROLL);
1716    elm_smart_scroller_bounce_allow_set(wd->scr, bounce, EINA_FALSE);
1717
1718    if (wd->more_item)
1719      {
1720         _item_del(wd->more_item);
1721         wd->more_item = NULL;
1722      }
1723
1724    if (shrink_mode == ELM_TOOLBAR_SHRINK_MENU)
1725      {
1726         elm_smart_scroller_policy_set(wd->scr, ELM_SMART_SCROLLER_POLICY_OFF, ELM_SMART_SCROLLER_POLICY_OFF);
1727
1728         wd->more_item = _item_new(obj, "more_menu", "More",
1729                                                 NULL, NULL);
1730      }
1731    else if (shrink_mode == ELM_TOOLBAR_SHRINK_HIDE)
1732      elm_smart_scroller_policy_set(wd->scr, ELM_SMART_SCROLLER_POLICY_OFF,
1733                                    ELM_SMART_SCROLLER_POLICY_OFF);
1734    else
1735      elm_smart_scroller_policy_set(wd->scr, ELM_SMART_SCROLLER_POLICY_AUTO,
1736                                    ELM_SMART_SCROLLER_POLICY_OFF);
1737    _sizing_eval(obj);
1738 }
1739
1740 /**
1741  * Get the shrink mode of toolbar @p obj.
1742  *
1743  * @param obj The toolbar object
1744  * @return See elm_toolbar_mode_shrink_set.
1745  *
1746  * @ingroup Toolbar
1747  */
1748 EAPI Elm_Toolbar_Shrink_Mode
1749 elm_toolbar_mode_shrink_get(const Evas_Object *obj)
1750 {
1751    ELM_CHECK_WIDTYPE(obj, widtype) ELM_TOOLBAR_SHRINK_NONE;
1752    Widget_Data *wd = elm_widget_data_get(obj);
1753
1754    if (!wd) return ELM_TOOLBAR_SHRINK_NONE;
1755    return wd->shrink_mode;
1756 }
1757
1758 /**
1759  * Set the homogenous mode of toolbar @p obj.
1760  *
1761  * @param obj The toolbar object
1762  * @param homogenous If true, the toolbar items will be uniform in size
1763  *
1764  * @ingroup Toolbar
1765  */
1766 EAPI void
1767 elm_toolbar_homogenous_set(Evas_Object *obj, Eina_Bool homogenous)
1768 {
1769    ELM_CHECK_WIDTYPE(obj, widtype);
1770    Widget_Data *wd = elm_widget_data_get(obj);
1771
1772    if (!wd) return;
1773    wd->homogeneous = !!homogenous;
1774    evas_object_smart_calculate(wd->bx);
1775 }
1776
1777 /**
1778  * Get the homogenous mode of toolbar @p obj.
1779  *
1780  * @param obj The toolbar object
1781  * @return If true, the toolbar items are uniform in size
1782  *
1783  * @ingroup Toolbar
1784  */
1785 EAPI Eina_Bool
1786 elm_toolbar_homogenous_get(const Evas_Object *obj)
1787 {
1788    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1789    Widget_Data *wd = elm_widget_data_get(obj);
1790
1791    if (!wd) return EINA_FALSE;
1792    return wd->homogeneous;
1793 }
1794
1795 /**
1796  * Set the parent object of the toolbar menu
1797  *
1798  * @param obj The toolbar object
1799  * @param parent The parent of the menu object
1800  *
1801  * @ingroup Toolbar
1802  */
1803 EAPI void
1804 elm_toolbar_menu_parent_set(Evas_Object *obj, Evas_Object *parent)
1805 {
1806    Elm_Toolbar_Item *it;
1807    ELM_CHECK_WIDTYPE(obj, widtype);
1808    Widget_Data *wd = elm_widget_data_get(obj);
1809
1810    if (!wd) return;
1811    EINA_SAFETY_ON_NULL_RETURN(parent);
1812    wd->menu_parent = parent;
1813    EINA_INLIST_FOREACH(wd->items, it)
1814      {
1815         if (it->o_menu)
1816           elm_menu_parent_set(it->o_menu, wd->menu_parent);
1817      }
1818    if ((wd->more_item) && (wd->more_item->o_menu))
1819       elm_menu_parent_set(wd->more_item->o_menu, wd->menu_parent);
1820 }
1821
1822 /**
1823  * Get the parent object of the toolbar menu
1824  *
1825  * @param obj The toolbar object
1826  * @return The parent of the menu object
1827  *
1828  * @ingroup Toolbar
1829  */
1830 EAPI Evas_Object *
1831 elm_toolbar_menu_parent_get(const Evas_Object *obj)
1832 {
1833    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1834    Widget_Data *wd = elm_widget_data_get(obj);
1835
1836    if (!wd) return NULL;
1837    return wd->menu_parent;
1838 }
1839
1840 /**
1841  * Set the alignment of the items.
1842  *
1843  * @param obj The toolbar object
1844  * @param align The new alignment. (left) 0.0 ... 1.0 (right)
1845  *
1846  * @ingroup Toolbar
1847  */
1848 EAPI void
1849 elm_toolbar_align_set(Evas_Object *obj, double align)
1850 {
1851    ELM_CHECK_WIDTYPE(obj, widtype);
1852    Widget_Data *wd = elm_widget_data_get(obj);
1853
1854    if (!wd) return;
1855    if (wd->align != align)
1856      evas_object_size_hint_align_set(wd->bx, align, 0.5);
1857    wd->align = align;
1858 }
1859
1860 /**
1861  * Get the alignment of the items.
1862  *
1863  * @param obj The toolbar object
1864  * @return The alignment. (left) 0.0 ... 1.0 (right)
1865  *
1866  * @ingroup Toolbar
1867  */
1868 EAPI double
1869 elm_toolbar_align_get(const Evas_Object *obj)
1870 {
1871    ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
1872    Widget_Data *wd = elm_widget_data_get(obj);
1873
1874    if (!wd) return 0.0;
1875    return wd->align;
1876 }
1877
1878 /**
1879  * Set whether the toolbar item opens a menu.
1880  *
1881  * @param item The toolbar item
1882  * @param menu If true, @p item will open a menu when selected
1883  *
1884  * @ingroup Toolbar
1885  */
1886 EAPI void
1887 elm_toolbar_item_menu_set(Elm_Toolbar_Item *item, Eina_Bool menu)
1888 {
1889    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1890    Widget_Data *wd = elm_widget_data_get(item->base.widget);
1891    if (!wd) return;
1892
1893    if (item->menu == menu) return;
1894    item->menu = menu;
1895    if (menu) _item_menu_create(wd, item);
1896    else _item_menu_destroy(item);
1897 }
1898
1899 /**
1900  * Set the text to be shown in the toolbar item.
1901  *
1902  * @param item Target item
1903  * @param text The text to set in the content
1904  *
1905  * Setup the text as tooltip to object. The item can have only one tooltip,
1906  * so any previous tooltip data is removed.
1907  *
1908  * @ingroup Toolbar
1909  */
1910 EAPI void
1911 elm_toolbar_item_tooltip_text_set(Elm_Toolbar_Item *item, const char *text)
1912 {
1913    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1914    elm_widget_item_tooltip_text_set(item, text);
1915 }
1916
1917 /**
1918  * Set the content to be shown in the tooltip item
1919  *
1920  * Setup the tooltip to item. The item can have only one tooltip,
1921  * so any previous tooltip data is removed. @p func(with @p data) will
1922  * be called every time that need show the tooltip and it should
1923  * return a valid Evas_Object. This object is then managed fully by
1924  * tooltip system and is deleted when the tooltip is gone.
1925  *
1926  * @param item the toolbar item being attached a tooltip.
1927  * @param func the function used to create the tooltip contents.
1928  * @param data what to provide to @a func as callback data/context.
1929  * @param del_cb called when data is not needed anymore, either when
1930  *        another callback replaces @func, the tooltip is unset with
1931  *        elm_toolbar_item_tooltip_unset() or the owner @a item
1932  *        dies. This callback receives as the first parameter the
1933  *        given @a data, and @c event_info is the item.
1934  *
1935  * @ingroup Toolbar
1936  */
1937 EAPI void
1938 elm_toolbar_item_tooltip_content_cb_set(Elm_Toolbar_Item *item, Elm_Tooltip_Item_Content_Cb func, const void *data, Evas_Smart_Cb del_cb)
1939 {
1940    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1941    elm_widget_item_tooltip_content_cb_set(item, func, data, del_cb);
1942 }
1943
1944 /**
1945  * Unset tooltip from item
1946  *
1947  * @param item toolbar item to remove previously set tooltip.
1948  *
1949  * Remove tooltip from item. The callback provided as del_cb to
1950  * elm_toolbar_item_tooltip_content_cb_set() will be called to notify
1951  * it is not used anymore.
1952  *
1953  * @see elm_toolbar_item_tooltip_content_cb_set()
1954  *
1955  * @ingroup Toolbar
1956  */
1957 EAPI void
1958 elm_toolbar_item_tooltip_unset(Elm_Toolbar_Item *item)
1959 {
1960    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1961    elm_widget_item_tooltip_unset(item);
1962 }
1963
1964 /**
1965  * Sets a different style for this item tooltip.
1966  *
1967  * @note before you set a style you should define a tooltip with
1968  *       elm_toolbar_item_tooltip_content_cb_set() or
1969  *       elm_toolbar_item_tooltip_text_set()
1970  *
1971  * @param item toolbar item with tooltip already set.
1972  * @param style the theme style to use (default, transparent, ...)
1973  *
1974  * @ingroup Toolbar
1975  */
1976 EAPI void
1977 elm_toolbar_item_tooltip_style_set(Elm_Toolbar_Item *item, const char *style)
1978 {
1979    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1980    elm_widget_item_tooltip_style_set(item, style);
1981 }
1982
1983 /**
1984  * Get the style for this item tooltip.
1985  *
1986  * @param item toolbar item with tooltip already set.
1987  * @return style the theme style in use, defaults to "default". If the
1988  *         object does not have a tooltip set, then NULL is returned.
1989  *
1990  * @ingroup Toolbar
1991  */
1992 EAPI const char *
1993 elm_toolbar_item_tooltip_style_get(const Elm_Toolbar_Item *item)
1994 {
1995    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
1996    return elm_widget_item_tooltip_style_get(item);
1997 }
1998
1999 /**
2000  * Set the cursor to be shown when mouse is over the toolbar item
2001  *
2002  * @param item Target item
2003  * @param cursor the cursor name to be used.
2004  *
2005  * @see elm_object_cursor_set()
2006  * @ingroup Toolbar
2007  */
2008 EAPI void
2009 elm_toolbar_item_cursor_set(Elm_Toolbar_Item *item, const char *cursor)
2010 {
2011    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2012    elm_widget_item_cursor_set(item, cursor);
2013 }
2014
2015 /**
2016  * Get the cursor to be shown when mouse is over the toolbar item
2017  *
2018  * @param item toolbar item with cursor already set.
2019  * @return the cursor name.
2020  *
2021  * @ingroup Toolbar
2022  */
2023 EAPI const char *
2024 elm_toolbar_item_cursor_get(const Elm_Toolbar_Item *item)
2025 {
2026    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
2027    return elm_widget_item_cursor_get(item);
2028 }
2029
2030 /**
2031  * Unset the cursor to be shown when mouse is over the toolbar item
2032  *
2033  * @param item Target item
2034  *
2035  * @see elm_object_cursor_unset()
2036  * @ingroup Toolbar
2037  */
2038 EAPI void
2039 elm_toolbar_item_cursor_unset(Elm_Toolbar_Item *item)
2040 {
2041    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2042    elm_widget_item_cursor_unset(item);
2043 }
2044
2045 /**
2046  * Sets a different style for this item cursor.
2047  *
2048  * @note before you set a style you should define a cursor with
2049  *       elm_toolbar_item_cursor_set()
2050  *
2051  * @param item toolbar item with cursor already set.
2052  * @param style the theme style to use (default, transparent, ...)
2053  *
2054  * @ingroup Toolbar
2055  */
2056 EAPI void
2057 elm_toolbar_item_cursor_style_set(Elm_Toolbar_Item *item, const char *style)
2058 {
2059    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2060    elm_widget_item_cursor_style_set(item, style);
2061 }
2062
2063 /**
2064  * Get the style for this item cursor.
2065  *
2066  * @param item toolbar item with cursor already set.
2067  * @return style the theme style in use, defaults to "default". If the
2068  *         object does not have a cursor set, then NULL is returned.
2069  *
2070  * @ingroup Toolbar
2071  */
2072 EAPI const char *
2073 elm_toolbar_item_cursor_style_get(const Elm_Toolbar_Item *item)
2074 {
2075    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
2076    return elm_widget_item_cursor_style_get(item);
2077 }
2078
2079 /**
2080  * Set if the cursor set should be searched on the theme or should use
2081  * the provided by the engine, only.
2082  *
2083  * @note before you set if should look on theme you should define a cursor
2084  * with elm_object_cursor_set(). By default it will only look for cursors
2085  * provided by the engine.
2086  *
2087  * @param item widget item with cursor already set.
2088  * @param engine_only boolean to define it cursors should be looked only
2089  * between the provided by the engine or searched on widget's theme as well.
2090  *
2091  * @ingroup Toolbar
2092  */
2093 EAPI void
2094 elm_toolbar_item_cursor_engine_only_set(Elm_Toolbar_Item *item, Eina_Bool engine_only)
2095 {
2096    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2097    elm_widget_item_cursor_engine_only_set(item, engine_only);
2098 }
2099
2100 /**
2101  * Get the cursor engine only usage for this item cursor.
2102  *
2103  * @param item widget item with cursor already set.
2104  * @return engine_only boolean to define it cursors should be looked only
2105  * between the provided by the engine or searched on widget's theme as well. If
2106  *         the object does not have a cursor set, then EINA_FALSE is returned.
2107  *
2108  * @ingroup Toolbar
2109  */
2110 EAPI Eina_Bool
2111 elm_toolbar_item_cursor_engine_only_get(const Elm_Toolbar_Item *item)
2112 {
2113    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
2114    return elm_widget_item_cursor_engine_only_get(item);
2115 }
2116
2117 /**
2118  * Get whether the toolbar item opens a menu.
2119  *
2120  * @param item The toolbar item
2121  * @return If true, @p item opens a menu when selected
2122  *
2123  * @ingroup Toolbar
2124  */
2125 EAPI Evas_Object *
2126 elm_toolbar_item_menu_get(Elm_Toolbar_Item *item)
2127 {
2128    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
2129    Widget_Data *wd = elm_widget_data_get(item->base.widget);
2130    if (!wd) return NULL;
2131    /* FIXME: It's not ok. This function needs to be reviewed. And should
2132     * receive a const item */
2133    elm_toolbar_item_menu_set(item, 1);
2134    return item->o_menu;
2135 }
2136
2137 /**
2138  * Returns a pointer to a toolbar item by its label
2139  *
2140  * @param obj The toolbar object
2141  * @param label The label of the item to find
2142  *
2143  * @return The pointer to the toolbar item matching @p label
2144  * Returns NULL on failure.
2145  *
2146  * @ingroup Toolbar
2147  */
2148 EAPI Elm_Toolbar_Item *
2149 elm_toolbar_item_find_by_label(const Evas_Object *obj, const char *label)
2150 {
2151    Elm_Toolbar_Item *it;
2152    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2153    Widget_Data *wd = elm_widget_data_get(obj);
2154
2155    if (!wd) return NULL;
2156    EINA_INLIST_FOREACH(wd->items, it)
2157      {
2158         if (!strcmp(it->label, label)) return it;
2159      }
2160
2161    return NULL;
2162 }
2163
2164 /**
2165  * Set the data item from the toolbar item
2166  *
2167  * This set the data value passed on the elm_toolbar_item_append() and
2168  * related item addition calls.
2169  *
2170  * @param item The item
2171  * @param data The new data pointer to set
2172  *
2173  * @ingroup Toolbar
2174  */
2175 EAPI void
2176 elm_toolbar_item_data_set(Elm_Toolbar_Item *item, const void *data)
2177 {
2178    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
2179    elm_widget_item_data_set(item, data);
2180 }
2181
2182 /**
2183  * Get the data item from the toolbar item
2184  *
2185  * This returns the data value passed on the elm_toolbar_item_append() and
2186  * related item addition calls.
2187  *
2188  * @param item The item
2189  * @return The data pointer provided when created
2190  *
2191  * @ingroup Toolbar
2192  */
2193 EAPI void *
2194 elm_toolbar_item_data_get(const Elm_Toolbar_Item *item)
2195 {
2196    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
2197    return elm_widget_item_data_get(item);
2198 }
2199
2200 /**
2201  * Set no select mode.
2202  *
2203  * This will turn off the ability to select items entirely and they will
2204  * neither appear selected nor emit selected signals. The clicked
2205  * callback function will still be called.
2206  *
2207  * @param obj The Toolbar object
2208  * @param no_select The no select mode (EINA_TRUE = on, EINA_FALSE = off)
2209  *
2210  * @ingroup Toolbar
2211  */
2212 EAPI void
2213 elm_toolbar_no_select_mode_set(Evas_Object *obj, Eina_Bool no_select)
2214 {
2215    ELM_CHECK_WIDTYPE(obj, widtype);
2216    Widget_Data *wd = elm_widget_data_get(obj);
2217    if (!wd) return;
2218    wd->no_select = no_select;
2219 }
2220
2221 /**
2222  * Gets no select mode.
2223  *
2224  * @param obj The Toolbar object
2225  * @return The no select mode (EINA_TRUE = on, EINA_FALSE = off)
2226  *
2227  * @ingroup Toolbar
2228  */
2229 EAPI Eina_Bool
2230 elm_toolbar_no_select_mode_get(const Evas_Object *obj)
2231 {
2232    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2233    Widget_Data *wd = elm_widget_data_get(obj);
2234    if (!wd) return EINA_FALSE;
2235    return wd->no_select;
2236 }
2237
2238 /**
2239  * Sets icon lookup order, for icons used in this toolbar.
2240  * Icons added before calling this function will not be affected.
2241  * The default lookup order is ELM_ICON_LOOKUP_THEME_FDO.
2242  *
2243  * @param obj The toolbar object
2244  * @param order The icon lookup order
2245  *
2246  * @ingroup Toolbar
2247  */
2248 EAPI void
2249 elm_toolbar_icon_order_lookup_set(Evas_Object *obj, Elm_Icon_Lookup_Order order)
2250 {
2251    ELM_CHECK_WIDTYPE(obj, widtype);
2252    Elm_Toolbar_Item *it;
2253    Widget_Data *wd = elm_widget_data_get(obj);
2254    if (!wd) return;
2255
2256    wd->lookup_order = order;
2257    EINA_INLIST_FOREACH(wd->items, it)
2258       elm_icon_order_lookup_set(it->icon, order);
2259    if (wd->more_item)
2260       elm_icon_order_lookup_set(wd->more_item->icon, order);
2261 }
2262
2263 /**
2264  * Gets the icon lookup order.
2265  *
2266  * @param obj The Toolbar object
2267  * @return The icon lookup order
2268  *
2269  * @ingroup Toolbar
2270  */
2271 EAPI Elm_Icon_Lookup_Order
2272 elm_toolbar_icon_order_lookup_get(const Evas_Object *obj)
2273 {
2274    ELM_CHECK_WIDTYPE(obj, widtype) ELM_ICON_LOOKUP_THEME_FDO;
2275    Widget_Data *wd = elm_widget_data_get(obj);
2276    if (!wd) return ELM_ICON_LOOKUP_THEME_FDO;
2277    return wd->lookup_order;
2278 }