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