more useless elm stuff: vertical toolbar orientation (by cedric's request) along...
[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
140    if (!wd) return;
141    if ((it->selected) || (it->disabled) || (it->separator)) return;
142
143    if (!wd->no_select)
144      {
145         it2 = elm_toolbar_selected_item_get(it->base.widget);
146         _item_unselect(it2);
147
148         it->selected = EINA_TRUE;
149         wd->selected_item = it;
150         edje_object_signal_emit(it->base.view, "elm,state,selected", "elm");
151         elm_widget_signal_emit(it->icon, "elm,state,selected", "elm");
152         _item_show(it);
153      }
154    obj2 = it->base.widget;
155    if (it->menu)
156      {
157         evas_object_show(it->o_menu);
158         evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_RESIZE,
159                                        _menu_move_resize, it);
160         evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_MOVE,
161                                        _menu_move_resize, it);
162
163         _menu_move_resize(it, NULL, NULL, NULL);
164      }
165    if (it->func) it->func((void *)(it->base.data), it->base.widget, it);
166    evas_object_smart_callback_call(obj2, SIG_CLICKED, it);
167 }
168
169 static void
170 _menu_hide(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
171 {
172    Elm_Toolbar_Item *selected;
173    Elm_Toolbar_Item *it = data;
174    selected = elm_toolbar_selected_item_get(it->base.widget);
175    _item_unselect(selected);
176 }
177
178 static void
179 _menu_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
180 {
181    // avoid hide being emitted during object deletion
182    evas_object_event_callback_del_full
183       (obj, EVAS_CALLBACK_HIDE, _menu_hide, data);
184 }
185
186 static void
187 _menu_move_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
188 {
189    Elm_Toolbar_Item *it = data;
190    Evas_Coord x,y,w,h;
191    Widget_Data *wd = elm_widget_data_get(it->base.widget);
192
193    if ((!wd) || (!wd->menu_parent)) return;
194    evas_object_geometry_get(it->base.view, &x, &y, &w, &h);
195    elm_menu_move(it->o_menu, x, y+h);
196 }
197
198 static void
199 _item_disable(Elm_Toolbar_Item *it, Eina_Bool disabled)
200 {
201    Widget_Data *wd = elm_widget_data_get(it->base.widget);
202
203    if (!wd) return;
204    if (it->disabled == disabled) return;
205    it->disabled = !!disabled;
206    if (it->disabled)
207      {
208         edje_object_signal_emit(it->base.view, "elm,state,disabled", "elm");
209         elm_widget_signal_emit(it->icon, "elm,state,disabled", "elm");
210      }
211    else
212      {
213         edje_object_signal_emit(it->base.view, "elm,state,enabled", "elm");
214         elm_widget_signal_emit(it->icon, "elm,state,enabled", "elm");
215      }
216 }
217
218 static void
219 _item_del(Elm_Toolbar_Item *it)
220 {
221    Elm_Toolbar_Item_State *it_state;
222    _item_unselect(it);
223    elm_widget_item_pre_notify_del(it);
224    EINA_LIST_FREE(it->states, it_state)
225      {
226         if (it->icon == it_state->icon)
227           it->icon = NULL;
228         eina_stringshare_del(it_state->label);
229         eina_stringshare_del(it_state->icon_str);
230         if (it_state->icon) evas_object_del(it_state->icon);
231         free(it_state);
232      }
233    eina_stringshare_del(it->label);
234    eina_stringshare_del(it->icon_str);
235    if (it->icon) evas_object_del(it->icon);
236    //TODO: See if checking for wd->menu_parent is necessary before deleting menu
237    if (it->o_menu) evas_object_del(it->o_menu);
238    elm_widget_item_del(it);
239 }
240
241 static void
242 _del_pre_hook(Evas_Object *obj)
243 {
244    Widget_Data *wd = elm_widget_data_get(obj);
245    Elm_Toolbar_Item *it, *next;
246
247    if (!wd) return;
248    it = ELM_TOOLBAR_ITEM_FROM_INLIST(wd->items);
249    while(it)
250      {
251         next = ELM_TOOLBAR_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
252         _item_del(it);
253         it = next;
254      }
255    if (wd->more_item)
256      _item_del(wd->more_item);
257 }
258
259 static void
260 _del_hook(Evas_Object *obj)
261 {
262    Widget_Data *wd = elm_widget_data_get(obj);
263
264    if (!wd) return;
265    free(wd);
266 }
267
268
269 static void
270 _mirrored_set_item(Evas_Object *obj __UNUSED__, Elm_Toolbar_Item *it, Eina_Bool mirrored)
271 {
272    edje_object_mirrored_set(it->base.view, mirrored);
273    elm_widget_mirrored_set(it->o_menu, mirrored);
274 }
275
276 static void
277 _theme_hook_item(Evas_Object *obj, Elm_Toolbar_Item *it, double scale, int icon_size)
278 {
279    Evas_Object *view = it->base.view;
280    Evas_Coord mw, mh;
281    const char *style = elm_widget_style_get(obj);
282
283    _mirrored_set_item(obj, it, elm_widget_mirrored_get(obj));
284    edje_object_scale_set(view, scale);
285    if (!it->separator)
286      {
287         _elm_theme_object_set(obj, view, "toolbar", "item", style);
288         if (it->selected)
289           {
290              edje_object_signal_emit(view, "elm,state,selected", "elm");
291              elm_widget_signal_emit(it->icon, "elm,state,selected", "elm");
292           }
293         if (it->disabled)
294           {
295              edje_object_signal_emit(view, "elm,state,disabled", "elm");
296              elm_widget_signal_emit(it->icon, "elm,state,disabled", "elm");
297           }
298         if (it->icon)
299           {
300              int ms = 0;
301
302              ms = ((double)icon_size * scale);
303              evas_object_size_hint_min_set(it->icon, ms, ms);
304              evas_object_size_hint_max_set(it->icon, ms, ms);
305              edje_object_part_swallow(view, "elm.swallow.icon",
306                                       it->icon);
307           }
308         edje_object_part_text_set(view, "elm.text", it->label);
309      }
310    else
311      _elm_theme_object_set(obj, view, "toolbar", "separator", style);
312
313    mw = mh = -1;
314    if (!it->separator)
315      elm_coords_finger_size_adjust(1, &mw, 1, &mh);
316    edje_object_size_min_restricted_calc(view, &mw, &mh, mw, mh);
317    if (!it->separator)
318      elm_coords_finger_size_adjust(1, &mw, 1, &mh);
319    evas_object_size_hint_min_set(view, mw, mh);
320 }
321
322 static void
323 _mirrored_set(Evas_Object *obj, Eina_Bool mirrored)
324 {
325    Widget_Data *wd = elm_widget_data_get(obj);
326    Elm_Toolbar_Item *it;
327
328    EINA_INLIST_FOREACH(wd->items, it)
329       _mirrored_set_item(obj, it, mirrored);
330    if (wd->more_item)
331      _mirrored_set_item(obj, wd->more_item, mirrored);
332 }
333
334 static void
335 _theme_hook(Evas_Object *obj)
336 {
337    Widget_Data *wd = elm_widget_data_get(obj);
338    Elm_Toolbar_Item *it;
339    double scale = 0;
340
341    if (!wd) return;
342    _elm_widget_mirrored_reload(obj);
343    elm_smart_scroller_object_theme_set(obj, wd->scr, "toolbar", "base", elm_widget_style_get(obj));
344    _mirrored_set(obj, elm_widget_mirrored_get(obj));
345    scale = (elm_widget_scale_get(obj) * _elm_config->scale);
346    edje_object_scale_set(wd->scr, scale);
347    wd->icon_size = _elm_toolbar_icon_size_get(wd);
348    EINA_INLIST_FOREACH(wd->items, it)
349       _theme_hook_item(obj, it, scale, wd->icon_size);
350    if (wd->more_item)
351      _theme_hook_item(obj, wd->more_item, scale, wd->icon_size);
352    _sizing_eval(obj);
353 }
354
355 static void
356 _sizing_eval(Evas_Object *obj)
357 {
358    Widget_Data *wd = elm_widget_data_get(obj);
359    Evas_Coord minw = -1, minh = -1, minw_bx, minh_bx;
360    Evas_Coord vw = 0, vh = 0;
361    Evas_Coord w, h;
362
363    if (!wd) return;
364    evas_object_smart_calculate(wd->bx);
365    edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
366                              &minw, &minh);
367    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
368 fprintf(stderr, "%i: w=%i, h=%i\n", __LINE__, w, h);
369    if (w < minw) w = minw;
370    if (h < minh) h = minh;
371 fprintf(stderr, "%i: w=%i, h=%i\n", __LINE__, w, h);
372    evas_object_resize(wd->scr, w, h);
373
374    evas_object_size_hint_min_get(wd->bx, &minw, &minh);
375    minw_bx = minw;
376    minh_bx = minh;
377 fprintf(stderr, "%i: minw=%i, minh=%i\n", __LINE__, minw, minh);
378    if (wd->vertical && (h > minh)) minh = h;
379    if ((!wd->vertical) && (w > minw)) minw = w;
380 fprintf(stderr, "%i: minw=%i, minh=%i\n", __LINE__, minw, minh);
381    evas_object_resize(wd->bx, minw, minh);
382    elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
383    switch (wd->shrink_mode)
384      {
385       case ELM_TOOLBAR_SHRINK_MENU: /* fallthrough */
386       case ELM_TOOLBAR_SHRINK_HIDE: /* fallthrough */
387       case ELM_TOOLBAR_SHRINK_SCROLL:
388         if (wd->vertical) minh = h - vh;
389         else minw = w - vw;
390         break;
391       case ELM_TOOLBAR_SHRINK_NONE:
392         if (wd->vertical) minh = minh_bx + (h - vh);
393         else minw = minw_bx + (w - vw);
394         break;
395      }
396 fprintf(stderr, "%i: minw=%i, minh=%i\n", __LINE__, minw, minh);
397    minh = minh + (h - vh);
398 fprintf(stderr, "%i: minw=%i, minh=%i\n", __LINE__, minw, minh);
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    _item_select(data);
607 }
608
609 static void
610 _mouse_in(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
611 {
612    Elm_Toolbar_Item *it = data;
613    edje_object_signal_emit(it->base.view, "elm,state,highlighted", "elm");
614    elm_widget_signal_emit(it->icon, "elm,state,highlighted", "elm");
615 }
616
617 static void
618 _mouse_out(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,unhighlighted", "elm");
622    elm_widget_signal_emit(it->icon, "elm,state,unhighlighted", "elm");
623 }
624
625 static void
626 _layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data)
627 {
628    Evas_Object *obj = (Evas_Object *) data;
629    Widget_Data *wd = elm_widget_data_get(obj);
630    if (!wd) return;
631    _els_box_layout(o, priv, !wd->vertical, wd->homogeneous, elm_widget_mirrored_get(obj));
632 }
633
634 static Elm_Toolbar_Item *
635 _item_new(Evas_Object *obj, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
636 {
637    Widget_Data *wd = elm_widget_data_get(obj);
638    Evas_Object *icon_obj;
639    Evas_Coord mw, mh;
640    Elm_Toolbar_Item *it;
641
642    icon_obj = elm_icon_add(obj);
643    elm_icon_order_lookup_set(icon_obj, wd->lookup_order);
644    if (!icon_obj) return NULL;
645    it = elm_widget_item_new(obj, Elm_Toolbar_Item);
646    if (!it)
647      {
648         evas_object_del(icon_obj);
649         return NULL;
650      }
651    it->label = eina_stringshare_add(label);
652    it->prio.visible = 1;
653    it->prio.priority = 0;
654    it->func = func;
655    it->separator = EINA_FALSE;
656    it->base.data = data;
657    it->base.view = edje_object_add(evas_object_evas_get(obj));
658    if (_item_icon_set(icon_obj, "toolbar/", icon))
659      {
660         it->icon = icon_obj;
661         it->icon_str = eina_stringshare_add(icon);
662      }
663    else
664      {
665         it->icon = NULL;
666         it->icon_str = NULL;
667         evas_object_del(icon_obj);
668      }
669
670    _elm_theme_object_set(obj, it->base.view, "toolbar", "item",
671                          elm_widget_style_get(obj));
672    edje_object_signal_callback_add(it->base.view, "elm,action,click", "elm",
673                                    _select, it);
674    edje_object_signal_callback_add(it->base.view, "elm,mouse,in", "elm",
675                                    _mouse_in, it);
676    edje_object_signal_callback_add(it->base.view, "elm,mouse,out", "elm",
677                                    _mouse_out, it);
678    elm_widget_sub_object_add(obj, it->base.view);
679    if (it->icon)
680      {
681         int ms = 0;
682
683         ms = ((double)wd->icon_size * _elm_config->scale);
684         evas_object_size_hint_min_set(it->icon, ms, ms);
685         evas_object_size_hint_max_set(it->icon, ms, ms);
686         edje_object_part_swallow(it->base.view, "elm.swallow.icon", it->icon);
687         evas_object_show(it->icon);
688         elm_widget_sub_object_add(obj, it->icon);
689      }
690    edje_object_part_text_set(it->base.view, "elm.text", it->label);
691    mw = mh = -1;
692    elm_coords_finger_size_adjust(1, &mw, 1, &mh);
693    edje_object_size_min_restricted_calc(it->base.view, &mw, &mh, mw, mh);
694    elm_coords_finger_size_adjust(1, &mw, 1, &mh);
695    if (wd->vertical)
696      {
697         evas_object_size_hint_weight_set(it->base.view, EVAS_HINT_EXPAND, -1.0);
698         evas_object_size_hint_align_set(it->base.view, EVAS_HINT_FILL, 0.5);
699      }
700    else
701      {
702         evas_object_size_hint_weight_set(it->base.view, -1.0, EVAS_HINT_EXPAND);
703         evas_object_size_hint_align_set(it->base.view, 0.5, EVAS_HINT_FILL);
704      }
705    evas_object_size_hint_min_set(it->base.view, mw, mh);
706    evas_object_event_callback_add(it->base.view, EVAS_CALLBACK_RESIZE,
707                                   _resize_item, obj);
708    return it;
709 }
710
711 EAPI Evas_Object *
712 elm_toolbar_add(Evas_Object *parent)
713 {
714    Evas_Object *obj;
715    Evas *e;
716    Widget_Data *wd;
717
718    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
719
720    ELM_SET_WIDTYPE(widtype, "toolbar");
721    elm_widget_type_set(obj, "toolbar");
722    elm_widget_sub_object_add(parent, obj);
723    elm_widget_data_set(obj, wd);
724    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
725    elm_widget_del_hook_set(obj, _del_hook);
726    elm_widget_theme_hook_set(obj, _theme_hook);
727    elm_widget_can_focus_set(obj, EINA_FALSE);
728
729    wd->more_item = NULL;
730    wd->selected_item = NULL;
731    wd->scr = elm_smart_scroller_add(e);
732    elm_smart_scroller_widget_set(wd->scr, obj);
733    elm_smart_scroller_object_theme_set(obj, wd->scr, "toolbar", "base", "default");
734    elm_smart_scroller_bounce_allow_set(wd->scr,
735                                        _elm_config->thumbscroll_bounce_enable,
736                                        EINA_FALSE);
737    elm_widget_resize_object_set(obj, wd->scr);
738    elm_smart_scroller_policy_set(wd->scr,
739                                  ELM_SMART_SCROLLER_POLICY_AUTO,
740                                  ELM_SMART_SCROLLER_POLICY_OFF);
741
742
743    wd->icon_size = _elm_toolbar_icon_size_get(wd);
744
745
746    wd->homogeneous = EINA_TRUE;
747    wd->align = 0.5;
748
749    wd->bx = evas_object_box_add(e);
750    evas_object_size_hint_align_set(wd->bx, wd->align, 0.5);
751    evas_object_box_layout_set(wd->bx, _layout, obj, NULL);
752    elm_widget_sub_object_add(obj, wd->bx);
753    elm_smart_scroller_child_set(wd->scr, wd->bx);
754    evas_object_show(wd->bx);
755
756    elm_toolbar_mode_shrink_set(obj, _elm_config->toolbar_shrink_mode);
757    evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_RESIZE, _resize, obj);
758    evas_object_event_callback_add(wd->bx, EVAS_CALLBACK_RESIZE, _resize, obj);
759    elm_toolbar_icon_order_lookup_set(obj, ELM_ICON_LOOKUP_THEME_FDO);
760
761    evas_object_smart_callbacks_descriptions_set(obj, _signals);
762
763    _sizing_eval(obj);
764    return obj;
765 }
766
767 EAPI void
768 elm_toolbar_icon_size_set(Evas_Object *obj, int icon_size)
769 {
770    ELM_CHECK_WIDTYPE(obj, widtype);
771    Widget_Data *wd = elm_widget_data_get(obj);
772    if (!wd) return;
773    if (wd->icon_size == icon_size) return;
774    wd->icon_size = icon_size;
775    _theme_hook(obj);
776 }
777
778 EAPI int
779 elm_toolbar_icon_size_get(const Evas_Object *obj)
780 {
781    ELM_CHECK_WIDTYPE(obj, widtype) 0;
782    Widget_Data *wd = elm_widget_data_get(obj);
783    if (!wd) return 0;
784    return wd->icon_size;
785 }
786
787 EAPI Elm_Toolbar_Item *
788 elm_toolbar_item_append(Evas_Object *obj, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
789 {
790    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
791    Widget_Data *wd = elm_widget_data_get(obj);
792    if (!wd) return NULL;
793
794    Elm_Toolbar_Item *it = _item_new(obj, icon, label, func, data);
795    if (!it) return NULL;
796
797    wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(it));
798    evas_object_box_append(wd->bx, it->base.view);
799    evas_object_show(it->base.view);
800    _sizing_eval(obj);
801
802    return it;
803 }
804
805 static void
806 _elm_toolbar_item_state_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
807 {
808    Elm_Toolbar_Item *it = event_info;
809    Elm_Toolbar_Item_State *it_state;
810
811    it_state = eina_list_data_get(it->current_state);
812    if (it_state->func)
813      it_state->func((void *)it_state->data, obj, event_info);
814 }
815
816 EAPI Elm_Toolbar_Item_State *
817 elm_toolbar_item_state_next(Elm_Toolbar_Item *item)
818 {
819    Widget_Data *wd;
820    Evas_Object *obj;
821    Eina_List *next_state;
822    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
823
824    obj = item->base.widget;
825    wd = elm_widget_data_get(obj);
826    if (!wd) return NULL;
827    if (!item->states) return NULL;
828
829    next_state = eina_list_next(item->current_state);
830    if (!next_state)
831      next_state = eina_list_next(item->states);
832    return eina_list_data_get(next_state);
833 }
834
835 EAPI Elm_Toolbar_Item_State *
836 elm_toolbar_item_state_prev(Elm_Toolbar_Item *item)
837 {
838    Widget_Data *wd;
839    Evas_Object *obj;
840    Eina_List *prev_state;
841    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
842
843    obj = item->base.widget;
844    wd = elm_widget_data_get(obj);
845    if (!wd) return NULL;
846    if (!item->states) return NULL;
847
848    prev_state = eina_list_prev(item->current_state);
849    if ((!prev_state) || (prev_state == item->states))
850      prev_state = eina_list_last(item->states);
851    return eina_list_data_get(prev_state);
852 }
853
854 EAPI void
855 elm_toolbar_item_state_unset(Elm_Toolbar_Item *it)
856 {
857    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it);
858    elm_toolbar_item_state_set(it, NULL);
859 }
860
861 EAPI Eina_Bool
862 elm_toolbar_item_state_set(Elm_Toolbar_Item *it, Elm_Toolbar_Item_State *state)
863 {
864    Widget_Data *wd;
865    Eina_List *next_state;
866    Elm_Toolbar_Item_State *it_state;
867    Evas_Object *obj;
868    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, EINA_FALSE);
869
870    obj = it->base.widget;
871    wd = elm_widget_data_get(obj);
872    if (!wd) return EINA_FALSE;
873    if (!it->states) return EINA_FALSE;
874
875    if (state)
876      {
877         next_state = eina_list_data_find_list(it->states, state);
878         if (!next_state) return EINA_FALSE;
879      }
880    else
881      next_state = it->states;
882
883    if (next_state == it->current_state) return EINA_TRUE;
884
885    it_state = eina_list_data_get(next_state);
886    if (eina_list_data_find(it->current_state, state))
887      {
888         _item_label_set(it, it_state->label, "elm,state,label_set,forward");
889         _elm_toolbar_item_icon_obj_set(obj, it, it_state->icon, it_state->icon_str,
890                                        wd->icon_size, "elm,state,icon_set,forward");
891      }
892    else
893      {
894         _item_label_set(it, it_state->label, "elm,state,label_set,backward");
895         _elm_toolbar_item_icon_obj_set(obj, it, it_state->icon, it_state->icon_str,
896                                        wd->icon_size, "elm,state,icon_set,backward");
897      }
898    if (it->disabled)
899      elm_widget_signal_emit(it->icon, "elm,state,disabled", "elm");
900    else
901      elm_widget_signal_emit(it->icon, "elm,state,enabled", "elm");
902
903    it->current_state = next_state;
904    return EINA_TRUE;
905 }
906
907 EAPI Elm_Toolbar_Item_State *
908 elm_toolbar_item_state_get(const Elm_Toolbar_Item *it)
909 {
910    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, NULL);
911    if ((!it->states) || (!it->current_state)) return NULL;
912    if (it->current_state == it->states) return NULL;
913
914    return eina_list_data_get(it->current_state);
915 }
916
917 static Elm_Toolbar_Item_State *
918 _item_state_new(const char *label, const char *icon_str, Evas_Object *icon, Evas_Smart_Cb func, const void *data)
919 {
920    Elm_Toolbar_Item_State *it_state;
921    it_state = ELM_NEW(Elm_Toolbar_Item_State);
922    it_state->label = eina_stringshare_add(label);
923    it_state->icon_str = eina_stringshare_add(icon_str);
924    it_state->icon = icon;
925    it_state->func = func;
926    it_state->data = data;
927    return it_state;
928 }
929
930 EAPI Elm_Toolbar_Item_State *
931 elm_toolbar_item_state_add(Elm_Toolbar_Item *item, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
932 {
933    Elm_Toolbar_Item_State *it_state;
934    Evas_Object *icon_obj;
935    Evas_Object *obj;
936    Widget_Data *wd;
937    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
938    obj = item->base.widget;
939    wd = elm_widget_data_get(item->base.widget);
940    if (!wd) return NULL;
941
942    if (!item->states)
943      {
944         it_state = _item_state_new(item->label, item->icon_str, item->icon,
945                                    item->func, item->base.data);
946         item->states = eina_list_append(item->states, it_state);
947         item->current_state = item->states;
948      }
949
950    icon_obj = elm_icon_add(obj);
951    elm_icon_order_lookup_set(icon_obj, wd->lookup_order);
952    if (!icon_obj) goto error_state_add;
953
954    if (!_item_icon_set(icon_obj, "toolbar/", icon))
955      {
956         evas_object_del(icon_obj);
957         icon_obj = NULL;
958         icon = NULL;
959      }
960
961    it_state = _item_state_new(label, icon, icon_obj, func, data);
962    item->states = eina_list_append(item->states, it_state);
963    item->func = _elm_toolbar_item_state_cb;
964    item->base.data = NULL;
965
966    return it_state;
967
968 error_state_add:
969    if (item->states && !eina_list_next(item->states))
970      {
971         eina_stringshare_del(item->label);
972         eina_stringshare_del(item->icon_str);
973         free(eina_list_data_get(item->states));
974         eina_list_free(item->states);
975         item->states = NULL;
976      }
977    return NULL;
978 }
979
980 EAPI Eina_Bool
981 elm_toolbar_item_state_del(Elm_Toolbar_Item *item, Elm_Toolbar_Item_State *state)
982 {
983    Eina_List *del_state;
984    Elm_Toolbar_Item_State *it_state;
985    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
986
987    if (!state) return EINA_FALSE;
988    if (!item->states) return EINA_FALSE;
989
990    del_state = eina_list_data_find_list(item->states, state);
991    if (del_state == item->states) return EINA_FALSE;
992    if (del_state == item->current_state)
993      elm_toolbar_item_state_unset(item);
994
995    eina_stringshare_del(state->label);
996    eina_stringshare_del(state->icon_str);
997    if (state->icon) evas_object_del(state->icon);
998    free(state);
999    item->states = eina_list_remove_list(item->states, del_state);
1000    if (item->states && !eina_list_next(item->states))
1001      {
1002         it_state = eina_list_data_get(item->states);
1003         item->base.data = it_state->data;
1004         item->func = it_state->func;
1005         eina_stringshare_del(it_state->label);
1006         eina_stringshare_del(it_state->icon_str);
1007         free(eina_list_data_get(item->states));
1008         eina_list_free(item->states);
1009         item->states = NULL;
1010      }
1011    return EINA_TRUE;
1012 }
1013
1014 EAPI Elm_Toolbar_Item *
1015 elm_toolbar_item_prepend(Evas_Object *obj, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
1016 {
1017    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1018    Widget_Data *wd = elm_widget_data_get(obj);
1019    if (!wd) return NULL;
1020
1021    Elm_Toolbar_Item *it = _item_new(obj, icon, label, func, data);
1022    if (!it) return NULL;
1023
1024    wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(it));
1025    evas_object_box_prepend(wd->bx, it->base.view);
1026    evas_object_show(it->base.view);
1027    _sizing_eval(obj);
1028
1029    return it;
1030 }
1031
1032 EAPI Elm_Toolbar_Item *
1033 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)
1034 {
1035    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1036    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(before, NULL);
1037    Widget_Data *wd = elm_widget_data_get(obj);
1038    if (!wd) return NULL;
1039
1040    Elm_Toolbar_Item *it = _item_new(obj, icon, label, func, data);
1041    if (!it) return NULL;
1042
1043    wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
1044                                             EINA_INLIST_GET(before));
1045    evas_object_box_insert_before(wd->bx, it->base.view, before->base.view);
1046    evas_object_show(it->base.view);
1047    _sizing_eval(obj);
1048
1049    return it;
1050 }
1051
1052 EAPI Elm_Toolbar_Item *
1053 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)
1054 {
1055    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1056    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(after, NULL);
1057    Widget_Data *wd = elm_widget_data_get(obj);
1058    if (!wd) return NULL;
1059
1060    Elm_Toolbar_Item *it = _item_new(obj, icon, label, func, data);
1061    if (!it) return NULL;
1062
1063    wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
1064                                            EINA_INLIST_GET(after));
1065    evas_object_box_insert_after(wd->bx, it->base.view, after->base.view);
1066    evas_object_show(it->base.view);
1067    _sizing_eval(obj);
1068
1069    return it;
1070 }
1071
1072 EAPI Elm_Toolbar_Item *
1073 elm_toolbar_first_item_get(const Evas_Object *obj)
1074 {
1075    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1076    Widget_Data *wd = elm_widget_data_get(obj);
1077    if (!wd || !wd->items) return NULL;
1078    Elm_Toolbar_Item *it = ELM_TOOLBAR_ITEM_FROM_INLIST(wd->items);
1079    return it;
1080 }
1081
1082 EAPI Elm_Toolbar_Item *
1083 elm_toolbar_last_item_get(const Evas_Object *obj)
1084 {
1085    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1086    Widget_Data *wd = elm_widget_data_get(obj);
1087    if (!wd || !wd->items) return NULL;
1088    Elm_Toolbar_Item *it = ELM_TOOLBAR_ITEM_FROM_INLIST(wd->items->last);
1089    return it;
1090 }
1091
1092 EAPI Elm_Toolbar_Item *
1093 elm_toolbar_item_next_get(const Elm_Toolbar_Item *item)
1094 {
1095    Elm_Toolbar_Item *next;
1096    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
1097    next = ELM_TOOLBAR_ITEM_FROM_INLIST(EINA_INLIST_GET(item)->next);
1098    return next;
1099 }
1100
1101 EAPI Elm_Toolbar_Item *
1102 elm_toolbar_item_prev_get(const Elm_Toolbar_Item *item)
1103 {
1104    Elm_Toolbar_Item *prev;
1105    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
1106    prev = ELM_TOOLBAR_ITEM_FROM_INLIST(EINA_INLIST_GET(item)->prev);
1107    return prev;
1108 }
1109
1110 EAPI Evas_Object *
1111 elm_toolbar_item_toolbar_get(const Elm_Toolbar_Item *item)
1112 {
1113    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
1114    return item->base.widget;
1115 }
1116
1117 EAPI void
1118 elm_toolbar_item_priority_set(Elm_Toolbar_Item *item, int priority)
1119 {
1120    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1121    if (item->prio.priority == priority) return;
1122    item->prio.priority = priority;
1123    _resize(item->base.widget, NULL, NULL, NULL);
1124 }
1125
1126 EAPI int
1127 elm_toolbar_item_priority_get(const Elm_Toolbar_Item *item)
1128 {
1129    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, 0);
1130    return item->prio.priority;
1131 }
1132
1133 EAPI const char *
1134 elm_toolbar_item_icon_get(const Elm_Toolbar_Item *item)
1135 {
1136    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
1137    return item->icon_str;
1138 }
1139
1140 EAPI const char *
1141 elm_toolbar_item_label_get(const Elm_Toolbar_Item *item)
1142 {
1143    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
1144    return item->label;
1145 }
1146
1147 static void
1148 _elm_toolbar_item_label_update(Elm_Toolbar_Item *item)
1149 {
1150    Evas_Coord mw = -1, mh = -1;
1151    Widget_Data *wd = elm_widget_data_get(item->base.widget);
1152    edje_object_part_text_set(item->base.view, "elm.text", item->label);
1153
1154    elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1155    edje_object_size_min_restricted_calc(item->base.view, &mw, &mh, mw, mh);
1156    elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1157    if (wd->vertical)
1158      {
1159         evas_object_size_hint_weight_set(item->base.view, EVAS_HINT_EXPAND, -1.0);
1160         evas_object_size_hint_align_set(item->base.view, EVAS_HINT_FILL, 0.5);
1161      }
1162    else
1163      {
1164         evas_object_size_hint_weight_set(item->base.view, -1.0, EVAS_HINT_EXPAND);
1165         evas_object_size_hint_align_set(item->base.view, 0.5, EVAS_HINT_FILL);
1166      }
1167    evas_object_size_hint_min_set(item->base.view, mw, mh);
1168 }
1169
1170 static void
1171 _elm_toolbar_item_label_set_cb (void *data, Evas_Object *obj, const char *emission, const char *source)
1172 {
1173    Elm_Toolbar_Item *item = data;
1174    _elm_toolbar_item_label_update(item);
1175    edje_object_signal_callback_del(obj, emission, source,
1176                                    _elm_toolbar_item_label_set_cb);
1177    edje_object_signal_emit (item->base.view, "elm,state,label,reset", "elm");
1178 }
1179
1180 static void
1181 _item_label_set(Elm_Toolbar_Item *item, const char *label, const char *signal)
1182 {
1183    const char *s;
1184
1185    if ((label) && (item->label) && (!strcmp(label, item->label))) return;
1186
1187    eina_stringshare_replace(&item->label, label);
1188    s = edje_object_data_get(item->base.view, "transition_animation_on");
1189    if ((s) && (atoi(s)))
1190      {
1191         edje_object_part_text_set(item->base.view, "elm.text_new", item->label);
1192         edje_object_signal_emit (item->base.view, signal, "elm");
1193         edje_object_signal_callback_add(item->base.view,
1194                                         "elm,state,label_set,done", "elm",
1195                                         _elm_toolbar_item_label_set_cb, item);
1196      }
1197    else
1198      _elm_toolbar_item_label_update(item);
1199    _resize(item->base.widget, NULL, NULL, NULL);
1200 }
1201
1202 EAPI void
1203 elm_toolbar_item_label_set(Elm_Toolbar_Item *item, const char *label)
1204 {
1205    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1206    _item_label_set(item, label, "elm,state,label_set");
1207 }
1208
1209 static void
1210 _elm_toolbar_item_icon_update(Elm_Toolbar_Item *item)
1211 {
1212    Elm_Toolbar_Item_State *it_state;
1213    Eina_List *l;
1214    Evas_Coord mw = -1, mh = -1;
1215    Widget_Data *wd = elm_widget_data_get(item->base.widget);
1216    Evas_Object *old_icon = edje_object_part_swallow_get(item->base.view,
1217                                                         "elm.swallow.icon");
1218    elm_widget_sub_object_del(item->base.view, old_icon);
1219    evas_object_hide(old_icon);
1220    edje_object_part_swallow(item->base.view, "elm.swallow.icon", item->icon);
1221    elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1222    edje_object_size_min_restricted_calc(item->base.view, &mw, &mh, mw, mh);
1223    elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1224    if (wd->vertical)
1225      {
1226         evas_object_size_hint_weight_set(item->base.view, EVAS_HINT_EXPAND, -1.0);
1227         evas_object_size_hint_align_set(item->base.view, EVAS_HINT_FILL, 0.5);
1228      }
1229    else
1230      {
1231         evas_object_size_hint_weight_set(item->base.view, -1.0, EVAS_HINT_EXPAND);
1232         evas_object_size_hint_align_set(item->base.view, 0.5, EVAS_HINT_FILL);
1233      }
1234    evas_object_size_hint_min_set(item->base.view, mw, mh);
1235
1236    EINA_LIST_FOREACH(item->states, l, it_state)
1237       if (it_state->icon == old_icon)
1238         return;
1239    evas_object_del(old_icon);
1240 }
1241
1242 EAPI Eina_Bool
1243 elm_toolbar_item_selected_get(const Elm_Toolbar_Item *item)
1244 {
1245    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
1246    return item->selected;
1247 }
1248
1249 EAPI void
1250 elm_toolbar_item_selected_set(Elm_Toolbar_Item *item, Eina_Bool selected)
1251 {
1252    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1253    Widget_Data *wd = elm_widget_data_get(item->base.widget);
1254    if (!wd) return;
1255
1256    if (item->selected == selected) return;
1257
1258    if (selected)
1259      _item_select(item);
1260    else
1261      _item_unselect(item);
1262 }
1263
1264 EAPI Elm_Toolbar_Item *
1265 elm_toolbar_selected_item_get(const Evas_Object *obj)
1266 {
1267    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1268    Widget_Data *wd = elm_widget_data_get(obj);
1269    if (!wd) return NULL;
1270    return wd->selected_item;
1271 }
1272
1273 static void
1274 _elm_toolbar_item_icon_set_cb (void *data, Evas_Object *obj, const char *emission, const char *source)
1275 {
1276    Elm_Toolbar_Item *item = data;
1277    edje_object_part_unswallow(item->base.view, item->icon);
1278    _elm_toolbar_item_icon_update(item);
1279    edje_object_signal_callback_del(obj, emission, source,
1280                                    _elm_toolbar_item_icon_set_cb);
1281    edje_object_signal_emit (item->base.view, "elm,state,icon,reset", "elm");
1282 }
1283
1284 static void
1285 _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)
1286 {
1287    Evas_Object *old_icon;
1288    int ms = 0;
1289    const char *s;
1290
1291    if (icon_str)
1292      eina_stringshare_replace(&item->icon_str, icon_str);
1293    else
1294      {
1295         eina_stringshare_del(item->icon_str);
1296         item->icon_str = NULL;
1297      }
1298    item->icon = icon_obj;
1299    if (icon_obj)
1300      {
1301         ms = (icon_size * _elm_config->scale);
1302         evas_object_size_hint_min_set(item->icon, ms, ms);
1303         evas_object_size_hint_max_set(item->icon, ms, ms);
1304         evas_object_show(item->icon);
1305         elm_widget_sub_object_add(obj, item->icon);
1306      }
1307    s = edje_object_data_get(item->base.view, "transition_animation_on");
1308    if ((s) && (atoi(s)))
1309      {
1310         old_icon = edje_object_part_swallow_get(item->base.view,
1311                                                 "elm.swallow.icon_new");
1312         if (old_icon)
1313           {
1314              elm_widget_sub_object_del(item->base.view, old_icon);
1315              evas_object_hide(old_icon);
1316           }
1317         edje_object_part_swallow(item->base.view, "elm.swallow.icon_new",
1318                                  item->icon);
1319         edje_object_signal_emit (item->base.view, signal, "elm");
1320         edje_object_signal_callback_add(item->base.view,
1321                                         "elm,state,icon_set,done", "elm",
1322                                         _elm_toolbar_item_icon_set_cb, item);
1323      }
1324    else
1325      _elm_toolbar_item_icon_update(item);
1326    _resize(obj, NULL, NULL, NULL);
1327 }
1328
1329 EAPI void
1330 elm_toolbar_item_icon_set(Elm_Toolbar_Item *item, const char *icon)
1331 {
1332    Evas_Object *icon_obj;
1333    Widget_Data *wd;
1334    Evas_Object *obj = item->base.widget;
1335
1336    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1337    wd = elm_widget_data_get(obj);
1338    if (!wd) return;
1339    if ((icon) && (item->icon_str) && (!strcmp(icon, item->icon_str))) return;
1340
1341    icon_obj = elm_icon_add(obj);
1342    if (!icon_obj) return;
1343    if (_item_icon_set(icon_obj, "toolbar/", icon))
1344      _elm_toolbar_item_icon_obj_set(obj, item, icon_obj, icon, wd->icon_size,
1345                                     "elm,state,icon_set");
1346    else
1347      {
1348         _elm_toolbar_item_icon_obj_set(obj, item, NULL, NULL, 0,
1349                                        "elm,state,icon_set");
1350         evas_object_del(icon_obj);
1351      }
1352 }
1353
1354 EAPI void
1355 elm_toolbar_item_del(Elm_Toolbar_Item *item)
1356 {
1357    Widget_Data *wd;
1358    Evas_Object *obj2;
1359
1360    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1361    wd = elm_widget_data_get(item->base.widget);
1362    if (!wd) return;
1363    obj2 = item->base.widget;
1364    wd->items = eina_inlist_remove(wd->items, EINA_INLIST_GET(item));
1365    _item_del(item);
1366    _theme_hook(obj2);
1367 }
1368
1369 EAPI void
1370 elm_toolbar_item_del_cb_set(Elm_Toolbar_Item *item, Evas_Smart_Cb func)
1371 {
1372    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1373    elm_widget_item_del_cb_set(item, func);
1374 }
1375
1376 EAPI Eina_Bool
1377 elm_toolbar_item_disabled_get(const Elm_Toolbar_Item *item)
1378 {
1379    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
1380    return item->disabled;
1381 }
1382
1383 EAPI void
1384 elm_toolbar_item_disabled_set(Elm_Toolbar_Item *item, Eina_Bool disabled)
1385 {
1386    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1387    _item_disable(item, disabled);
1388    _resize(item->base.widget, NULL, NULL, NULL);
1389 }
1390
1391 EAPI void
1392 elm_toolbar_item_separator_set(Elm_Toolbar_Item *item, Eina_Bool separator)
1393 {
1394    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1395    Evas_Object *obj = item->base.widget;
1396    Widget_Data *wd = elm_widget_data_get(obj);
1397    double scale;
1398    if (item->separator == separator) return;
1399    item->separator = separator;
1400    scale = (elm_widget_scale_get(obj) * _elm_config->scale);
1401    _theme_hook_item(obj, item, scale, wd->icon_size);
1402 }
1403
1404 EAPI Eina_Bool
1405 elm_toolbar_item_separator_get(const Elm_Toolbar_Item *item)
1406 {
1407    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
1408    return item->separator;
1409 }
1410
1411 EAPI void
1412 elm_toolbar_mode_shrink_set(Evas_Object *obj, Elm_Toolbar_Shrink_Mode shrink_mode)
1413 {
1414    ELM_CHECK_WIDTYPE(obj, widtype);
1415    Widget_Data *wd = elm_widget_data_get(obj);
1416    Eina_Bool bounce;
1417
1418    if (!wd) return;
1419    wd->shrink_mode = shrink_mode;
1420    bounce = (_elm_config->thumbscroll_bounce_enable) &&
1421       (shrink_mode == ELM_TOOLBAR_SHRINK_SCROLL);
1422    elm_smart_scroller_bounce_allow_set(wd->scr, bounce, EINA_FALSE);
1423
1424    if (wd->more_item)
1425      {
1426         _item_del(wd->more_item);
1427         wd->more_item = NULL;
1428      }
1429
1430    if (shrink_mode == ELM_TOOLBAR_SHRINK_MENU)
1431      {
1432         elm_smart_scroller_policy_set(wd->scr, ELM_SMART_SCROLLER_POLICY_OFF, ELM_SMART_SCROLLER_POLICY_OFF);
1433
1434         wd->more_item = _item_new(obj, "more_menu", "More",
1435                                   NULL, NULL);
1436      }
1437    else if (shrink_mode == ELM_TOOLBAR_SHRINK_HIDE)
1438      elm_smart_scroller_policy_set(wd->scr, ELM_SMART_SCROLLER_POLICY_OFF,
1439                                    ELM_SMART_SCROLLER_POLICY_OFF);
1440    else
1441      elm_smart_scroller_policy_set(wd->scr, ELM_SMART_SCROLLER_POLICY_AUTO,
1442                                    ELM_SMART_SCROLLER_POLICY_OFF);
1443    _sizing_eval(obj);
1444 }
1445
1446 EAPI Elm_Toolbar_Shrink_Mode
1447 elm_toolbar_mode_shrink_get(const Evas_Object *obj)
1448 {
1449    ELM_CHECK_WIDTYPE(obj, widtype) ELM_TOOLBAR_SHRINK_NONE;
1450    Widget_Data *wd = elm_widget_data_get(obj);
1451
1452    if (!wd) return ELM_TOOLBAR_SHRINK_NONE;
1453    return wd->shrink_mode;
1454 }
1455
1456 EAPI void
1457 elm_toolbar_homogeneous_set(Evas_Object *obj, Eina_Bool homogeneous)
1458 {
1459    ELM_CHECK_WIDTYPE(obj, widtype);
1460    Widget_Data *wd = elm_widget_data_get(obj);
1461
1462    if (!wd) return;
1463    wd->homogeneous = !!homogeneous;
1464    evas_object_smart_calculate(wd->bx);
1465 }
1466
1467 EINA_DEPRECATED EAPI void
1468 elm_toolbar_homogenous_set(Evas_Object *obj, Eina_Bool homogenous)
1469 {
1470    elm_toolbar_homogeneous_set(obj, homogenous);
1471 }
1472
1473 EAPI Eina_Bool
1474 elm_toolbar_homogeneous_get(const Evas_Object *obj)
1475 {
1476    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1477    Widget_Data *wd = elm_widget_data_get(obj);
1478
1479    if (!wd) return EINA_FALSE;
1480    return wd->homogeneous;
1481 }
1482
1483 EINA_DEPRECATED EAPI Eina_Bool
1484 elm_toolbar_homogenous_get(const Evas_Object *obj)
1485 {
1486    return elm_toolbar_homogeneous_get(obj);
1487 }
1488
1489 EAPI void
1490 elm_toolbar_menu_parent_set(Evas_Object *obj, Evas_Object *parent)
1491 {
1492    Elm_Toolbar_Item *it;
1493    ELM_CHECK_WIDTYPE(obj, widtype);
1494    Widget_Data *wd = elm_widget_data_get(obj);
1495
1496    if (!wd) return;
1497    EINA_SAFETY_ON_NULL_RETURN(parent);
1498    wd->menu_parent = parent;
1499    EINA_INLIST_FOREACH(wd->items, it)
1500      {
1501         if (it->o_menu)
1502           elm_menu_parent_set(it->o_menu, wd->menu_parent);
1503      }
1504    if ((wd->more_item) && (wd->more_item->o_menu))
1505      elm_menu_parent_set(wd->more_item->o_menu, wd->menu_parent);
1506 }
1507
1508 EAPI Evas_Object *
1509 elm_toolbar_menu_parent_get(const Evas_Object *obj)
1510 {
1511    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1512    Widget_Data *wd = elm_widget_data_get(obj);
1513
1514    if (!wd) return NULL;
1515    return wd->menu_parent;
1516 }
1517
1518 EAPI void
1519 elm_toolbar_align_set(Evas_Object *obj, double align)
1520 {
1521    ELM_CHECK_WIDTYPE(obj, widtype);
1522    Widget_Data *wd = elm_widget_data_get(obj);
1523
1524    if (!wd) return;
1525    if (wd->align != align)
1526      evas_object_size_hint_align_set(wd->bx, align, 0.5);
1527    wd->align = align;
1528 }
1529
1530 EAPI double
1531 elm_toolbar_align_get(const Evas_Object *obj)
1532 {
1533    ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
1534    Widget_Data *wd = elm_widget_data_get(obj);
1535
1536    if (!wd) return 0.0;
1537    return wd->align;
1538 }
1539
1540 EAPI void
1541 elm_toolbar_item_menu_set(Elm_Toolbar_Item *item, Eina_Bool menu)
1542 {
1543    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1544    Widget_Data *wd = elm_widget_data_get(item->base.widget);
1545    if (!wd) return;
1546
1547    if (item->menu == menu) return;
1548    item->menu = menu;
1549    if (menu) _item_menu_create(wd, item);
1550    else _item_menu_destroy(item);
1551 }
1552
1553 EAPI void
1554 elm_toolbar_item_tooltip_text_set(Elm_Toolbar_Item *item, const char *text)
1555 {
1556    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1557    elm_widget_item_tooltip_text_set(item, text);
1558 }
1559
1560 EAPI void
1561 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)
1562 {
1563    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1564    elm_widget_item_tooltip_content_cb_set(item, func, data, del_cb);
1565 }
1566
1567 EAPI void
1568 elm_toolbar_item_tooltip_unset(Elm_Toolbar_Item *item)
1569 {
1570    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1571    elm_widget_item_tooltip_unset(item);
1572 }
1573
1574 EAPI void
1575 elm_toolbar_item_tooltip_style_set(Elm_Toolbar_Item *item, const char *style)
1576 {
1577    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1578    elm_widget_item_tooltip_style_set(item, style);
1579 }
1580
1581 EAPI const char *
1582 elm_toolbar_item_tooltip_style_get(const Elm_Toolbar_Item *item)
1583 {
1584    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
1585    return elm_widget_item_tooltip_style_get(item);
1586 }
1587
1588 EAPI void
1589 elm_toolbar_item_cursor_set(Elm_Toolbar_Item *item, const char *cursor)
1590 {
1591    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1592    elm_widget_item_cursor_set(item, cursor);
1593 }
1594
1595 EAPI const char *
1596 elm_toolbar_item_cursor_get(const Elm_Toolbar_Item *item)
1597 {
1598    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
1599    return elm_widget_item_cursor_get(item);
1600 }
1601
1602 EAPI void
1603 elm_toolbar_item_cursor_unset(Elm_Toolbar_Item *item)
1604 {
1605    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1606    elm_widget_item_cursor_unset(item);
1607 }
1608
1609 EAPI void
1610 elm_toolbar_item_cursor_style_set(Elm_Toolbar_Item *item, const char *style)
1611 {
1612    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1613    elm_widget_item_cursor_style_set(item, style);
1614 }
1615
1616 EAPI const char *
1617 elm_toolbar_item_cursor_style_get(const Elm_Toolbar_Item *item)
1618 {
1619    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
1620    return elm_widget_item_cursor_style_get(item);
1621 }
1622
1623 EAPI void
1624 elm_toolbar_item_cursor_engine_only_set(Elm_Toolbar_Item *item, Eina_Bool engine_only)
1625 {
1626    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1627    elm_widget_item_cursor_engine_only_set(item, engine_only);
1628 }
1629
1630 EAPI Eina_Bool
1631 elm_toolbar_item_cursor_engine_only_get(const Elm_Toolbar_Item *item)
1632 {
1633    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, EINA_FALSE);
1634    return elm_widget_item_cursor_engine_only_get(item);
1635 }
1636
1637 EAPI Evas_Object *
1638 elm_toolbar_item_menu_get(Elm_Toolbar_Item *item)
1639 {
1640    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
1641    Widget_Data *wd = elm_widget_data_get(item->base.widget);
1642    if (!wd) return NULL;
1643    /* FIXME: It's not ok. This function needs to be reviewed. And should
1644     * receive a const item */
1645    elm_toolbar_item_menu_set(item, 1);
1646    return item->o_menu;
1647 }
1648
1649 EAPI Elm_Toolbar_Item *
1650 elm_toolbar_item_find_by_label(const Evas_Object *obj, const char *label)
1651 {
1652    Elm_Toolbar_Item *it;
1653    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1654    Widget_Data *wd = elm_widget_data_get(obj);
1655
1656    if (!wd) return NULL;
1657    EINA_INLIST_FOREACH(wd->items, it)
1658      {
1659         if (!strcmp(it->label, label)) return it;
1660      }
1661
1662    return NULL;
1663 }
1664
1665 EAPI void
1666 elm_toolbar_item_data_set(Elm_Toolbar_Item *item, const void *data)
1667 {
1668    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item);
1669    elm_widget_item_data_set(item, data);
1670 }
1671
1672 EAPI void *
1673 elm_toolbar_item_data_get(const Elm_Toolbar_Item *item)
1674 {
1675    ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(item, NULL);
1676    return elm_widget_item_data_get(item);
1677 }
1678
1679 EAPI void
1680 elm_toolbar_no_select_mode_set(Evas_Object *obj, Eina_Bool no_select)
1681 {
1682    ELM_CHECK_WIDTYPE(obj, widtype);
1683    Widget_Data *wd = elm_widget_data_get(obj);
1684    if (!wd) return;
1685    wd->no_select = no_select;
1686 }
1687
1688 EAPI Eina_Bool
1689 elm_toolbar_no_select_mode_get(const Evas_Object *obj)
1690 {
1691    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1692    Widget_Data *wd = elm_widget_data_get(obj);
1693    if (!wd) return EINA_FALSE;
1694    return wd->no_select;
1695 }
1696
1697 EAPI void
1698 elm_toolbar_icon_order_lookup_set(Evas_Object *obj, Elm_Icon_Lookup_Order order)
1699 {
1700    ELM_CHECK_WIDTYPE(obj, widtype);
1701    Elm_Toolbar_Item *it;
1702    Widget_Data *wd = elm_widget_data_get(obj);
1703    if (!wd) return;
1704
1705    wd->lookup_order = order;
1706    EINA_INLIST_FOREACH(wd->items, it)
1707       elm_icon_order_lookup_set(it->icon, order);
1708    if (wd->more_item)
1709      elm_icon_order_lookup_set(wd->more_item->icon, order);
1710 }
1711
1712 EAPI Elm_Icon_Lookup_Order
1713 elm_toolbar_icon_order_lookup_get(const Evas_Object *obj)
1714 {
1715    ELM_CHECK_WIDTYPE(obj, widtype) ELM_ICON_LOOKUP_THEME_FDO;
1716    Widget_Data *wd = elm_widget_data_get(obj);
1717    if (!wd) return ELM_ICON_LOOKUP_THEME_FDO;
1718    return wd->lookup_order;
1719 }
1720
1721 EAPI void
1722 elm_toolbar_orientation_set(Evas_Object *obj, Eina_Bool vertical)
1723 {
1724    ELM_CHECK_WIDTYPE(obj, widtype);
1725    Widget_Data *wd = elm_widget_data_get(obj);
1726    if (!wd) return;
1727    wd->vertical = vertical;
1728    _sizing_eval(obj);
1729 }
1730
1731 EAPI Eina_Bool
1732 elm_toolbar_orientation_get(Evas_Object *obj)
1733 {
1734    ELM_CHECK_WIDTYPE(obj, widtype);
1735    Widget_Data *wd = elm_widget_data_get(obj);
1736    if (!wd) return EINA_FALSE;
1737    return wd->vertical;
1738 }