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