clicking a toolbar item is now a toggle:
[framework/uifw/elementary.git] / src / lib / elm_toolbar.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 typedef struct _Widget_Data Widget_Data;
5
6 struct _Widget_Data
7 {
8    Evas_Object *scr, *bx;
9    Evas_Object *menu_parent;
10    Eina_Inlist *items;
11    Elm_Toolbar_Item *more_item, *selected_item;
12    Elm_Toolbar_Shrink_Mode shrink_mode;
13    Elm_Icon_Lookup_Order lookup_order;
14    int icon_size;
15    double align;
16    Eina_Bool homogeneous : 1;
17    Eina_Bool no_select : 1;
18    Eina_Bool vertical : 1;
19    Ecore_Job *resize_job;
20 };
21
22 struct _Elm_Toolbar_Item
23 {
24    Elm_Widget_Item base;
25    EINA_INLIST;
26    const char *label;
27    const char *icon_str;
28    Evas_Object *icon;
29    Evas_Object *o_menu;
30    Evas_Smart_Cb func;
31    struct {
32       int priority;
33       Eina_Bool visible : 1;
34    } prio;
35    Eina_Bool selected : 1;
36    Eina_Bool disabled : 1;
37    Eina_Bool separator : 1;
38    Eina_Bool menu : 1;
39    Eina_List *states;
40    Eina_List *current_state;
41 };
42
43 #define ELM_TOOLBAR_ITEM_FROM_INLIST(item)      \
44   ((item) ? EINA_INLIST_CONTAINER_GET(item, Elm_Toolbar_Item) : NULL)
45
46 struct _Elm_Toolbar_Item_State
47 {
48    const char *label;
49    const char *icon_str;
50    Evas_Object *icon;
51    Evas_Smart_Cb func;
52    const void *data;
53 };
54
55 static const char *widtype = NULL;
56 static void _item_show(Elm_Toolbar_Item *it);
57 static void _item_select(Elm_Toolbar_Item *it);
58 static void _item_unselect(Elm_Toolbar_Item *it);
59 static void _item_disable(Elm_Toolbar_Item *it, Eina_Bool disabled);
60 static void _del_pre_hook(Evas_Object *obj);
61 static void _del_hook(Evas_Object *obj);
62 static void _mirrored_set(Evas_Object *obj, Eina_Bool mirrored);
63 static void _mirrored_set_item(Evas_Object *obj, Elm_Toolbar_Item *it, Eina_Bool mirrored);
64 static void _theme_hook(Evas_Object *obj);
65 static void _sizing_eval(Evas_Object *obj);
66 static void _resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
67 static void _menu_move_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
68 static void _menu_hide(void *data, Evas *e, Evas_Object *obj, void *event_info);
69 static void _layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data);
70 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);
71 static void _item_label_set(Elm_Toolbar_Item *item, const char *label, const char *signal);
72
73 static const char SIG_CLICKED[] = "clicked";
74
75 static const Evas_Smart_Cb_Description _signals[] = {
76    {SIG_CLICKED, ""},
77    {NULL, NULL}
78 };
79
80
81 static Eina_Bool
82 _item_icon_set(Evas_Object *icon_obj, const char *type, const char *icon)
83 {
84    char icon_str[512];
85
86    if ((!type) || (!*type)) goto end;
87    if ((!icon) || (!*icon)) return EINA_FALSE;
88    if ((snprintf(icon_str, sizeof(icon_str), "%s%s", type, icon) > 0)
89        && (elm_icon_standard_set(icon_obj, icon_str)))
90      return EINA_TRUE;
91 end:
92    if (elm_icon_standard_set(icon_obj, icon))
93      return EINA_TRUE;
94    WRN("couldn't find icon definition for '%s'", icon);
95    return EINA_FALSE;
96 }
97
98 static int
99 _elm_toolbar_icon_size_get(Widget_Data *wd)
100 {
101    const char *icon_size = edje_object_data_get(
102       elm_smart_scroller_edje_object_get(wd->scr), "icon_size");
103    if (icon_size)
104      return atoi(icon_size);
105    return _elm_config->icon_size;
106 }
107
108 static void
109 _item_show(Elm_Toolbar_Item *it)
110 {
111    Widget_Data *wd = elm_widget_data_get(it->base.widget);
112    Evas_Coord x, y, w, h, bx, by;
113
114    if (!wd) return;
115    evas_object_geometry_get(wd->bx, &bx, &by, NULL, NULL);
116    evas_object_geometry_get(it->base.view, &x, &y, &w, &h);
117    elm_smart_scroller_child_region_show(wd->scr, x - bx, y - by, w, h);
118 }
119
120 static void
121 _item_unselect(Elm_Toolbar_Item *item)
122 {
123    Widget_Data *wd;
124    if ((!item) || (!item->selected)) return;
125    wd = elm_widget_data_get(item->base.widget);
126    if (!wd) return;
127    item->selected = EINA_FALSE;
128    wd->selected_item = NULL;
129    edje_object_signal_emit(item->base.view, "elm,state,unselected", "elm");
130    elm_widget_signal_emit(item->icon, "elm,state,unselected", "elm");
131 }
132
133 static void
134 _item_select(Elm_Toolbar_Item *it)
135 {
136    Elm_Toolbar_Item *it2;
137    Widget_Data *wd = elm_widget_data_get(it->base.widget);
138    Evas_Object *obj2;
139    Eina_Bool sel;
140
141    if (!wd) return;
142    if ((it->disabled) || (it->separator)) return;
143    sel = it->selected;
144
145    if (!wd->no_select)
146      {
147         if (sel) _item_unselect(it);
148         else
149           {
150              it2 = elm_toolbar_selected_item_get(it->base.widget);
151              _item_unselect(it2);
152
153              it->selected = EINA_TRUE;
154              wd->selected_item = it;
155              edje_object_signal_emit(it->base.view, "elm,state,selected", "elm");
156              elm_widget_signal_emit(it->icon, "elm,state,selected", "elm");
157              _item_show(it);
158           }
159      }
160    obj2 = it->base.widget;
161    if (it->menu && (!sel))
162      {
163         evas_object_show(it->o_menu);
164         evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_RESIZE,
165                                        _menu_move_resize, it);
166         evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_MOVE,
167                                        _menu_move_resize, it);
168
169         _menu_move_resize(it, NULL, NULL, NULL);
170      }
171    if (it->func) it->func((void *)(it->base.data), it->base.widget, it);
172    evas_object_smart_callback_call(obj2, SIG_CLICKED, it);
173 }
174
175 static void
176 _menu_hide(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
177 {
178    Elm_Toolbar_Item *selected;
179    Elm_Toolbar_Item *it = data;
180    selected = elm_toolbar_selected_item_get(it->base.widget);
181    _item_unselect(selected);
182 }
183
184 static void
185 _menu_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
186 {
187    // avoid hide being emitted during object deletion
188    evas_object_event_callback_del_full
189       (obj, EVAS_CALLBACK_HIDE, _menu_hide, data);
190 }
191
192 static void
193 _menu_move_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
194 {
195    Elm_Toolbar_Item *it = data;
196    Evas_Coord x,y,w,h;
197    Widget_Data *wd = elm_widget_data_get(it->base.widget);
198
199    if ((!wd) || (!wd->menu_parent)) return;
200    evas_object_geometry_get(it->base.view, &x, &y, &w, &h);
201    elm_menu_move(it->o_menu, x, y+h);
202 }
203
204 static void
205 _item_disable(Elm_Toolbar_Item *it, Eina_Bool disabled)
206 {
207    Widget_Data *wd = elm_widget_data_get(it->base.widget);
208
209    if (!wd) return;
210    if (it->disabled == disabled) return;
211    it->disabled = !!disabled;
212    if (it->disabled)
213      {
214         edje_object_signal_emit(it->base.view, "elm,state,disabled", "elm");
215         elm_widget_signal_emit(it->icon, "elm,state,disabled", "elm");
216      }
217    else
218      {
219         edje_object_signal_emit(it->base.view, "elm,state,enabled", "elm");
220         elm_widget_signal_emit(it->icon, "elm,state,enabled", "elm");
221      }
222 }
223
224 static void
225 _item_del(Elm_Toolbar_Item *it)
226 {
227    Elm_Toolbar_Item_State *it_state;
228    _item_unselect(it);
229    elm_widget_item_pre_notify_del(it);
230    EINA_LIST_FREE(it->states, it_state)
231      {
232         if (it->icon == it_state->icon)
233           it->icon = NULL;
234         eina_stringshare_del(it_state->label);
235         eina_stringshare_del(it_state->icon_str);
236         if (it_state->icon) evas_object_del(it_state->icon);
237         free(it_state);
238      }
239    eina_stringshare_del(it->label);
240    eina_stringshare_del(it->icon_str);
241    if (it->icon) evas_object_del(it->icon);
242    //TODO: See if checking for wd->menu_parent is necessary before deleting menu
243    if (it->o_menu) evas_object_del(it->o_menu);
244    elm_widget_item_del(it);
245 }
246
247 static void
248 _del_pre_hook(Evas_Object *obj)
249 {
250    Widget_Data *wd = elm_widget_data_get(obj);
251    Elm_Toolbar_Item *it, *next;
252
253    if (!wd) return;
254    it = ELM_TOOLBAR_ITEM_FROM_INLIST(wd->items);
255    while(it)
256      {
257         next = ELM_TOOLBAR_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
258         _item_del(it);
259         it = next;
260      }
261    if (wd->more_item)
262      _item_del(wd->more_item);
263 }
264
265 static void
266 _del_hook(Evas_Object *obj)
267 {
268    Widget_Data *wd = elm_widget_data_get(obj);
269
270    if (!wd) return;
271    free(wd);
272 }
273
274
275 static void
276 _mirrored_set_item(Evas_Object *obj __UNUSED__, Elm_Toolbar_Item *it, Eina_Bool mirrored)
277 {
278    edje_object_mirrored_set(it->base.view, mirrored);
279    elm_widget_mirrored_set(it->o_menu, mirrored);
280 }
281
282 static void
283 _theme_hook_item(Evas_Object *obj, Elm_Toolbar_Item *it, double scale, int icon_size)
284 {
285    Evas_Object *view = it->base.view;
286    Evas_Coord mw, mh;
287    const char *style = elm_widget_style_get(obj);
288
289    _mirrored_set_item(obj, it, elm_widget_mirrored_get(obj));
290    edje_object_scale_set(view, scale);
291    if (!it->separator)
292      {
293         _elm_theme_object_set(obj, view, "toolbar", "item", style);
294         if (it->selected)
295           {
296              edje_object_signal_emit(view, "elm,state,selected", "elm");
297              elm_widget_signal_emit(it->icon, "elm,state,selected", "elm");
298           }
299         if (it->disabled)
300           {
301              edje_object_signal_emit(view, "elm,state,disabled", "elm");
302              elm_widget_signal_emit(it->icon, "elm,state,disabled", "elm");
303           }
304         if (it->icon)
305           {
306              int ms = 0;
307
308              ms = ((double)icon_size * scale);
309              evas_object_size_hint_min_set(it->icon, ms, ms);
310              evas_object_size_hint_max_set(it->icon, ms, ms);
311              edje_object_part_swallow(view, "elm.swallow.icon",
312                                       it->icon);
313           }
314         edje_object_part_text_set(view, "elm.text", it->label);
315      }
316    else
317      _elm_theme_object_set(obj, view, "toolbar", "separator", style);
318
319    mw = mh = -1;
320    if (!it->separator)
321      elm_coords_finger_size_adjust(1, &mw, 1, &mh);
322    edje_object_size_min_restricted_calc(view, &mw, &mh, mw, mh);
323    if (!it->separator)
324      elm_coords_finger_size_adjust(1, &mw, 1, &mh);
325    evas_object_size_hint_min_set(view, mw, mh);
326 }
327
328 static void
329 _mirrored_set(Evas_Object *obj, Eina_Bool mirrored)
330 {
331    Widget_Data *wd = elm_widget_data_get(obj);
332    Elm_Toolbar_Item *it;
333
334    EINA_INLIST_FOREACH(wd->items, it)
335       _mirrored_set_item(obj, it, mirrored);
336    if (wd->more_item)
337      _mirrored_set_item(obj, wd->more_item, mirrored);
338 }
339
340 static void
341 _theme_hook(Evas_Object *obj)
342 {
343    Widget_Data *wd = elm_widget_data_get(obj);
344    Elm_Toolbar_Item *it;
345    double scale = 0;
346
347    if (!wd) return;
348    _elm_widget_mirrored_reload(obj);
349    elm_smart_scroller_object_theme_set(obj, wd->scr, "toolbar", "base", elm_widget_style_get(obj));
350    _mirrored_set(obj, elm_widget_mirrored_get(obj));
351    scale = (elm_widget_scale_get(obj) * _elm_config->scale);
352    edje_object_scale_set(wd->scr, scale);
353    wd->icon_size = _elm_toolbar_icon_size_get(wd);
354    EINA_INLIST_FOREACH(wd->items, it)
355       _theme_hook_item(obj, it, scale, wd->icon_size);
356    if (wd->more_item)
357      _theme_hook_item(obj, wd->more_item, scale, wd->icon_size);
358    _sizing_eval(obj);
359 }
360
361 static void
362 _sizing_eval(Evas_Object *obj)
363 {
364    Widget_Data *wd = elm_widget_data_get(obj);
365    Evas_Coord minw = -1, minh = -1, minw_bx, minh_bx;
366    Evas_Coord vw = 0, vh = 0;
367    Evas_Coord w, h;
368
369    if (!wd) return;
370    evas_object_smart_calculate(wd->bx);
371    edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
372                              &minw, &minh);
373    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
374    if (w < minw) w = minw;
375    if (h < minh) h = minh;
376    evas_object_resize(wd->scr, w, h);
377
378    evas_object_size_hint_min_get(wd->bx, &minw, &minh);
379    minw_bx = minw;
380    minh_bx = minh;
381    if (wd->vertical && (h > minh)) minh = h;
382    if ((!wd->vertical) && (w > minw)) minw = w;
383    evas_object_resize(wd->bx, minw, minh);
384    elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
385    switch (wd->shrink_mode)
386      {
387       case ELM_TOOLBAR_SHRINK_MENU: /* fallthrough */
388       case ELM_TOOLBAR_SHRINK_HIDE: /* fallthrough */
389       case ELM_TOOLBAR_SHRINK_SCROLL:
390         if (wd->vertical) minh = h - vh;
391         else minw = w - vw;
392         break;
393       case ELM_TOOLBAR_SHRINK_NONE:
394         if (wd->vertical) minh = minh_bx + (h - vh);
395         else minw = minw_bx + (w - vw);
396         break;
397      }
398    minh = minh + (h - vh);
399    evas_object_size_hint_min_set(obj, minw, minh);
400    evas_object_size_hint_max_set(obj, -1, -1);
401 }
402
403 static void
404 _item_menu_create(Widget_Data *wd, Elm_Toolbar_Item *item)
405 {
406    item->o_menu = elm_menu_add(item->base.view);
407    if (wd->menu_parent)
408      elm_menu_parent_set(item->o_menu, wd->menu_parent);
409    evas_object_event_callback_add(item->o_menu, EVAS_CALLBACK_HIDE,
410                                   _menu_hide, item);
411    evas_object_event_callback_add(item->o_menu, EVAS_CALLBACK_DEL,
412                                   _menu_del, item);
413 }
414
415 static void
416 _item_menu_destroy(Elm_Toolbar_Item *item)
417 {
418    if (item->o_menu)
419      {
420         evas_object_del(item->o_menu);
421         item->o_menu = NULL;
422      }
423 }
424
425 static int
426 _toolbar_item_prio_compare_cb(const void *i1, const void *i2)
427 {
428    const Elm_Toolbar_Item *eti1 = i1;
429    const Elm_Toolbar_Item *eti2 = i2;
430
431    if (!eti2) return 1;
432    if (!eti1) return -1;
433
434    return eti2->prio.priority - eti1->prio.priority;
435 }
436
437 static void
438 _fix_items_visibility(Widget_Data *wd, Evas_Coord *iw, Evas_Coord vw)
439 {
440    Elm_Toolbar_Item *it;
441    Eina_List *sorted = NULL;
442    Evas_Coord ciw;
443
444    EINA_INLIST_FOREACH(wd->items, it)
445      {
446         sorted = eina_list_sorted_insert(sorted,
447                                          _toolbar_item_prio_compare_cb, it);
448      }
449
450    if (wd->more_item)
451      {
452         evas_object_geometry_get(wd->more_item->base.view, NULL, NULL, &ciw, NULL);
453         *iw += ciw;
454      }
455    EINA_LIST_FREE(sorted, it)
456      {
457         evas_object_geometry_get(it->base.view, NULL, NULL, &ciw, NULL);
458         *iw += ciw;
459         it->prio.visible = (*iw <= vw);
460      }
461 }
462
463 static void
464 _elm_toolbar_item_menu_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
465 {
466    Elm_Toolbar_Item *it = data;
467    if (it->func) it->func((void *)(it->base.data), it->base.widget, it);
468 }
469
470 static void
471 _resize_job(void *data)
472 {
473    Widget_Data *wd = elm_widget_data_get(data);
474    Evas_Coord mw, mh, vw, vh, w, h;
475    Elm_Toolbar_Item *it;
476    Evas_Object *obj = (Evas_Object *) data;
477
478    if (!wd) return;
479    wd->resize_job = NULL;
480    elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
481    evas_object_size_hint_min_get(wd->bx, &mw, &mh);
482    evas_object_geometry_get(wd->bx, NULL, NULL, &w, &h);
483    if (wd->shrink_mode == ELM_TOOLBAR_SHRINK_MENU)
484      {
485         Evas_Coord iw = 0, more_w;
486
487         evas_object_resize(wd->bx, vw, h);
488         _fix_items_visibility(wd, &iw, vw);
489         evas_object_geometry_get(wd->more_item->base.view, NULL, NULL, &more_w, NULL);
490         if (iw - more_w <= vw)
491           iw -= more_w;
492
493         /* All items are removed from the box object, since removing individual
494          * items won't trigger a resize. Items are be readded below. */
495         evas_object_box_remove_all(wd->bx, EINA_FALSE);
496         if (iw > vw)
497           {
498              Evas_Object *menu;
499
500              _item_menu_destroy(wd->more_item);
501              _item_menu_create(wd, wd->more_item);
502              menu = elm_toolbar_item_menu_get(wd->more_item);
503
504              EINA_INLIST_FOREACH(wd->items, it)
505                {
506                   if (!it->prio.visible)
507                     {
508                        if (it->separator)
509                          elm_menu_item_separator_add(menu, NULL);
510                        else
511                          {
512                             Elm_Menu_Item *item;
513                             item = elm_menu_item_add(menu, NULL, it->icon_str, it->label,
514                                                      _elm_toolbar_item_menu_cb, it);
515                             elm_menu_item_disabled_set(item, it->disabled);
516                             if (it->o_menu) elm_menu_clone(it->o_menu, menu, item);
517                          }
518                        evas_object_hide(it->base.view);
519                     }
520                   else
521                     {
522                        evas_object_box_append(wd->bx, it->base.view);
523                        evas_object_show(it->base.view);
524                     }
525                }
526
527              evas_object_box_append(wd->bx, wd->more_item->base.view);
528              evas_object_show(wd->more_item->base.view);
529           }
530         else
531           {
532              /* All items are visible, show them all (except for the "More"
533               * button, of course). */
534              EINA_INLIST_FOREACH(wd->items, it)
535                {
536                   evas_object_show(it->base.view);
537                   evas_object_box_append(wd->bx, it->base.view);
538                }
539              evas_object_hide(wd->more_item->base.view);
540           }
541      }
542    else if (wd->shrink_mode == ELM_TOOLBAR_SHRINK_HIDE)
543      {
544         Evas_Coord iw = 0;
545
546         evas_object_resize(wd->bx, vw, h);
547         _fix_items_visibility(wd, &iw, vw);
548         evas_object_box_remove_all(wd->bx, EINA_FALSE);
549         if (iw > vw)
550           {
551              EINA_INLIST_FOREACH(wd->items, it)
552                {
553                   if (!it->prio.visible)
554                     evas_object_hide(it->base.view);
555                   else
556                     {
557                        evas_object_box_append(wd->bx, it->base.view);
558                        evas_object_show(it->base.view);
559                     }
560                }
561           }
562         else
563           {
564              /* All items are visible, show them all */
565              EINA_INLIST_FOREACH(wd->items, it)
566                {
567                   evas_object_show(it->base.view);
568                   evas_object_box_append(wd->bx, it->base.view);
569                }
570           }
571      }
572    else
573      {
574         if ((vw >= mw) && (w != vw)) evas_object_resize(wd->bx, vw, h);
575         EINA_INLIST_FOREACH(wd->items, it)
576           {
577              if (it->selected)
578                {
579                   _item_show(it);
580                   break;
581                }
582           }
583      }
584
585    _mirrored_set(obj, elm_widget_mirrored_get(obj));
586 }
587
588 static void
589 _resize_item(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
590 {
591    _sizing_eval(data);
592    _resize(data, NULL, NULL, NULL);
593 }
594
595 static void
596 _resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
597 {
598    Widget_Data *wd = elm_widget_data_get(data);
599    if (!wd->resize_job)
600      wd->resize_job = ecore_job_add(_resize_job, data);
601 }
602
603 static void
604 _select(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
605 {
606    Elm_Toolbar_Item *it = data;
607
608    if ((_elm_config->access_mode == ELM_ACCESS_MODE_OFF) ||
609        (_elm_access_2nd_click_timeout(it->base.view)))
610      {
611         if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
612            _elm_access_say(E_("Selected"));
613         _item_select(it);
614      }
615 }
616
617 static void
618 _mouse_in(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
619 {
620    Elm_Toolbar_Item *it = data;
621    edje_object_signal_emit(it->base.view, "elm,state,highlighted", "elm");
622    elm_widget_signal_emit(it->icon, "elm,state,highlighted", "elm");
623 }
624
625 static void
626 _mouse_out(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
627 {
628    Elm_Toolbar_Item *it = data;
629    edje_object_signal_emit(it->base.view, "elm,state,unhighlighted", "elm");
630    elm_widget_signal_emit(it->icon, "elm,state,unhighlighted", "elm");
631 }
632
633 static void
634 _layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data)
635 {
636    Evas_Object *obj = (Evas_Object *) data;
637    Widget_Data *wd = elm_widget_data_get(obj);
638    if (!wd) return;
639    _els_box_layout(o, priv, !wd->vertical, wd->homogeneous, elm_widget_mirrored_get(obj));
640 }
641
642 static char *
643 _access_info_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, Elm_Widget_Item *item)
644 {
645    Elm_Toolbar_Item *it = (Elm_Toolbar_Item *)item;
646    const char *txt = item->access_info;
647    if (!txt) txt = it->label;
648    if (txt) return strdup(txt);
649    return NULL;
650 }
651
652 static char *
653 _access_state_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, Elm_Widget_Item *item __UNUSED__)
654 {
655    Elm_Toolbar_Item *it = (Elm_Toolbar_Item *)item;
656    if (it->separator)
657       return strdup(E_("Separator"));
658    else if (it->disabled)
659       return strdup(E_("State: Disabled"));
660    else if (it->selected)
661       return strdup(E_("State: Selected"));
662    else if (it->menu)
663       return strdup(E_("Has menu"));
664    return NULL;
665 }
666
667 static Elm_Toolbar_Item *
668 _item_new(Evas_Object *obj, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
669 {
670    Widget_Data *wd = elm_widget_data_get(obj);
671    Evas_Object *icon_obj;
672    Evas_Coord mw, mh;
673    Elm_Toolbar_Item *it;
674
675    icon_obj = elm_icon_add(obj);
676    elm_icon_order_lookup_set(icon_obj, wd->lookup_order);
677    if (!icon_obj) return NULL;
678    it = elm_widget_item_new(obj, Elm_Toolbar_Item);
679    if (!it)
680      {
681         evas_object_del(icon_obj);
682         return NULL;
683      }
684    it->label = eina_stringshare_add(label);
685    it->prio.visible = 1;
686    it->prio.priority = 0;
687    it->func = func;
688    it->separator = EINA_FALSE;
689    it->base.data = data;
690    it->base.view = edje_object_add(evas_object_evas_get(obj));
691    _elm_access_item_register((Elm_Widget_Item *)it, it->base.view);
692    _elm_access_text_set(_elm_access_item_get((Elm_Widget_Item *)it),
693                         ELM_ACCESS_TYPE, E_("Tool Item"));
694    _elm_access_callback_set(_elm_access_item_get((Elm_Widget_Item *)it),
695                             ELM_ACCESS_INFO, _access_info_cb, it);
696    _elm_access_callback_set(_elm_access_item_get((Elm_Widget_Item *)it),
697                             ELM_ACCESS_STATE, _access_state_cb, it);
698
699    if (_item_icon_set(icon_obj, "toolbar/", icon))
700      {
701         it->icon = icon_obj;
702         it->icon_str = eina_stringshare_add(icon);
703      }
704    else
705      {
706         it->icon = NULL;
707         it->icon_str = NULL;
708         evas_object_del(icon_obj);
709      }
710
711    _elm_theme_object_set(obj, it->base.view, "toolbar", "item",
712                          elm_widget_style_get(obj));
713    edje_object_signal_callback_add(it->base.view, "elm,action,click", "elm",
714                                    _select, it);
715    edje_object_signal_callback_add(it->base.view, "elm,mouse,in", "elm",
716                                    _mouse_in, it);
717    edje_object_signal_callback_add(it->base.view, "elm,mouse,out", "elm",
718                                    _mouse_out, it);
719    elm_widget_sub_object_add(obj, it->base.view);
720    if (it->icon)
721      {
722         int ms = 0;
723
724         ms = ((double)wd->icon_size * _elm_config->scale);
725         evas_object_size_hint_min_set(it->icon, ms, ms);
726         evas_object_size_hint_max_set(it->icon, ms, ms);
727         edje_object_part_swallow(it->base.view, "elm.swallow.icon", it->icon);
728         evas_object_show(it->icon);
729         elm_widget_sub_object_add(obj, it->icon);
730      }
731    edje_object_part_text_set(it->base.view, "elm.text", it->label);
732    mw = mh = -1;
733    elm_coords_finger_size_adjust(1, &mw, 1, &mh);
734    edje_object_size_min_restricted_calc(it->base.view, &mw, &mh, mw, mh);
735    elm_coords_finger_size_adjust(1, &mw, 1, &mh);
736    if (wd->vertical)
737      {
738         evas_object_size_hint_weight_set(it->base.view, EVAS_HINT_EXPAND, -1.0);
739         evas_object_size_hint_align_set(it->base.view, EVAS_HINT_FILL, 0.5);
740      }
741    else
742      {
743         evas_object_size_hint_weight_set(it->base.view, -1.0, EVAS_HINT_EXPAND);
744         evas_object_size_hint_align_set(it->base.view, 0.5, EVAS_HINT_FILL);
745      }
746    evas_object_size_hint_min_set(it->base.view, mw, mh);
747    evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_RESIZE,
748                                   _resize_item, obj);
749    return it;
750 }
751
752 EAPI Evas_Object *
753 elm_toolbar_add(Evas_Object *parent)
754 {
755    Evas_Object *obj;
756    Evas *e;
757    Widget_Data *wd;
758
759    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
760
761    ELM_SET_WIDTYPE(widtype, "toolbar");
762    elm_widget_type_set(obj, "toolbar");
763    elm_widget_sub_object_add(parent, obj);
764    elm_widget_data_set(obj, wd);
765    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
766    elm_widget_del_hook_set(obj, _del_hook);
767    elm_widget_theme_hook_set(obj, _theme_hook);
768    elm_widget_can_focus_set(obj, EINA_FALSE);
769
770    wd->more_item = NULL;
771    wd->selected_item = NULL;
772    wd->scr = elm_smart_scroller_add(e);
773    elm_smart_scroller_widget_set(wd->scr, obj);
774    elm_smart_scroller_object_theme_set(obj, wd->scr, "toolbar", "base", "default");
775    elm_smart_scroller_bounce_allow_set(wd->scr,
776                                        _elm_config->thumbscroll_bounce_enable,
777                                        EINA_FALSE);
778    elm_widget_resize_object_set(obj, wd->scr);
779    elm_smart_scroller_policy_set(wd->scr,
780                                  ELM_SMART_SCROLLER_POLICY_AUTO,
781                                  ELM_SMART_SCROLLER_POLICY_OFF);
782
783
784    wd->icon_size = _elm_toolbar_icon_size_get(wd);
785
786
787    wd->homogeneous = EINA_TRUE;
788    wd->align = 0.5;
789
790    wd->bx = evas_object_box_add(e);
791    evas_object_size_hint_align_set(wd->bx, wd->align, 0.5);
792    evas_object_box_layout_set(wd->bx, _layout, obj, NULL);
793    elm_widget_sub_object_add(obj, wd->bx);
794    elm_smart_scroller_child_set(wd->scr, wd->bx);
795    evas_object_show(wd->bx);
796
797    elm_toolbar_mode_shrink_set(obj, _elm_config->toolbar_shrink_mode);
798    evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_RESIZE, _resize, obj);
799    evas_object_event_callback_add(wd->bx, EVAS_CALLBACK_RESIZE, _resize, obj);
800    elm_toolbar_icon_order_lookup_set(obj, ELM_ICON_LOOKUP_THEME_FDO);
801
802    evas_object_smart_callbacks_descriptions_set(obj, _signals);
803
804    _sizing_eval(obj);
805    return obj;
806 }
807
808 EAPI void
809 elm_toolbar_icon_size_set(Evas_Object *obj, int icon_size)
810 {
811    ELM_CHECK_WIDTYPE(obj, widtype);
812    Widget_Data *wd = elm_widget_data_get(obj);
813    if (!wd) return;
814    if (wd->icon_size == icon_size) return;
815    wd->icon_size = icon_size;
816    _theme_hook(obj);
817 }
818
819 EAPI int
820 elm_toolbar_icon_size_get(const Evas_Object *obj)
821 {
822    ELM_CHECK_WIDTYPE(obj, widtype) 0;
823    Widget_Data *wd = elm_widget_data_get(obj);
824    if (!wd) return 0;
825    return wd->icon_size;
826 }
827
828 EAPI Elm_Toolbar_Item *
829 elm_toolbar_item_append(Evas_Object *obj, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
830 {
831    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
832    Widget_Data *wd = elm_widget_data_get(obj);
833    if (!wd) return NULL;
834
835    Elm_Toolbar_Item *it = _item_new(obj, icon, label, func, data);
836    if (!it) return NULL;
837
838    wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(it));
839    evas_object_box_append(wd->bx, it->base.view);
840    evas_object_show(it->base.view);
841    _sizing_eval(obj);
842
843    return it;
844 }
845
846 static void
847 _elm_toolbar_item_state_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
848 {
849    Elm_Toolbar_Item *it = event_info;
850    Elm_Toolbar_Item_State *it_state;
851
852    it_state = eina_list_data_get(it->current_state);
853    if (it_state->func)
854      it_state->func((void *)it_state->data, obj, event_info);
855 }
856
857 EAPI Elm_Toolbar_Item_State *
858 elm_toolbar_item_state_next(Elm_Toolbar_Item *item)
859 {
860    Widget_Data *wd;
861    Evas_Object *obj;
862    Eina_List *next_state;
863    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
864
865    obj = item->base.widget;
866    wd = elm_widget_data_get(obj);
867    if (!wd) return NULL;
868    if (!item->states) return NULL;
869
870    next_state = eina_list_next(item->current_state);
871    if (!next_state)
872      next_state = eina_list_next(item->states);
873    return eina_list_data_get(next_state);
874 }
875
876 EAPI Elm_Toolbar_Item_State *
877 elm_toolbar_item_state_prev(Elm_Toolbar_Item *item)
878 {
879    Widget_Data *wd;
880    Evas_Object *obj;
881    Eina_List *prev_state;
882    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
883
884    obj = item->base.widget;
885    wd = elm_widget_data_get(obj);
886    if (!wd) return NULL;
887    if (!item->states) return NULL;
888
889    prev_state = eina_list_prev(item->current_state);
890    if ((!prev_state) || (prev_state == item->states))
891      prev_state = eina_list_last(item->states);
892    return eina_list_data_get(prev_state);
893 }
894
895 EAPI void
896 elm_toolbar_item_state_unset(Elm_Toolbar_Item *it)
897 {
898    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
899    elm_toolbar_item_state_set(it, NULL);
900 }
901
902 EAPI Eina_Bool
903 elm_toolbar_item_state_set(Elm_Toolbar_Item *it, Elm_Toolbar_Item_State *state)
904 {
905    Widget_Data *wd;
906    Eina_List *next_state;
907    Elm_Toolbar_Item_State *it_state;
908    Evas_Object *obj;
909    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
910
911    obj = it->base.widget;
912    wd = elm_widget_data_get(obj);
913    if (!wd) return EINA_FALSE;
914    if (!it->states) return EINA_FALSE;
915
916    if (state)
917      {
918         next_state = eina_list_data_find_list(it->states, state);
919         if (!next_state) return EINA_FALSE;
920      }
921    else
922      next_state = it->states;
923
924    if (next_state == it->current_state) return EINA_TRUE;
925
926    it_state = eina_list_data_get(next_state);
927    if (eina_list_data_find(it->current_state, state))
928      {
929         _item_label_set(it, it_state->label, "elm,state,label_set,forward");
930         _elm_toolbar_item_icon_obj_set(obj, it, it_state->icon, it_state->icon_str,
931                                        wd->icon_size, "elm,state,icon_set,forward");
932      }
933    else
934      {
935         _item_label_set(it, it_state->label, "elm,state,label_set,backward");
936         _elm_toolbar_item_icon_obj_set(obj, it, it_state->icon, it_state->icon_str,
937                                        wd->icon_size, "elm,state,icon_set,backward");
938      }
939    if (it->disabled)
940      elm_widget_signal_emit(it->icon, "elm,state,disabled", "elm");
941    else
942      elm_widget_signal_emit(it->icon, "elm,state,enabled", "elm");
943
944    it->current_state = next_state;
945    return EINA_TRUE;
946 }
947
948 EAPI Elm_Toolbar_Item_State *
949 elm_toolbar_item_state_get(const Elm_Toolbar_Item *it)
950 {
951    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
952    if ((!it->states) || (!it->current_state)) return NULL;
953    if (it->current_state == it->states) return NULL;
954
955    return eina_list_data_get(it->current_state);
956 }
957
958 static Elm_Toolbar_Item_State *
959 _item_state_new(const char *label, const char *icon_str, Evas_Object *icon, Evas_Smart_Cb func, const void *data)
960 {
961    Elm_Toolbar_Item_State *it_state;
962    it_state = ELM_NEW(Elm_Toolbar_Item_State);
963    it_state->label = eina_stringshare_add(label);
964    it_state->icon_str = eina_stringshare_add(icon_str);
965    it_state->icon = icon;
966    it_state->func = func;
967    it_state->data = data;
968    return it_state;
969 }
970
971 EAPI Elm_Toolbar_Item_State *
972 elm_toolbar_item_state_add(Elm_Toolbar_Item *item, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
973 {
974    Elm_Toolbar_Item_State *it_state;
975    Evas_Object *icon_obj;
976    Evas_Object *obj;
977    Widget_Data *wd;
978    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
979    obj = item->base.widget;
980    wd = elm_widget_data_get(item->base.widget);
981    if (!wd) return NULL;
982
983    if (!item->states)
984      {
985         it_state = _item_state_new(item->label, item->icon_str, item->icon,
986                                    item->func, item->base.data);
987         item->states = eina_list_append(item->states, it_state);
988         item->current_state = item->states;
989      }
990
991    icon_obj = elm_icon_add(obj);
992    elm_icon_order_lookup_set(icon_obj, wd->lookup_order);
993    if (!icon_obj) goto error_state_add;
994
995    if (!_item_icon_set(icon_obj, "toolbar/", icon))
996      {
997         evas_object_del(icon_obj);
998         icon_obj = NULL;
999         icon = NULL;
1000      }
1001
1002    it_state = _item_state_new(label, icon, icon_obj, func, data);
1003    item->states = eina_list_append(item->states, it_state);
1004    item->func = _elm_toolbar_item_state_cb;
1005    item->base.data = NULL;
1006
1007    return it_state;
1008
1009 error_state_add:
1010    if (item->states && !eina_list_next(item->states))
1011      {
1012         eina_stringshare_del(item->label);
1013         eina_stringshare_del(item->icon_str);
1014         free(eina_list_data_get(item->states));
1015         eina_list_free(item->states);
1016         item->states = NULL;
1017      }
1018    return NULL;
1019 }
1020
1021 EAPI Eina_Bool
1022 elm_toolbar_item_state_del(Elm_Toolbar_Item *item, Elm_Toolbar_Item_State *state)
1023 {
1024    Eina_List *del_state;
1025    Elm_Toolbar_Item_State *it_state;
1026    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
1027
1028    if (!state) return EINA_FALSE;
1029    if (!item->states) return EINA_FALSE;
1030
1031    del_state = eina_list_data_find_list(item->states, state);
1032    if (del_state == item->states) return EINA_FALSE;
1033    if (del_state == item->current_state)
1034      elm_toolbar_item_state_unset(item);
1035
1036    eina_stringshare_del(state->label);
1037    eina_stringshare_del(state->icon_str);
1038    if (state->icon) evas_object_del(state->icon);
1039    free(state);
1040    item->states = eina_list_remove_list(item->states, del_state);
1041    if (item->states && !eina_list_next(item->states))
1042      {
1043         it_state = eina_list_data_get(item->states);
1044         item->base.data = it_state->data;
1045         item->func = it_state->func;
1046         eina_stringshare_del(it_state->label);
1047         eina_stringshare_del(it_state->icon_str);
1048         free(eina_list_data_get(item->states));
1049         eina_list_free(item->states);
1050         item->states = NULL;
1051      }
1052    return EINA_TRUE;
1053 }
1054
1055 EAPI Elm_Toolbar_Item *
1056 elm_toolbar_item_prepend(Evas_Object *obj, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
1057 {
1058    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1059    Widget_Data *wd = elm_widget_data_get(obj);
1060    if (!wd) return NULL;
1061
1062    Elm_Toolbar_Item *it = _item_new(obj, icon, label, func, data);
1063    if (!it) return NULL;
1064
1065    wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(it));
1066    evas_object_box_prepend(wd->bx, it->base.view);
1067    evas_object_show(it->base.view);
1068    _sizing_eval(obj);
1069
1070    return it;
1071 }
1072
1073 EAPI Elm_Toolbar_Item *
1074 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)
1075 {
1076    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1077    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(before, NULL);
1078    Widget_Data *wd = elm_widget_data_get(obj);
1079    if (!wd) return NULL;
1080
1081    Elm_Toolbar_Item *it = _item_new(obj, icon, label, func, data);
1082    if (!it) return NULL;
1083
1084    wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
1085                                             EINA_INLIST_GET(before));
1086    evas_object_box_insert_before(wd->bx, it->base.view, before->base.view);
1087    evas_object_show(it->base.view);
1088    _sizing_eval(obj);
1089
1090    return it;
1091 }
1092
1093 EAPI Elm_Toolbar_Item *
1094 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)
1095 {
1096    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1097    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(after, NULL);
1098    Widget_Data *wd = elm_widget_data_get(obj);
1099    if (!wd) return NULL;
1100
1101    Elm_Toolbar_Item *it = _item_new(obj, icon, label, func, data);
1102    if (!it) return NULL;
1103
1104    wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
1105                                            EINA_INLIST_GET(after));
1106    evas_object_box_insert_after(wd->bx, it->base.view, after->base.view);
1107    evas_object_show(it->base.view);
1108    _sizing_eval(obj);
1109
1110    return it;
1111 }
1112
1113 EAPI Elm_Toolbar_Item *
1114 elm_toolbar_first_item_get(const Evas_Object *obj)
1115 {
1116    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1117    Widget_Data *wd = elm_widget_data_get(obj);
1118    if (!wd || !wd->items) return NULL;
1119    Elm_Toolbar_Item *it = ELM_TOOLBAR_ITEM_FROM_INLIST(wd->items);
1120    return it;
1121 }
1122
1123 EAPI Elm_Toolbar_Item *
1124 elm_toolbar_last_item_get(const Evas_Object *obj)
1125 {
1126    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1127    Widget_Data *wd = elm_widget_data_get(obj);
1128    if (!wd || !wd->items) return NULL;
1129    Elm_Toolbar_Item *it = ELM_TOOLBAR_ITEM_FROM_INLIST(wd->items->last);
1130    return it;
1131 }
1132
1133 EAPI Elm_Toolbar_Item *
1134 elm_toolbar_item_next_get(const Elm_Toolbar_Item *item)
1135 {
1136    Elm_Toolbar_Item *next;
1137    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
1138    next = ELM_TOOLBAR_ITEM_FROM_INLIST(EINA_INLIST_GET(item)->next);
1139    return next;
1140 }
1141
1142 EAPI Elm_Toolbar_Item *
1143 elm_toolbar_item_prev_get(const Elm_Toolbar_Item *item)
1144 {
1145    Elm_Toolbar_Item *prev;
1146    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
1147    prev = ELM_TOOLBAR_ITEM_FROM_INLIST(EINA_INLIST_GET(item)->prev);
1148    return prev;
1149 }
1150
1151 EAPI Evas_Object *
1152 elm_toolbar_item_toolbar_get(const Elm_Toolbar_Item *item)
1153 {
1154    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
1155    return item->base.widget;
1156 }
1157
1158 EAPI void
1159 elm_toolbar_item_priority_set(Elm_Toolbar_Item *item, int priority)
1160 {
1161    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1162    if (item->prio.priority == priority) return;
1163    item->prio.priority = priority;
1164    _resize(item->base.widget, NULL, NULL, NULL);
1165 }
1166
1167 EAPI int
1168 elm_toolbar_item_priority_get(const Elm_Toolbar_Item *item)
1169 {
1170    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, 0);
1171    return item->prio.priority;
1172 }
1173
1174 EAPI const char *
1175 elm_toolbar_item_icon_get(const Elm_Toolbar_Item *item)
1176 {
1177    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
1178    return item->icon_str;
1179 }
1180
1181 EAPI const char *
1182 elm_toolbar_item_label_get(const Elm_Toolbar_Item *item)
1183 {
1184    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
1185    return item->label;
1186 }
1187
1188 static void
1189 _elm_toolbar_item_label_update(Elm_Toolbar_Item *item)
1190 {
1191    Evas_Coord mw = -1, mh = -1;
1192    Widget_Data *wd = elm_widget_data_get(item->base.widget);
1193    edje_object_part_text_set(item->base.view, "elm.text", item->label);
1194
1195    elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1196    edje_object_size_min_restricted_calc(item->base.view, &mw, &mh, mw, mh);
1197    elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1198    if (wd->vertical)
1199      {
1200         evas_object_size_hint_weight_set(item->base.view, EVAS_HINT_EXPAND, -1.0);
1201         evas_object_size_hint_align_set(item->base.view, EVAS_HINT_FILL, 0.5);
1202      }
1203    else
1204      {
1205         evas_object_size_hint_weight_set(item->base.view, -1.0, EVAS_HINT_EXPAND);
1206         evas_object_size_hint_align_set(item->base.view, 0.5, EVAS_HINT_FILL);
1207      }
1208    evas_object_size_hint_min_set(item->base.view, mw, mh);
1209 }
1210
1211 static void
1212 _elm_toolbar_item_label_set_cb (void *data, Evas_Object *obj, const char *emission, const char *source)
1213 {
1214    Elm_Toolbar_Item *item = data;
1215    _elm_toolbar_item_label_update(item);
1216    edje_object_signal_callback_del(obj, emission, source,
1217                                    _elm_toolbar_item_label_set_cb);
1218    edje_object_signal_emit (item->base.view, "elm,state,label,reset", "elm");
1219 }
1220
1221 static void
1222 _item_label_set(Elm_Toolbar_Item *item, const char *label, const char *signal)
1223 {
1224    const char *s;
1225
1226    if ((label) && (item->label) && (!strcmp(label, item->label))) return;
1227
1228    eina_stringshare_replace(&item->label, label);
1229    s = edje_object_data_get(item->base.view, "transition_animation_on");
1230    if ((s) && (atoi(s)))
1231      {
1232         edje_object_part_text_set(item->base.view, "elm.text_new", item->label);
1233         edje_object_signal_emit (item->base.view, signal, "elm");
1234         edje_object_signal_callback_add(item->base.view,
1235                                         "elm,state,label_set,done", "elm",
1236                                         _elm_toolbar_item_label_set_cb, item);
1237      }
1238    else
1239      _elm_toolbar_item_label_update(item);
1240    _resize(item->base.widget, NULL, NULL, NULL);
1241 }
1242
1243 EAPI void
1244 elm_toolbar_item_label_set(Elm_Toolbar_Item *item, const char *label)
1245 {
1246    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1247    _item_label_set(item, label, "elm,state,label_set");
1248 }
1249
1250 static void
1251 _elm_toolbar_item_icon_update(Elm_Toolbar_Item *item)
1252 {
1253    Elm_Toolbar_Item_State *it_state;
1254    Eina_List *l;
1255    Evas_Coord mw = -1, mh = -1;
1256    Widget_Data *wd = elm_widget_data_get(item->base.widget);
1257    Evas_Object *old_icon = edje_object_part_swallow_get(item->base.view,
1258                                                         "elm.swallow.icon");
1259    elm_widget_sub_object_del(item->base.view, old_icon);
1260    evas_object_hide(old_icon);
1261    edje_object_part_swallow(item->base.view, "elm.swallow.icon", item->icon);
1262    elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1263    edje_object_size_min_restricted_calc(item->base.view, &mw, &mh, mw, mh);
1264    elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1265    if (wd->vertical)
1266      {
1267         evas_object_size_hint_weight_set(item->base.view, EVAS_HINT_EXPAND, -1.0);
1268         evas_object_size_hint_align_set(item->base.view, EVAS_HINT_FILL, 0.5);
1269      }
1270    else
1271      {
1272         evas_object_size_hint_weight_set(item->base.view, -1.0, EVAS_HINT_EXPAND);
1273         evas_object_size_hint_align_set(item->base.view, 0.5, EVAS_HINT_FILL);
1274      }
1275    evas_object_size_hint_min_set(item->base.view, mw, mh);
1276
1277    EINA_LIST_FOREACH(item->states, l, it_state)
1278       if (it_state->icon == old_icon)
1279         return;
1280    evas_object_del(old_icon);
1281 }
1282
1283 EAPI Eina_Bool
1284 elm_toolbar_item_selected_get(const Elm_Toolbar_Item *item)
1285 {
1286    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
1287    return item->selected;
1288 }
1289
1290 EAPI void
1291 elm_toolbar_item_selected_set(Elm_Toolbar_Item *item, Eina_Bool selected)
1292 {
1293    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1294    Widget_Data *wd = elm_widget_data_get(item->base.widget);
1295    if (!wd) return;
1296
1297    if (item->selected == selected) return;
1298
1299    if (selected)
1300      _item_select(item);
1301    else
1302      _item_unselect(item);
1303 }
1304
1305 EAPI Elm_Toolbar_Item *
1306 elm_toolbar_selected_item_get(const Evas_Object *obj)
1307 {
1308    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1309    Widget_Data *wd = elm_widget_data_get(obj);
1310    if (!wd) return NULL;
1311    return wd->selected_item;
1312 }
1313
1314 static void
1315 _elm_toolbar_item_icon_set_cb (void *data, Evas_Object *obj, const char *emission, const char *source)
1316 {
1317    Elm_Toolbar_Item *item = data;
1318    edje_object_part_unswallow(item->base.view, item->icon);
1319    _elm_toolbar_item_icon_update(item);
1320    edje_object_signal_callback_del(obj, emission, source,
1321                                    _elm_toolbar_item_icon_set_cb);
1322    edje_object_signal_emit (item->base.view, "elm,state,icon,reset", "elm");
1323 }
1324
1325 static void
1326 _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)
1327 {
1328    Evas_Object *old_icon;
1329    int ms = 0;
1330    const char *s;
1331
1332    if (icon_str)
1333      eina_stringshare_replace(&item->icon_str, icon_str);
1334    else
1335      {
1336         eina_stringshare_del(item->icon_str);
1337         item->icon_str = NULL;
1338      }
1339    item->icon = icon_obj;
1340    if (icon_obj)
1341      {
1342         ms = (icon_size * _elm_config->scale);
1343         evas_object_size_hint_min_set(item->icon, ms, ms);
1344         evas_object_size_hint_max_set(item->icon, ms, ms);
1345         evas_object_show(item->icon);
1346         elm_widget_sub_object_add(obj, item->icon);
1347      }
1348    s = edje_object_data_get(item->base.view, "transition_animation_on");
1349    if ((s) && (atoi(s)))
1350      {
1351         old_icon = edje_object_part_swallow_get(item->base.view,
1352                                                 "elm.swallow.icon_new");
1353         if (old_icon)
1354           {
1355              elm_widget_sub_object_del(item->base.view, old_icon);
1356              evas_object_hide(old_icon);
1357           }
1358         edje_object_part_swallow(item->base.view, "elm.swallow.icon_new",
1359                                  item->icon);
1360         edje_object_signal_emit (item->base.view, signal, "elm");
1361         edje_object_signal_callback_add(item->base.view,
1362                                         "elm,state,icon_set,done", "elm",
1363                                         _elm_toolbar_item_icon_set_cb, item);
1364      }
1365    else
1366      _elm_toolbar_item_icon_update(item);
1367    _resize(obj, NULL, NULL, NULL);
1368 }
1369
1370 EAPI void
1371 elm_toolbar_item_icon_set(Elm_Toolbar_Item *item, const char *icon)
1372 {
1373    Evas_Object *icon_obj;
1374    Widget_Data *wd;
1375    Evas_Object *obj = item->base.widget;
1376
1377    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1378    wd = elm_widget_data_get(obj);
1379    if (!wd) return;
1380    if ((icon) && (item->icon_str) && (!strcmp(icon, item->icon_str))) return;
1381
1382    icon_obj = elm_icon_add(obj);
1383    if (!icon_obj) return;
1384    if (_item_icon_set(icon_obj, "toolbar/", icon))
1385      _elm_toolbar_item_icon_obj_set(obj, item, icon_obj, icon, wd->icon_size,
1386                                     "elm,state,icon_set");
1387    else
1388      {
1389         _elm_toolbar_item_icon_obj_set(obj, item, NULL, NULL, 0,
1390                                        "elm,state,icon_set");
1391         evas_object_del(icon_obj);
1392      }
1393 }
1394
1395 EAPI void
1396 elm_toolbar_item_del(Elm_Toolbar_Item *item)
1397 {
1398    Widget_Data *wd;
1399    Evas_Object *obj2;
1400
1401    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1402    wd = elm_widget_data_get(item->base.widget);
1403    if (!wd) return;
1404    obj2 = item->base.widget;
1405    wd->items = eina_inlist_remove(wd->items, EINA_INLIST_GET(item));
1406    _item_del(item);
1407    _theme_hook(obj2);
1408 }
1409
1410 EAPI void
1411 elm_toolbar_item_del_cb_set(Elm_Toolbar_Item *item, Evas_Smart_Cb func)
1412 {
1413    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1414    elm_widget_item_del_cb_set(item, func);
1415 }
1416
1417 EAPI Eina_Bool
1418 elm_toolbar_item_disabled_get(const Elm_Toolbar_Item *item)
1419 {
1420    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
1421    return item->disabled;
1422 }
1423
1424 EAPI void
1425 elm_toolbar_item_disabled_set(Elm_Toolbar_Item *item, Eina_Bool disabled)
1426 {
1427    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1428    _item_disable(item, disabled);
1429    _resize(item->base.widget, NULL, NULL, NULL);
1430 }
1431
1432 EAPI void
1433 elm_toolbar_item_separator_set(Elm_Toolbar_Item *item, Eina_Bool separator)
1434 {
1435    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1436    Evas_Object *obj = item->base.widget;
1437    Widget_Data *wd = elm_widget_data_get(obj);
1438    double scale;
1439    if (item->separator == separator) return;
1440    item->separator = separator;
1441    scale = (elm_widget_scale_get(obj) * _elm_config->scale);
1442    _theme_hook_item(obj, item, scale, wd->icon_size);
1443 }
1444
1445 EAPI Eina_Bool
1446 elm_toolbar_item_separator_get(const Elm_Toolbar_Item *item)
1447 {
1448    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
1449    return item->separator;
1450 }
1451
1452 EAPI void
1453 elm_toolbar_mode_shrink_set(Evas_Object *obj, Elm_Toolbar_Shrink_Mode shrink_mode)
1454 {
1455    ELM_CHECK_WIDTYPE(obj, widtype);
1456    Widget_Data *wd = elm_widget_data_get(obj);
1457    Eina_Bool bounce;
1458
1459    if (!wd) return;
1460    wd->shrink_mode = shrink_mode;
1461    bounce = (_elm_config->thumbscroll_bounce_enable) &&
1462       (shrink_mode == ELM_TOOLBAR_SHRINK_SCROLL);
1463    elm_smart_scroller_bounce_allow_set(wd->scr, bounce, EINA_FALSE);
1464
1465    if (wd->more_item)
1466      {
1467         _item_del(wd->more_item);
1468         wd->more_item = NULL;
1469      }
1470
1471    if (shrink_mode == ELM_TOOLBAR_SHRINK_MENU)
1472      {
1473         elm_smart_scroller_policy_set(wd->scr, ELM_SMART_SCROLLER_POLICY_OFF, ELM_SMART_SCROLLER_POLICY_OFF);
1474
1475         wd->more_item = _item_new(obj, "more_menu", "More",
1476                                   NULL, NULL);
1477      }
1478    else if (shrink_mode == ELM_TOOLBAR_SHRINK_HIDE)
1479      elm_smart_scroller_policy_set(wd->scr, ELM_SMART_SCROLLER_POLICY_OFF,
1480                                    ELM_SMART_SCROLLER_POLICY_OFF);
1481    else
1482      elm_smart_scroller_policy_set(wd->scr, ELM_SMART_SCROLLER_POLICY_AUTO,
1483                                    ELM_SMART_SCROLLER_POLICY_OFF);
1484    _sizing_eval(obj);
1485 }
1486
1487 EAPI Elm_Toolbar_Shrink_Mode
1488 elm_toolbar_mode_shrink_get(const Evas_Object *obj)
1489 {
1490    ELM_CHECK_WIDTYPE(obj, widtype) ELM_TOOLBAR_SHRINK_NONE;
1491    Widget_Data *wd = elm_widget_data_get(obj);
1492
1493    if (!wd) return ELM_TOOLBAR_SHRINK_NONE;
1494    return wd->shrink_mode;
1495 }
1496
1497 EAPI void
1498 elm_toolbar_homogeneous_set(Evas_Object *obj, Eina_Bool homogeneous)
1499 {
1500    ELM_CHECK_WIDTYPE(obj, widtype);
1501    Widget_Data *wd = elm_widget_data_get(obj);
1502
1503    if (!wd) return;
1504    wd->homogeneous = !!homogeneous;
1505    evas_object_smart_calculate(wd->bx);
1506 }
1507
1508 EINA_DEPRECATED EAPI void
1509 elm_toolbar_homogenous_set(Evas_Object *obj, Eina_Bool homogenous)
1510 {
1511    elm_toolbar_homogeneous_set(obj, homogenous);
1512 }
1513
1514 EAPI Eina_Bool
1515 elm_toolbar_homogeneous_get(const Evas_Object *obj)
1516 {
1517    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1518    Widget_Data *wd = elm_widget_data_get(obj);
1519
1520    if (!wd) return EINA_FALSE;
1521    return wd->homogeneous;
1522 }
1523
1524 EINA_DEPRECATED EAPI Eina_Bool
1525 elm_toolbar_homogenous_get(const Evas_Object *obj)
1526 {
1527    return elm_toolbar_homogeneous_get(obj);
1528 }
1529
1530 EAPI void
1531 elm_toolbar_menu_parent_set(Evas_Object *obj, Evas_Object *parent)
1532 {
1533    Elm_Toolbar_Item *it;
1534    ELM_CHECK_WIDTYPE(obj, widtype);
1535    Widget_Data *wd = elm_widget_data_get(obj);
1536
1537    if (!wd) return;
1538    EINA_SAFETY_ON_NULL_RETURN(parent);
1539    wd->menu_parent = parent;
1540    EINA_INLIST_FOREACH(wd->items, it)
1541      {
1542         if (it->o_menu)
1543           elm_menu_parent_set(it->o_menu, wd->menu_parent);
1544      }
1545    if ((wd->more_item) && (wd->more_item->o_menu))
1546      elm_menu_parent_set(wd->more_item->o_menu, wd->menu_parent);
1547 }
1548
1549 EAPI Evas_Object *
1550 elm_toolbar_menu_parent_get(const Evas_Object *obj)
1551 {
1552    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1553    Widget_Data *wd = elm_widget_data_get(obj);
1554
1555    if (!wd) return NULL;
1556    return wd->menu_parent;
1557 }
1558
1559 EAPI void
1560 elm_toolbar_align_set(Evas_Object *obj, double align)
1561 {
1562    ELM_CHECK_WIDTYPE(obj, widtype);
1563    Widget_Data *wd = elm_widget_data_get(obj);
1564
1565    if (!wd) return;
1566    if (wd->align != align)
1567      evas_object_size_hint_align_set(wd->bx, align, 0.5);
1568    wd->align = align;
1569 }
1570
1571 EAPI double
1572 elm_toolbar_align_get(const Evas_Object *obj)
1573 {
1574    ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
1575    Widget_Data *wd = elm_widget_data_get(obj);
1576
1577    if (!wd) return 0.0;
1578    return wd->align;
1579 }
1580
1581 EAPI void
1582 elm_toolbar_item_menu_set(Elm_Toolbar_Item *item, Eina_Bool menu)
1583 {
1584    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1585    Widget_Data *wd = elm_widget_data_get(item->base.widget);
1586    if (!wd) return;
1587
1588    if (item->menu == menu) return;
1589    item->menu = menu;
1590    if (menu) _item_menu_create(wd, item);
1591    else _item_menu_destroy(item);
1592 }
1593
1594 EAPI void
1595 elm_toolbar_item_tooltip_text_set(Elm_Toolbar_Item *item, const char *text)
1596 {
1597    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1598    elm_widget_item_tooltip_text_set(item, text);
1599 }
1600
1601 EAPI void
1602 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)
1603 {
1604    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1605    elm_widget_item_tooltip_content_cb_set(item, func, data, del_cb);
1606 }
1607
1608 EAPI void
1609 elm_toolbar_item_tooltip_unset(Elm_Toolbar_Item *item)
1610 {
1611    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1612    elm_widget_item_tooltip_unset(item);
1613 }
1614
1615 EAPI void
1616 elm_toolbar_item_tooltip_style_set(Elm_Toolbar_Item *item, const char *style)
1617 {
1618    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1619    elm_widget_item_tooltip_style_set(item, style);
1620 }
1621
1622 EAPI const char *
1623 elm_toolbar_item_tooltip_style_get(const Elm_Toolbar_Item *item)
1624 {
1625    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
1626    return elm_widget_item_tooltip_style_get(item);
1627 }
1628
1629 EAPI void
1630 elm_toolbar_item_cursor_set(Elm_Toolbar_Item *item, const char *cursor)
1631 {
1632    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1633    elm_widget_item_cursor_set(item, cursor);
1634 }
1635
1636 EAPI const char *
1637 elm_toolbar_item_cursor_get(const Elm_Toolbar_Item *item)
1638 {
1639    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
1640    return elm_widget_item_cursor_get(item);
1641 }
1642
1643 EAPI void
1644 elm_toolbar_item_cursor_unset(Elm_Toolbar_Item *item)
1645 {
1646    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1647    elm_widget_item_cursor_unset(item);
1648 }
1649
1650 EAPI void
1651 elm_toolbar_item_cursor_style_set(Elm_Toolbar_Item *item, const char *style)
1652 {
1653    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1654    elm_widget_item_cursor_style_set(item, style);
1655 }
1656
1657 EAPI const char *
1658 elm_toolbar_item_cursor_style_get(const Elm_Toolbar_Item *item)
1659 {
1660    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
1661    return elm_widget_item_cursor_style_get(item);
1662 }
1663
1664 EAPI void
1665 elm_toolbar_item_cursor_engine_only_set(Elm_Toolbar_Item *item, Eina_Bool engine_only)
1666 {
1667    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1668    elm_widget_item_cursor_engine_only_set(item, engine_only);
1669 }
1670
1671 EAPI Eina_Bool
1672 elm_toolbar_item_cursor_engine_only_get(const Elm_Toolbar_Item *item)
1673 {
1674    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
1675    return elm_widget_item_cursor_engine_only_get(item);
1676 }
1677
1678 EAPI Evas_Object *
1679 elm_toolbar_item_menu_get(Elm_Toolbar_Item *item)
1680 {
1681    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
1682    Widget_Data *wd = elm_widget_data_get(item->base.widget);
1683    if (!wd) return NULL;
1684    /* FIXME: It's not ok. This function needs to be reviewed. And should
1685     * receive a const item */
1686    elm_toolbar_item_menu_set(item, 1);
1687    return item->o_menu;
1688 }
1689
1690 EAPI Elm_Toolbar_Item *
1691 elm_toolbar_item_find_by_label(const Evas_Object *obj, const char *label)
1692 {
1693    Elm_Toolbar_Item *it;
1694    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1695    Widget_Data *wd = elm_widget_data_get(obj);
1696
1697    if (!wd) return NULL;
1698    EINA_INLIST_FOREACH(wd->items, it)
1699      {
1700         if (!strcmp(it->label, label)) return it;
1701      }
1702
1703    return NULL;
1704 }
1705
1706 EAPI void
1707 elm_toolbar_item_data_set(Elm_Toolbar_Item *item, const void *data)
1708 {
1709    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1710    elm_widget_item_data_set(item, data);
1711 }
1712
1713 EAPI void *
1714 elm_toolbar_item_data_get(const Elm_Toolbar_Item *item)
1715 {
1716    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
1717    return elm_widget_item_data_get(item);
1718 }
1719
1720 EAPI void
1721 elm_toolbar_no_select_mode_set(Evas_Object *obj, Eina_Bool no_select)
1722 {
1723    ELM_CHECK_WIDTYPE(obj, widtype);
1724    Widget_Data *wd = elm_widget_data_get(obj);
1725    if (!wd) return;
1726    wd->no_select = no_select;
1727 }
1728
1729 EAPI Eina_Bool
1730 elm_toolbar_no_select_mode_get(const Evas_Object *obj)
1731 {
1732    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1733    Widget_Data *wd = elm_widget_data_get(obj);
1734    if (!wd) return EINA_FALSE;
1735    return wd->no_select;
1736 }
1737
1738 EAPI void
1739 elm_toolbar_icon_order_lookup_set(Evas_Object *obj, Elm_Icon_Lookup_Order order)
1740 {
1741    ELM_CHECK_WIDTYPE(obj, widtype);
1742    Elm_Toolbar_Item *it;
1743    Widget_Data *wd = elm_widget_data_get(obj);
1744    if (!wd) return;
1745
1746    wd->lookup_order = order;
1747    EINA_INLIST_FOREACH(wd->items, it)
1748       elm_icon_order_lookup_set(it->icon, order);
1749    if (wd->more_item)
1750      elm_icon_order_lookup_set(wd->more_item->icon, order);
1751 }
1752
1753 EAPI Elm_Icon_Lookup_Order
1754 elm_toolbar_icon_order_lookup_get(const Evas_Object *obj)
1755 {
1756    ELM_CHECK_WIDTYPE(obj, widtype) ELM_ICON_LOOKUP_THEME_FDO;
1757    Widget_Data *wd = elm_widget_data_get(obj);
1758    if (!wd) return ELM_ICON_LOOKUP_THEME_FDO;
1759    return wd->lookup_order;
1760 }
1761
1762 EAPI void
1763 elm_toolbar_orientation_set(Evas_Object *obj, Eina_Bool vertical)
1764 {
1765    ELM_CHECK_WIDTYPE(obj, widtype);
1766    Widget_Data *wd = elm_widget_data_get(obj);
1767    if (!wd) return;
1768    wd->vertical = vertical;
1769    _sizing_eval(obj);
1770 }
1771
1772 EAPI Eina_Bool
1773 elm_toolbar_orientation_get(Evas_Object *obj)
1774 {
1775    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1776    Widget_Data *wd = elm_widget_data_get(obj);
1777    if (!wd) return EINA_FALSE;
1778    return wd->vertical;
1779 }