Initialize Tizen 2.3
[framework/uifw/elementary.git] / mobile / src / lib / elm_toolbar.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include "elm_widget_toolbar.h"
4
5 EAPI const char ELM_TOOLBAR_SMART_NAME[] = "elm_toolbar";
6
7 #define ELM_TOOLBAR_ITEM_FROM_INLIST(item) \
8   ((item) ? EINA_INLIST_CONTAINER_GET(item, Elm_Toolbar_Item) : NULL)
9
10 static const char SIG_SCROLL[] = "scroll";
11 static const char SIG_SCROLL_ANIM_START[] = "scroll,anim,start";
12 static const char SIG_SCROLL_ANIM_STOP[] = "scroll,anim,stop";
13 static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start";
14 static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop";
15 static const char SIG_CLICKED[] = "clicked";
16 static const char SIG_LONGPRESSED[] = "longpressed";
17 static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
18 static const char SIG_LANG_CHANGED[] = "language,changed";
19 static const char SIG_ACCESS_CHANGED[] = "access,changed";
20 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
21    {SIG_SCROLL, ""},
22    {SIG_SCROLL_ANIM_START, ""},
23    {SIG_SCROLL_ANIM_STOP, ""},
24    {SIG_SCROLL_DRAG_START, ""},
25    {SIG_SCROLL_DRAG_STOP, ""},
26    {SIG_CLICKED, ""},
27    {SIG_LONGPRESSED, ""},
28    {SIG_CLICKED_DOUBLE, ""},
29    {SIG_LANG_CHANGED, ""},
30    {SIG_ACCESS_CHANGED, ""},
31    {NULL, NULL}
32 };
33
34 static const Evas_Smart_Interface *_smart_interfaces[] =
35 {
36    (Evas_Smart_Interface *)&ELM_SCROLLABLE_IFACE, NULL
37 };
38
39 EVAS_SMART_SUBCLASS_IFACE_NEW
40   (ELM_TOOLBAR_SMART_NAME, _elm_toolbar, Elm_Toolbar_Smart_Class,
41   Elm_Widget_Smart_Class, elm_widget_smart_class_get, _smart_callbacks,
42   _smart_interfaces);
43
44 static void _item_select(Elm_Toolbar_Item *it);
45 static Elm_Toolbar_Item *_highlight_next_item_get(Evas_Object *obj,
46                                                   Evas_Object *box,
47                                                   Eina_Bool reverse);
48 static int
49 _toolbar_item_prio_compare_cb(const void *i1,
50                               const void *i2)
51 {
52    const Elm_Toolbar_Item *eti1 = i1;
53    const Elm_Toolbar_Item *eti2 = i2;
54
55    if (!eti2) return 1;
56    if (!eti1) return -1;
57
58    if (eti2->prio.priority == eti1->prio.priority)
59      return -1;
60
61    return eti2->prio.priority - eti1->prio.priority;
62 }
63
64 static void
65 _items_visibility_fix(Elm_Toolbar_Smart_Data *sd,
66                       Evas_Coord *iw,
67                       Evas_Coord vw,
68                       Eina_Bool *more)
69 {
70    Elm_Toolbar_Item *it, *prev;
71    Evas_Coord ciw = 0, cih = 0;
72    Eina_List *sorted = NULL;
73    int count = 0, i = 0;
74
75    *more = EINA_FALSE;
76
77    EINA_INLIST_FOREACH(sd->items, it)
78      {
79         if (it->separator)
80           {
81              prev = ELM_TOOLBAR_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
82              if (prev) it->prio.priority = prev->prio.priority;
83           }
84      }
85
86    EINA_INLIST_FOREACH(sd->items, it)
87      {
88         sorted = eina_list_sorted_insert
89             (sorted, _toolbar_item_prio_compare_cb, it);
90      }
91
92    if (sd->more_item)
93      {
94         evas_object_geometry_get(sd->VIEW(more_item), NULL, NULL, &ciw, &cih);
95         if (sd->vertical) *iw += cih;
96         else *iw += ciw;
97      }
98
99    EINA_LIST_FREE(sorted, it)
100      {
101         if (it->prio.priority > sd->standard_priority)
102           {
103              evas_object_geometry_get(VIEW(it), NULL, NULL, &ciw, &cih);
104              if (sd->vertical) *iw += cih;
105              else *iw += ciw;
106              it->prio.visible = (*iw <= vw);
107              it->in_box = sd->bx;
108              if (!it->separator) count++;
109           }
110         else
111           {
112              it->prio.visible = EINA_FALSE;
113              if (!it->separator) i++;
114              if (i <= (count + 1))
115                it->in_box = sd->bx_more;
116              else
117                it->in_box = sd->bx_more2;
118              *more = EINA_TRUE;
119           }
120      }
121 }
122
123 static void
124 _item_menu_destroy(Elm_Toolbar_Item *item)
125 {
126    if (item->o_menu)
127      {
128         evas_object_del(item->o_menu);
129         item->o_menu = NULL;
130      }
131    item->menu = EINA_FALSE;
132 }
133
134 static void
135 _item_unselect(Elm_Toolbar_Item *item)
136 {
137    if ((!item) || (!item->selected)) return;
138
139    ELM_TOOLBAR_DATA_GET(WIDGET(item), sd);
140
141    item->selected = EINA_FALSE;
142    sd->selected_item = NULL;
143    edje_object_signal_emit(VIEW(item), "elm,state,unselected", "elm");
144    elm_widget_signal_emit(item->icon, "elm,state,unselected", "elm");
145 }
146
147 static void
148 _item_unhighlight(Elm_Toolbar_Item *item)
149 {
150    if (!item) return;
151
152    ELM_TOOLBAR_DATA_GET(WIDGET(item), sd);
153
154    if (!sd->highlighted_item) return;
155
156    if (item == sd->highlighted_item)
157      {
158         edje_object_signal_emit(VIEW(sd->highlighted_item), "elm,highlight,off", "elm");
159         sd->highlighted_item = NULL;
160      }
161 }
162
163 static void
164 _menu_hide(void *data,
165            Evas *e __UNUSED__,
166            Evas_Object *obj __UNUSED__,
167            void *event_info __UNUSED__)
168 {
169    Elm_Toolbar_Item *selected;
170    Elm_Toolbar_Item *it = data;
171
172    selected = (Elm_Toolbar_Item *)elm_toolbar_selected_item_get(WIDGET(it));
173    _item_unselect(selected);
174 }
175
176 static void
177 _menu_del(void *data,
178           Evas *e __UNUSED__,
179           Evas_Object *obj,
180           void *event_info __UNUSED__)
181 {
182    // avoid hide being emitted during object deletion
183    evas_object_event_callback_del_full
184      (obj, EVAS_CALLBACK_HIDE, _menu_hide, data);
185 }
186
187 static void
188 _item_menu_create(Elm_Toolbar_Smart_Data *sd,
189                   Elm_Toolbar_Item *item)
190 {
191    item->o_menu = elm_menu_add(elm_widget_parent_get(WIDGET(item)));
192    item->menu = EINA_TRUE;
193
194    if (sd->menu_parent)
195      elm_menu_parent_set(item->o_menu, sd->menu_parent);
196
197    evas_object_event_callback_add
198      (item->o_menu, EVAS_CALLBACK_HIDE, _menu_hide, item);
199    evas_object_event_callback_add
200      (item->o_menu, EVAS_CALLBACK_DEL, _menu_del, item);
201 }
202
203 static void
204 _elm_toolbar_item_menu_cb(void *data,
205                           Evas_Object *obj __UNUSED__,
206                           void *event_info __UNUSED__)
207 {
208    Elm_Toolbar_Item *it = data;
209
210    if (it->func) it->func((void *)(it->base.data), WIDGET(it), it);
211 }
212
213 static void
214 _item_show(Elm_Toolbar_Item *it)
215 {
216    Evas_Coord x, y, w, h, bx, by;
217
218    ELM_TOOLBAR_DATA_GET(WIDGET(it), sd);
219
220    evas_object_geometry_get(sd->bx, &bx, &by, NULL, NULL);
221    evas_object_geometry_get(VIEW(it), &x, &y, &w, &h);
222    sd->s_iface->content_region_show
223      (ELM_WIDGET_DATA(sd)->obj, x - bx, y - by, w, h);
224 }
225
226 static void
227 _item_mirrored_set(Evas_Object *obj __UNUSED__,
228                    Elm_Toolbar_Item *it,
229                    Eina_Bool mirrored)
230 {
231    edje_object_mirrored_set(VIEW(it), mirrored);
232    if (it->o_menu) elm_widget_mirrored_set(it->o_menu, mirrored);
233 }
234
235 static void
236 _mirrored_set(Evas_Object *obj,
237               Eina_Bool mirrored)
238 {
239    Elm_Toolbar_Item *it;
240
241    ELM_TOOLBAR_DATA_GET(obj, sd);
242
243    EINA_INLIST_FOREACH(sd->items, it)
244      _item_mirrored_set(obj, it, mirrored);
245    if (sd->more_item)
246      _item_mirrored_set(obj, sd->more_item, mirrored);
247 }
248
249 static void
250 _items_size_fit(Evas_Object *obj, Evas_Coord *bl, Evas_Coord view)
251 {
252    Elm_Toolbar_Item *it, *prev;
253    Eina_Bool full = EINA_FALSE, more = EINA_FALSE;
254    Evas_Coord min, mw, mh;
255    int sumf = 0, sumb = 0, prev_min = 0;
256
257    ELM_TOOLBAR_DATA_GET(obj, sd);
258
259    EINA_INLIST_FOREACH(sd->items, it)
260      {
261         min = mw = mh = -1;
262         if (it->in_box && it->in_box == sd->bx)
263           {
264              if (!it->separator && !it->object)
265                elm_coords_finger_size_adjust(1, &mw, 1, &mh);
266              edje_object_size_min_restricted_calc(VIEW(it), &mw, &mh, mw, mh);
267              if (!it->separator && !it->object)
268                elm_coords_finger_size_adjust(1, &mw, 1, &mh);
269           }
270         else if (!more)
271           {
272              more = EINA_TRUE;
273              elm_coords_finger_size_adjust(1, &mw, 1, &mh);
274              edje_object_size_min_restricted_calc(sd->VIEW(more_item), &mw, &mh, mw, mh);
275              elm_coords_finger_size_adjust(1, &mw, 1, &mh);
276           }
277
278         if (mw != -1 || mh != -1)
279           {
280              if (sd->vertical) min = mh;
281              else min = mw;
282
283              if ((!full) && ((sumf + min) > view))
284                {
285                   prev = ELM_TOOLBAR_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
286                   if (prev && prev->separator)
287                     {
288                        sumf -= prev_min;
289                        sumb += prev_min;
290                     }
291                   full = EINA_TRUE;
292                }
293
294              if (!full) sumf += min;
295              else sumb += min;
296              prev_min = min;
297           }
298      }
299    if (sumf != 0) *bl = (Evas_Coord)(((sumf + sumb) * view) / sumf);
300 }
301
302 static Eina_Bool
303 _elm_toolbar_item_coordinates_calc(Elm_Toolbar_Item *item,
304                                    Elm_Toolbar_Item_Scrollto_Type type,
305                                    Evas_Coord *x,
306                                    Evas_Coord *y,
307                                    Evas_Coord *w,
308                                    Evas_Coord *h)
309 {
310    Evas_Coord ix, iy, iw, ih, bx, by, vw, vh;
311
312    ELM_TOOLBAR_DATA_GET(WIDGET(item), sd);
313
314    sd->s_iface->content_viewport_size_get(WIDGET(item), &vw, &vh);
315    evas_object_geometry_get(sd->bx, &bx, &by, NULL, NULL);
316    evas_object_geometry_get(VIEW(item), &ix, &iy, &iw, &ih);
317
318    switch (type)
319      {
320       case ELM_TOOLBAR_ITEM_SCROLLTO_IN:
321          *x = ix - bx;
322          *y = iy - by;
323          *w = iw;
324          *h = ih;
325          break;
326
327       case ELM_TOOLBAR_ITEM_SCROLLTO_FIRST:
328          *x = ix - bx;
329          *y = iy - by;
330          *w = vw;
331          *h = vh;
332          break;
333
334       case ELM_TOOLBAR_ITEM_SCROLLTO_MIDDLE:
335          *x = ix - bx + (iw / 2) - (vw / 2);
336          *y = iy - by + (ih / 2) - (vh / 2);
337          *w = vw;
338          *h = vh;
339          break;
340
341       case ELM_TOOLBAR_ITEM_SCROLLTO_LAST:
342          *x = ix - bx + iw - vw;
343          *y = iy - by + ih - vh;
344          *w = vw;
345          *h = vh;
346          break;
347
348       default:
349          return EINA_FALSE;
350      }
351
352    return EINA_TRUE;
353 }
354
355 static void
356 _resize_job(void *data)
357 {
358    Evas_Object *obj = (Evas_Object *)data;
359    Evas_Coord mw, mh, vw = 0, vh = 0, w = 0, h = 0;
360    Elm_Toolbar_Item *it;
361    Evas_Object *o; // TIZEN ONLY
362    Eina_List *l; // TIZEN ONLY
363    Eina_List *list;
364    Eina_Bool more;
365
366    ELM_TOOLBAR_DATA_GET(obj, sd);
367
368    sd->resize_job = NULL;
369    sd->s_iface->content_viewport_size_get(obj, &vw, &vh);
370    evas_object_size_hint_min_get(sd->bx, &mw, &mh);
371    evas_object_geometry_get(sd->bx, NULL, NULL, &w, &h);
372
373    if (sd->shrink_mode == ELM_TOOLBAR_SHRINK_MENU)
374      {
375         Evas_Coord iw = 0, ih = 0, more_w = 0, more_h = 0;
376
377         if (sd->vertical)
378           {
379              h = vh;
380              _items_visibility_fix(sd, &ih, vh, &more);
381           }
382         else
383           {
384              w = vw;
385              _items_visibility_fix(sd, &iw, vw, &more);
386           }
387         evas_object_geometry_get
388           (sd->VIEW(more_item), NULL, NULL, &more_w, &more_h);
389
390         if (sd->vertical)
391           {
392              if ((ih - more_h) <= vh) ih -= more_h;
393           }
394         else
395           {
396              if ((iw - more_w) <= vw) iw -= more_w;
397           }
398
399         /* All items are removed from the box object, since removing
400          * individual items won't trigger a resize. Items are be
401          * readded below. */
402         evas_object_box_remove_all(sd->bx, EINA_FALSE);
403         if (((sd->vertical) && (ih > vh)) ||
404             ((!sd->vertical) && (iw > vw)) || more)
405           {
406              Evas_Object *menu;
407
408              _item_menu_destroy(sd->more_item);
409              _item_menu_create(sd, sd->more_item);
410              menu =
411                elm_toolbar_item_menu_get((Elm_Object_Item *)sd->more_item);
412              EINA_INLIST_FOREACH(sd->items, it)
413                {
414                   if (!it->prio.visible)
415                     {
416                        if (it->separator)
417                          elm_menu_item_separator_add(menu, NULL);
418                        else
419                          {
420                             Elm_Object_Item *menu_it;
421
422                             menu_it = elm_menu_item_add
423                                 (menu, NULL, it->icon_str, it->label,
424                                 _elm_toolbar_item_menu_cb, it);
425                             elm_object_item_disabled_set
426                               (menu_it, elm_widget_item_disabled_get(it));
427                             if (it->o_menu)
428                               elm_menu_clone(it->o_menu, menu, menu_it);
429                          }
430                        evas_object_hide(VIEW(it));
431                     }
432                   else
433                     {
434                        evas_object_box_append(sd->bx, VIEW(it));
435                        evas_object_show(VIEW(it));
436                     }
437                }
438              evas_object_box_append(sd->bx, sd->VIEW(more_item));
439              evas_object_show(sd->VIEW(more_item));
440           }
441         else
442           {
443              /* All items are visible, show them all (except for the
444               * "More" button, of course). */
445              EINA_INLIST_FOREACH(sd->items, it)
446                {
447                   evas_object_show(VIEW(it));
448                   evas_object_box_append(sd->bx, VIEW(it));
449                }
450              evas_object_hide(sd->VIEW(more_item));
451           }
452      }
453    else if (sd->shrink_mode == ELM_TOOLBAR_SHRINK_HIDE)
454      {
455         Evas_Coord iw = 0, ih = 0;
456
457         if (sd->vertical)
458           {
459              h = vh;
460              _items_visibility_fix(sd, &ih, vh, &more);
461           }
462         else
463           {
464              w = vw;
465              _items_visibility_fix(sd, &iw, vw, &more);
466           }
467         evas_object_box_remove_all(sd->bx, EINA_FALSE);
468         if (((sd->vertical) && (ih > vh)) ||
469             ((!sd->vertical) && (iw > vw)) || more)
470           {
471              EINA_INLIST_FOREACH(sd->items, it)
472                {
473                   if (!it->prio.visible)
474                     evas_object_hide(VIEW(it));
475                   else
476                     {
477                        evas_object_box_append(sd->bx, VIEW(it));
478                        evas_object_show(VIEW(it));
479                     }
480                }
481           }
482         else
483           {
484              /* All items are visible, show them all */
485              EINA_INLIST_FOREACH(sd->items, it)
486                {
487                   evas_object_show(VIEW(it));
488                   evas_object_box_append(sd->bx, VIEW(it));
489                }
490           }
491      }
492    else if (sd->shrink_mode == ELM_TOOLBAR_SHRINK_EXPAND)
493      {
494         Evas_Coord iw = 0, ih = 0;
495
496         if (sd->vertical)
497           h = (vh >= mh) ? vh : mh;
498         else
499           w = (vw >= mw) ? vw : mw;
500
501         if (sd->vertical)
502           _items_visibility_fix(sd, &ih, vh, &more);
503         else
504           _items_visibility_fix(sd, &iw, vw, &more);
505
506         evas_object_box_remove_all(sd->bx, EINA_FALSE);
507         evas_object_box_remove_all(sd->bx_more, EINA_FALSE);
508         evas_object_box_remove_all(sd->bx_more2, EINA_FALSE);
509
510         EINA_INLIST_FOREACH(sd->items, it)
511           {
512              if (it->in_box)
513                {
514                   evas_object_box_append(it->in_box, VIEW(it));
515                   evas_object_show(VIEW(it));
516                }
517           }
518         if (more)
519           {
520              evas_object_box_append(sd->bx, sd->VIEW(more_item));
521              evas_object_show(sd->VIEW(more_item));
522           }
523         else
524           evas_object_hide(sd->VIEW(more_item));
525
526         if (sd->vertical)
527           {
528              if (h > vh) _items_size_fit(obj, &h, vh);
529              if (sd->item_count - sd->separator_count > 0)
530                sd->s_iface->paging_set(obj, 0.0, 0.0, 0, (h / (sd->item_count - sd->separator_count)));
531           }
532         else
533           {
534              if (w > vw) _items_size_fit(obj, &w, vw);
535              if (sd->item_count - sd->separator_count > 0)
536                sd->s_iface->paging_set(obj, 0.0, 0.0, (w / (sd->item_count - sd->separator_count)), 0);
537           }
538      }
539    else
540      {
541         if (sd->vertical)
542           {
543              if ((vh >= mh) && (h != vh)) h = vh;
544           }
545         else
546           {
547              if ((vw >= mw) && (w != vw)) w = vw;
548           }
549         EINA_INLIST_FOREACH(sd->items, it)
550           {
551              if (it->selected)
552                {
553                   _item_show(it);
554                   break;
555                }
556           }
557      }
558
559    if (sd->transverse_expanded)
560      {
561         if (sd->vertical)
562           w = vw;
563         else
564           h = vh;
565      }
566
567    evas_object_resize(sd->bx, w, h);
568
569 //// TIZEN ONLY
570    list = evas_object_box_children_get(sd->bx);
571    EINA_LIST_FOREACH(list, l, o)
572      {
573         if (o == eina_list_nth(list, 0))
574           {
575              edje_object_signal_emit(o, "elm,order,first,item", "elm");
576              if (eina_list_count(list) == 1)
577                edje_object_signal_emit(o, "elm,order,last,item", "elm");
578           }
579         else if (o == eina_list_nth(list, eina_list_count(list)-1))
580           edje_object_signal_emit(o, "elm,order,last,item", "elm");
581         else
582           edje_object_signal_emit(o, "elm,order,default,item", "elm");
583      }
584 //
585
586 // Remove the first or last separator since it is not neccessary
587    list = evas_object_box_children_get(sd->bx_more);
588    EINA_INLIST_FOREACH(sd->items, it)
589      {
590         if (it->separator &&
591             ((VIEW(it) == eina_list_data_get(list)) ||
592              (VIEW(it) == eina_list_nth(list, eina_list_count(list) - 1))))
593           {
594              evas_object_box_remove(sd->bx_more, VIEW(it));
595              evas_object_move(VIEW(it), -9999, -9999);
596              evas_object_hide(VIEW(it));
597           }
598      }
599    list = evas_object_box_children_get(sd->bx_more2);
600    EINA_INLIST_FOREACH(sd->items, it)
601      {
602         if (it->separator &&
603             ((VIEW(it) == eina_list_data_get(list)) ||
604              (VIEW(it) == eina_list_nth(list, eina_list_count(list) - 1))))
605           {
606              evas_object_box_remove(sd->bx_more2, VIEW(it));
607              evas_object_move(VIEW(it), -9999, -9999);
608              evas_object_hide(VIEW(it));
609           }
610      }
611
612    _mirrored_set(obj, elm_widget_mirrored_get(obj));
613 }
614
615 // FIXME: There are applications which do not use elm_win as top widget.
616 // This is workaround! Those could not use focus!
617 static Eina_Bool _focus_enabled(Evas_Object *obj)
618 {
619    if (!elm_widget_focus_get(obj)) return EINA_FALSE;
620
621    const Evas_Object *win = elm_widget_top_get(obj);
622    const char *type = evas_object_type_get(win);
623
624    if (type && !strcmp(type, "elm_win"))
625      {
626         return elm_win_focus_highlight_enabled_get(win);
627      }
628    return EINA_FALSE;
629 }
630
631 static Eina_Bool
632 _elm_toolbar_smart_on_focus(Evas_Object *obj)
633 {
634    Elm_Toolbar_Item *it = NULL;
635    Evas_Coord x, y, w, h;
636
637    ELM_TOOLBAR_DATA_GET(obj, sd);
638
639    if (elm_widget_focus_get(obj))
640      {
641         evas_object_focus_set(ELM_WIDGET_DATA(sd)->resize_obj, EINA_TRUE);
642         // FIXME: There are applications which do not use elm_win as top widget.
643         // This is workaround! Those could not use focus!
644         if (_focus_enabled(obj))
645           {
646              it = _highlight_next_item_get(obj, sd->bx, EINA_FALSE);
647
648              if(!it)
649                return EINA_FALSE;
650
651              if (sd->highlighted_item)
652                edje_object_signal_emit(VIEW(sd->highlighted_item), "elm,highlight,off", "elm");
653
654              sd->highlighted_item = it;
655              edje_object_signal_emit(VIEW(sd->highlighted_item), "elm,highlight,on", "elm");
656
657              if (_elm_toolbar_item_coordinates_calc(
658                    sd->highlighted_item, ELM_TOOLBAR_ITEM_SCROLLTO_IN, &x, &y, &w, &h))
659                sd->s_iface->region_bring_in(obj, x, y, w, h);
660           }
661      }
662    else
663      {
664         if (sd->highlighted_item)
665           {
666              edje_object_signal_emit(VIEW(sd->highlighted_item), "elm,highlight,off", "elm");
667              sd->highlighted_item = NULL;
668           }
669      evas_object_focus_set(ELM_WIDGET_DATA(sd)->resize_obj, EINA_FALSE);
670    }
671
672    return EINA_TRUE;
673 }
674
675 static Elm_Toolbar_Item *
676 _highlight_next_item_get(Evas_Object *obj, Evas_Object *box, Eina_Bool reverse)
677 {
678    ELM_TOOLBAR_DATA_GET(obj, sd);
679    Eina_List *list = NULL;
680    Elm_Toolbar_Item *it = NULL;
681    Evas_Object *it_obj = NULL;
682
683    list = evas_object_box_children_get(box);
684    if (reverse)
685      list = eina_list_reverse(list);
686
687    if (sd->highlighted_item)
688      {
689         list = eina_list_data_find_list(list, VIEW(sd->highlighted_item));
690         if (list) list = eina_list_next(list);
691      }
692    it_obj = eina_list_data_get(list);
693    if (it_obj) it = evas_object_data_get(it_obj, "item");
694    else it = NULL;
695
696    while (it &&
697           (it->separator ||
698            elm_object_item_disabled_get((Elm_Object_Item *)it)))
699      {
700         if (list) list = eina_list_next(list);
701         if (!list)
702           {
703              it = NULL;
704              break;
705           }
706         it_obj = eina_list_data_get(list);
707         if (it_obj) it = evas_object_data_get(it_obj, "item");
708         else it = NULL;
709      }
710
711    return it;
712 }
713
714 static Eina_Bool
715 _elm_toolbar_smart_event(Evas_Object *obj,
716                          Evas_Object *src __UNUSED__,
717                          Evas_Callback_Type type __UNUSED__,
718                          void *event_info)
719 {
720    (void) src;
721    (void) type;
722    Elm_Toolbar_Item *it = NULL;
723    Evas_Coord x, y, w, h;
724
725    ELM_TOOLBAR_DATA_GET(obj, sd);
726
727    Evas_Event_Key_Down *ev = event_info;
728
729    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
730    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
731    if (!sd->items) return EINA_FALSE;
732    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
733
734    if ((!strcmp(ev->keyname, "Return")) ||
735             ((!strcmp(ev->keyname, "KP_Enter")) && !ev->string))
736      {
737         if (sd->highlighted_item)
738           _item_select(sd->highlighted_item);
739         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
740         return EINA_TRUE;
741      }
742    else if ((!strcmp(ev->keyname, "Left")) ||
743             ((!strcmp(ev->keyname, "KP_Left")) && !ev->string))
744      {
745         if (!sd->vertical)
746           it = _highlight_next_item_get(obj, sd->bx, EINA_TRUE);
747         else
748           return EINA_FALSE;
749      }
750    else if ((!strcmp(ev->keyname, "Right")) ||
751             ((!strcmp(ev->keyname, "KP_Right")) && !ev->string))
752      {
753         if (!sd->vertical)
754           it = _highlight_next_item_get(obj, sd->bx, EINA_FALSE);
755         else
756           return EINA_FALSE;
757      }
758    else if ((!strcmp(ev->keyname, "Up")) ||
759             ((!strcmp(ev->keyname, "KP_Up")) && !ev->string))
760      {
761         if (sd->vertical)
762           it = _highlight_next_item_get(obj, sd->bx, EINA_TRUE);
763         else
764           return EINA_FALSE;
765      }
766    else if ((!strcmp(ev->keyname, "Down")) ||
767             ((!strcmp(ev->keyname, "KP_Down")) && !ev->string))
768      {
769         if (sd->vertical)
770           it = _highlight_next_item_get(obj, sd->bx, EINA_FALSE);
771         else
772           return EINA_FALSE;
773      }
774
775    if (!it)
776      return EINA_FALSE;
777
778    if (sd->highlighted_item)
779      edje_object_signal_emit(VIEW(sd->highlighted_item), "elm,highlight,off", "elm");
780    sd->highlighted_item = it;
781    edje_object_signal_emit(VIEW(sd->highlighted_item), "elm,highlight,on", "elm");
782
783    if (_elm_toolbar_item_coordinates_calc(
784          sd->highlighted_item, ELM_TOOLBAR_ITEM_SCROLLTO_IN, &x, &y, &w, &h))
785      sd->s_iface->region_bring_in(obj, x, y, w, h);
786
787    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
788    return EINA_TRUE;
789 }
790
791 static void
792 _resize_cb(void *data,
793            Evas *e __UNUSED__,
794            Evas_Object *obj __UNUSED__,
795            void *event_info __UNUSED__)
796 {
797    Evas_Coord x, y, h;
798
799    ELM_TOOLBAR_DATA_GET(data, sd);
800
801    evas_object_geometry_get(data, &x, &y, NULL, &h);
802    evas_object_move(sd->more, x, y + h);
803
804    if (sd->resize_job) ecore_job_del(sd->resize_job);
805    sd->resize_job = ecore_job_add(_resize_job, data);
806 }
807
808 static void
809 _item_disable_hook(Elm_Object_Item *it)
810 {
811    Elm_Toolbar_Item *toolbar_it = (Elm_Toolbar_Item *)it;
812
813    if (elm_widget_item_disabled_get(toolbar_it))
814      {
815         edje_object_signal_emit(VIEW(toolbar_it), "elm,state,disabled", "elm");
816         elm_widget_signal_emit(toolbar_it->icon, "elm,state,disabled", "elm");
817      }
818    else
819      {
820         edje_object_signal_emit(VIEW(toolbar_it), "elm,state,enabled", "elm");
821         elm_widget_signal_emit(toolbar_it->icon, "elm,state,enabled", "elm");
822      }
823
824    _resize_cb(WIDGET(toolbar_it), NULL, NULL, NULL);
825 }
826
827 static Eina_Bool
828 _item_icon_set(Evas_Object *icon_obj,
829                const char *type,
830                const char *icon)
831 {
832    char icon_str[512];
833
834    if ((!type) || (!*type)) goto end;
835    if ((!icon) || (!*icon)) return EINA_FALSE;
836    if ((snprintf(icon_str, sizeof(icon_str), "%s%s", type, icon) > 0)
837        && (elm_icon_standard_set(icon_obj, icon_str)))
838      return EINA_TRUE;
839 end:
840    if (elm_icon_standard_set(icon_obj, icon))
841      return EINA_TRUE;
842
843    WRN("couldn't find icon definition for '%s'", icon);
844    return EINA_FALSE;
845 }
846
847 static int
848 _elm_toolbar_icon_size_get(Elm_Toolbar_Smart_Data *sd)
849 {
850    const char *icon_size = edje_object_data_get
851        (ELM_WIDGET_DATA(sd)->resize_obj, "icon_size");
852
853    if (icon_size) return atoi(icon_size);
854
855    return _elm_config->icon_size;
856 }
857
858 static void
859 _menu_move_resize_cb(void *data,
860                      Evas *e __UNUSED__,
861                      Evas_Object *obj __UNUSED__,
862                      void *event_info __UNUSED__)
863 {
864    Elm_Toolbar_Item *it = data;
865    Evas_Coord x, y, h;
866
867    ELM_TOOLBAR_DATA_GET(WIDGET(it), sd);
868
869    if (!sd->menu_parent) return;
870    evas_object_geometry_get(VIEW(it), &x, &y, NULL, &h);
871    elm_menu_move(it->o_menu, x, y + h);
872 }
873
874 static void
875 _item_select(Elm_Toolbar_Item *it)
876 {
877    Elm_Toolbar_Item *it2;
878    Evas_Object *obj2;
879    Eina_Bool sel;
880
881    ELM_TOOLBAR_DATA_GET(WIDGET(it), sd);
882
883    if (elm_widget_item_disabled_get(it) || (it->separator) || (it->object))
884      return;
885    sel = it->selected;
886
887    if (sd->select_mode != ELM_OBJECT_SELECT_MODE_NONE)
888      {
889         if (sel)
890           {
891              if (sd->shrink_mode == ELM_TOOLBAR_SHRINK_EXPAND)
892                {
893                   if (sd->more_item == it)
894                     {
895                        elm_layout_signal_emit
896                          (sd->more, "elm,state,close", "elm");
897                        _item_unselect(it);
898                     }
899                }
900              if (sd->select_mode != ELM_OBJECT_SELECT_MODE_ALWAYS)
901                _item_unselect(it);
902           }
903         else
904           {
905              it2 = (Elm_Toolbar_Item *)
906                elm_toolbar_selected_item_get(WIDGET(it));
907              _item_unselect(it2);
908
909              it->selected = EINA_TRUE;
910              sd->selected_item = it;
911              if (sd->shrink_mode == ELM_TOOLBAR_SHRINK_EXPAND)
912                {
913                   if (sd->more_item == it)
914                     {
915                        if (!evas_object_box_children_get(sd->bx_more2))
916                          elm_layout_signal_emit
917                            (sd->more, "elm,state,open", "elm");
918                        else
919                          elm_layout_signal_emit
920                            (sd->more, "elm,state,open2", "elm");
921                     }
922                   else
923                     {
924                        if (it->in_box != sd->bx)
925                          {
926                             edje_object_signal_emit
927                               (sd->VIEW(more_item), "elm,state,selected",
928                               "elm");
929                             elm_widget_signal_emit
930                               (sd->more_item->icon, "elm,state,selected",
931                               "elm");
932                          }
933                        else
934                          {
935                             edje_object_signal_emit
936                               (sd->VIEW(more_item), "elm,state,unselected",
937                               "elm");
938                             elm_widget_signal_emit
939                               (sd->more_item->icon, "elm,state,unselected",
940                               "elm");
941                          }
942                        elm_layout_signal_emit
943                          (sd->more, "elm,state,close", "elm");
944                     }
945                }
946              edje_object_signal_emit(VIEW(it), "elm,state,selected", "elm");
947              elm_widget_signal_emit(it->icon, "elm,state,selected", "elm");
948              _item_show(it);
949           }
950      }
951
952    obj2 = WIDGET(it);
953    if (it->menu && (!sel))
954      {
955         evas_object_show(it->o_menu);
956         evas_object_event_callback_add
957           (VIEW(it), EVAS_CALLBACK_RESIZE, _menu_move_resize_cb, it);
958         evas_object_event_callback_add
959           (VIEW(it), EVAS_CALLBACK_MOVE, _menu_move_resize_cb, it);
960
961         _menu_move_resize_cb(it, NULL, NULL, NULL);
962      }
963
964    if ((!sel) || (sd->select_mode == ELM_OBJECT_SELECT_MODE_ALWAYS))
965      {
966         if (it->func) it->func((void *)(it->base.data), WIDGET(it), it);
967      }
968    evas_object_smart_callback_call(obj2, SIG_CLICKED, it);
969 }
970
971 static void
972 _item_del(Elm_Toolbar_Item *it)
973 {
974    Elm_Toolbar_Item_State *it_state;
975
976    _item_unselect(it);
977    _item_unhighlight(it);
978
979    EINA_LIST_FREE(it->states, it_state)
980      {
981         if (it->icon == it_state->icon)
982           it->icon = NULL;
983         eina_stringshare_del(it_state->label);
984         eina_stringshare_del(it_state->icon_str);
985         if (it_state->icon) evas_object_del(it_state->icon);
986         free(it_state);
987      }
988
989    eina_stringshare_del(it->label);
990    if (it->label)
991      edje_object_signal_emit(VIEW(it), "elm,state,text,hidden", "elm");
992    eina_stringshare_del(it->icon_str);
993
994    if (it->icon)
995      {
996         edje_object_signal_emit(VIEW(it), "elm,state,icon,hidden", "elm");
997         evas_object_del(it->icon);
998      }
999
1000    if (it->object) evas_object_del(it->object);
1001    //TODO: See if checking for sd->menu_parent is necessary before
1002    //deleting menu
1003    if (it->o_menu) evas_object_del(it->o_menu);
1004 }
1005
1006 static void
1007 _item_theme_hook(Evas_Object *obj,
1008                  Elm_Toolbar_Item *it,
1009                  double scale,
1010                  int icon_size)
1011 {
1012    Evas_Coord mw, mh, minw, minh;
1013    Evas_Object *view = VIEW(it);
1014    const char *style;
1015
1016    ELM_TOOLBAR_DATA_GET(obj, sd);
1017
1018    style = elm_widget_style_get(obj);
1019
1020    _item_mirrored_set(obj, it, elm_widget_mirrored_get(obj));
1021    edje_object_scale_set(view, scale);
1022
1023    if (!it->separator && !it->object)
1024      {
1025         elm_widget_theme_object_set(obj, view, "toolbar", "item", style);
1026         if (it->selected)
1027           {
1028              edje_object_signal_emit(view, "elm,state,selected", "elm");
1029              elm_widget_signal_emit(it->icon, "elm,state,selected", "elm");
1030           }
1031         if (elm_widget_item_disabled_get(it))
1032           {
1033              edje_object_signal_emit(view, "elm,state,disabled", "elm");
1034              elm_widget_signal_emit(it->icon, "elm,state,disabled", "elm");
1035           }
1036         if (it->icon)
1037           {
1038              int ms = 0;
1039
1040              ms = ((double)icon_size * scale);
1041              evas_object_size_hint_min_set(it->icon, ms, ms);
1042              evas_object_size_hint_max_set(it->icon, ms, ms);
1043              edje_object_part_swallow(view, "elm.swallow.icon", it->icon);
1044              edje_object_signal_emit
1045                (VIEW(it), "elm,state,icon,visible", "elm");
1046           }
1047         if (it->label)
1048           {
1049              edje_object_part_text_escaped_set(view, "elm.text", it->label);
1050              edje_object_signal_emit(VIEW(it), "elm,state,text,visible", "elm");
1051           }
1052      }
1053    else
1054      {
1055         if (!it->object)
1056           {
1057              elm_widget_theme_object_set
1058                (obj, view, "toolbar", "separator", style);
1059              if (sd->vertical)
1060                {
1061                   evas_object_size_hint_weight_set
1062                     (view, EVAS_HINT_EXPAND, -1.0);
1063                   evas_object_size_hint_align_set
1064                     (view, EVAS_HINT_FILL, EVAS_HINT_FILL);
1065                }
1066              else
1067                {
1068                   evas_object_size_hint_weight_set
1069                     (view, -1.0, EVAS_HINT_EXPAND);
1070                   evas_object_size_hint_align_set
1071                     (view, EVAS_HINT_FILL, EVAS_HINT_FILL);
1072                }
1073           }
1074         else
1075           {
1076              elm_widget_theme_object_set
1077                (obj, view, "toolbar", "object", style);
1078              edje_object_part_swallow(view, "elm.swallow.object", it->object);
1079           }
1080      }
1081
1082    mw = mh = minw = minh = -1;
1083    if (!it->separator && !it->object)
1084      elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1085
1086    // If the min size is changed by edje signal in edc,
1087    //the below function should be called before the calculation.
1088    edje_object_message_signal_process(view);
1089    edje_object_size_min_restricted_calc(view, &mw, &mh, mw, mh);
1090    if (!it->separator && !it->object)
1091      elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1092    evas_object_size_hint_min_set(view, mw, mh);
1093 }
1094
1095 static void
1096 _inform_item_number(Evas_Object *obj)
1097 {
1098    ELM_TOOLBAR_DATA_GET(obj, sd);
1099    Elm_Toolbar_Item *it;
1100    char buf[sizeof("elm,action,click,") + 3];
1101    static int scount = 0;
1102    int count = 0;
1103
1104    EINA_INLIST_FOREACH(sd->items, it)
1105      {
1106         if (!it->separator) count++;
1107      }
1108    if (scount != count)
1109      {
1110         scount = count;
1111         sprintf(buf, "elm,number,item,%d", count);
1112
1113         EINA_INLIST_FOREACH(sd->items, it)
1114           {
1115              if (!it->separator && !it->object)
1116                edje_object_signal_emit(VIEW(it), buf, "elm");
1117           }
1118      }
1119 }
1120
1121 static void
1122 _sizing_eval(Evas_Object *obj)
1123 {
1124    Evas_Coord minw = -1, minh = -1, minw_bx = -1, minh_bx = -1;
1125    Evas_Coord vw = 0, vh = 0;
1126    Evas_Coord w, h;
1127
1128    ELM_TOOLBAR_DATA_GET(obj, sd);
1129
1130    evas_object_smart_need_recalculate_set(sd->bx, EINA_TRUE);
1131    evas_object_smart_calculate(sd->bx);
1132    edje_object_size_min_calc(ELM_WIDGET_DATA(sd)->resize_obj, &minw, &minh);
1133    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1134
1135    if (w < minw) w = minw;
1136    if (h < minh) h = minh;
1137
1138    evas_object_resize(ELM_WIDGET_DATA(sd)->resize_obj, w, h);
1139
1140    evas_object_size_hint_min_get(sd->bx, &minw_bx, &minh_bx);
1141    sd->s_iface->content_viewport_size_get(obj, &vw, &vh);
1142
1143    if (sd->shrink_mode == ELM_TOOLBAR_SHRINK_NONE)
1144      {
1145         minw = minw_bx + (w - vw);
1146         minh = minh_bx + (h - vh);
1147      }
1148    else if (sd->shrink_mode == ELM_TOOLBAR_SHRINK_EXPAND)
1149      {
1150         if (sd->vertical)
1151           {
1152              minw = minw_bx + (w - vw);
1153              if (minh_bx <= vh) minh_bx = vh;
1154              else _items_size_fit(obj, &minh_bx, vh);
1155           }
1156         else
1157           {
1158              minh = minh_bx + (h - vh);
1159              if (minw_bx <= vw) minw_bx = vw;
1160              else _items_size_fit(obj, &minw_bx, vw);
1161           }
1162      }
1163    else
1164      {
1165         if (sd->vertical)
1166           {
1167              minw = minw_bx + (w - vw);
1168              minh = h - vh;
1169           }
1170         else
1171           {
1172              minw = w - vw;
1173              minh = minh_bx + (h - vh);
1174           }
1175      }
1176
1177    if (sd->transverse_expanded)
1178      {
1179         if (sd->vertical)
1180           minw_bx = vw;
1181         else
1182           minh_bx = vh;
1183      }
1184
1185    evas_object_resize(sd->bx, minw_bx, minh_bx);
1186    evas_object_resize(sd->more, minw_bx, minh_bx);
1187    evas_object_size_hint_min_set(obj, minw, minh);
1188    evas_object_size_hint_max_set(obj, -1, -1);
1189
1190    _inform_item_number(obj);
1191 }
1192
1193 static Eina_Bool
1194 _elm_toolbar_smart_theme(Evas_Object *obj)
1195 {
1196    Elm_Toolbar_Item *it;
1197    double scale = 0;
1198    const char *str;
1199
1200    ELM_TOOLBAR_DATA_GET(obj, sd);
1201
1202    if (sd->on_deletion)
1203      return EINA_TRUE;
1204
1205    if (!ELM_WIDGET_CLASS(_elm_toolbar_parent_sc)->theme(obj))
1206      return EINA_FALSE;
1207
1208    elm_widget_theme_object_set
1209      (obj, ELM_WIDGET_DATA(sd)->resize_obj, "toolbar", "base",
1210      elm_widget_style_get(obj));
1211
1212    str = edje_object_data_get(ELM_WIDGET_DATA(sd)->resize_obj, "focus_highlight");
1213    if ((str) && (!strcmp(str, "on")))
1214      elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
1215    else
1216      elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
1217
1218    elm_layout_theme_set
1219      (sd->more, "toolbar", "more", elm_widget_style_get(obj));
1220
1221    _mirrored_set(obj, elm_widget_mirrored_get(obj));
1222
1223    sd->theme_icon_size = _elm_toolbar_icon_size_get(sd);
1224    if (sd->priv_icon_size) sd->icon_size = sd->priv_icon_size;
1225    else sd->icon_size = sd->theme_icon_size;
1226
1227    EINA_INLIST_FOREACH(sd->items, it)
1228      _item_theme_hook(obj, it, scale, sd->icon_size);
1229
1230    if (sd->more_item)
1231      _item_theme_hook(obj, sd->more_item, scale, sd->icon_size);
1232
1233    _sizing_eval(obj);
1234
1235    return EINA_TRUE;
1236 }
1237
1238 static void
1239 _elm_toolbar_item_label_update(Elm_Toolbar_Item *item)
1240 {
1241    Evas_Coord mw = -1, mh = -1, minw = -1, minh = -1;
1242
1243    ELM_TOOLBAR_DATA_GET(WIDGET(item), sd);
1244
1245    edje_object_part_text_escaped_set(VIEW(item), "elm.text", item->label);
1246    if (item->label)
1247      edje_object_signal_emit(VIEW(item), "elm,state,text,visible", "elm");
1248    else
1249      edje_object_signal_emit(VIEW(item), "elm,state,text,hidden", "elm");
1250
1251    elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1252    // If the min size is changed by edje signal in edc,
1253    //the below function should be called before the calculation.
1254    edje_object_message_signal_process(VIEW(item));
1255    edje_object_size_min_restricted_calc(VIEW(item), &mw, &mh, mw, mh);
1256    elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1257    if (sd->shrink_mode != ELM_TOOLBAR_SHRINK_EXPAND)
1258      {
1259         if (sd->vertical)
1260           {
1261              evas_object_size_hint_weight_set
1262                (VIEW(item), EVAS_HINT_EXPAND, -1.0);
1263              evas_object_size_hint_align_set
1264                (VIEW(item), EVAS_HINT_FILL, EVAS_HINT_FILL);
1265           }
1266         else
1267           {
1268              evas_object_size_hint_weight_set
1269                (VIEW(item), -1.0, EVAS_HINT_EXPAND);
1270              evas_object_size_hint_align_set
1271                (VIEW(item), EVAS_HINT_FILL, EVAS_HINT_FILL);
1272           }
1273      }
1274    else
1275      {
1276         evas_object_size_hint_weight_set
1277           (VIEW(item), EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1278         evas_object_size_hint_align_set
1279           (VIEW(item), EVAS_HINT_FILL, EVAS_HINT_FILL);
1280      }
1281
1282    evas_object_size_hint_min_get(VIEW(item), &minw, &minh);
1283    if ((minw < mw) && (minh < mh))
1284      evas_object_size_hint_min_set(VIEW(item), mw, mh);
1285    else if ((minw < mw) && (minh > mh))
1286      evas_object_size_hint_min_set(VIEW(item), mw, minh);
1287    else if ((minw > mw) && (minh < mh))
1288      evas_object_size_hint_min_set(VIEW(item), minw, mh);
1289 }
1290
1291 static void
1292 _elm_toolbar_item_label_set_cb(void *data,
1293                                Evas_Object *obj,
1294                                const char *emission,
1295                                const char *source)
1296 {
1297    Elm_Toolbar_Item *item = data;
1298
1299    _elm_toolbar_item_label_update(item);
1300    edje_object_signal_callback_del
1301      (obj, emission, source, _elm_toolbar_item_label_set_cb);
1302    edje_object_signal_emit(VIEW(item), "elm,state,label,reset", "elm");
1303 }
1304
1305 static void
1306 _item_label_set(Elm_Toolbar_Item *item,
1307                 const char *label,
1308                 const char *sig)
1309 {
1310    const char *s;
1311
1312    if ((label) && (item->label) && (!strcmp(label, item->label))) return;
1313
1314    eina_stringshare_replace(&item->label, label);
1315    s = edje_object_data_get(VIEW(item), "transition_animation_on");
1316    if ((s) && (atoi(s)))
1317      {
1318         edje_object_part_text_escaped_set
1319           (VIEW(item), "elm.text_new", item->label);
1320         edje_object_signal_emit(VIEW(item), sig, "elm");
1321         edje_object_signal_callback_add
1322           (VIEW(item), "elm,state,label_set,done", "elm",
1323           _elm_toolbar_item_label_set_cb, item);
1324      }
1325    else
1326      _elm_toolbar_item_label_update(item);
1327
1328    _resize_cb(WIDGET(item), NULL, NULL, NULL);
1329 }
1330
1331 static void
1332 _item_text_set_hook(Elm_Object_Item *it,
1333                     const char *part,
1334                     const char *label)
1335 {
1336    Elm_Toolbar_Item *item;
1337    char buf[256];
1338    item = (Elm_Toolbar_Item *)it;
1339
1340    if ((!part) || (!strcmp(part, "default")) ||
1341        (!strcmp(part, "elm.text")))
1342      {
1343         _item_label_set(((Elm_Toolbar_Item *)it), label, "elm,state,label_set");
1344      }
1345    else
1346      {
1347         if (label)
1348           {
1349              snprintf(buf, sizeof(buf), "elm,state,%s,visible", part);
1350              edje_object_signal_emit(VIEW(item), buf, "elm");
1351           }
1352         else
1353           {
1354              snprintf(buf, sizeof(buf), "elm,state,%s,hidden", part);
1355              edje_object_signal_emit(VIEW(item), buf, "elm");
1356           }
1357         edje_object_part_text_escaped_set(VIEW(item), part, label);
1358      }
1359 }
1360
1361 static const char *
1362 _item_text_get_hook(const Elm_Object_Item *it,
1363                     const char *part)
1364 {
1365    char buf[256];
1366
1367    if (!part || !strcmp(part, "default"))
1368      snprintf(buf, sizeof(buf), "elm.text");
1369    else
1370      snprintf(buf, sizeof(buf), "%s", part);
1371
1372    return edje_object_part_text_get(VIEW(it), buf);
1373 }
1374
1375 static void
1376 _item_content_set_hook(Elm_Object_Item *it,
1377                        const char *part,
1378                        Evas_Object *content)
1379 {
1380    Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
1381    Evas_Object *obj = WIDGET(item);
1382    double scale;
1383
1384    ELM_TOOLBAR_DATA_GET(obj, sd);
1385
1386    if (part && strcmp(part, "object")) return;
1387    if (item->object == content) return;
1388
1389    if (item->object) evas_object_del(item->object);
1390
1391    item->object = content;
1392    if (item->object)
1393      elm_widget_sub_object_add(obj, item->object);
1394
1395    scale = (elm_widget_scale_get(obj) * elm_config_scale_get());
1396    _item_theme_hook(obj, item, scale, sd->icon_size);
1397 }
1398
1399 static Evas_Object *
1400 _item_content_get_hook(const Elm_Object_Item *it,
1401                        const char *part)
1402 {
1403    if (part && strcmp(part, "object")) return NULL;
1404    return ((Elm_Toolbar_Item *)it)->object;
1405 }
1406
1407 static Evas_Object *
1408 _item_content_unset_hook(Elm_Object_Item *it,
1409                          const char *part)
1410 {
1411    Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
1412    Evas_Object *obj = WIDGET(item);
1413    Evas_Object *o;
1414    double scale;
1415
1416    ELM_TOOLBAR_DATA_GET(obj, sd);
1417
1418    if (part && strcmp(part, "object")) return NULL;
1419
1420    edje_object_part_unswallow(VIEW(it), item->object);
1421    elm_widget_sub_object_del(obj, item->object);
1422    o = item->object;
1423    item->object = NULL;
1424    scale = (elm_widget_scale_get(obj) * elm_config_scale_get());
1425    _item_theme_hook(obj, item, scale, sd->icon_size);
1426
1427    return o;
1428 }
1429
1430 static Eina_Bool
1431 _elm_toolbar_smart_translate(Evas_Object *obj)
1432 {
1433    ELM_TOOLBAR_DATA_GET(obj, sd);
1434    Elm_Toolbar_Item *it;
1435
1436    EINA_INLIST_FOREACH(sd->items, it)
1437      elm_widget_item_translate(it);
1438
1439    evas_object_smart_callback_call(obj, SIG_LANG_CHANGED, NULL);
1440
1441    return EINA_TRUE;
1442 }
1443
1444 static void
1445 _item_resize(void *data,
1446              Evas *e __UNUSED__,
1447              Evas_Object *obj __UNUSED__,
1448              void *event_info __UNUSED__)
1449 {
1450    _sizing_eval(data);
1451    _resize_cb(data, NULL, NULL, NULL);
1452 }
1453
1454 static void
1455 _move_cb(void *data,
1456          Evas *e __UNUSED__,
1457          Evas_Object *obj __UNUSED__,
1458          void *event_info __UNUSED__)
1459 {
1460    Evas_Coord x, y, h;
1461
1462    ELM_TOOLBAR_DATA_GET(data, sd);
1463    evas_object_geometry_get(data, &x, &y, NULL, &h);
1464    evas_object_move(sd->more, x, y + h);
1465 }
1466
1467 // FIXME: There are applications which do not use elm_win as top widget.
1468 // This is workaround! Those could not use focus!
1469 static void
1470 _highlight_off_cb(void *data __UNUSED__,
1471          Evas *e __UNUSED__,
1472          Evas_Object *obj,
1473          void *event_info __UNUSED__)
1474 {
1475    ELM_TOOLBAR_DATA_GET(obj, sd);
1476
1477    if (sd->highlighted_item)
1478      {
1479         edje_object_signal_emit(VIEW(sd->highlighted_item), "elm,highlight,off", "elm");
1480         sd->highlighted_item = NULL;
1481      }
1482 }
1483
1484 static void
1485 _select_filter_cb(Elm_Toolbar_Item *it,
1486                   Evas_Object *obj __UNUSED__,
1487                   const char *emission,
1488                   const char *source __UNUSED__)
1489 {
1490    int button;
1491    char buf[sizeof("elm,action,click,") + 1];
1492
1493    button = atoi(emission + sizeof("mouse,clicked,") - 1);
1494    if (button == 1) return;  /* regular left click event */
1495    snprintf(buf, sizeof(buf), "elm,action,click,%d", button);
1496    edje_object_signal_emit(VIEW(it), buf, "elm");
1497 }
1498
1499 static void
1500 _select_cb(void *data,
1501            Evas_Object *obj __UNUSED__,
1502            const char *emission __UNUSED__,
1503            const char *source __UNUSED__)
1504 {
1505    Elm_Toolbar_Item *it = data;
1506
1507    if ((_elm_config->access_mode == ELM_ACCESS_MODE_OFF) ||
1508        (_elm_access_2nd_click_timeout(VIEW(it))))
1509      {
1510         if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
1511           _elm_access_say(E_("Selected"));
1512         _item_select(it);
1513      }
1514 }
1515
1516 static void
1517 _item_move_cb(void *data,
1518          Evas *e __UNUSED__,
1519          Evas_Object *obj __UNUSED__,
1520          void *event_info __UNUSED__)
1521 {
1522    Elm_Toolbar_Item *item = data;
1523
1524    item->on_move = EINA_FALSE;
1525
1526    evas_object_event_callback_del_full
1527      (VIEW(item), EVAS_CALLBACK_MOVE, _item_move_cb, data);
1528 }
1529
1530 static void
1531 _items_change(Elm_Toolbar_Item *reorder_from, Elm_Toolbar_Item *reorder_to)
1532 {
1533    Elm_Toolbar_Item *prev = NULL, *next = NULL;
1534    int tmp;
1535
1536    if (!reorder_from || !reorder_to) return;
1537
1538    ELM_TOOLBAR_DATA_GET(WIDGET(reorder_from), sd);
1539    if (reorder_from == reorder_to) return;
1540
1541    if ((!reorder_from->separator) && (!reorder_to->separator))
1542      {
1543         prev = ELM_TOOLBAR_ITEM_FROM_INLIST
1544             (EINA_INLIST_GET(reorder_from)->prev);
1545         if (prev == reorder_to)
1546           prev = reorder_from;
1547         if (!prev)
1548           next = ELM_TOOLBAR_ITEM_FROM_INLIST
1549               (EINA_INLIST_GET(reorder_from)->next);
1550         if (next == reorder_to)
1551           next = NULL;
1552
1553         sd->items = eina_inlist_remove
1554             (sd->items, EINA_INLIST_GET(reorder_from));
1555         sd->items = eina_inlist_append_relative
1556             (sd->items, EINA_INLIST_GET(reorder_from),
1557             EINA_INLIST_GET(reorder_to));
1558
1559         sd->items = eina_inlist_remove
1560             (sd->items, EINA_INLIST_GET(reorder_to));
1561         if (prev)
1562           sd->items = eina_inlist_append_relative
1563               (sd->items, EINA_INLIST_GET(reorder_to),
1564               EINA_INLIST_GET(prev));
1565         else if (next)
1566           sd->items = eina_inlist_prepend_relative
1567               (sd->items, EINA_INLIST_GET(reorder_to),
1568               EINA_INLIST_GET(next));
1569         else
1570           sd->items = eina_inlist_prepend
1571              (sd->items, EINA_INLIST_GET(reorder_to));
1572
1573         evas_object_box_remove(sd->bx, VIEW(reorder_from));
1574         evas_object_box_insert_after(sd->bx, VIEW(reorder_from),
1575                                      VIEW(reorder_to));
1576         evas_object_box_remove(sd->bx, VIEW(reorder_to));
1577         if (prev)
1578           evas_object_box_insert_after(sd->bx, VIEW(reorder_to),
1579                                        VIEW(prev));
1580         else if (next)
1581           evas_object_box_insert_before(sd->bx, VIEW(reorder_to),
1582                                         VIEW(next));
1583         else
1584           evas_object_box_prepend(sd->bx, VIEW(reorder_to));
1585
1586         tmp = reorder_from->prio.priority;
1587         reorder_from->prio.priority = reorder_to->prio.priority;
1588         reorder_to->prio.priority = tmp;
1589
1590         reorder_from->on_move = EINA_TRUE;
1591         reorder_to->on_move = EINA_TRUE;
1592
1593         evas_object_event_callback_add
1594            (VIEW(reorder_from), EVAS_CALLBACK_MOVE,
1595            _item_move_cb, reorder_from);
1596         evas_object_event_callback_add
1597            (VIEW(reorder_to), EVAS_CALLBACK_MOVE,
1598            _item_move_cb, reorder_to);
1599      }
1600
1601    _resize_cb(WIDGET(reorder_from), NULL, NULL, NULL);
1602 }
1603
1604 static void
1605 _transit_del_cb(void *data, Elm_Transit *transit __UNUSED__)
1606 {
1607    Elm_Toolbar_Item *it, *item = data;
1608    ELM_TOOLBAR_DATA_GET(WIDGET(item), sd);
1609
1610    if (item->reorder_to)
1611      {
1612         if (item->reorder_to == sd->reorder_empty)
1613           sd->reorder_empty = item;
1614         else if (item == sd->reorder_empty)
1615           sd->reorder_empty = item->reorder_to;
1616
1617         _items_change(item->reorder_to, item);
1618
1619         EINA_INLIST_FOREACH(sd->items, it)
1620           {
1621              if (it != item)
1622                {
1623                   if (it->reorder_to == item)
1624                     it->reorder_to = item->reorder_to;
1625                   else if (it->reorder_to == item->reorder_to)
1626                     it->reorder_to = item;
1627                }
1628           }
1629      }
1630    if (item->proxy)
1631      {
1632         evas_object_image_source_visible_set(elm_image_object_get(item->proxy), EINA_TRUE);
1633         evas_object_del(item->proxy);
1634         item->proxy = NULL;
1635      }
1636    item->trans = NULL;
1637
1638    if (item->reorder_to)
1639      {
1640         EINA_INLIST_FOREACH(sd->items, it)
1641            if (it->trans) break;
1642
1643         if (!it) sd->reorder_empty = sd->reorder_item;
1644      }
1645    item->reorder_to = NULL;
1646 }
1647
1648 static void
1649 _item_transition_start
1650 (Elm_Toolbar_Item *it, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
1651 {
1652    Evas_Coord tx, ty;
1653    Evas_Object *obj = WIDGET(it);
1654    ELM_TOOLBAR_DATA_GET(obj, sd);
1655
1656    it->proxy = elm_image_add(obj);
1657    elm_image_aspect_fixed_set(it->proxy, EINA_FALSE);
1658    evas_object_image_source_set(elm_image_object_get(it->proxy), VIEW(it));
1659    evas_object_image_source_visible_set(elm_image_object_get(it->proxy), EINA_FALSE);
1660    evas_object_image_source_clip_set(elm_image_object_get(it->proxy), EINA_FALSE);
1661
1662    it->trans = elm_transit_add();
1663    elm_transit_object_add(it->trans, it->proxy);
1664    evas_object_geometry_get(VIEW(sd->reorder_empty), &tx, &ty, NULL, NULL);
1665    evas_object_move(it->proxy, x, y);
1666    evas_object_resize(it->proxy, w, h);
1667    evas_object_show(it->proxy);
1668
1669    elm_transit_effect_translation_add(it->trans, 0, 0, tx - x, 0);
1670    elm_transit_duration_set(it->trans, 0.3);
1671    elm_transit_del_cb_set(it->trans, _transit_del_cb, it);
1672    elm_transit_go(it->trans);
1673
1674    it->reorder_to = sd->reorder_empty;
1675 }
1676
1677 static void
1678 _animate_missed_items(Elm_Toolbar_Item *prev, Elm_Toolbar_Item *next)
1679 {
1680    ELM_TOOLBAR_DATA_GET(WIDGET(prev), sd);
1681    Elm_Toolbar_Item *it, *it2;
1682    Eina_List *list, *l;
1683    Evas_Object *o;
1684    Eina_Bool reverse = EINA_FALSE;
1685    Evas_Coord fx, fy, fw, fh;
1686
1687    list = evas_object_box_children_get(sd->bx);
1688
1689    EINA_LIST_FOREACH(list, l, o)
1690      {
1691         if (o == VIEW(prev))
1692           break;
1693         else if (o == VIEW(next))
1694           reverse = EINA_TRUE;
1695      }
1696
1697    if (!reverse)
1698      l = eina_list_next(l);
1699    else
1700      l = eina_list_prev(l);
1701
1702    while (VIEW(next) != eina_list_data_get(l))
1703      {
1704         EINA_INLIST_FOREACH(sd->items, it)
1705           {
1706              if (VIEW(it) == eina_list_data_get(l))
1707                {
1708                   if (!it->trans && it != sd->reorder_item)
1709                     {
1710                        evas_object_geometry_get(VIEW(sd->reorder_empty), &fx, &fy, &fw, &fh);
1711                        _item_transition_start(it, fx, fy, fw, fh);
1712                        sd->reorder_empty = it;
1713                     }
1714                   EINA_INLIST_FOREACH(sd->items, it2)
1715                     {
1716                        if (it == it2->reorder_to) break;
1717                     }
1718                   if (it2)
1719                     {
1720                        it2->reorder_to = NULL;
1721                        evas_object_geometry_get(it2->proxy, &fx, &fy, &fw, &fh);
1722                        if (it2->trans) elm_transit_del(it2->trans);
1723                        _item_transition_start(it2, fx, fy, fw, fh);
1724                        sd->reorder_empty = it;
1725                     }
1726                }
1727           }
1728         if (!reverse)
1729           l = eina_list_next(l);
1730         else
1731           l = eina_list_prev(l);
1732      }
1733 }
1734
1735 static void
1736 _mouse_move_reorder(Elm_Toolbar_Item *item,
1737                     Evas *evas __UNUSED__,
1738                     Evas_Object *obj __UNUSED__,
1739                     Evas_Event_Mouse_Move *ev)
1740 {
1741    Evas_Coord x, y, w, h;
1742    Evas_Coord fx, fy, fw, fh;
1743    Elm_Toolbar_Item *it, *it2;
1744
1745    ELM_TOOLBAR_DATA_GET(WIDGET(item), sd);
1746
1747    evas_object_geometry_get(VIEW(item), &x, &y, &w, &h);
1748    if (sd->vertical)
1749      evas_object_move(item->proxy, x, ev->cur.canvas.y - (h / 2));
1750    else
1751      evas_object_move(item->proxy, ev->cur.canvas.x - (w / 2), y);
1752    evas_object_show(item->proxy);
1753
1754    if (sd->reorder_empty->on_move) return;
1755
1756    evas_object_geometry_get(sd->VIEW(reorder_empty), &x, &y, &w, &h);
1757    if (ev->cur.canvas.x < x || ev->cur.canvas.x > x + w)
1758      {
1759         EINA_INLIST_FOREACH(sd->items, it)
1760           {
1761              if (it->on_move) continue;
1762              evas_object_geometry_get(VIEW(it), &x, &y, &w, &h);
1763              if (ev->cur.canvas.x > x && ev->cur.canvas.x < x + w) break;
1764           }
1765         if (it && (it != sd->reorder_empty))
1766           {
1767              _animate_missed_items(sd->reorder_empty, it);
1768              if (!it->trans && it != item)
1769                {
1770                   evas_object_geometry_get(VIEW(it), &fx, &fy, &fw, &fh);
1771                   _item_transition_start(it, fx, fy, fw, fh);
1772                   sd->reorder_empty = it;
1773                }
1774              EINA_INLIST_FOREACH(sd->items, it2)
1775                {
1776                   if (it == it2->reorder_to) break;
1777                }
1778              if (it2)
1779                {
1780                   it2->reorder_to = NULL;
1781                   evas_object_geometry_get(it2->proxy, &fx, &fy, &fw, &fh);
1782                   if (it2->trans) elm_transit_del(it2->trans);
1783                   _item_transition_start(it2, fx, fy, fw, fh);
1784                   sd->reorder_empty = it;
1785                }
1786           }
1787      }
1788 }
1789
1790 static void
1791 _mouse_up_reorder(Elm_Toolbar_Item *it,
1792                   Evas *evas __UNUSED__,
1793                   Evas_Object *obj,
1794                   Evas_Event_Mouse_Up *ev __UNUSED__)
1795 {
1796    ELM_TOOLBAR_DATA_GET(WIDGET(it), sd);
1797
1798    evas_object_event_callback_del_full
1799      (obj, EVAS_CALLBACK_MOUSE_MOVE,
1800      (Evas_Object_Event_Cb)_mouse_move_reorder, it);
1801    evas_object_event_callback_del_full
1802      (sd->more, EVAS_CALLBACK_MOUSE_MOVE,
1803      (Evas_Object_Event_Cb)_mouse_move_reorder, it);
1804    evas_object_event_callback_del_full
1805      (VIEW(it), EVAS_CALLBACK_MOUSE_MOVE,
1806      (Evas_Object_Event_Cb)_mouse_move_reorder, it);
1807    evas_object_event_callback_del_full
1808      (obj, EVAS_CALLBACK_MOUSE_UP,
1809      (Evas_Object_Event_Cb)_mouse_up_reorder, it);
1810    evas_object_event_callback_del_full
1811      (sd->more, EVAS_CALLBACK_MOUSE_UP,
1812      (Evas_Object_Event_Cb)_mouse_up_reorder, it);
1813
1814    if (it->proxy)
1815      {
1816         evas_object_image_source_visible_set(elm_image_object_get(it->proxy), EINA_TRUE);
1817         evas_object_del(it->proxy);
1818         it->proxy = NULL;
1819      }
1820    sd->s_iface->hold_set(obj, EINA_FALSE);
1821 }
1822
1823 static void
1824 _item_reorder_start(Elm_Toolbar_Item *item)
1825 {
1826    Evas_Object *obj = WIDGET(item);
1827    Evas_Coord x, y, w, h;
1828
1829    ELM_TOOLBAR_DATA_GET(obj, sd);
1830
1831    sd->reorder_empty = sd->reorder_item = item;
1832
1833    item->proxy = elm_image_add(obj);
1834    elm_image_aspect_fixed_set(item->proxy, EINA_FALSE);
1835    evas_object_image_source_set(elm_image_object_get(item->proxy), VIEW(item));
1836    evas_object_image_source_visible_set(elm_image_object_get(item->proxy), EINA_FALSE);
1837    evas_object_image_source_clip_set(elm_image_object_get(item->proxy), EINA_FALSE);
1838    evas_object_layer_set(item->proxy, 100);
1839    edje_object_signal_emit(VIEW(item), "elm,state,moving", "elm");
1840
1841    evas_object_event_callback_add
1842      (obj, EVAS_CALLBACK_MOUSE_MOVE,
1843      (Evas_Object_Event_Cb)_mouse_move_reorder, item);
1844
1845    evas_object_event_callback_add
1846      (sd->more, EVAS_CALLBACK_MOUSE_MOVE,
1847      (Evas_Object_Event_Cb)_mouse_move_reorder, item);
1848
1849    evas_object_event_callback_add
1850      (item->proxy, EVAS_CALLBACK_MOUSE_MOVE,
1851      (Evas_Object_Event_Cb)_mouse_move_reorder, item);
1852
1853    evas_object_event_callback_add
1854      (obj, EVAS_CALLBACK_MOUSE_UP,
1855      (Evas_Object_Event_Cb)_mouse_up_reorder, item);
1856
1857    evas_object_event_callback_add
1858      (sd->more, EVAS_CALLBACK_MOUSE_UP,
1859      (Evas_Object_Event_Cb)_mouse_up_reorder, item);
1860
1861    evas_object_geometry_get(VIEW(item), &x, &y, &w, &h);
1862    evas_object_resize(item->proxy, w, h);
1863    evas_object_move(item->proxy, x, y);
1864    evas_object_show(item->proxy);
1865
1866    sd->s_iface->hold_set(WIDGET(item), EINA_TRUE);
1867 }
1868
1869 static Eina_Bool
1870 _long_press_cb(void *data)
1871 {
1872    Elm_Toolbar_Item *it = data;
1873    ELM_TOOLBAR_DATA_GET(WIDGET(it), sd);
1874
1875    sd->long_timer = NULL;
1876    sd->long_press = EINA_TRUE;
1877
1878    if (sd->reorder_mode)
1879      _item_reorder_start(it);
1880
1881    evas_object_smart_callback_call(WIDGET(it), SIG_LONGPRESSED, it);
1882
1883    return ECORE_CALLBACK_CANCEL;
1884 }
1885
1886 static void
1887 _mouse_move_cb(Elm_Toolbar_Item *it,
1888                Evas *evas __UNUSED__,
1889                Evas_Object *obj __UNUSED__,
1890                Evas_Event_Mouse_Move *ev)
1891 {
1892    Evas_Coord x, y, w, h;
1893
1894    ELM_TOOLBAR_DATA_GET(WIDGET(it), sd);
1895    evas_object_geometry_get(VIEW(it), &x, &y, &w, &h);
1896
1897    if ((sd->long_timer) &&
1898        ((x > ev->cur.canvas.x) || (ev->cur.canvas.x > x + w) ||
1899         (y > ev->cur.canvas.y) || (ev->cur.canvas.y > y + h)))
1900      {
1901         ecore_timer_del(sd->long_timer);
1902         sd->long_timer = NULL;
1903      }
1904 }
1905
1906 static void
1907 _mouse_down_cb(Elm_Toolbar_Item *it,
1908                Evas *evas __UNUSED__,
1909                Evas_Object *obj __UNUSED__,
1910                Evas_Event_Mouse_Down *ev)
1911 {
1912    ELM_TOOLBAR_DATA_GET(WIDGET(it), sd);
1913
1914    if (ev->button != 1) return;
1915    if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
1916      evas_object_smart_callback_call(WIDGET(it), SIG_CLICKED_DOUBLE, it);
1917    sd->long_press = EINA_FALSE;
1918    if (sd->long_timer)
1919      ecore_timer_interval_set
1920        (sd->long_timer, _elm_config->longpress_timeout);
1921    else
1922      sd->long_timer = ecore_timer_add
1923          (_elm_config->longpress_timeout, _long_press_cb, it);
1924
1925    evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_MOVE,
1926                                   (Evas_Object_Event_Cb)_mouse_move_cb, it);
1927 }
1928
1929 static void
1930 _mouse_up_cb(Elm_Toolbar_Item *it,
1931              Evas *evas __UNUSED__,
1932              Evas_Object *obj __UNUSED__,
1933              Evas_Event_Mouse_Up *ev)
1934 {
1935    ELM_TOOLBAR_DATA_GET(WIDGET(it), sd);
1936
1937    if (ev->button != 1) return;
1938    if (sd->long_timer)
1939      {
1940         ecore_timer_del(sd->long_timer);
1941         sd->long_timer = NULL;
1942      }
1943    evas_object_event_callback_del_full
1944      (VIEW(it), EVAS_CALLBACK_MOUSE_MOVE,
1945      (Evas_Object_Event_Cb)_mouse_move_cb, it);
1946 }
1947
1948 static void
1949 _mouse_in_cb(void *data,
1950              Evas_Object *obj __UNUSED__,
1951              const char *emission __UNUSED__,
1952              const char *source __UNUSED__)
1953 {
1954    Elm_Toolbar_Item *it = data;
1955
1956    edje_object_signal_emit(VIEW(it), "elm,state,highlighted", "elm");
1957    elm_widget_signal_emit(it->icon, "elm,state,highlighted", "elm");
1958 }
1959
1960 static void
1961 _mouse_out_cb(void *data,
1962               Evas_Object *obj __UNUSED__,
1963               const char *emission __UNUSED__,
1964               const char *source __UNUSED__)
1965 {
1966    Elm_Toolbar_Item *it = data;
1967
1968    edje_object_signal_emit(VIEW(it), "elm,state,unhighlighted", "elm");
1969    elm_widget_signal_emit(it->icon, "elm,state,unhighlighted", "elm");
1970 }
1971
1972 static void
1973 _scroll_cb(Evas_Object *obj,
1974            void *data __UNUSED__)
1975 {
1976    evas_object_smart_callback_call(obj, SIG_SCROLL, NULL);
1977 }
1978
1979 static void
1980 _scroll_anim_start_cb(Evas_Object *obj,
1981                       void *data __UNUSED__)
1982 {
1983    evas_object_smart_callback_call(obj, SIG_SCROLL_ANIM_START, NULL);
1984 }
1985
1986 static void
1987 _scroll_anim_stop_cb(Evas_Object *obj,
1988                      void *data __UNUSED__)
1989 {
1990    evas_object_smart_callback_call(obj, SIG_SCROLL_ANIM_STOP, NULL);
1991 }
1992
1993 static void
1994 _scroll_drag_start_cb(Evas_Object *obj,
1995                       void *data __UNUSED__)
1996 {
1997   ELM_TOOLBAR_DATA_GET(obj, sd);
1998
1999    if (sd->long_timer)
2000      {
2001         ecore_timer_del(sd->long_timer);
2002         sd->long_timer = NULL;
2003      }
2004
2005    evas_object_smart_callback_call(obj, SIG_SCROLL_DRAG_START, NULL);
2006 }
2007
2008 static void
2009 _scroll_drag_stop_cb(Evas_Object *obj,
2010                      void *data __UNUSED__)
2011 {
2012    evas_object_smart_callback_call(obj, SIG_SCROLL_DRAG_STOP, NULL);
2013 }
2014
2015 static void
2016 _layout(Evas_Object *o,
2017         Evas_Object_Box_Data *priv,
2018         void *data)
2019 {
2020    Evas_Object *obj = (Evas_Object *)data;
2021
2022    ELM_TOOLBAR_DATA_GET(obj, sd);
2023    _els_box_layout
2024      (o, priv, !sd->vertical, sd->homogeneous, elm_widget_mirrored_get(obj));
2025 }
2026
2027 static char *
2028 _access_info_cb(void *data, Evas_Object *obj __UNUSED__)
2029 {
2030    Elm_Toolbar_Item *it = (Elm_Toolbar_Item *)data;
2031    const char *txt = ((Elm_Widget_Item *)it)->access_info;
2032
2033    if (!txt) txt = it->label;
2034    if (txt) return strdup(txt);
2035
2036    return NULL;
2037 }
2038
2039 static char *
2040 _access_state_cb(void *data, Evas_Object *obj __UNUSED__)
2041 {
2042    Elm_Toolbar_Item *it = (Elm_Toolbar_Item *)data;
2043
2044    if (it->separator)
2045      return strdup(E_("Separator"));
2046    else if (elm_widget_item_disabled_get(it))
2047      return strdup(E_("State: Disabled"));
2048    else if (it->selected)
2049      return strdup(E_("State: Selected"));
2050    else if (it->menu)
2051      return strdup(E_("Has menu"));
2052
2053    return NULL;
2054 }
2055
2056 static Eina_Bool
2057 _item_del_pre_hook(Elm_Object_Item *it)
2058 {
2059    Elm_Toolbar_Item *item, *next = NULL;
2060    Evas_Object *obj;
2061
2062    item = (Elm_Toolbar_Item *)it;
2063
2064    ELM_TOOLBAR_DATA_GET(WIDGET(item), sd);
2065
2066    obj = WIDGET(item);
2067
2068    if (item != sd->more_item) /* more item does not get in the list */
2069      {
2070         if (!sd->on_deletion)
2071           next = ELM_TOOLBAR_ITEM_FROM_INLIST(EINA_INLIST_GET(item)->next);
2072         sd->items = eina_inlist_remove(sd->items, EINA_INLIST_GET(item));
2073         sd->item_count--;
2074         if (!sd->on_deletion)
2075           {
2076              if (!next) next = ELM_TOOLBAR_ITEM_FROM_INLIST(sd->items);
2077              if ((sd->select_mode == ELM_OBJECT_SELECT_MODE_ALWAYS) &&
2078                  item->selected && next) _item_select(next);
2079           }
2080      }
2081
2082    _item_del(item);
2083
2084    if (item != sd->more_item)
2085      _elm_toolbar_smart_theme(obj);
2086
2087    return EINA_TRUE;
2088 }
2089
2090 static void
2091 _access_activate_cb(void *data __UNUSED__,
2092                     Evas_Object *part_obj __UNUSED__,
2093                     Elm_Object_Item *item)
2094 {
2095    Elm_Toolbar_Item *it;
2096    it = (Elm_Toolbar_Item *)item;
2097
2098    if (elm_widget_item_disabled_get(it)) return;
2099
2100    if (!it->selected)
2101      {
2102         _elm_access_say(E_("Selected"));
2103         _item_select(it);
2104      }
2105 }
2106
2107 static void
2108 _access_widget_item_register(Elm_Toolbar_Item *it)
2109 {
2110    Elm_Access_Info *ai;
2111    _elm_access_widget_item_register((Elm_Widget_Item *)it);
2112    ai = _elm_access_object_get(it->base.access_obj);
2113
2114    _elm_access_text_set(ai, ELM_ACCESS_TYPE, E_("Toolbar Item"));
2115    _elm_access_callback_set(ai, ELM_ACCESS_INFO, _access_info_cb, it);
2116    _elm_access_callback_set(ai, ELM_ACCESS_STATE, _access_state_cb, it);
2117    _elm_access_activate_callback_set(ai, _access_activate_cb, NULL);
2118 }
2119
2120 static Elm_Toolbar_Item *
2121 _item_new(Evas_Object *obj,
2122           const char *icon,
2123           const char *label,
2124           Evas_Smart_Cb func,
2125           const void *data)
2126 {
2127    Evas_Object *icon_obj;
2128    Elm_Toolbar_Item *it;
2129    Evas_Coord mw, mh;
2130
2131    ELM_TOOLBAR_DATA_GET(obj, sd);
2132
2133    icon_obj = elm_icon_add(obj);
2134    elm_icon_order_lookup_set(icon_obj, sd->lookup_order);
2135    if (!icon_obj) return NULL;
2136
2137    it = elm_widget_item_new(obj, Elm_Toolbar_Item);
2138    if (!it)
2139      {
2140         evas_object_del(icon_obj);
2141         return NULL;
2142      }
2143
2144    elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
2145    elm_widget_item_disable_hook_set(it, _item_disable_hook);
2146    elm_widget_item_text_set_hook_set(it, _item_text_set_hook);
2147    elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
2148    elm_widget_item_content_set_hook_set(it, _item_content_set_hook);
2149    elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
2150    elm_widget_item_content_unset_hook_set(it, _item_content_unset_hook);
2151
2152    it->label = eina_stringshare_add(label);
2153    it->prio.visible = 1;
2154    it->prio.priority = 0;
2155    it->func = func;
2156    it->separator = EINA_FALSE;
2157    it->object = NULL;
2158    it->base.data = data;
2159
2160    VIEW(it) = edje_object_add(evas_object_evas_get(obj));
2161    evas_object_data_set(VIEW(it), "item", it);
2162
2163    if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
2164      _access_widget_item_register(it);
2165
2166    if (_item_icon_set(icon_obj, "toolbar/", icon))
2167      {
2168         it->icon = icon_obj;
2169         it->icon_str = eina_stringshare_add(icon);
2170      }
2171    else
2172      {
2173         it->icon = NULL;
2174         it->icon_str = NULL;
2175         evas_object_del(icon_obj);
2176      }
2177
2178    elm_widget_theme_object_set
2179      (obj, VIEW(it), "toolbar", "item", elm_widget_style_get(obj));
2180    edje_object_signal_callback_add
2181      (VIEW(it), "elm,action,click", "elm", _select_cb, it);
2182    edje_object_signal_callback_add
2183      (VIEW(it), "mouse,clicked,*", "*", (Edje_Signal_Cb)_select_filter_cb, it);
2184    edje_object_signal_callback_add
2185      (VIEW(it), "elm,mouse,in", "elm", _mouse_in_cb, it);
2186    edje_object_signal_callback_add
2187      (VIEW(it), "elm,mouse,out", "elm", _mouse_out_cb, it);
2188    evas_object_event_callback_add
2189      (VIEW(it), EVAS_CALLBACK_MOUSE_DOWN, (Evas_Object_Event_Cb)_mouse_down_cb,
2190      it);
2191    evas_object_event_callback_add
2192      (VIEW(it), EVAS_CALLBACK_MOUSE_UP, (Evas_Object_Event_Cb)_mouse_up_cb, it);
2193    elm_widget_sub_object_add(obj, VIEW(it));
2194
2195    if (it->icon)
2196      {
2197         int ms = 0;
2198
2199         ms = ((double)sd->icon_size * elm_config_scale_get());
2200         evas_object_size_hint_min_set(it->icon, ms, ms);
2201         evas_object_size_hint_max_set(it->icon, ms, ms);
2202         edje_object_part_swallow(VIEW(it), "elm.swallow.icon", it->icon);
2203         edje_object_signal_emit(VIEW(it), "elm,state,icon,visible", "elm");
2204         evas_object_show(it->icon);
2205         elm_widget_sub_object_add(obj, it->icon);
2206      }
2207    if (it->label)
2208      {
2209         edje_object_part_text_escaped_set(VIEW(it), "elm.text", it->label);
2210         edje_object_signal_emit(VIEW(it), "elm,state,text,visible", "elm");
2211      }
2212
2213    mw = mh = -1;
2214    if (!it->separator && !it->object)
2215      elm_coords_finger_size_adjust(1, &mw, 1, &mh);
2216    // If the min size is changed by edje signal in edc,
2217    //the below function should be called before the calculation.
2218    edje_object_message_signal_process(VIEW(it));
2219    edje_object_size_min_restricted_calc(VIEW(it), &mw, &mh, mw, mh);
2220    if (!it->separator && !it->object)
2221      elm_coords_finger_size_adjust(1, &mw, 1, &mh);
2222    if (sd->shrink_mode != ELM_TOOLBAR_SHRINK_EXPAND)
2223      {
2224         if (sd->vertical)
2225           {
2226              evas_object_size_hint_weight_set(VIEW(it), EVAS_HINT_EXPAND, -1.0);
2227              evas_object_size_hint_align_set
2228                (VIEW(it), EVAS_HINT_FILL, EVAS_HINT_FILL);
2229           }
2230         else
2231           {
2232              evas_object_size_hint_weight_set(VIEW(it), -1.0, EVAS_HINT_EXPAND);
2233              evas_object_size_hint_align_set
2234                (VIEW(it), EVAS_HINT_FILL, EVAS_HINT_FILL);
2235           }
2236      }
2237    else
2238      {
2239         evas_object_size_hint_weight_set
2240           (VIEW(it), EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
2241         evas_object_size_hint_align_set
2242           (VIEW(it), EVAS_HINT_FILL, EVAS_HINT_FILL);
2243      }
2244
2245    evas_object_size_hint_min_set(VIEW(it), mw, mh);
2246    evas_object_size_hint_max_set(VIEW(it), -1, -1);
2247    evas_object_event_callback_add
2248      (VIEW(it), EVAS_CALLBACK_RESIZE, _item_resize, obj);
2249
2250    if ((!sd->items) && (sd->select_mode == ELM_OBJECT_SELECT_MODE_ALWAYS))
2251      _item_select(it);
2252    return it;
2253 }
2254
2255 static void
2256 _elm_toolbar_item_icon_update(Elm_Toolbar_Item *item)
2257 {
2258    Evas_Coord mw = -1, mh = -1, minw = -1, minh = -1;
2259    Elm_Toolbar_Item_State *it_state;
2260    Evas_Object *old_icon =
2261      edje_object_part_swallow_get(VIEW(item), "elm.swallow.icon");
2262    Eina_List *l;
2263
2264    ELM_TOOLBAR_DATA_GET(WIDGET(item), sd);
2265
2266    elm_widget_sub_object_del(VIEW(item), old_icon);
2267    edje_object_part_swallow(VIEW(item), "elm.swallow.icon", item->icon);
2268    if (item->icon)
2269        edje_object_signal_emit(VIEW(item), "elm,state,icon,visible", "elm");
2270    else
2271        edje_object_signal_emit(VIEW(item), "elm,state,icon,hidden", "elm");
2272    evas_object_hide(old_icon);
2273    elm_coords_finger_size_adjust(1, &mw, 1, &mh);
2274    // If the min size is changed by edje signal in edc,
2275    //the below function should be called before the calculation.
2276    edje_object_message_signal_process(VIEW(item));
2277    edje_object_size_min_restricted_calc(VIEW(item), &mw, &mh, mw, mh);
2278    elm_coords_finger_size_adjust(1, &mw, 1, &mh);
2279    if (sd->shrink_mode != ELM_TOOLBAR_SHRINK_EXPAND)
2280      {
2281         if (sd->vertical)
2282           {
2283              evas_object_size_hint_weight_set
2284                (VIEW(item), EVAS_HINT_EXPAND, -1.0);
2285              evas_object_size_hint_align_set
2286                (VIEW(item), EVAS_HINT_FILL, EVAS_HINT_FILL);
2287           }
2288         else
2289           {
2290              evas_object_size_hint_weight_set
2291                (VIEW(item), -1.0, EVAS_HINT_EXPAND);
2292              evas_object_size_hint_align_set
2293                (VIEW(item), EVAS_HINT_FILL, EVAS_HINT_FILL);
2294           }
2295      }
2296    else
2297      {
2298         evas_object_size_hint_weight_set
2299           (VIEW(item), EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
2300         evas_object_size_hint_align_set
2301           (VIEW(item), EVAS_HINT_FILL, EVAS_HINT_FILL);
2302      }
2303
2304    evas_object_size_hint_min_get(VIEW(item), &minw, &minh);
2305    if ((minw < mw) && (minh < mh))
2306      evas_object_size_hint_min_set(VIEW(item), mw, mh);
2307    else if ((minw < mw) && (minh > mh))
2308      evas_object_size_hint_min_set(VIEW(item), mw, minh);
2309    else if ((minw > mw) && (minh < mh))
2310      evas_object_size_hint_min_set(VIEW(item), minw, mh);
2311
2312    EINA_LIST_FOREACH(item->states, l, it_state)
2313      {
2314         if (it_state->icon == old_icon) return;
2315      }
2316    evas_object_del(old_icon);
2317 }
2318
2319 static void
2320 _elm_toolbar_item_icon_set_cb(void *data,
2321                               Evas_Object *obj,
2322                               const char *emission,
2323                               const char *source)
2324 {
2325    Elm_Toolbar_Item *item = data;
2326
2327    edje_object_part_unswallow(VIEW(item), item->icon);
2328    _elm_toolbar_item_icon_update(item);
2329    edje_object_signal_callback_del
2330      (obj, emission, source, _elm_toolbar_item_icon_set_cb);
2331    edje_object_signal_emit(VIEW(item), "elm,state,icon,reset", "elm");
2332 }
2333
2334 static void
2335 _elm_toolbar_item_icon_obj_set(Evas_Object *obj,
2336                                Elm_Toolbar_Item *item,
2337                                Evas_Object *icon_obj,
2338                                const char *icon_str,
2339                                double icon_size,
2340                                const char *sig)
2341 {
2342    Evas_Object *old_icon;
2343    const char *s;
2344    int ms = 0;
2345
2346    if (icon_str)
2347      eina_stringshare_replace(&item->icon_str, icon_str);
2348    else
2349      {
2350         eina_stringshare_del(item->icon_str);
2351         item->icon_str = NULL;
2352      }
2353    item->icon = icon_obj;
2354    if (icon_obj)
2355      {
2356         ms = (icon_size * elm_config_scale_get());
2357         evas_object_size_hint_min_set(item->icon, ms, ms);
2358         evas_object_size_hint_max_set(item->icon, ms, ms);
2359         evas_object_show(item->icon);
2360         elm_widget_sub_object_add(obj, item->icon);
2361      }
2362    s = edje_object_data_get(VIEW(item), "transition_animation_on");
2363    if ((s) && (atoi(s)))
2364      {
2365         old_icon = edje_object_part_swallow_get
2366             (VIEW(item), "elm.swallow.icon_new");
2367         if (old_icon)
2368           {
2369              elm_widget_sub_object_del(VIEW(item), old_icon);
2370              evas_object_hide(old_icon);
2371           }
2372         edje_object_part_swallow
2373           (VIEW(item), "elm.swallow.icon_new", item->icon);
2374         edje_object_signal_emit(VIEW(item), sig, "elm");
2375         edje_object_signal_callback_add
2376           (VIEW(item), "elm,state,icon_set,done", "elm",
2377           _elm_toolbar_item_icon_set_cb, item);
2378      }
2379    else
2380      _elm_toolbar_item_icon_update(item);
2381
2382    _resize_cb(obj, NULL, NULL, NULL);
2383 }
2384
2385 static void
2386 _elm_toolbar_item_state_cb(void *data __UNUSED__,
2387                            Evas_Object *obj __UNUSED__,
2388                            void *event_info)
2389 {
2390    Elm_Toolbar_Item *it = event_info;
2391    Elm_Toolbar_Item_State *it_state;
2392
2393    it_state = eina_list_data_get(it->current_state);
2394    if (it_state->func)
2395      it_state->func((void *)it_state->data, obj, event_info);
2396 }
2397
2398 static Elm_Toolbar_Item_State *
2399 _item_state_new(const char *label,
2400                 const char *icon_str,
2401                 Evas_Object *icon,
2402                 Evas_Smart_Cb func,
2403                 const void *data)
2404 {
2405    Elm_Toolbar_Item_State *it_state;
2406
2407    it_state = ELM_NEW(Elm_Toolbar_Item_State);
2408    it_state->label = eina_stringshare_add(label);
2409    it_state->icon_str = eina_stringshare_add(icon_str);
2410    it_state->icon = icon;
2411    it_state->func = func;
2412    it_state->data = data;
2413
2414    return it_state;
2415 }
2416
2417 static void
2418 _elm_toolbar_action_left_cb(void *data,
2419                             Evas_Object *o __UNUSED__,
2420                             const char *sig __UNUSED__,
2421                             const char *src __UNUSED__)
2422 {
2423    Evas_Object *obj = data;
2424    Elm_Toolbar_Item *it, *it2;
2425    Eina_Bool done = EINA_FALSE;
2426
2427    ELM_TOOLBAR_DATA_GET(obj, sd);
2428
2429    EINA_INLIST_FOREACH(sd->items, it)
2430      {
2431         if (it->selected)
2432           {
2433              Eina_Bool found = EINA_FALSE;
2434
2435              EINA_INLIST_REVERSE_FOREACH(sd->items, it2)
2436                {
2437                   if (elm_object_item_disabled_get((Elm_Object_Item *)it2))
2438                     continue;
2439                   if (it2 == it)
2440                     {
2441                        found = EINA_TRUE;
2442                        continue;
2443                     }
2444                   if (!found) continue;
2445                   if (it2->separator) continue;
2446                   _item_unselect(it);
2447                   _item_select(it2);
2448                   break;
2449                }
2450              done = EINA_TRUE;
2451              break;
2452           }
2453      }
2454    if (!done)
2455      {
2456         EINA_INLIST_FOREACH(sd->items, it)
2457           {
2458              if (elm_object_item_disabled_get((Elm_Object_Item *)it)) continue;
2459              if (it->separator) continue;
2460              _item_select(it);
2461              break;
2462           }
2463      }
2464 }
2465
2466 static void
2467 _elm_toolbar_action_right_cb(void *data,
2468                              Evas_Object *o __UNUSED__,
2469                              const char *sig __UNUSED__,
2470                              const char *src __UNUSED__)
2471 {
2472    Evas_Object *obj = data;
2473    Elm_Toolbar_Item *it, *it2;
2474    Eina_Bool done = EINA_FALSE;
2475
2476    ELM_TOOLBAR_DATA_GET(obj, sd);
2477
2478    EINA_INLIST_FOREACH(sd->items, it)
2479      {
2480         if (it->selected)
2481           {
2482              Eina_Bool found = EINA_FALSE;
2483
2484              EINA_INLIST_FOREACH(sd->items, it2)
2485                {
2486                   if (elm_object_item_disabled_get((Elm_Object_Item *)it2))
2487                     continue;
2488                   if (it2 == it)
2489                     {
2490                        found = EINA_TRUE;
2491                        continue;
2492                     }
2493                   if (!found) continue;
2494                   if (it2->separator) continue;
2495                   _item_unselect(it);
2496                   _item_select(it2);
2497                   break;
2498                }
2499              done = EINA_TRUE;
2500              break;
2501           }
2502      }
2503    if (!done)
2504      {
2505         EINA_INLIST_REVERSE_FOREACH(sd->items, it)
2506           {
2507              if (elm_object_item_disabled_get((Elm_Object_Item *)it)) continue;
2508              if (it->separator) continue;
2509              _item_select(it);
2510              break;
2511           }
2512      }
2513 }
2514
2515 static void
2516 _elm_toolbar_action_up_cb(void *data,
2517                           Evas_Object *o,
2518                           const char *sig,
2519                           const char *src)
2520 {
2521    _elm_toolbar_action_left_cb(data, o, sig, src);
2522 }
2523
2524 static void
2525 _elm_toolbar_action_down_cb(void *data,
2526                             Evas_Object *o,
2527                             const char *sig,
2528                             const char *src)
2529 {
2530    _elm_toolbar_action_right_cb(data, o, sig, src);
2531 }
2532
2533 static void
2534 _elm_toolbar_smart_add(Evas_Object *obj)
2535 {
2536    EVAS_SMART_DATA_ALLOC(obj, Elm_Toolbar_Smart_Data);
2537
2538    ELM_WIDGET_DATA(priv)->resize_obj =
2539      edje_object_add(evas_object_evas_get(obj));
2540
2541    ELM_WIDGET_CLASS(_elm_toolbar_parent_sc)->base.add(obj);
2542
2543    elm_widget_theme_object_set
2544      (obj, ELM_WIDGET_DATA(priv)->resize_obj, "toolbar", "base",
2545      elm_widget_style_get(obj));
2546
2547    priv->hit_rect = evas_object_rectangle_add(evas_object_evas_get(obj));
2548    evas_object_smart_member_add(priv->hit_rect, obj);
2549    elm_widget_sub_object_add(obj, priv->hit_rect);
2550
2551    /* common scroller hit rectangle setup */
2552    evas_object_color_set(priv->hit_rect, 0, 0, 0, 0);
2553    evas_object_show(priv->hit_rect);
2554    evas_object_repeat_events_set(priv->hit_rect, EINA_TRUE);
2555
2556    elm_widget_can_focus_set(obj, EINA_TRUE);
2557
2558    priv->s_iface = evas_object_smart_interface_get
2559        (obj, ELM_SCROLLABLE_IFACE_NAME);
2560
2561    priv->s_iface->objects_set
2562      (obj, ELM_WIDGET_DATA(priv)->resize_obj, priv->hit_rect);
2563
2564    priv->more_item = NULL;
2565    priv->selected_item = NULL;
2566    priv->standard_priority = -99999;
2567
2568    priv->s_iface->bounce_allow_set
2569      (obj, _elm_config->thumbscroll_bounce_enable, EINA_FALSE);
2570    priv->s_iface->policy_set
2571      (obj, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
2572    priv->s_iface->scroll_cb_set(obj, _scroll_cb);
2573    priv->s_iface->animate_start_cb_set(obj, _scroll_anim_start_cb);
2574    priv->s_iface->animate_stop_cb_set(obj, _scroll_anim_stop_cb);
2575    priv->s_iface->drag_start_cb_set(obj, _scroll_drag_start_cb);
2576    priv->s_iface->drag_stop_cb_set(obj, _scroll_drag_stop_cb);
2577
2578    edje_object_signal_callback_add
2579      (ELM_WIDGET_DATA(priv)->resize_obj, "elm,action,left", "elm",
2580      _elm_toolbar_action_left_cb, obj);
2581    edje_object_signal_callback_add
2582      (ELM_WIDGET_DATA(priv)->resize_obj, "elm,action,right", "elm",
2583      _elm_toolbar_action_right_cb, obj);
2584    edje_object_signal_callback_add
2585      (ELM_WIDGET_DATA(priv)->resize_obj, "elm,action,up", "elm",
2586      _elm_toolbar_action_up_cb, obj);
2587    edje_object_signal_callback_add
2588      (ELM_WIDGET_DATA(priv)->resize_obj, "elm,action,down", "elm",
2589      _elm_toolbar_action_down_cb, obj);
2590
2591    priv->shrink_mode = ELM_TOOLBAR_SHRINK_NONE;
2592    priv->priv_icon_size = 0; // unset
2593    priv->theme_icon_size = _elm_toolbar_icon_size_get(priv);
2594    if (priv->priv_icon_size) priv->icon_size = priv->priv_icon_size;
2595    else priv->icon_size = priv->theme_icon_size;
2596
2597    priv->homogeneous = EINA_TRUE;
2598    priv->align = 0.5;
2599
2600    priv->bx = evas_object_box_add(evas_object_evas_get(obj));
2601    evas_object_size_hint_align_set(priv->bx, priv->align, 0.5);
2602    evas_object_box_layout_set(priv->bx, _layout, obj, NULL);
2603    elm_widget_sub_object_add(obj, priv->bx);
2604    priv->s_iface->content_set(obj, priv->bx);
2605    evas_object_show(priv->bx);
2606
2607    priv->more = elm_layout_add(obj);
2608    elm_layout_theme_set(priv->more, "toolbar", "more", "default");
2609    elm_widget_sub_object_add(obj, priv->more);
2610    evas_object_show(priv->more);
2611
2612    priv->bx_more = evas_object_box_add(evas_object_evas_get(obj));
2613    evas_object_size_hint_align_set(priv->bx_more, priv->align, 0.5);
2614    evas_object_box_layout_set(priv->bx_more, _layout, obj, NULL);
2615    elm_widget_sub_object_add(obj, priv->bx_more);
2616    elm_layout_content_set
2617      (priv->more, "elm.swallow.content", priv->bx_more);
2618    evas_object_show(priv->bx_more);
2619
2620    priv->bx_more2 = evas_object_box_add(evas_object_evas_get(obj));
2621    evas_object_size_hint_align_set(priv->bx_more2, priv->align, 0.5);
2622    evas_object_box_layout_set(priv->bx_more2, _layout, obj, NULL);
2623    elm_widget_sub_object_add(obj, priv->bx_more2);
2624    elm_layout_content_set
2625      (priv->more, "elm.swallow.content2", priv->bx_more2);
2626    evas_object_show(priv->bx_more2);
2627
2628    elm_toolbar_shrink_mode_set(obj, _elm_config->toolbar_shrink_mode);
2629    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize_cb, obj);
2630    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _move_cb, obj);
2631    // FIXME: There are applications which do not use elm_win as top widget.
2632    // This is workaround! Those could not use focus!
2633    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN, _highlight_off_cb, obj);
2634    evas_object_event_callback_add
2635      (priv->bx, EVAS_CALLBACK_RESIZE, _resize_cb, obj);
2636    elm_toolbar_icon_order_lookup_set(obj, ELM_ICON_LOOKUP_THEME_FDO);
2637
2638    _sizing_eval(obj);
2639 }
2640
2641 static void
2642 _elm_toolbar_smart_del(Evas_Object *obj)
2643 {
2644    Elm_Toolbar_Item *it, *next;
2645
2646    ELM_TOOLBAR_DATA_GET(obj, sd);
2647
2648    sd->on_deletion = EINA_TRUE;
2649
2650    if (sd->resize_job)
2651      ecore_job_del(sd->resize_job);
2652
2653    sd->resize_job = NULL;
2654
2655    it = ELM_TOOLBAR_ITEM_FROM_INLIST(sd->items);
2656    while (it)
2657      {
2658         next = ELM_TOOLBAR_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
2659         elm_widget_item_del(it);
2660         it = next;
2661      }
2662    if (sd->more_item)
2663      {
2664         elm_widget_item_del(sd->more_item);
2665         sd->more_item = NULL;
2666      }
2667    if (sd->long_timer)
2668      {
2669         ecore_timer_del(sd->long_timer);
2670         sd->long_timer = NULL;
2671      }
2672
2673    ELM_WIDGET_CLASS(_elm_toolbar_parent_sc)->base.del(obj);
2674 }
2675
2676 static void
2677 _elm_toolbar_smart_move(Evas_Object *obj,
2678                         Evas_Coord x,
2679                         Evas_Coord y)
2680 {
2681    ELM_TOOLBAR_DATA_GET(obj, sd);
2682
2683    ELM_WIDGET_CLASS(_elm_toolbar_parent_sc)->base.move(obj, x, y);
2684
2685    evas_object_move(sd->hit_rect, x, y);
2686 }
2687
2688 static void
2689 _elm_toolbar_smart_resize(Evas_Object *obj,
2690                           Evas_Coord w,
2691                           Evas_Coord h)
2692 {
2693    ELM_TOOLBAR_DATA_GET(obj, sd);
2694
2695    ELM_WIDGET_CLASS(_elm_toolbar_parent_sc)->base.resize(obj, w, h);
2696
2697    evas_object_resize(sd->hit_rect, w, h);
2698 }
2699
2700 static void
2701 _elm_toolbar_smart_member_add(Evas_Object *obj,
2702                               Evas_Object *member)
2703 {
2704    ELM_TOOLBAR_DATA_GET(obj, sd);
2705
2706    ELM_WIDGET_CLASS(_elm_toolbar_parent_sc)->base.member_add(obj, member);
2707
2708    if (sd->hit_rect)
2709      evas_object_raise(sd->hit_rect);
2710 }
2711
2712 static Eina_List *
2713 _access_item_find_append(const Evas_Object *obj,
2714                          Evas_Object *bx,
2715                          Eina_List *items)
2716 {
2717    Elm_Toolbar_Item *it;
2718    Eina_List *list;
2719
2720    ELM_TOOLBAR_DATA_GET(obj, sd);
2721
2722    list = evas_object_box_children_get(bx);
2723    if (!list) return items;
2724
2725    EINA_INLIST_FOREACH (sd->items, it)
2726      {
2727         if (it->separator) continue;
2728         if (eina_list_data_find(list, it->base.view))
2729           items = eina_list_append(items, it->base.access_obj);
2730      }
2731
2732    return items;
2733 }
2734
2735 static Eina_Bool
2736 _elm_toolbar_smart_focus_next(const Evas_Object *obj,
2737                               Elm_Focus_Direction dir,
2738                               Evas_Object **next)
2739 {
2740    Eina_List *items = NULL;
2741
2742    ELM_TOOLBAR_DATA_GET(obj, sd);
2743
2744    if (sd->more_item && sd->more_item->selected)
2745      {
2746         items = _access_item_find_append(obj, sd->bx_more, items);
2747         items = _access_item_find_append(obj, sd->bx_more2, items);
2748         items = eina_list_append(items, sd->more_item->base.access_obj);
2749      }
2750    else
2751      {
2752         items = _access_item_find_append(obj, sd->bx, items);
2753         if (sd->more_item &&
2754             eina_list_data_find(evas_object_box_children_get(sd->bx),
2755                                             sd->more_item->base.view))
2756           items = eina_list_append(items, sd->more_item->base.access_obj);
2757      }
2758
2759    return elm_widget_focus_list_next_get
2760             (obj, items, eina_list_data_get, dir, next);
2761 }
2762
2763 static void
2764 _access_obj_process(Elm_Toolbar_Smart_Data * sd, Eina_Bool is_access)
2765 {
2766    Elm_Toolbar_Item *it;
2767
2768    EINA_INLIST_FOREACH (sd->items, it)
2769      {
2770         if (is_access) _access_widget_item_register(it);
2771         else _elm_access_widget_item_unregister((Elm_Widget_Item *)it);
2772      }
2773 }
2774
2775 static void
2776 _elm_toolbar_smart_access(Evas_Object *obj, Eina_Bool is_access)
2777 {
2778    ELM_TOOLBAR_CHECK(obj);
2779    ELM_TOOLBAR_DATA_GET(obj, sd);
2780
2781    if (is_access)
2782      ELM_WIDGET_CLASS(ELM_WIDGET_DATA(sd)->api)->focus_next =
2783        _elm_toolbar_smart_focus_next;
2784    else
2785      ELM_WIDGET_CLASS(ELM_WIDGET_DATA(sd)->api)->focus_next = NULL;
2786    _access_obj_process(sd, is_access);
2787
2788    evas_object_smart_callback_call(obj, SIG_ACCESS_CHANGED, NULL);
2789 }
2790
2791 static void
2792 _elm_toolbar_smart_set_user(Elm_Toolbar_Smart_Class *sc)
2793 {
2794    ELM_WIDGET_CLASS(sc)->base.add = _elm_toolbar_smart_add;
2795    ELM_WIDGET_CLASS(sc)->base.del = _elm_toolbar_smart_del;
2796    ELM_WIDGET_CLASS(sc)->base.move = _elm_toolbar_smart_move;
2797    ELM_WIDGET_CLASS(sc)->base.resize = _elm_toolbar_smart_resize;
2798    ELM_WIDGET_CLASS(sc)->base.member_add = _elm_toolbar_smart_member_add;
2799
2800    ELM_WIDGET_CLASS(sc)->on_focus = _elm_toolbar_smart_on_focus;
2801    ELM_WIDGET_CLASS(sc)->event = _elm_toolbar_smart_event;
2802    ELM_WIDGET_CLASS(sc)->theme = _elm_toolbar_smart_theme;
2803    ELM_WIDGET_CLASS(sc)->translate = _elm_toolbar_smart_translate;
2804
2805    if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
2806      ELM_WIDGET_CLASS(sc)->focus_next = _elm_toolbar_smart_focus_next;
2807
2808    ELM_WIDGET_CLASS(sc)->access = _elm_toolbar_smart_access;
2809 }
2810
2811 EAPI const Elm_Toolbar_Smart_Class *
2812 elm_toolbar_smart_class_get(void)
2813 {
2814    static Elm_Toolbar_Smart_Class _sc =
2815      ELM_TOOLBAR_SMART_CLASS_INIT_NAME_VERSION(ELM_TOOLBAR_SMART_NAME);
2816    static const Elm_Toolbar_Smart_Class *class = NULL;
2817    Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
2818
2819    if (class)
2820      return class;
2821
2822    _elm_toolbar_smart_set(&_sc);
2823    esc->callbacks = _smart_callbacks;
2824    class = &_sc;
2825
2826    return class;
2827 }
2828
2829 EAPI Evas_Object *
2830 elm_toolbar_add(Evas_Object *parent)
2831 {
2832    Evas_Object *obj;
2833
2834    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
2835
2836    obj = elm_widget_add(_elm_toolbar_smart_class_new(), parent);
2837    if (!obj) return NULL;
2838
2839    if (!elm_widget_sub_object_add(parent, obj))
2840      ERR("could not add %p as sub object of %p", obj, parent);
2841
2842    return obj;
2843 }
2844
2845 EAPI void
2846 elm_toolbar_icon_size_set(Evas_Object *obj,
2847                           int icon_size)
2848 {
2849    ELM_TOOLBAR_CHECK(obj);
2850    ELM_TOOLBAR_DATA_GET(obj, sd);
2851
2852    if (sd->priv_icon_size == icon_size) return;
2853    sd->priv_icon_size = icon_size;
2854
2855    if (sd->priv_icon_size) sd->icon_size = sd->priv_icon_size;
2856    else sd->icon_size = sd->theme_icon_size;
2857
2858    _elm_toolbar_smart_theme(obj);
2859 }
2860
2861 EAPI int
2862 elm_toolbar_icon_size_get(const Evas_Object *obj)
2863 {
2864    ELM_TOOLBAR_CHECK(obj) 0;
2865    ELM_TOOLBAR_DATA_GET(obj, sd);
2866
2867    return sd->priv_icon_size;
2868 }
2869
2870 EAPI Elm_Object_Item *
2871 elm_toolbar_item_append(Evas_Object *obj,
2872                         const char *icon,
2873                         const char *label,
2874                         Evas_Smart_Cb func,
2875                         const void *data)
2876 {
2877    Elm_Toolbar_Item *it;
2878    double scale;
2879
2880    ELM_TOOLBAR_CHECK(obj) NULL;
2881    ELM_TOOLBAR_DATA_GET(obj, sd);
2882
2883    it = _item_new(obj, icon, label, func, data);
2884    if (!it) return NULL;
2885    scale = (elm_widget_scale_get(obj) * elm_config_scale_get());
2886
2887    sd->items = eina_inlist_append(sd->items, EINA_INLIST_GET(it));
2888    evas_object_box_append(sd->bx, VIEW(it));
2889    evas_object_show(VIEW(it));
2890
2891    _item_theme_hook(obj, it, scale, sd->icon_size);
2892    _sizing_eval(obj);
2893    sd->item_count++;
2894
2895    return (Elm_Object_Item *)it;
2896 }
2897
2898 EAPI Elm_Object_Item *
2899 elm_toolbar_item_prepend(Evas_Object *obj,
2900                          const char *icon,
2901                          const char *label,
2902                          Evas_Smart_Cb func,
2903                          const void *data)
2904 {
2905    Elm_Toolbar_Item *it;
2906    double scale;
2907
2908    ELM_TOOLBAR_CHECK(obj) NULL;
2909    ELM_TOOLBAR_DATA_GET(obj, sd);
2910
2911    it = _item_new(obj, icon, label, func, data);
2912    if (!it) return NULL;
2913    scale = (elm_widget_scale_get(obj) * elm_config_scale_get());
2914
2915    sd->items = eina_inlist_prepend(sd->items, EINA_INLIST_GET(it));
2916    evas_object_box_prepend(sd->bx, VIEW(it));
2917    evas_object_show(VIEW(it));
2918    _item_theme_hook(obj, it, scale, sd->icon_size);
2919    _sizing_eval(obj);
2920    sd->item_count++;
2921
2922    return (Elm_Object_Item *)it;
2923 }
2924
2925 EAPI Elm_Object_Item *
2926 elm_toolbar_item_insert_before(Evas_Object *obj,
2927                                Elm_Object_Item *before,
2928                                const char *icon,
2929                                const char *label,
2930                                Evas_Smart_Cb func,
2931                                const void *data)
2932 {
2933    Elm_Toolbar_Item *it, *_before;
2934    double scale;
2935
2936    ELM_TOOLBAR_CHECK(obj) NULL;
2937    ELM_TOOLBAR_ITEM_CHECK_OR_RETURN(before, NULL);
2938    ELM_TOOLBAR_DATA_GET(obj, sd);
2939
2940    _before = (Elm_Toolbar_Item *)before;
2941    it = _item_new(obj, icon, label, func, data);
2942    if (!it) return NULL;
2943    scale = (elm_widget_scale_get(obj) * elm_config_scale_get());
2944
2945    sd->items = eina_inlist_prepend_relative
2946        (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(_before));
2947    evas_object_box_insert_before(sd->bx, VIEW(it), VIEW(_before));
2948    evas_object_show(VIEW(it));
2949    _item_theme_hook(obj, it, scale, sd->icon_size);
2950    _sizing_eval(obj);
2951    sd->item_count++;
2952
2953    return (Elm_Object_Item *)it;
2954 }
2955
2956 EAPI Elm_Object_Item *
2957 elm_toolbar_item_insert_after(Evas_Object *obj,
2958                               Elm_Object_Item *after,
2959                               const char *icon,
2960                               const char *label,
2961                               Evas_Smart_Cb func,
2962                               const void *data)
2963 {
2964    Elm_Toolbar_Item *it, *_after;
2965    double scale;
2966
2967    ELM_TOOLBAR_CHECK(obj) NULL;
2968    ELM_TOOLBAR_ITEM_CHECK_OR_RETURN(after, NULL);
2969
2970    ELM_TOOLBAR_DATA_GET(obj, sd);
2971    _after = (Elm_Toolbar_Item *)after;
2972    it = _item_new(obj, icon, label, func, data);
2973    if (!it) return NULL;
2974    scale = (elm_widget_scale_get(obj) * elm_config_scale_get());
2975
2976    sd->items = eina_inlist_append_relative
2977        (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(_after));
2978    evas_object_box_insert_after(sd->bx, VIEW(it), VIEW(_after));
2979    evas_object_show(VIEW(it));
2980    _item_theme_hook(obj, it, scale, sd->icon_size);
2981    _sizing_eval(obj);
2982    sd->item_count++;
2983
2984    return (Elm_Object_Item *)it;
2985 }
2986
2987 EAPI Elm_Object_Item *
2988 elm_toolbar_first_item_get(const Evas_Object *obj)
2989 {
2990    ELM_TOOLBAR_CHECK(obj) NULL;
2991    ELM_TOOLBAR_DATA_GET(obj, sd);
2992
2993    if (!sd->items) return NULL;
2994    return (Elm_Object_Item *)ELM_TOOLBAR_ITEM_FROM_INLIST(sd->items);
2995 }
2996
2997 EAPI Elm_Object_Item *
2998 elm_toolbar_last_item_get(const Evas_Object *obj)
2999 {
3000    ELM_TOOLBAR_CHECK(obj) NULL;
3001    ELM_TOOLBAR_DATA_GET(obj, sd);
3002
3003    if (!sd->items) return NULL;
3004
3005    return (Elm_Object_Item *)ELM_TOOLBAR_ITEM_FROM_INLIST(sd->items->last);
3006 }
3007
3008 EAPI Elm_Object_Item *
3009 elm_toolbar_item_next_get(const Elm_Object_Item *it)
3010 {
3011    ELM_TOOLBAR_ITEM_CHECK_OR_RETURN(it, NULL);
3012
3013    return (Elm_Object_Item *)ELM_TOOLBAR_ITEM_FROM_INLIST(
3014             EINA_INLIST_GET(((Elm_Toolbar_Item *)it))->next);
3015 }
3016
3017 EAPI Elm_Object_Item *
3018 elm_toolbar_item_prev_get(const Elm_Object_Item *it)
3019 {
3020    ELM_TOOLBAR_ITEM_CHECK_OR_RETURN(it, NULL);
3021
3022    return (Elm_Object_Item *)ELM_TOOLBAR_ITEM_FROM_INLIST(
3023             EINA_INLIST_GET(((Elm_Toolbar_Item *)it))->prev);
3024 }
3025
3026 EAPI void
3027 elm_toolbar_item_priority_set(Elm_Object_Item *it,
3028                               int priority)
3029 {
3030    Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
3031
3032    ELM_TOOLBAR_ITEM_CHECK_OR_RETURN(it);
3033
3034    if (item->prio.priority == priority) return;
3035    item->prio.priority = priority;
3036    _resize_cb(WIDGET(item), NULL, NULL, NULL);
3037 }
3038
3039 EAPI int
3040 elm_toolbar_item_priority_get(const Elm_Object_Item *it)
3041 {
3042    ELM_TOOLBAR_ITEM_CHECK_OR_RETURN(it, 0);
3043
3044    return ((Elm_Toolbar_Item *)it)->prio.priority;
3045 }
3046
3047 EAPI Elm_Object_Item *
3048 elm_toolbar_item_find_by_label(const Evas_Object *obj,
3049                                const char *label)
3050 {
3051    Elm_Toolbar_Item *it;
3052
3053    ELM_TOOLBAR_CHECK(obj) NULL;
3054    ELM_TOOLBAR_DATA_GET(obj, sd);
3055
3056    EINA_INLIST_FOREACH(sd->items, it)
3057      {
3058         if (!strcmp(it->label, label))
3059           return (Elm_Object_Item *)it;
3060      }
3061
3062    return NULL;
3063 }
3064
3065 EAPI void
3066 elm_toolbar_item_selected_set(Elm_Object_Item *it,
3067                               Eina_Bool selected)
3068 {
3069    Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
3070
3071    ELM_TOOLBAR_ITEM_CHECK_OR_RETURN(it);
3072
3073    if (item->selected == selected) return;
3074    if (selected) _item_select(item);
3075    else _item_unselect(item);
3076 }
3077
3078 EAPI Eina_Bool
3079 elm_toolbar_item_selected_get(const Elm_Object_Item *it)
3080 {
3081    ELM_TOOLBAR_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
3082
3083    return ((Elm_Toolbar_Item *)it)->selected;
3084 }
3085
3086 EAPI Elm_Object_Item *
3087 elm_toolbar_selected_item_get(const Evas_Object *obj)
3088 {
3089    ELM_TOOLBAR_CHECK(obj) NULL;
3090    ELM_TOOLBAR_DATA_GET(obj, sd);
3091
3092    return (Elm_Object_Item *)sd->selected_item;
3093 }
3094
3095 EAPI Elm_Object_Item *
3096 elm_toolbar_more_item_get(const Evas_Object *obj)
3097 {
3098    ELM_TOOLBAR_CHECK(obj) NULL;
3099    ELM_TOOLBAR_DATA_GET(obj, sd);
3100
3101    return (Elm_Object_Item *)sd->more_item;
3102 }
3103
3104 EAPI void
3105 elm_toolbar_item_icon_set(Elm_Object_Item *it,
3106                           const char *icon)
3107 {
3108    Evas_Object *obj;
3109    Evas_Object *icon_obj;
3110    Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
3111
3112    ELM_TOOLBAR_ITEM_CHECK_OR_RETURN(it);
3113
3114    obj = WIDGET(item);
3115    ELM_TOOLBAR_DATA_GET(obj, sd);
3116    if ((icon) && (item->icon_str) && (!strcmp(icon, item->icon_str))) return;
3117
3118    icon_obj = elm_icon_add(obj);
3119    if (!icon_obj) return;
3120    if (_item_icon_set(icon_obj, "toolbar/", icon))
3121      _elm_toolbar_item_icon_obj_set
3122        (obj, item, icon_obj, icon, sd->icon_size, "elm,state,icon_set");
3123    else
3124      {
3125         _elm_toolbar_item_icon_obj_set
3126           (obj, item, NULL, NULL, 0, "elm,state,icon_set");
3127         evas_object_del(icon_obj);
3128      }
3129 }
3130
3131 EAPI const char *
3132 elm_toolbar_item_icon_get(const Elm_Object_Item *it)
3133 {
3134    ELM_TOOLBAR_ITEM_CHECK_OR_RETURN(it, NULL);
3135
3136    return ((Elm_Toolbar_Item *)it)->icon_str;
3137 }
3138
3139 EAPI Evas_Object *
3140 elm_toolbar_item_object_get(const Elm_Object_Item *it)
3141 {
3142    Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
3143
3144    ELM_TOOLBAR_ITEM_CHECK_OR_RETURN(it, NULL);
3145
3146    return VIEW(item);
3147 }
3148
3149 EAPI Evas_Object *
3150 elm_toolbar_item_icon_object_get(Elm_Object_Item *it)
3151 {
3152    ELM_TOOLBAR_ITEM_CHECK_OR_RETURN(it, NULL);
3153
3154    return ((Elm_Toolbar_Item *)it)->icon;
3155 }
3156
3157 EAPI Eina_Bool
3158 elm_toolbar_item_icon_memfile_set(Elm_Object_Item *it,
3159                                   const void *img,
3160                                   size_t size,
3161                                   const char *format,
3162                                   const char *key)
3163 {
3164    Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
3165    Evas_Object *icon_obj;
3166    Evas_Object *obj;
3167    Eina_Bool ret;
3168
3169    ELM_TOOLBAR_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
3170
3171    obj = WIDGET(item);
3172    ELM_TOOLBAR_DATA_GET(obj, sd);
3173
3174    if (img && size)
3175      {
3176         icon_obj = elm_icon_add(obj);
3177         evas_object_repeat_events_set(icon_obj, EINA_TRUE);
3178         ret = elm_image_memfile_set(icon_obj, img, size, format, key);
3179         if (!ret)
3180           {
3181              evas_object_del(icon_obj);
3182              return EINA_FALSE;
3183           }
3184         _elm_toolbar_item_icon_obj_set
3185           (obj, item, icon_obj, NULL, sd->icon_size, "elm,state,icon_set");
3186      }
3187    else
3188      _elm_toolbar_item_icon_obj_set
3189        (obj, item, NULL, NULL, 0, "elm,state,icon_set");
3190    return EINA_TRUE;
3191 }
3192
3193 EAPI Eina_Bool
3194 elm_toolbar_item_icon_file_set(Elm_Object_Item *it,
3195                                const char *file,
3196                                const char *key)
3197 {
3198    Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
3199    Evas_Object *icon_obj;
3200    Evas_Object *obj;
3201    Eina_Bool ret;
3202
3203    ELM_TOOLBAR_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
3204
3205    obj = WIDGET(item);
3206    ELM_TOOLBAR_DATA_GET(obj, sd);
3207
3208    if (file)
3209      {
3210         icon_obj = elm_icon_add(obj);
3211         evas_object_repeat_events_set(icon_obj, EINA_TRUE);
3212         ret = elm_image_file_set(icon_obj, file, key);
3213         if (!ret)
3214           {
3215              evas_object_del(icon_obj);
3216              return EINA_FALSE;
3217           }
3218         _elm_toolbar_item_icon_obj_set
3219           (obj, item, icon_obj, NULL, sd->icon_size, "elm,state,icon_set");
3220      }
3221    else
3222      _elm_toolbar_item_icon_obj_set
3223        (obj, item, NULL, NULL, 0, "elm,state,icon_set");
3224    return EINA_TRUE;
3225 }
3226
3227 EAPI void
3228 elm_toolbar_item_separator_set(Elm_Object_Item *it,
3229                                Eina_Bool separator)
3230 {
3231    Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
3232    Evas_Object *obj = WIDGET(item);
3233    double scale;
3234
3235    ELM_TOOLBAR_ITEM_CHECK_OR_RETURN(it);
3236    ELM_TOOLBAR_DATA_GET(obj, sd);
3237
3238    if (item->separator == separator) return;
3239    item->separator = separator;
3240    scale = (elm_widget_scale_get(obj) * elm_config_scale_get());
3241    _item_theme_hook(obj, item, scale, sd->icon_size);
3242    evas_object_size_hint_min_set(VIEW(item), -1, -1);
3243    if (separator) sd->separator_count++;
3244    else sd->separator_count--;
3245 }
3246
3247 EAPI Eina_Bool
3248 elm_toolbar_item_separator_get(const Elm_Object_Item *it)
3249 {
3250    ELM_TOOLBAR_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
3251
3252    return ((Elm_Toolbar_Item *)it)->separator;
3253 }
3254
3255 EAPI void
3256 elm_toolbar_shrink_mode_set(Evas_Object *obj,
3257                             Elm_Toolbar_Shrink_Mode shrink_mode)
3258 {
3259    Eina_Bool bounce;
3260
3261    ELM_TOOLBAR_CHECK(obj);
3262    ELM_TOOLBAR_DATA_GET(obj, sd);
3263
3264    if (sd->shrink_mode == shrink_mode) return;
3265    sd->shrink_mode = shrink_mode;
3266    bounce = (_elm_config->thumbscroll_bounce_enable) &&
3267      (shrink_mode == ELM_TOOLBAR_SHRINK_SCROLL);
3268    sd->s_iface->bounce_allow_set(obj, bounce, EINA_FALSE);
3269
3270    if (sd->more_item)
3271      {
3272         elm_widget_item_del(sd->more_item);
3273         sd->more_item = NULL;
3274      }
3275
3276    if (shrink_mode == ELM_TOOLBAR_SHRINK_MENU)
3277      {
3278         elm_toolbar_homogeneous_set(obj, EINA_FALSE);
3279         sd->s_iface->policy_set
3280           (obj, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
3281         sd->more_item = _item_new(obj, "more_menu", "More", NULL, NULL);
3282      }
3283    else if (shrink_mode == ELM_TOOLBAR_SHRINK_HIDE)
3284      {
3285         elm_toolbar_homogeneous_set(obj, EINA_FALSE);
3286         sd->s_iface->policy_set
3287           (obj, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF);
3288      }
3289    else if (shrink_mode == ELM_TOOLBAR_SHRINK_EXPAND)
3290      {
3291         elm_toolbar_homogeneous_set(obj, EINA_FALSE);
3292         sd->s_iface->policy_set
3293           (obj, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
3294         sd->more_item = _item_new(obj, "more_menu", "More", NULL, NULL);
3295      }
3296    else
3297      sd->s_iface->policy_set
3298        (obj, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
3299
3300    _sizing_eval(obj);
3301 }
3302
3303 EAPI Elm_Toolbar_Shrink_Mode
3304 elm_toolbar_shrink_mode_get(const Evas_Object *obj)
3305 {
3306    ELM_TOOLBAR_CHECK(obj) ELM_TOOLBAR_SHRINK_NONE;
3307    ELM_TOOLBAR_DATA_GET(obj, sd);
3308
3309    return sd->shrink_mode;
3310 }
3311
3312 EAPI void
3313 elm_toolbar_transverse_expanded_set(Evas_Object *obj, Eina_Bool transverse_expanded)
3314 {
3315    ELM_TOOLBAR_CHECK(obj);
3316    ELM_TOOLBAR_DATA_GET(obj, sd);
3317
3318    if (sd->transverse_expanded == transverse_expanded) return;
3319    sd->transverse_expanded = transverse_expanded;
3320
3321    _sizing_eval(obj);
3322 }
3323
3324 EAPI Eina_Bool
3325 elm_toolbar_transverse_expanded_get(const Evas_Object *obj)
3326 {
3327    ELM_TOOLBAR_CHECK(obj) EINA_FALSE;
3328    ELM_TOOLBAR_DATA_GET(obj, sd);
3329
3330    return sd->transverse_expanded;
3331 }
3332
3333 EAPI void
3334 elm_toolbar_homogeneous_set(Evas_Object *obj,
3335                             Eina_Bool homogeneous)
3336 {
3337    ELM_TOOLBAR_CHECK(obj);
3338    ELM_TOOLBAR_DATA_GET(obj, sd);
3339
3340    homogeneous = !!homogeneous;
3341    if (homogeneous == sd->homogeneous) return;
3342    sd->homogeneous = homogeneous;
3343    if (homogeneous) elm_toolbar_shrink_mode_set(obj, ELM_TOOLBAR_SHRINK_NONE);
3344    evas_object_smart_calculate(sd->bx);
3345 }
3346
3347 EAPI Eina_Bool
3348 elm_toolbar_homogeneous_get(const Evas_Object *obj)
3349 {
3350    ELM_TOOLBAR_CHECK(obj) EINA_FALSE;
3351    ELM_TOOLBAR_DATA_GET(obj, sd);
3352
3353    return sd->homogeneous;
3354 }
3355
3356 EAPI void
3357 elm_toolbar_menu_parent_set(Evas_Object *obj,
3358                             Evas_Object *parent)
3359 {
3360    Elm_Toolbar_Item *it;
3361
3362    ELM_TOOLBAR_CHECK(obj);
3363    ELM_TOOLBAR_DATA_GET(obj, sd);
3364    EINA_SAFETY_ON_NULL_RETURN(parent);
3365
3366    sd->menu_parent = parent;
3367    EINA_INLIST_FOREACH(sd->items, it)
3368      {
3369         if (it->o_menu)
3370           elm_menu_parent_set(it->o_menu, sd->menu_parent);
3371      }
3372    if ((sd->more_item) && (sd->more_item->o_menu))
3373      elm_menu_parent_set(sd->more_item->o_menu, sd->menu_parent);
3374 }
3375
3376 EAPI Evas_Object *
3377 elm_toolbar_menu_parent_get(const Evas_Object *obj)
3378 {
3379    ELM_TOOLBAR_CHECK(obj) NULL;
3380    ELM_TOOLBAR_DATA_GET(obj, sd);
3381
3382    return sd->menu_parent;
3383 }
3384
3385 EAPI void
3386 elm_toolbar_align_set(Evas_Object *obj,
3387                       double align)
3388 {
3389    ELM_TOOLBAR_CHECK(obj);
3390    ELM_TOOLBAR_DATA_GET(obj, sd);
3391
3392    if (sd->vertical)
3393      {
3394         if (sd->align != align)
3395           evas_object_size_hint_align_set(sd->bx, 0.5, align);
3396      }
3397    else
3398      {
3399         if (sd->align != align)
3400           evas_object_size_hint_align_set(sd->bx, align, 0.5);
3401      }
3402    sd->align = align;
3403 }
3404
3405 EAPI double
3406 elm_toolbar_align_get(const Evas_Object *obj)
3407 {
3408    ELM_TOOLBAR_CHECK(obj) 0.0;
3409    ELM_TOOLBAR_DATA_GET(obj, sd);
3410
3411    return sd->align;
3412 }
3413
3414 EAPI void
3415 elm_toolbar_item_menu_set(Elm_Object_Item *it,
3416                           Eina_Bool menu)
3417 {
3418    Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
3419
3420    ELM_TOOLBAR_ITEM_CHECK_OR_RETURN(it);
3421    ELM_TOOLBAR_DATA_GET(WIDGET(item), sd);
3422
3423    if (item->menu == menu) return;
3424    if (menu) _item_menu_create(sd, item);
3425    else _item_menu_destroy(item);
3426 }
3427
3428 EAPI Evas_Object *
3429 elm_toolbar_item_menu_get(const Elm_Object_Item *it)
3430 {
3431    Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
3432
3433    ELM_TOOLBAR_ITEM_CHECK_OR_RETURN(it, NULL);
3434
3435    if (!item->menu) return NULL;
3436    return item->o_menu;
3437 }
3438
3439 EAPI Elm_Toolbar_Item_State *
3440 elm_toolbar_item_state_add(Elm_Object_Item *it,
3441                            const char *icon,
3442                            const char *label,
3443                            Evas_Smart_Cb func,
3444                            const void *data)
3445 {
3446    Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
3447    Elm_Toolbar_Item_State *it_state;
3448    Evas_Object *icon_obj;
3449    Evas_Object *obj;
3450
3451    ELM_TOOLBAR_ITEM_CHECK_OR_RETURN(it, NULL);
3452
3453    obj = WIDGET(item);
3454    ELM_TOOLBAR_DATA_GET(WIDGET(item), sd);
3455
3456    if (!item->states)
3457      {
3458         it_state = _item_state_new
3459             (item->label, item->icon_str, item->icon, item->func,
3460             item->base.data);
3461         item->states = eina_list_append(item->states, it_state);
3462         item->current_state = item->states;
3463      }
3464
3465    icon_obj = elm_icon_add(obj);
3466    elm_icon_order_lookup_set(icon_obj, sd->lookup_order);
3467    if (!icon_obj) goto error_state_add;
3468
3469    if (!_item_icon_set(icon_obj, "toolbar/", icon))
3470      {
3471         evas_object_del(icon_obj);
3472         icon_obj = NULL;
3473         icon = NULL;
3474      }
3475
3476    it_state = _item_state_new(label, icon, icon_obj, func, data);
3477    item->states = eina_list_append(item->states, it_state);
3478    item->func = _elm_toolbar_item_state_cb;
3479    item->base.data = NULL;
3480
3481    return it_state;
3482
3483 error_state_add:
3484    if (item->states && !eina_list_next(item->states))
3485      {
3486         eina_stringshare_del(item->label);
3487         eina_stringshare_del(item->icon_str);
3488         free(eina_list_data_get(item->states));
3489         eina_list_free(item->states);
3490         item->states = NULL;
3491      }
3492    return NULL;
3493 }
3494
3495 EAPI Eina_Bool
3496 elm_toolbar_item_state_del(Elm_Object_Item *it,
3497                            Elm_Toolbar_Item_State *state)
3498 {
3499    Elm_Toolbar_Item_State *it_state;
3500    Elm_Toolbar_Item *item;
3501    Eina_List *del_state;
3502
3503    ELM_TOOLBAR_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
3504
3505    if (!state) return EINA_FALSE;
3506
3507    item = (Elm_Toolbar_Item *)it;
3508    if (!item->states) return EINA_FALSE;
3509
3510    del_state = eina_list_data_find_list(item->states, state);
3511    if (del_state == item->states) return EINA_FALSE;
3512    if (del_state == item->current_state)
3513      elm_toolbar_item_state_unset(it);
3514
3515    eina_stringshare_del(state->label);
3516    eina_stringshare_del(state->icon_str);
3517    if (state->icon) evas_object_del(state->icon);
3518    free(state);
3519
3520    item->states = eina_list_remove_list(item->states, del_state);
3521    if (item->states && !eina_list_next(item->states))
3522      {
3523         it_state = eina_list_data_get(item->states);
3524         item->base.data = it_state->data;
3525         item->func = it_state->func;
3526         eina_stringshare_del(it_state->label);
3527         eina_stringshare_del(it_state->icon_str);
3528         free(eina_list_data_get(item->states));
3529         eina_list_free(item->states);
3530         item->states = NULL;
3531      }
3532
3533    return EINA_TRUE;
3534 }
3535
3536 EAPI Eina_Bool
3537 elm_toolbar_item_state_set(Elm_Object_Item *it,
3538                            Elm_Toolbar_Item_State *state)
3539 {
3540    Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
3541    Elm_Toolbar_Item_State *it_state;
3542    Eina_List *next_state;
3543    Evas_Object *obj;
3544
3545    ELM_TOOLBAR_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
3546
3547    obj = WIDGET(item);
3548    ELM_TOOLBAR_DATA_GET(obj, sd);
3549    if (!item->states) return EINA_FALSE;
3550
3551    if (state)
3552      {
3553         next_state = eina_list_data_find_list(item->states, state);
3554         if (!next_state) return EINA_FALSE;
3555      }
3556    else
3557      next_state = item->states;
3558
3559    if (next_state == item->current_state) return EINA_TRUE;
3560
3561    it_state = eina_list_data_get(next_state);
3562    if (eina_list_data_find(item->current_state, state))
3563      {
3564         _item_label_set(item, it_state->label, "elm,state,label_set,forward");
3565         _elm_toolbar_item_icon_obj_set
3566           (obj, item, it_state->icon, it_state->icon_str,
3567           sd->icon_size, "elm,state,icon_set,forward");
3568      }
3569    else
3570      {
3571         _item_label_set(item, it_state->label, "elm,state,label_set,backward");
3572         _elm_toolbar_item_icon_obj_set
3573           (obj, item, it_state->icon, it_state->icon_str,
3574           sd->icon_size, "elm,state,icon_set,backward");
3575      }
3576    if (elm_widget_item_disabled_get(item))
3577      elm_widget_signal_emit(item->icon, "elm,state,disabled", "elm");
3578    else
3579      elm_widget_signal_emit(item->icon, "elm,state,enabled", "elm");
3580
3581    item->current_state = next_state;
3582
3583    return EINA_TRUE;
3584 }
3585
3586 EAPI void
3587 elm_toolbar_item_state_unset(Elm_Object_Item *it)
3588 {
3589    elm_toolbar_item_state_set(it, NULL);
3590 }
3591
3592 EAPI Elm_Toolbar_Item_State *
3593 elm_toolbar_item_state_get(const Elm_Object_Item *it)
3594 {
3595    Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
3596
3597    ELM_TOOLBAR_ITEM_CHECK_OR_RETURN(it, NULL);
3598
3599    if ((!item->states) || (!item->current_state)) return NULL;
3600    if (item->current_state == item->states) return NULL;
3601
3602    return eina_list_data_get(item->current_state);
3603 }
3604
3605 EAPI Elm_Toolbar_Item_State *
3606 elm_toolbar_item_state_next(Elm_Object_Item *it)
3607 {
3608    Eina_List *next_state;
3609    Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
3610
3611    ELM_TOOLBAR_ITEM_CHECK_OR_RETURN(it, NULL);
3612
3613    if (!item->states) return NULL;
3614
3615    next_state = eina_list_next(item->current_state);
3616    if (!next_state)
3617      next_state = eina_list_next(item->states);
3618    return eina_list_data_get(next_state);
3619 }
3620
3621 EAPI Elm_Toolbar_Item_State *
3622 elm_toolbar_item_state_prev(Elm_Object_Item *it)
3623 {
3624    Eina_List *prev_state;
3625    Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
3626
3627    ELM_TOOLBAR_ITEM_CHECK_OR_RETURN(it, NULL);
3628
3629    if (!item->states) return NULL;
3630
3631    prev_state = eina_list_prev(item->current_state);
3632    if ((!prev_state) || (prev_state == item->states))
3633      prev_state = eina_list_last(item->states);
3634    return eina_list_data_get(prev_state);
3635 }
3636
3637 EAPI void
3638 elm_toolbar_icon_order_lookup_set(Evas_Object *obj,
3639                                   Elm_Icon_Lookup_Order order)
3640 {
3641    Elm_Toolbar_Item *it;
3642
3643    ELM_TOOLBAR_CHECK(obj);
3644    ELM_TOOLBAR_DATA_GET(obj, sd);
3645
3646    if (sd->lookup_order == order) return;
3647    sd->lookup_order = order;
3648    EINA_INLIST_FOREACH(sd->items, it)
3649      elm_icon_order_lookup_set(it->icon, order);
3650    if (sd->more_item)
3651      elm_icon_order_lookup_set(sd->more_item->icon, order);
3652 }
3653
3654 EAPI Elm_Icon_Lookup_Order
3655 elm_toolbar_icon_order_lookup_get(const Evas_Object *obj)
3656 {
3657    ELM_TOOLBAR_CHECK(obj) ELM_ICON_LOOKUP_THEME_FDO;
3658    ELM_TOOLBAR_DATA_GET(obj, sd);
3659
3660    return sd->lookup_order;
3661 }
3662
3663 EAPI void
3664 elm_toolbar_horizontal_set(Evas_Object *obj,
3665                            Eina_Bool horizontal)
3666 {
3667    ELM_TOOLBAR_CHECK(obj);
3668    ELM_TOOLBAR_DATA_GET(obj, sd);
3669
3670    horizontal = !!horizontal;
3671    if (!horizontal == sd->vertical) return;
3672    sd->vertical = !horizontal;
3673    if (sd->vertical)
3674      evas_object_size_hint_align_set(sd->bx, 0.5, sd->align);
3675    else
3676      evas_object_size_hint_align_set(sd->bx, sd->align, 0.5);
3677
3678    _sizing_eval(obj);
3679 }
3680
3681 EAPI Eina_Bool
3682 elm_toolbar_horizontal_get(const Evas_Object *obj)
3683 {
3684    ELM_TOOLBAR_CHECK(obj) EINA_FALSE;
3685    ELM_TOOLBAR_DATA_GET(obj, sd);
3686
3687    return !sd->vertical;
3688 }
3689
3690 EAPI unsigned int
3691 elm_toolbar_items_count(const Evas_Object *obj)
3692 {
3693    ELM_TOOLBAR_CHECK(obj) 0;
3694    ELM_TOOLBAR_DATA_GET(obj, sd);
3695
3696    return sd->item_count;
3697 }
3698
3699 EAPI void
3700 elm_toolbar_standard_priority_set(Evas_Object *obj,
3701                                   int priority)
3702 {
3703    ELM_TOOLBAR_CHECK(obj);
3704    ELM_TOOLBAR_DATA_GET(obj, sd);
3705
3706    if (sd->standard_priority == priority) return;
3707    sd->standard_priority = priority;
3708    _resize_cb(obj, NULL, NULL, NULL);
3709 }
3710
3711 EAPI int
3712 elm_toolbar_standard_priority_get(const Evas_Object *obj)
3713 {
3714    ELM_TOOLBAR_CHECK(obj) 0;
3715    ELM_TOOLBAR_DATA_GET(obj, sd);
3716
3717    return sd->standard_priority;
3718 }
3719
3720 EAPI void
3721 elm_toolbar_select_mode_set(Evas_Object *obj,
3722                             Elm_Object_Select_Mode mode)
3723 {
3724    ELM_TOOLBAR_CHECK(obj);
3725    ELM_TOOLBAR_DATA_GET(obj, sd);
3726
3727    if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
3728      return;
3729
3730    if (sd->select_mode == mode) return;
3731
3732    if ((mode == ELM_OBJECT_SELECT_MODE_ALWAYS) &&
3733        (sd->select_mode != ELM_OBJECT_SELECT_MODE_ALWAYS) &&
3734        sd->items)
3735      _item_select(ELM_TOOLBAR_ITEM_FROM_INLIST(sd->items));
3736
3737    if (sd->select_mode != mode)
3738      sd->select_mode = mode;
3739 }
3740
3741 EAPI Elm_Object_Select_Mode
3742 elm_toolbar_select_mode_get(const Evas_Object *obj)
3743 {
3744    ELM_TOOLBAR_CHECK(obj) ELM_OBJECT_SELECT_MODE_MAX;
3745    ELM_TOOLBAR_DATA_GET(obj, sd);
3746
3747    return sd->select_mode;
3748 }
3749
3750 EAPI void
3751 elm_toolbar_reorder_mode_set(Evas_Object *obj,
3752                              Eina_Bool    reorder_mode)
3753 {
3754    ELM_TOOLBAR_CHECK(obj);
3755    ELM_TOOLBAR_DATA_GET(obj, sd);
3756
3757    sd->reorder_mode = !!reorder_mode;
3758 }
3759
3760 EAPI Eina_Bool
3761 elm_toolbar_reorder_mode_get(const Evas_Object *obj)
3762 {
3763    ELM_TOOLBAR_CHECK(obj) EINA_FALSE;
3764    ELM_TOOLBAR_DATA_GET(obj, sd);
3765
3766    return sd->reorder_mode;
3767 }
3768
3769 EAPI void
3770 elm_toolbar_item_show(Elm_Object_Item *it, Elm_Toolbar_Item_Scrollto_Type type)
3771 {
3772    Evas_Coord x, y, w, h;
3773    Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
3774
3775    ELM_TOOLBAR_ITEM_CHECK_OR_RETURN(it);
3776    ELM_TOOLBAR_DATA_GET(WIDGET(item), sd);
3777
3778    if (_elm_toolbar_item_coordinates_calc(item, type, &x, &y, &w, &h))
3779      sd->s_iface->content_region_show(WIDGET(item), x, y, w, h);
3780 }
3781
3782 EAPI void
3783 elm_toolbar_item_bring_in(Elm_Object_Item *it, Elm_Toolbar_Item_Scrollto_Type type)
3784 {
3785    Evas_Coord x, y, w, h;
3786    Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
3787
3788    ELM_TOOLBAR_ITEM_CHECK_OR_RETURN(it);
3789    ELM_TOOLBAR_DATA_GET(WIDGET(item), sd);
3790
3791    if (_elm_toolbar_item_coordinates_calc(item, type, &x, &y, &w, &h))
3792      sd->s_iface->region_bring_in(WIDGET(item), x, y, w, h);
3793 }