elementary/map - map supports language,changed
[framework/uifw/elementary.git] / src / lib / elc_multibuttonentry.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include "elm_widget_multibuttonentry.h"
4
5 //#define _VI_EFFECT 0
6
7 #ifdef _VI_EFFECT
8 #define TRANSIT_DURATION 0.167
9 #define ANIMATE_FRAME 10
10 #endif
11
12 EAPI const char ELM_MULTIBUTTONENTRY_SMART_NAME[] = "elm_multibuttonentry";
13
14 //widget signals
15 static const char SIG_ITEM_SELECTED[] = "item,selected";
16 static const char SIG_ITEM_ADDED[] = "item,added";
17 static const char SIG_ITEM_DELETED[] = "item,deleted";
18 static const char SIG_ITEM_CLICKED[] = "item,clicked";
19 static const char SIG_CLICKED[] = "clicked";
20 static const char SIG_FOCUSED[] = "focused";
21 static const char SIG_UNFOCUSED[] = "unfocused";
22 static const char SIG_EXPANDED[] = "expanded";
23 static const char SIG_CONTRACTED[] = "contracted";
24 static const char SIG_EXPAND_STATE_CHANGED[] = "expand,state,changed";
25 static const char SIG_LONGPRESSED[] = "longpressed";
26
27 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
28    {SIG_ITEM_SELECTED, ""},
29    {SIG_ITEM_ADDED, ""},
30    {SIG_ITEM_DELETED, ""},
31    {SIG_ITEM_CLICKED, ""},
32    {SIG_CLICKED, ""},
33    {SIG_FOCUSED, ""},
34    {SIG_UNFOCUSED, ""},
35    {SIG_EXPANDED, ""},
36    {SIG_CONTRACTED, ""},
37    {SIG_EXPAND_STATE_CHANGED, ""},
38    {SIG_LONGPRESSED, ""},
39    {NULL, NULL}
40 };
41
42 EVAS_SMART_SUBCLASS_NEW
43   (ELM_MULTIBUTTONENTRY_SMART_NAME, _elm_multibuttonentry,
44   Elm_Multibuttonentry_Smart_Class, Elm_Layout_Smart_Class,
45   elm_layout_smart_class_get, _smart_callbacks);
46
47 static Eina_Bool
48 _elm_multibuttonentry_smart_focus_next(const Evas_Object *obj,
49                                Elm_Focus_Direction dir,
50                                Evas_Object **next)
51 {
52    Eina_List *items = NULL;
53    Eina_List *elist = NULL;
54    Elm_Multibuttonentry_Item *it;
55
56    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
57
58    if (!sd)
59      return EINA_FALSE;
60
61    if (!elm_widget_focus_next_get(sd->box, dir, next))
62      {
63         elm_widget_focused_object_clear(sd->box);
64         elm_widget_focus_next_get(sd->box, dir, next);
65      }
66
67    EINA_LIST_FOREACH(sd->items, elist, it)
68      items = eina_list_append(items, it->base.access_obj);
69
70    return elm_widget_focus_list_next_get
71             (obj, items, eina_list_data_get, dir, next);
72 }
73
74 static char *
75 _access_label_info_cb(void *data, Evas_Object *obj __UNUSED__)
76 {
77    Evas_Object *mbe = (Evas_Object *)data;
78    const char *txt = NULL;
79
80    ELM_MULTIBUTTONENTRY_DATA_GET(mbe, sd);
81
82    if (!mbe) return NULL;
83
84    if (!txt)
85      {
86         txt = elm_object_part_text_get(sd->label, "mbe.label");
87         return strdup(txt);
88      }
89    else return strdup(txt);
90
91    return NULL;
92 }
93
94 static char *
95 _access_shrink_info_cb(void *data, Evas_Object *obj __UNUSED__)
96 {
97    Evas_Object *mbe = (Evas_Object *)data;
98    const char *txt = NULL;
99    Eina_Strbuf *buf = NULL;
100    char *str = NULL;
101
102    ELM_MULTIBUTTONENTRY_DATA_GET(mbe, sd);
103
104    if (!mbe) return NULL;
105
106    if (!txt) txt = elm_object_text_get(sd->end);
107    if (txt)
108      {
109         buf = eina_strbuf_new();
110         eina_strbuf_append(buf, E_("And "));
111         eina_strbuf_append(buf, txt);
112         eina_strbuf_append(buf, E_(" more"));
113         str = eina_strbuf_string_steal(buf);
114         eina_strbuf_free(buf);
115         return str;
116      }
117    return NULL;
118 }
119
120 static Eina_Bool
121 _guide_packed(Evas_Object *obj)
122 {
123    Eina_List *children;
124
125    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
126
127    if (!sd->guide) return EINA_FALSE;
128
129    children = elm_box_children_get(sd->box);
130    if (sd->guide == eina_list_data_get(eina_list_last(children)))
131      {
132         eina_list_free(children);
133         return EINA_TRUE;
134      }
135    else
136      {
137         eina_list_free(children);
138         return EINA_FALSE;
139      }
140 }
141
142 static Eina_Bool
143 _label_packed(Evas_Object *obj)
144 {
145    Eina_List *children;
146
147    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
148
149    if (!sd->label) return EINA_FALSE;
150
151    children = elm_box_children_get(sd->box);
152    if (sd->label == eina_list_data_get(children))
153      {
154         eina_list_free(children);
155         return EINA_TRUE;
156      }
157    else
158      {
159         eina_list_free(children);
160         return EINA_FALSE;
161      }
162 }
163
164 static void
165 _guide_set(Evas_Object *obj,
166            const char *text)
167 {
168    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
169
170    if (!sd->guide && !strlen(text)) return;
171
172    if (!sd->guide)
173      {
174         sd->guide = elm_layout_add(obj);
175         elm_layout_theme_set
176            (sd->guide, "multibuttonentry", "guidetext", elm_widget_style_get(obj));
177         evas_object_size_hint_weight_set
178            (sd->guide, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
179         evas_object_size_hint_align_set
180            (sd->guide, EVAS_HINT_FILL, EVAS_HINT_FILL);
181      }
182    elm_object_text_set(sd->guide, text);
183
184    if (!sd->items && !elm_object_focus_get(obj) && !_guide_packed(obj))
185      {
186         if (sd->editable)
187           {
188              elm_box_unpack(sd->box, sd->entry);
189              evas_object_hide(sd->entry);
190           }
191
192         elm_box_pack_end(sd->box, sd->guide);
193         evas_object_show(sd->guide);
194      }
195 }
196
197 static void
198 _label_set(Evas_Object *obj,
199            const char *text)
200 {
201    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
202
203    if (!sd->label && !strlen(text)) return;
204
205    if (!sd->label)
206      {
207         sd->label = elm_layout_add(obj);
208         elm_layout_theme_set
209            (sd->label, "multibuttonentry", "label", elm_widget_style_get(obj));
210      }
211    elm_object_part_text_set(sd->label, "mbe.label", text);
212
213    if (strlen(text) && !_label_packed(obj))
214      {
215         elm_box_pack_start(sd->box, sd->label);
216         evas_object_show(sd->label);
217      }
218    else if (!strlen(text) && _label_packed(obj))
219      {
220         elm_box_unpack(sd->box, sd->label);
221         evas_object_hide(sd->label);
222      }
223
224    // ACCESS
225    if (_elm_config->access_mode)
226      {
227         _elm_access_object_register(obj, ELM_WIDGET_DATA(sd)->resize_obj);
228         _elm_access_callback_set(_elm_access_object_get(obj), ELM_ACCESS_INFO, _access_label_info_cb, obj);
229      }
230 }
231
232 #ifdef _VI_EFFECT
233 static void
234 _box_layout_pre_calculate(Evas_Object *obj,
235                           Elm_Multibuttonentry_Item *except_it,
236                           Evas_Coord *minh_wo_entry,
237                           Evas_Coord *minh)
238 {
239    Evas_Coord mnw, mnh, x, w, hpad = 0, vpad = 0;
240    Evas_Coord linew = 0, lineh = 0;
241    int line_num;
242    Eina_List *l;
243    Elm_Multibuttonentry_Item *it;
244
245    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
246
247    evas_object_geometry_get(sd->box, &x, NULL, &w, NULL);
248    elm_box_padding_get(sd->box, &hpad, &vpad);
249
250    line_num = 1;
251
252    if (sd->label && _label_packed(obj))
253      {
254         evas_object_size_hint_min_get(sd->label, &mnw, &mnh);
255
256         linew = mnw;
257         linew += hpad;
258         lineh = mnh;
259      }
260
261    EINA_LIST_FOREACH(sd->items, l, it)
262      {
263         if (it == except_it) continue;
264
265         evas_object_size_hint_min_get(VIEW(it), &mnw, &mnh);
266
267         linew += mnw;
268         if (lineh < mnh) lineh = mnh;
269
270         if (linew > w)
271           {
272              linew = mnw;
273              line_num++;
274           }
275
276
277         linew += hpad;
278      }
279
280    if (minh_wo_entry)
281      *minh_wo_entry = lineh * line_num + (line_num - 1) * vpad;
282
283    if (sd->editable)
284      {
285         // get entry size after text is reset
286         elm_object_text_set(sd->entry, "");
287         elm_layout_sizing_eval(sd->entry);
288         evas_object_size_hint_min_get(sd->entry, &mnw, &mnh);
289
290         linew += mnw;
291         if (lineh < mnh) lineh = mnh;
292
293         if (linew > w) line_num++;
294      }
295
296    if (minh)
297      *minh = lineh * line_num + (line_num - 1) * vpad;
298 }
299
300 static void
301 _on_item_expanding_transit_del(void *data,
302                                Elm_Transit *transit __UNUSED__)
303 {
304    Elm_Multibuttonentry_Item *it = data;
305
306    evas_object_data_set(VIEW(it), "transit", NULL);
307    evas_object_smart_callback_call(WIDGET(it), SIG_ITEM_ADDED, it);
308 }
309
310 static Eina_Bool
311 _rect_expanding_animate(void *data)
312 {
313    Evas_Coord w, h, eh;
314    Evas_Object *rect;
315    Elm_Multibuttonentry_Item *it = data;
316
317    ELM_MULTIBUTTONENTRY_DATA_GET(WIDGET(it), sd);
318
319    rect = (Evas_Object *)evas_object_data_get(VIEW(it), "effect_rect");
320    if (!rect) return ECORE_CALLBACK_CANCEL;
321
322    evas_object_geometry_get(sd->entry, NULL, NULL, NULL, &eh);
323    evas_object_size_hint_min_get(rect, &w, &h);
324
325    if (h >= eh)
326      {
327         Eina_List *children;
328         Elm_Multibuttonentry_Item *last_it;
329
330         evas_object_del(rect);
331         evas_object_data_set(VIEW(it), "effect_rect", NULL);
332
333         // if last item is unpacked, add it
334         children = elm_box_children_get(sd->box);
335         last_it = eina_list_data_get(eina_list_last(sd->items));
336         if (VIEW(last_it) != eina_list_data_get(eina_list_last(children)))
337           {
338              elm_box_pack_end(sd->box, VIEW(last_it));
339              evas_object_show(VIEW(last_it));
340           }
341         eina_list_free(children);
342
343         if (sd->editable)
344           {
345              elm_box_pack_end(sd->box, sd->entry);
346              evas_object_show(sd->entry);
347              if (elm_object_focus_get(WIDGET(it)))
348                elm_object_focus_set(sd->entry, EINA_TRUE);
349           }
350
351         return ECORE_CALLBACK_CANCEL;
352      }
353    else
354      evas_object_size_hint_min_set(rect, w, h + eh / ANIMATE_FRAME);
355
356    return ECORE_CALLBACK_RENEW;
357 }
358
359 static void
360 _item_adding_effect_add(Evas_Object *obj,
361                         Elm_Multibuttonentry_Item *it)
362 {
363    Elm_Transit *trans;
364    Evas_Coord minh_wo_entry, minh;
365    Eina_Bool floating = EINA_FALSE;;
366
367    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
368
369    _box_layout_pre_calculate(obj, NULL, &minh_wo_entry, &minh);
370
371    // if box will be expanded, add resizing effect
372    if (sd->boxh < minh)
373      {
374         Evas_Coord bx, by, bw, bh;
375         Evas_Object *rect;
376         Ecore_Animator *anim;
377
378         evas_object_geometry_get(sd->box, &bx, &by, &bw, &bh);
379
380         // if box will be expanded with item and entry
381         if (minh_wo_entry == minh)
382           {
383              Elm_Multibuttonentry_Item *last_it;
384
385              last_it = eina_list_data_get(eina_list_last(sd->items));
386              if (it == last_it)
387                {
388                   Evas_Coord iw, ih, vpad;
389
390                   evas_object_size_hint_min_get(VIEW(it), &iw, &ih);
391                   elm_box_padding_get(sd->box, NULL, &vpad);
392
393                   evas_object_move(VIEW(it), bx, by + bh + vpad);
394                   evas_object_resize(VIEW(it), iw, ih);
395                   evas_object_show(VIEW(it));
396
397                   floating = EINA_TRUE;
398                }
399              else
400                {
401                   elm_box_unpack(sd->box, VIEW(last_it));
402                   evas_object_hide(VIEW(last_it));
403                }
404           }
405
406         if (sd->editable)
407           {
408              if (elm_object_focus_get(sd->entry))
409                elm_object_focus_set(sd->entry, EINA_FALSE);
410              elm_box_unpack(sd->box, sd->entry);
411              evas_object_hide(sd->entry);
412              elm_entry_input_panel_show(sd->entry);
413           }
414
415         rect = evas_object_rectangle_add(evas_object_evas_get(obj));
416         evas_object_color_set(rect, 0, 0, 0, 0);
417         evas_object_size_hint_min_set(rect, bw, 0);
418         evas_object_data_set(VIEW(it), "effect_rect", rect);
419         elm_box_pack_end(sd->box, rect);
420         evas_object_show(rect);
421
422         anim = ecore_animator_add(_rect_expanding_animate, it);
423         evas_object_data_set(rect, "animator", anim);
424      }
425
426    if (!floating)
427      {
428         Eina_List *cur;
429         cur = eina_list_data_find_list(sd->items, it);
430         if (cur == sd->items)
431           {
432              if (sd->label && _label_packed(obj))
433                elm_box_pack_after(sd->box, VIEW(it), sd->label);
434              else
435                elm_box_pack_start(sd->box, VIEW(it));
436           }
437         else
438           {
439              Elm_Multibuttonentry_Item *prev_it;
440              prev_it = eina_list_data_get(eina_list_prev(cur));
441              elm_box_pack_after(sd->box, VIEW(it), VIEW(prev_it));
442           }
443         evas_object_show(VIEW(it));
444      }
445
446    trans = elm_transit_add();
447    elm_transit_object_add(trans, VIEW(it));
448    elm_transit_effect_zoom_add(trans, 0.9, 1.0);
449    elm_transit_effect_color_add(trans, 0, 0, 0, 0, 255, 255, 255, 255);
450    elm_transit_del_cb_set(trans, _on_item_expanding_transit_del, it);
451    elm_transit_duration_set(trans, TRANSIT_DURATION);
452    evas_object_data_set(VIEW(it), "transit", trans);
453    elm_transit_go(trans);
454 }
455
456 static void
457 _on_item_contracting_transit_del(void *data,
458                                  Elm_Transit *transit __UNUSED__)
459 {
460    Evas_Object *rect;
461    Elm_Multibuttonentry_Item *it = data;
462
463    ELM_MULTIBUTTONENTRY_DATA_GET(WIDGET(it), sd);
464
465    evas_object_data_set(VIEW(it), "transit", NULL);
466
467    rect = (Evas_Object *)evas_object_data_get(VIEW(it), "effect_rect");
468    if (rect)
469      {
470         evas_object_hide(VIEW(it));
471         return;
472      }
473
474    // delete item and set focus to entry
475    if (sd->editable && elm_object_focus_get(WIDGET(it)))
476      elm_object_focus_set(sd->entry, EINA_TRUE);
477
478    elm_object_item_del((Elm_Object_Item *)it);
479 }
480
481 static Eina_Bool
482 _rect_contracting_animate(void *data)
483 {
484    Evas_Coord w, h, eh;
485    Evas_Object *rect;
486    Elm_Multibuttonentry_Item *it = data;
487
488    ELM_MULTIBUTTONENTRY_DATA_GET(WIDGET(it), sd);
489
490    rect = (Evas_Object *)evas_object_data_get(VIEW(it), "effect_rect");
491    if (!rect) return ECORE_CALLBACK_CANCEL;
492
493    evas_object_geometry_get(sd->entry, NULL, NULL, NULL, &eh);
494    evas_object_size_hint_min_get(rect, &w, &h);
495
496    if (h <= 0)
497      {
498         Elm_Transit *trans;
499         Elm_Multibuttonentry_Item *last_it;
500
501         evas_object_del(rect);
502         evas_object_data_set(VIEW(it), "effect_rect", NULL);
503
504         // if last item is unpacked, add it
505         last_it = eina_list_data_get(eina_list_last(sd->items));
506         if (it != last_it)
507           {
508              if (!evas_object_visible_get(VIEW(last_it)))
509                {
510                   elm_box_pack_end(sd->box, VIEW(last_it));
511                   evas_object_show(VIEW(last_it));
512                }
513           }
514
515         if (sd->editable)
516           {
517              elm_box_pack_end(sd->box, sd->entry);
518              evas_object_show(sd->entry);
519              if (elm_object_focus_get(WIDGET(it)))
520                elm_object_focus_set(sd->entry, EINA_TRUE);
521           }
522
523         // delete the button
524         trans = (Elm_Transit *)evas_object_data_get(VIEW(it), "transit");
525         if (!trans)
526           _on_item_contracting_transit_del(it, NULL);
527
528         return ECORE_CALLBACK_CANCEL;
529      }
530    else
531      evas_object_size_hint_min_set(rect, w, h - eh / ANIMATE_FRAME);
532
533    return ECORE_CALLBACK_RENEW;
534 }
535
536 static void
537 _item_deleting_effect_add(Evas_Object *obj,
538                           Elm_Multibuttonentry_Item *it)
539 {
540    Elm_Transit *trans;
541    Evas_Coord minh;
542
543    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
544
545    _box_layout_pre_calculate(obj, it, NULL, &minh);
546
547    // if box will be contracted, add resizing effect
548    if (sd->boxh > minh)
549      {
550         Evas_Coord bx, bw, ix, eh;
551         Ecore_Animator *anim;
552         Evas_Object *rect;
553         Elm_Multibuttonentry_Item *last_it;
554
555         last_it = eina_list_data_get(eina_list_last(sd->items));
556         evas_object_geometry_get(sd->box, &bx, NULL, &bw, NULL);
557         evas_object_geometry_get(VIEW(last_it), &ix, NULL, NULL, NULL);
558
559         // if box will be contracted with item and entry
560         if (ix == bx)
561           {
562              if (it == last_it)
563                elm_box_unpack(sd->box, VIEW(it));
564              else
565                {
566                   elm_box_unpack(sd->box, VIEW(last_it));
567                   evas_object_hide(VIEW(last_it));
568                }
569           }
570
571         if (sd->editable)
572           {
573              if (elm_object_focus_get(sd->entry))
574                elm_object_focus_set(sd->entry, EINA_FALSE);
575              elm_box_unpack(sd->box, sd->entry);
576              evas_object_hide(sd->entry);
577              elm_entry_input_panel_show(sd->entry);
578           }
579
580         rect = evas_object_rectangle_add(evas_object_evas_get(obj));
581         evas_object_color_set(rect, 0, 0, 0, 0);
582         evas_object_geometry_get(sd->entry, NULL, NULL, NULL, &eh);
583         evas_object_size_hint_min_set(rect, bw, eh);
584         evas_object_data_set(VIEW(it), "effect_rect", rect);
585         elm_box_pack_end(sd->box, rect);
586         evas_object_show(rect);
587
588         anim = ecore_animator_add(_rect_contracting_animate, it);
589         evas_object_data_set(rect, "animator", anim);
590      }
591
592    trans = elm_transit_add();
593    elm_transit_object_add(trans, VIEW(it));
594    elm_transit_effect_zoom_add(trans, 1.0, 0.9);
595    elm_transit_effect_color_add(trans, 255, 255, 255, 255, 0, 0, 0, 0);
596    elm_transit_del_cb_set(trans, _on_item_contracting_transit_del, it);
597    elm_transit_duration_set(trans, TRANSIT_DURATION);
598    evas_object_data_set(VIEW(it), "transit", trans);
599    elm_transit_go(trans);
600
601 }
602 #endif
603
604 static void
605 _layout_expand(Evas_Object *obj)
606 {
607    int count, items_count, i;
608    Eina_List *children;
609    Elm_Multibuttonentry_Item *it;
610
611    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
612
613    if (!sd->items) return;
614    if (sd->expanded_state) return;
615
616    children = elm_box_children_get(sd->box);
617    count = eina_list_count(children);
618    if (sd->end)
619      {
620         evas_object_del(sd->end);
621         sd->end = NULL;
622         count--;
623      }
624    if (sd->label && _label_packed(obj)) count--;
625    eina_list_free(children);
626
627    items_count = eina_list_count(sd->items);
628    for (i = count; i < items_count; i++)
629      {
630         it = eina_list_nth(sd->items, i);
631         elm_box_pack_end(sd->box, VIEW(it));
632         evas_object_show(VIEW(it));
633      }
634
635    if (sd->editable)
636      {
637         elm_box_pack_end(sd->box, sd->entry);
638         evas_object_show(sd->entry);
639      }
640
641    sd->expanded_state = EINA_TRUE;
642    evas_object_smart_callback_call(obj, SIG_EXPAND_STATE_CHANGED, NULL);
643 }
644
645 static void
646 _layout_shrink(Evas_Object *obj,
647                Eina_Bool force)
648 {
649    Evas_Coord w, mnw, linew = 0, hpad = 0;
650    int count = 0, items_count, i;
651    Eina_List *l, *children;
652    Evas_Object *child;
653    Elm_Multibuttonentry_Item *it;
654 #ifdef _VI_EFFECT
655    Elm_Transit *trans;
656    Evas_Object *rect;
657    Ecore_Animator *anim;
658 #endif
659
660    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
661
662    if (!sd->items) return;
663    if (!sd->expanded_state && !force) return;
664
665    evas_object_geometry_get(sd->box, NULL, NULL, &w, NULL);
666    elm_box_padding_get(sd->box, &hpad, NULL);
667
668    if (sd->label && _label_packed(obj))
669      {
670         evas_object_size_hint_min_get(sd->label, &mnw, NULL);
671         linew += mnw;
672         linew += hpad;
673      }
674
675    EINA_LIST_FOREACH(sd->items, l, it)
676      {
677         evas_object_size_hint_min_get(VIEW(it), &mnw, NULL);
678         linew += mnw;
679
680         if (linew > w)
681           {
682              linew -= mnw;
683              break;
684           }
685
686         count++;
687         linew += hpad;
688      }
689
690    if (!count) return;
691
692    items_count = eina_list_count(sd->items);
693    if (count < items_count)
694      {
695         const char *str = NULL;
696         char buf[16];
697
698         str = elm_layout_data_get(obj, "closed_button_type");
699         if (!sd->end)
700           {
701              sd->end = elm_layout_add(obj);
702              if (str && !strcmp(str, "image"))
703                elm_layout_theme_set(sd->end, "multibuttonentry",
704                                     "closedbutton", elm_widget_style_get(obj));
705              else
706                elm_layout_theme_set(sd->end, "multibuttonentry",
707                                     "number", elm_widget_style_get(obj));
708           }
709         if (!str || strcmp(str, "image"))
710           {
711              snprintf(buf, sizeof(buf), "+%d", items_count - count);
712              elm_object_text_set(sd->end, buf);
713
714              // ACCESS
715              if (_elm_config->access_mode && sd->end)
716                {
717                   _elm_access_object_register(obj, ELM_WIDGET_DATA(sd)->resize_obj);
718                   _elm_access_callback_set(_elm_access_object_get(obj), ELM_ACCESS_INFO, _access_shrink_info_cb, obj);
719                }
720           }
721         evas_object_smart_calculate(sd->end);
722         evas_object_size_hint_min_get(sd->end, &mnw, NULL);
723         linew += mnw;
724
725         if (linew > w)
726           {
727              count--;
728              if (!str || strcmp(str, "image"))
729                {
730                   snprintf(buf, sizeof(buf), "+%d", items_count - count);
731                   elm_object_text_set(sd->end, buf);
732
733                   // ACCESS
734                   if (_elm_config->access_mode && sd->end)
735                    {
736                       _elm_access_object_register(obj, ELM_WIDGET_DATA(sd)->resize_obj);
737                       _elm_access_callback_set(_elm_access_object_get(obj), ELM_ACCESS_INFO, _access_shrink_info_cb, obj);
738                    }
739                }
740           }
741
742         if (!force)
743           {
744 #ifdef _VI_EFFECT
745              // reset last inserted item's effect_rect
746              it = eina_list_nth(sd->items, count - 1);
747              rect = (Evas_Object *)evas_object_data_get(VIEW(it), "effect_rect");
748              if (rect)
749                {
750                   anim = (Ecore_Animator*)evas_object_data_get(rect, "animator");
751                   if (anim) ecore_animator_del(anim);
752
753                   evas_object_del(rect);
754                   evas_object_data_set(VIEW(it), "effect_rect", NULL);
755                }
756 #endif
757
758              for (i = count; i < items_count; i++)
759                {
760                   it = eina_list_nth(sd->items, i);
761 #ifdef _VI_EFFECT
762                   // reset all effects
763                   trans = (Elm_Transit *)evas_object_data_get(VIEW(it), "transit");
764                   if (trans) elm_transit_del(trans);
765
766                   rect = (Evas_Object *)evas_object_data_get(VIEW(it), "effect_rect");
767                   if (rect)
768                     {
769                        anim = (Ecore_Animator*)evas_object_data_get(rect, "animator");
770                        if (anim) ecore_animator_del(anim);
771
772                        evas_object_del(rect);
773                        evas_object_data_set(VIEW(it), "effect_rect", NULL);
774                     }
775 #endif
776                   elm_box_unpack(sd->box, VIEW(it));
777                   evas_object_hide(VIEW(it));
778                }
779
780              if (sd->editable)
781                {
782                   elm_box_unpack(sd->box, sd->entry);
783                   evas_object_hide(sd->entry);
784                }
785           }
786         else
787           {
788              // if it is called from item_append_xxx, item_del functions,
789              // all items are unpacked and packed again
790 #ifdef _VI_EFFECT
791              // reset last inserted item's effect_rect
792              it = eina_list_nth(sd->items, count - 1);
793              rect = (Evas_Object *)evas_object_data_get(VIEW(it), "effect_rect");
794              if (rect)
795                {
796                   anim = (Ecore_Animator*)evas_object_data_get(rect, "animator");
797                   if (anim) ecore_animator_del(anim);
798
799                   evas_object_del(rect);
800                   evas_object_data_set(VIEW(it), "effect_rect", NULL);
801                }
802
803              for (i = count; i < items_count; i++)
804                {
805                   it = eina_list_nth(sd->items, i);
806                   // reset all effects
807                   trans = (Elm_Transit *)evas_object_data_get(VIEW(it), "transit");
808                   if (trans) elm_transit_del(trans);
809
810                   rect = (Evas_Object *)evas_object_data_get(VIEW(it), "effect_rect");
811                   if (rect)
812                     {
813                        anim = (Ecore_Animator*)evas_object_data_get(rect, "animator");
814                        if (anim) ecore_animator_del(anim);
815
816                        evas_object_del(rect);
817                        evas_object_data_set(VIEW(it), "effect_rect", NULL);
818                     }
819                }
820 #endif
821
822              children = elm_box_children_get(sd->box);
823              EINA_LIST_FREE(children, child)
824                {
825                   if (child != sd->label)
826                     {
827                        elm_box_unpack(sd->box, child);
828                        evas_object_hide(child);
829                     }
830                }
831
832              for (i = 0; i < count; i++)
833                {
834                   it = eina_list_nth(sd->items, i);
835                   elm_box_pack_end(sd->box, VIEW(it));
836                   evas_object_show(VIEW(it));
837                }
838           }
839
840         elm_box_pack_end(sd->box, sd->end);
841         evas_object_show(sd->end);
842
843         sd->expanded_state = EINA_FALSE;
844      }
845    else
846      {
847         if (!force)
848           {
849 #ifdef _VI_EFFECT
850              // reset last inserted item's effect_rect
851              it = eina_list_nth(sd->items, count - 1);
852              rect = (Evas_Object *)evas_object_data_get(VIEW(it), "effect_rect");
853              if (rect)
854                {
855                   anim = (Ecore_Animator*)evas_object_data_get(rect, "animator");
856                   if (anim) ecore_animator_del(anim);
857
858                   evas_object_del(rect);
859                   evas_object_data_set(VIEW(it), "effect_rect", NULL);
860
861                   if (sd->editable)
862                     {
863                        elm_box_pack_end(sd->box, sd->entry);
864                        evas_object_show(sd->entry);
865                        if (elm_object_focus_get(WIDGET(it)))
866                          elm_object_focus_set(sd->entry, EINA_TRUE);
867                     }
868                }
869 #endif
870              if (sd->editable)
871                {
872                   evas_object_size_hint_min_get(sd->entry, &mnw, NULL);
873                   linew += mnw;
874                   if (linew > w)
875                     {
876                        elm_box_unpack(sd->box, sd->entry);
877                        evas_object_hide(sd->entry);
878                        sd->expanded_state = EINA_FALSE;
879                     }
880                }
881           }
882         else
883           {
884              if (sd->end)
885                {
886                   evas_object_del(sd->end);
887                   sd->end = NULL;
888                }
889
890              // if it is called from item_append_xxx, item_del functions,
891              // all items are unpacked and packed again
892 #ifdef _VI_EFFECT
893              // reset last inserted item's effect_rect
894              it = eina_list_nth(sd->items, count - 1);
895              rect = (Evas_Object *)evas_object_data_get(VIEW(it), "effect_rect");
896              if (rect)
897                {
898                   anim = (Ecore_Animator*)evas_object_data_get(rect, "animator");
899                   if (anim) ecore_animator_del(anim);
900
901                   evas_object_del(rect);
902                   evas_object_data_set(VIEW(it), "effect_rect", NULL);
903                }
904 #endif
905
906              children = elm_box_children_get(sd->box);
907              EINA_LIST_FREE(children, child)
908                {
909                   if (child != sd->label)
910                     {
911                        elm_box_unpack(sd->box, child);
912                        evas_object_hide(child);
913                     }
914                }
915
916              for (i = 0; i < count; i++)
917                {
918                   it = eina_list_nth(sd->items, i);
919                   elm_box_pack_end(sd->box, VIEW(it));
920                   evas_object_show(VIEW(it));
921                }
922
923              sd->expanded_state = EINA_TRUE;
924
925              if (sd->editable)
926                {
927                   evas_object_size_hint_min_get(sd->entry, &mnw, NULL);
928                   linew += mnw;
929                   if (linew > w)
930                     sd->expanded_state = EINA_FALSE;
931                   else
932                     {
933                        elm_box_pack_end(sd->box, sd->entry);
934                        evas_object_show(sd->entry);
935                     }
936                }
937           }
938      }
939
940    if (!sd->expanded_state && !force)
941      evas_object_smart_callback_call(obj, SIG_EXPAND_STATE_CHANGED, NULL);
942 }
943
944 static Eina_Bool
945 _box_min_size_calculate(Evas_Object *box,
946                         Evas_Object_Box_Data *priv,
947                         int *line_height)
948 {
949    Evas_Coord mnw, mnh, w, minw, minh = 0, linew = 0, lineh = 0;
950    int line_num;
951    Eina_List *l;
952    Evas_Object_Box_Option *opt;
953
954    evas_object_geometry_get(box, NULL, NULL, &w, NULL);
955    evas_object_size_hint_min_get(box, &minw, NULL);
956    if (!w) return EINA_FALSE;
957
958    line_num = 1;
959    EINA_LIST_FOREACH(priv->children, l, opt)
960      {
961         evas_object_size_hint_min_get(opt->obj, &mnw, &mnh);
962
963 #ifdef _VI_EFFECT
964         if (mnw == w &&
965             !strcmp(evas_object_type_get(opt->obj), "rectangle"))
966           break;
967 #endif
968
969         linew += mnw;
970         if (lineh < mnh) lineh = mnh;
971
972         if (linew > w)
973           {
974              linew = mnw;
975              line_num++;
976           }
977
978         if (l != eina_list_last(priv->children))
979           linew += priv->pad.h;
980      }
981
982    minh = lineh * line_num + (line_num - 1) * priv->pad.v;
983
984 #ifdef _VI_EFFECT
985    // if last item is effect_rect
986    if (opt && opt->obj && mnw == w &&
987        !strcmp(evas_object_type_get(opt->obj), "rectangle"))
988      {
989         minh += priv->pad.v;
990         minh += mnh;
991      }
992 #endif
993
994    evas_object_size_hint_min_set(box, minw, minh);
995    *line_height = lineh;
996
997    return EINA_TRUE;
998 }
999
1000 static void
1001 _box_layout(Evas_Object *o,
1002             Evas_Object_Box_Data *priv,
1003             void *data)
1004 {
1005    Evas_Coord x, y, w, h, xx, yy, minw, minh, linew = 0, lineh = 0;
1006    double ax, ay;
1007    Eina_Bool rtl;
1008    Eina_List *l;
1009    Evas_Object *obj;
1010    Evas_Object_Box_Option *opt;
1011
1012    if (!_box_min_size_calculate(o, priv, &lineh)) return;
1013
1014    evas_object_geometry_get(o, &x, &y, &w, &h);
1015    evas_object_size_hint_min_get(o, &minw, &minh);
1016    evas_object_size_hint_align_get(o, &ax, &ay);
1017
1018    rtl = elm_widget_mirrored_get(data);
1019    if (rtl) ax = 1.0 - ax;
1020
1021    if (w < minw)
1022      {
1023         x = x + ((w - minw) * (1.0 - ax));
1024         w = minw;
1025      }
1026    if (h < minh)
1027      {
1028         y = y + ((h - minh) * (1.0 - ay));
1029         h = minh;
1030      }
1031
1032    xx = x;
1033    yy = y;
1034    EINA_LIST_FOREACH(priv->children, l, opt)
1035      {
1036         Evas_Coord mnw, mnh, ww, hh, ow, oh;
1037         double wx, wy;
1038         Eina_Bool fw, fh, xw, xh;
1039
1040         obj = opt->obj;
1041         evas_object_size_hint_align_get(obj, &ax, &ay);
1042         evas_object_size_hint_weight_get(obj, &wx, &wy);
1043         evas_object_size_hint_min_get(obj, &mnw, &mnh);
1044
1045         fw = fh = EINA_FALSE;
1046         xw = xh = EINA_FALSE;
1047         if (ax == -1.0) {fw = EINA_TRUE; ax = 0.5;}
1048         if (ay == -1.0) {fh = EINA_TRUE; ay = 0.5;}
1049         if (rtl) ax = 1.0 - ax;
1050         if (wx > 0.0) xw = EINA_TRUE;
1051         if (wy > 0.0) xh = EINA_TRUE;
1052
1053         ww = mnw;
1054         if (xw)
1055           {
1056              if (ww <= w - linew) ww = w - linew;
1057              else ww = w;
1058           }
1059         hh = lineh;
1060
1061         ow = mnw;
1062         if (fw) ow = ww;
1063         oh = mnh;
1064         if (fh) oh = hh;
1065
1066         linew += ww;
1067         if (linew > w && l != priv->children)
1068           {
1069              xx = x;
1070              yy += hh;
1071              yy += priv->pad.v;
1072              linew = ww;
1073           }
1074         linew += priv->pad.h;
1075
1076         evas_object_move(obj,
1077                          ((!rtl) ? (xx) : (x + (w - (xx - x) - ww)))
1078                          + (Evas_Coord)(((double)(ww - ow)) * ax),
1079                          yy + (Evas_Coord)(((double)(hh - oh)) * ay));
1080         evas_object_resize(obj, ow, oh);
1081
1082         xx += ww;
1083         xx += priv->pad.h;
1084      }
1085 }
1086
1087 static void
1088 _on_box_resize(void *data,
1089                Evas *e __UNUSED__,
1090                Evas_Object *obj,
1091                void *event_info __UNUSED__)
1092 {
1093    Evas_Coord w, h;
1094
1095    ELM_MULTIBUTTONENTRY_DATA_GET(data, sd);
1096
1097    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1098
1099    if (sd->boxh < h)
1100      evas_object_smart_callback_call(data, SIG_EXPANDED, NULL);
1101    else if (sd->boxh > h)
1102      evas_object_smart_callback_call(data, SIG_CONTRACTED, NULL);
1103
1104    // on rotation, items should be packed again in the shrinked layout
1105    if (sd->boxw && sd->boxw != w)
1106      {
1107         if (!elm_object_focus_get(data) && !sd->expanded)
1108           _layout_shrink(data, EINA_TRUE);
1109      }
1110
1111    sd->boxh = h;
1112    sd->boxw = w;
1113 }
1114
1115 static Elm_Multibuttonentry_Item_Filter *
1116 _filter_new(Elm_Multibuttonentry_Item_Filter_Cb func,
1117             const void *data)
1118 {
1119    Elm_Multibuttonentry_Item_Filter *ft;
1120
1121    ft = ELM_NEW(Elm_Multibuttonentry_Item_Filter);
1122    if (!ft) return NULL;
1123
1124    ft->func = func;
1125    ft->data = data;
1126
1127    return ft;
1128 }
1129
1130 static void
1131 _on_item_clicked(void *data,
1132                  Evas_Object *obj __UNUSED__,
1133                  const char *emission __UNUSED__,
1134                  const char *source __UNUSED__)
1135 {
1136    Elm_Multibuttonentry_Item *it = data;
1137
1138    ELM_MULTIBUTTONENTRY_DATA_GET(WIDGET(it), sd);
1139
1140    evas_object_focus_set(elm_layout_edje_get(VIEW(it)), EINA_TRUE);
1141
1142    // handles input panel because it can be hidden by user
1143    if (sd->editable)
1144      elm_entry_input_panel_show(sd->entry);
1145
1146    evas_object_smart_callback_call(WIDGET(it), SIG_ITEM_CLICKED, it);
1147 }
1148
1149 static void
1150 _on_item_selected(void *data,
1151                   Evas_Object *obj __UNUSED__,
1152                   const char *emission __UNUSED__,
1153                   const char *source __UNUSED__)
1154 {
1155    Elm_Multibuttonentry_Item *it = data;
1156
1157    if (it->func) it->func((void *)it->base.data, WIDGET(it), it);
1158
1159    evas_object_smart_callback_call(WIDGET(it), SIG_ITEM_SELECTED, it);
1160 }
1161
1162 static void
1163 _on_item_focus(void *data,
1164                Evas *e __UNUSED__,
1165                Evas_Object *obj,
1166                void *event_info __UNUSED__)
1167 {
1168    Elm_Multibuttonentry_Item *it = data;
1169
1170    ELM_MULTIBUTTONENTRY_DATA_GET(WIDGET(it), sd);
1171
1172    if (evas_object_focus_get(obj))
1173      {
1174         if (elm_object_focus_get(sd->entry))
1175           elm_object_focus_set(sd->entry, EINA_FALSE);
1176
1177         sd->selected_item = (Elm_Object_Item *)it;
1178         elm_layout_signal_emit(VIEW(it), "focused", "");
1179
1180         if (sd->editable)
1181           elm_entry_input_panel_show(sd->entry);
1182      }
1183    else
1184      {
1185         sd->selected_item = NULL;
1186         elm_layout_signal_emit(VIEW(it), "default", "");
1187
1188         if (sd->editable)
1189           elm_entry_input_panel_hide(sd->entry);
1190      }
1191 }
1192
1193 static Eina_Bool
1194 _long_press_cb(void *data)
1195 {
1196    Elm_Multibuttonentry_Item *it = data;
1197
1198    ELM_MULTIBUTTONENTRY_DATA_GET(WIDGET(it), sd);
1199
1200    sd->longpress_timer = NULL;
1201    sd->long_pressed = EINA_TRUE;
1202
1203    evas_object_smart_callback_call(WIDGET(it), SIG_LONGPRESSED, it);
1204
1205    return ECORE_CALLBACK_CANCEL;
1206 }
1207
1208 static void
1209 _mouse_down_cb(Elm_Multibuttonentry_Item *it,
1210                Evas *evas __UNUSED__,
1211                Evas_Object *obj __UNUSED__,
1212                Evas_Event_Mouse_Down *ev)
1213 {
1214    ELM_MULTIBUTTONENTRY_DATA_GET(WIDGET(it), sd);
1215
1216    if (ev->button != 1) return;
1217
1218    sd->long_pressed = EINA_FALSE;
1219
1220    if (sd->longpress_timer) ecore_timer_del(sd->longpress_timer);
1221    sd->longpress_timer = ecore_timer_add
1222        (_elm_config->longpress_timeout, _long_press_cb, it);
1223 }
1224
1225 static void
1226 _mouse_up_cb(Elm_Multibuttonentry_Item *it,
1227              Evas *evas __UNUSED__,
1228              Evas_Object *obj __UNUSED__,
1229              Evas_Event_Mouse_Down *ev __UNUSED__)
1230 {
1231    ELM_MULTIBUTTONENTRY_DATA_GET(WIDGET(it), sd);
1232
1233    if (sd->longpress_timer)
1234      {
1235         ecore_timer_del(sd->longpress_timer);
1236         sd->longpress_timer = NULL;
1237      }
1238 }
1239
1240 static void
1241 _item_text_set_hook(Elm_Object_Item *it,
1242                     const char *part,
1243                     const char *text)
1244 {
1245    if (part && strcmp(part, "elm.btn.text")) return;
1246    if (!text) return;
1247
1248    elm_object_part_text_set(VIEW(it), "elm.btn.text", text);
1249 }
1250
1251 static const char *
1252 _item_text_get_hook(const Elm_Object_Item *it,
1253                     const char *part)
1254 {
1255    if (part && strcmp(part, "elm.btn.text")) return NULL;
1256
1257    return elm_object_part_text_get(VIEW(it), "elm.btn.text");
1258 }
1259
1260 static Eina_Bool
1261 _item_del_pre_hook(Elm_Object_Item *it)
1262 {
1263    ELM_MULTIBUTTONENTRY_DATA_GET(WIDGET(it), sd);
1264
1265    sd->items = eina_list_remove(sd->items, it);
1266
1267    if (!elm_object_focus_get(WIDGET(it)) && !sd->expanded)
1268      _layout_shrink(WIDGET(it), EINA_TRUE);
1269
1270 #ifdef _VI_EFFECT
1271    Elm_Transit *trans;
1272    Evas_Object *rect;
1273
1274    trans = (Elm_Transit *)evas_object_data_get(VIEW(it), "transit");
1275    if (trans)
1276      {
1277         elm_transit_del_cb_set(trans, NULL, NULL);
1278         elm_transit_del(trans);
1279      }
1280
1281    rect = (Evas_Object *)evas_object_data_get(VIEW(it), "effect_rect");
1282    if (rect)
1283      {
1284         Ecore_Animator *anim;
1285         anim = (Ecore_Animator*)evas_object_data_get(rect, "animator");
1286         if (anim) ecore_animator_del(anim);
1287
1288         evas_object_del(rect);
1289         evas_object_data_set(VIEW(it), "effect_rect", NULL);
1290
1291         if (sd->editable)
1292           {
1293              elm_box_pack_end(sd->box, sd->entry);
1294              evas_object_show(sd->entry);
1295              if (elm_object_focus_get(WIDGET(it)))
1296                elm_object_focus_set(sd->entry, EINA_TRUE);
1297           }
1298      }
1299 #endif
1300
1301    if (!sd->items && !elm_object_focus_get(WIDGET(it)) &&
1302        sd->guide && !_guide_packed(WIDGET(it)))
1303      {
1304         if (sd->editable)
1305           {
1306              elm_box_unpack(sd->box, sd->entry);
1307              evas_object_hide(sd->entry);
1308           }
1309
1310         elm_box_pack_end(sd->box, sd->guide);
1311         evas_object_show(sd->guide);
1312      }
1313
1314    evas_object_smart_callback_call(WIDGET(it), SIG_ITEM_DELETED, it);
1315
1316    return EINA_TRUE;
1317 }
1318
1319 static char *
1320 _access_info_cb(void *data, Evas_Object *obj __UNUSED__)
1321 {
1322    Elm_Multibuttonentry_Item *it = (Elm_Multibuttonentry_Item *)data;
1323    const char *txt = NULL;
1324    Eina_Strbuf *buf = NULL;
1325    char *str = NULL;
1326
1327    if (!it) return NULL;
1328
1329    if (!txt)txt = elm_object_item_text_get((Elm_Object_Item *)it);
1330    if (txt)
1331      {
1332         buf = eina_strbuf_new();
1333         eina_strbuf_append(buf, E_(" double tap to edit"));
1334         eina_strbuf_prepend(buf, txt);
1335         str = eina_strbuf_string_steal(buf);
1336         eina_strbuf_free(buf);
1337         return str;
1338      }
1339
1340    return NULL;
1341 }
1342
1343 static char *
1344 _access_state_cb(void *data, Evas_Object *obj __UNUSED__)
1345 {
1346    Elm_Multibuttonentry_Item *it = (Elm_Multibuttonentry_Item *)data;
1347    if (!it) return NULL;
1348
1349    if (it->base.disabled)
1350      return strdup(E_("State: Disabled"));
1351
1352    return NULL;
1353 }
1354
1355 static void
1356 _access_activate_cb(void *data __UNUSED__,
1357                     Evas_Object *part_obj __UNUSED__,
1358                     Elm_Object_Item *item)
1359 {
1360    _on_item_selected(item, NULL, NULL, NULL);
1361 }
1362
1363 static void
1364 _access_widget_item_register(Elm_Multibuttonentry_Item *it, Eina_Bool is_access)
1365 {
1366    Elm_Access_Info *ai;
1367
1368    if (!is_access) _elm_access_widget_item_unregister((Elm_Widget_Item *)it);
1369    else
1370      {
1371         _elm_access_widget_item_register((Elm_Widget_Item *)it);
1372
1373         ai = _elm_access_object_get(it->base.access_obj);
1374
1375         _elm_access_callback_set(ai, ELM_ACCESS_INFO, _access_info_cb, it);
1376         _elm_access_callback_set(ai, ELM_ACCESS_STATE, _access_state_cb, it);
1377         _elm_access_activate_callback_set(ai, _access_activate_cb, it);
1378      }
1379 }
1380
1381 static Elm_Multibuttonentry_Item *
1382 _item_new(Evas_Object *obj,
1383           const char *text,
1384           Evas_Smart_Cb func,
1385           const void *data)
1386 {
1387    Elm_Multibuttonentry_Item *it;
1388    Elm_Multibuttonentry_Item_Filter *ft;
1389    Eina_List *l;
1390    const char *str;
1391    Evas_Coord minw, minh, maxw = 0;
1392
1393    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
1394
1395    EINA_LIST_FOREACH(sd->filters, l, ft)
1396      {
1397         if (!ft->func(obj, text, data, ft->data))
1398           return NULL;
1399      }
1400
1401    it = elm_widget_item_new(obj, Elm_Multibuttonentry_Item);
1402    if (!it) return NULL;
1403
1404    VIEW(it) = elm_layout_add(obj);
1405    elm_layout_theme_set
1406       (VIEW(it), "multibuttonentry", "btn", elm_widget_style_get(obj));
1407    elm_layout_signal_callback_add
1408       (VIEW(it), "elm,action,clicked", "", _on_item_clicked, it);
1409    elm_layout_signal_callback_add
1410       (VIEW(it), "elm,action,selected", "", _on_item_selected, it);
1411    evas_object_event_callback_add
1412       (elm_layout_edje_get(VIEW(it)),
1413        EVAS_CALLBACK_FOCUS_IN, _on_item_focus, it);
1414    evas_object_event_callback_add
1415       (elm_layout_edje_get(VIEW(it)),
1416        EVAS_CALLBACK_FOCUS_OUT, _on_item_focus, it);
1417    evas_object_event_callback_add
1418       (elm_layout_edje_get(VIEW(it)),
1419        EVAS_CALLBACK_MOUSE_DOWN, (Evas_Object_Event_Cb)_mouse_down_cb, it);
1420    evas_object_event_callback_add
1421       (elm_layout_edje_get(VIEW(it)),
1422        EVAS_CALLBACK_MOUSE_UP, (Evas_Object_Event_Cb)_mouse_up_cb, it);
1423    elm_object_part_text_set(VIEW(it), "elm.btn.text", text);
1424
1425    it->func = func;
1426    it->base.data = data;
1427
1428    // adjust item size if item is longer than maximum size
1429    evas_object_smart_calculate(VIEW(it));
1430    evas_object_size_hint_min_get(VIEW(it), &minw, &minh);
1431    str = elm_layout_data_get(VIEW(it), "button_max_size");
1432    if (str) maxw = atoi(str);
1433    maxw = maxw * elm_widget_scale_get(obj) * elm_config_scale_get();
1434    if (minw > maxw)
1435      {
1436         elm_layout_signal_emit(VIEW(it), "elm,state,text,ellipsis", "");
1437         elm_layout_sizing_eval(VIEW(it));
1438      }
1439
1440    elm_widget_item_text_set_hook_set(it, _item_text_set_hook);
1441    elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
1442    elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
1443
1444    sd->item_be_selected = EINA_TRUE;
1445
1446    // ACCESS
1447    if (_elm_config->access_mode) _access_widget_item_register(it, EINA_TRUE);
1448
1449    return it;
1450 }
1451
1452 static void
1453 _on_entry_unfocused(void *data,
1454                     Evas_Object *obj,
1455                     void *event_info __UNUSED__)
1456 {
1457    char *str;
1458
1459    ELM_MULTIBUTTONENTRY_DATA_GET(data, sd);
1460
1461    str = elm_entry_markup_to_utf8(elm_object_text_get(obj));
1462    if (strlen(str))
1463      {
1464         Elm_Multibuttonentry_Item *it;
1465
1466         it = _item_new(data, str, NULL, NULL);
1467         if (!it) return;
1468
1469         sd->items = eina_list_append(sd->items, it);
1470 #ifdef _VI_EFFECT
1471         _item_adding_effect_add(data, it);
1472 #else
1473         elm_box_pack_before(sd->box, VIEW(it), obj);
1474         evas_object_show(VIEW(it));
1475         evas_object_smart_callback_call(data, SIG_ITEM_ADDED, it);
1476 #endif
1477
1478         elm_object_text_set(obj, "");
1479      }
1480    free(str);
1481 }
1482
1483 // handles semicolon, comma (before inserting them to the entry)
1484 static void
1485 _entry_filter(void *data,
1486               Evas_Object *entry,
1487               char **text)
1488 {
1489    char *str;
1490
1491    ELM_MULTIBUTTONENTRY_DATA_GET(data, sd);
1492
1493    if (!*text || !strlen(*text)) return;
1494
1495    // cancels item_be_selected when text inserting is started
1496    if (strcmp(*text, ";") && strcmp(*text, ","))
1497      {
1498         sd->item_be_selected = EINA_FALSE;
1499         return;
1500      }
1501
1502    str = elm_entry_markup_to_utf8(elm_object_text_get(entry));
1503    if (strlen(str))
1504      {
1505         Elm_Multibuttonentry_Item *it;
1506
1507         it = _item_new(data, str, NULL, NULL);
1508         if (!it) return;
1509
1510         sd->items = eina_list_append(sd->items, it);
1511 #ifdef _VI_EFFECT
1512         _item_adding_effect_add(data, it);
1513 #else
1514         elm_box_pack_before(sd->box, VIEW(it), entry);
1515         evas_object_show(VIEW(it));
1516         evas_object_smart_callback_call(data, SIG_ITEM_ADDED, it);
1517 #endif
1518
1519         elm_object_text_set(entry, "");
1520      }
1521    free(str);
1522
1523    free(*text);
1524    *text = NULL;
1525 }
1526
1527 // handles enter key
1528 static void
1529 _on_entry_key_down(void *data,
1530                  Evas *e __UNUSED__,
1531                  Evas_Object *obj,
1532                  void *event_info)
1533 {
1534    char *str;
1535    Evas_Event_Key_Up *ev = (Evas_Event_Key_Up *)event_info;
1536
1537    ELM_MULTIBUTTONENTRY_DATA_GET(data, sd);
1538
1539    // cancels item_be_selected when text inserting is started
1540    if (strcmp(ev->keyname, "KP_Enter") && strcmp(ev->keyname, "Return") &&
1541        strcmp(ev->keyname, "BackSpace") && strcmp(ev->keyname, "Delete") &&
1542        strcmp(ev->keyname, "semicolon") && strcmp(ev->keyname, "comma"))
1543      {
1544         sd->item_be_selected = EINA_FALSE;
1545         return;
1546      }
1547
1548    if (!strcmp(ev->keyname, "KP_Enter") || !strcmp(ev->keyname, "Return"))
1549      {
1550         str = elm_entry_markup_to_utf8(elm_object_text_get(obj));
1551         if (strlen(str))
1552           {
1553              Elm_Multibuttonentry_Item *it;
1554
1555              it = _item_new(data, str, NULL, NULL);
1556              if (!it) return;
1557
1558              sd->items = eina_list_append(sd->items, it);
1559 #ifdef _VI_EFFECT
1560              _item_adding_effect_add(data, it);
1561 #else
1562              elm_box_pack_before(sd->box, VIEW(it), obj);
1563              evas_object_show(VIEW(it));
1564              evas_object_smart_callback_call(data, SIG_ITEM_ADDED, it);
1565 #endif
1566
1567              elm_object_text_set(obj, "");
1568           }
1569         free(str);
1570      }
1571 }
1572
1573 // handles delete key
1574 // it can be pressed when button is selected, so it is handled on layout_key_down
1575 static void
1576 _on_layout_key_down(void *data __UNUSED__,
1577                   Evas *e __UNUSED__,
1578                   Evas_Object *obj,
1579                   void *event_info)
1580 {
1581    char *str;
1582    Evas_Event_Key_Up *ev = (Evas_Event_Key_Up *)event_info;
1583
1584    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
1585
1586    if (strcmp(ev->keyname, "BackSpace") && strcmp(ev->keyname, "Delete"))
1587      return;
1588
1589    str = elm_entry_markup_to_utf8(elm_object_text_get(sd->entry));
1590    if (strlen(str))
1591      {
1592         free(str);
1593         return;
1594      }
1595    free(str);
1596
1597    if (!sd->items) return;
1598
1599    if (!sd->selected_item)
1600      {
1601         if (sd->item_be_selected) // 2nd delete
1602           {
1603              Elm_Multibuttonentry_Item *it;
1604
1605              it = eina_list_data_get(eina_list_last(sd->items));
1606              evas_object_focus_set(elm_layout_edje_get(VIEW(it)), EINA_TRUE);
1607           }
1608         else // 1st delete
1609           sd->item_be_selected = EINA_TRUE;
1610      }
1611    else // 3rd delete
1612      {
1613 #ifdef _VI_EFFECT
1614         Elm_Transit *trans;
1615         Evas_Object *rect;
1616
1617         trans = (Elm_Transit *)evas_object_data_get(VIEW(sd->selected_item), "transit");
1618         rect = (Evas_Object *)evas_object_data_get(VIEW(sd->selected_item), "effect_rect");
1619
1620         if (!trans && !rect)
1621           _item_deleting_effect_add
1622              (obj, (Elm_Multibuttonentry_Item *)sd->selected_item);
1623 #else
1624         elm_object_item_del(sd->selected_item);
1625
1626         if (sd->editable)
1627           elm_object_focus_set(sd->entry, EINA_TRUE);
1628 #endif
1629      }
1630 }
1631
1632 static void
1633 _on_layout_clicked(void *data __UNUSED__,
1634                    Evas_Object *obj,
1635                    const char *emission __UNUSED__,
1636                    const char *source __UNUSED__)
1637 {
1638    evas_object_smart_callback_call(obj, SIG_CLICKED, NULL);
1639 }
1640
1641 static Eina_Bool
1642 _elm_multibuttonentry_smart_on_focus(Evas_Object *obj)
1643 {
1644    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
1645
1646    if (!ELM_WIDGET_CLASS(_elm_multibuttonentry_parent_sc)->on_focus(obj))
1647      return EINA_FALSE;
1648
1649    if (elm_object_focus_get(obj))
1650      {
1651         // ACCESS
1652         //if ((_elm_config->access_mode == ELM_ACCESS_MODE_ON)) return EINA_TRUE;
1653
1654         if (sd->guide && _guide_packed(obj))
1655           {
1656              elm_box_unpack(sd->box, sd->guide);
1657              evas_object_hide(sd->guide);
1658
1659              if (sd->editable)
1660                {
1661                   elm_box_pack_end(sd->box, sd->entry);
1662                   evas_object_show(sd->entry);
1663                }
1664           }
1665         // when object gets focused, it should be expanded layout
1666         else if (!sd->expanded)
1667           _layout_expand(obj);
1668
1669         if (sd->editable)
1670           {
1671              elm_layout_signal_emit(obj, "elm,state,event,allow", "");
1672              elm_object_focus_set(sd->entry, EINA_TRUE);
1673           }
1674
1675         evas_object_smart_callback_call(obj, SIG_FOCUSED, NULL);
1676      }
1677    else
1678      {
1679         if (!sd->items && sd->guide)
1680           {
1681              if (sd->editable)
1682                {
1683                   elm_box_unpack(sd->box, sd->entry);
1684                   evas_object_hide(sd->entry);
1685                }
1686
1687              elm_box_pack_end(sd->box, sd->guide);
1688              evas_object_show(sd->guide);
1689           }
1690         // if shrinked mode was set, it goes back to shrinked layout
1691         else if (!sd->expanded)
1692           _layout_shrink(obj, EINA_FALSE);
1693
1694         if (sd->editable)
1695           elm_layout_signal_emit(obj, "elm,state,event,block", "");
1696
1697         if (sd->selected_item)
1698           evas_object_focus_set
1699              (elm_layout_edje_get(VIEW(sd->selected_item)), EINA_FALSE);
1700
1701         evas_object_smart_callback_call(obj, SIG_UNFOCUSED, NULL);
1702      }
1703
1704    return EINA_TRUE;
1705 }
1706
1707 static Eina_Bool
1708 _elm_multibuttonentry_smart_text_set(Evas_Object *obj,
1709                                      const char *part,
1710                                      const char *text)
1711 {
1712    if (!part || (part && !strcmp(part, "label")))
1713      {
1714         if (text) _label_set(obj, text);
1715         return EINA_TRUE;
1716      }
1717    else if (part && !strcmp(part, "guide"))
1718      {
1719         if (text) _guide_set(obj, text);
1720         return EINA_TRUE;
1721      }
1722    else return _elm_multibuttonentry_parent_sc->text_set(obj, part, text);
1723 }
1724
1725 static const char *
1726 _elm_multibuttonentry_smart_text_get(const Evas_Object *obj,
1727                                      const char *part)
1728 {
1729    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
1730
1731    if (!part || !strcmp(part, "label"))
1732      return elm_object_part_text_get(sd->label, "mbe.label");
1733    else if (!strcmp(part, "guide"))
1734      return elm_object_text_get(sd->guide);
1735    else return _elm_multibuttonentry_parent_sc->text_get(obj, part);
1736 }
1737
1738 static void
1739 _elm_multibuttonentry_smart_sizing_eval(Evas_Object *obj)
1740 {
1741    Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
1742
1743    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
1744
1745    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
1746    edje_object_size_min_restricted_calc
1747       (ELM_WIDGET_DATA(sd)->resize_obj, &minw, &minh, minw, minh);
1748    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
1749    evas_object_size_hint_min_set(obj, minw, minh);
1750    evas_object_size_hint_max_set(obj, maxw, maxh);
1751 }
1752
1753 static Eina_Bool
1754 _elm_multibuttonentry_smart_theme(Evas_Object *obj)
1755 {
1756    const char *str;
1757    int hpad = 0, vpad = 0;
1758    Eina_List *l;
1759    Elm_Multibuttonentry_Item *it;
1760
1761    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
1762
1763    if (!ELM_WIDGET_CLASS(_elm_multibuttonentry_parent_sc)->theme(obj))
1764      return EINA_FALSE;
1765
1766    str = elm_layout_data_get(obj, "horizontal_pad");
1767    if (str) hpad = atoi(str);
1768    str = elm_layout_data_get(obj, "vertical_pad");
1769    if (str) vpad = atoi(str);
1770    elm_box_padding_set
1771       (sd->box,
1772        hpad * elm_widget_scale_get(obj) * elm_config_scale_get(),
1773        vpad * elm_widget_scale_get(obj) * elm_config_scale_get());
1774
1775    elm_layout_theme_set
1776       (sd->label, "multibuttonentry", "label", elm_widget_style_get(obj));
1777    elm_layout_theme_set
1778       (sd->guide, "multibuttonentry", "guidetext", elm_widget_style_get(obj));
1779    elm_layout_theme_set
1780       (sd->end, "multibuttonentry", "number", elm_widget_style_get(obj));
1781    EINA_LIST_FOREACH(sd->items, l, it)
1782       elm_layout_theme_set
1783       (VIEW(it), "multibuttonentry", "btn", elm_widget_style_get(obj));
1784
1785    elm_layout_sizing_eval(obj);
1786
1787    return EINA_TRUE;
1788 }
1789
1790 static void
1791 _elm_multibuttonentry_smart_add(Evas_Object *obj)
1792 {
1793    const char *str;
1794    int hpad = 0, vpad = 0;
1795
1796    EVAS_SMART_DATA_ALLOC(obj, Elm_Multibuttonentry_Smart_Data);
1797
1798    ELM_WIDGET_CLASS(_elm_multibuttonentry_parent_sc)->base.add(obj);
1799    elm_layout_theme_set
1800       (obj, "multibuttonentry", "base", elm_widget_style_get(obj));
1801    elm_layout_signal_callback_add
1802       (obj, "elm,action,clicked", "", _on_layout_clicked, NULL);
1803    evas_object_event_callback_add
1804       (obj, EVAS_CALLBACK_KEY_DOWN, _on_layout_key_down, NULL);
1805
1806    priv->box = elm_box_add(obj);
1807    str = elm_layout_data_get(obj, "horizontal_pad");
1808    if (str) hpad = atoi(str);
1809    str = elm_layout_data_get(obj, "vertical_pad");
1810    if (str) vpad = atoi(str);
1811    elm_box_padding_set
1812       (priv->box,
1813        hpad * elm_widget_scale_get(obj) * elm_config_scale_get(),
1814        vpad * elm_widget_scale_get(obj) * elm_config_scale_get());
1815    elm_box_layout_set(priv->box, _box_layout, NULL, NULL);
1816    elm_layout_content_set(obj, "box.swallow", priv->box);
1817    evas_object_event_callback_add
1818       (priv->box, EVAS_CALLBACK_RESIZE, _on_box_resize, obj);
1819
1820    priv->entry = elm_entry_add(obj);
1821    elm_entry_single_line_set(priv->entry, EINA_TRUE);
1822    elm_entry_scrollable_set(priv->entry, EINA_TRUE);
1823    elm_entry_cnp_mode_set(priv->entry, ELM_CNP_MODE_PLAINTEXT);
1824    evas_object_size_hint_weight_set
1825       (priv->entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1826    evas_object_size_hint_align_set
1827       (priv->entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
1828    evas_object_event_callback_add
1829       (priv->entry, EVAS_CALLBACK_KEY_DOWN, _on_entry_key_down, obj);
1830    evas_object_smart_callback_add
1831       (priv->entry, "unfocused", _on_entry_unfocused, obj);
1832    elm_entry_markup_filter_append(priv->entry, _entry_filter, obj);
1833    elm_box_pack_end(priv->box, priv->entry);
1834    evas_object_show(priv->entry);
1835
1836    elm_widget_can_focus_set(obj, EINA_TRUE);
1837
1838    priv->editable = EINA_TRUE;
1839    priv->expanded = EINA_TRUE;
1840    priv->expanded_state = EINA_TRUE;
1841
1842 #if 0
1843    // ACCESS
1844    _elm_access_object_register(obj, ELM_WIDGET_DATA(priv)->resize_obj);
1845    _elm_access_text_set
1846       (_elm_access_object_get(obj), ELM_ACCESS_TYPE, E_("multi button entry"));
1847    _elm_access_callback_set
1848       (_elm_access_object_get(obj), ELM_ACCESS_INFO, _access_info_cb, NULL);
1849 #endif
1850 }
1851
1852 static void
1853 _elm_multibuttonentry_smart_del(Evas_Object *obj)
1854 {
1855    Elm_Multibuttonentry_Item *it;
1856    Elm_Multibuttonentry_Item_Filter *ft;
1857
1858    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
1859
1860 #ifdef _VI_EFFECT
1861    EINA_LIST_FREE(sd->items, it)
1862      {
1863         Elm_Transit *trans;
1864         Evas_Object *rect;
1865
1866         trans = (Elm_Transit *)evas_object_data_get(VIEW(it), "transit");
1867         if (trans)
1868           {
1869              elm_transit_del_cb_set(trans, NULL, NULL);
1870              elm_transit_del(trans);
1871           }
1872
1873         rect = (Evas_Object *)evas_object_data_get(VIEW(it), "effect_rect");
1874         if (rect)
1875           {
1876              Ecore_Animator *anim;
1877              anim = (Ecore_Animator*)evas_object_data_get(rect, "animator");
1878              if (anim) ecore_animator_del(anim);
1879
1880              evas_object_del(rect);
1881              evas_object_data_set(VIEW(it), "effect_rect", NULL);
1882           }
1883         elm_widget_item_free(it);
1884      }
1885 #else
1886    EINA_LIST_FREE(sd->items, it)
1887       elm_widget_item_free(it);
1888 #endif
1889
1890    EINA_LIST_FREE(sd->filters, ft)
1891       free(ft);
1892
1893    if (sd->end) evas_object_del(sd->end);
1894    if (sd->guide) evas_object_del(sd->guide);
1895    if (sd->label) evas_object_del(sd->label);
1896    if (sd->entry) evas_object_del(sd->entry);
1897    if (sd->box) evas_object_del(sd->box);
1898    if (sd->longpress_timer) ecore_timer_del(sd->longpress_timer);
1899
1900    ELM_WIDGET_CLASS(_elm_multibuttonentry_parent_sc)->base.del(obj);
1901 }
1902
1903 static void
1904 _elm_multibuttonentry_smart_access(Evas_Object *obj, Eina_Bool is_access)
1905 {
1906    Eina_List *elist = NULL;
1907    Elm_Multibuttonentry_Item *it;
1908
1909    ELM_MULTIBUTTONENTRY_CHECK(obj);
1910    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
1911
1912    EINA_LIST_FOREACH(sd->items, elist, it)
1913      _access_widget_item_register(it, is_access);
1914 }
1915
1916 static void
1917 _elm_multibuttonentry_smart_set_user(Elm_Multibuttonentry_Smart_Class *sc)
1918 {
1919    ELM_WIDGET_CLASS(sc)->base.add = _elm_multibuttonentry_smart_add;
1920    ELM_WIDGET_CLASS(sc)->base.del = _elm_multibuttonentry_smart_del;
1921
1922    ELM_WIDGET_CLASS(sc)->theme = _elm_multibuttonentry_smart_theme;
1923    ELM_WIDGET_CLASS(sc)->on_focus = _elm_multibuttonentry_smart_on_focus;
1924
1925    /* not a 'focus chain manager' */
1926    ELM_WIDGET_CLASS(sc)->focus_next = NULL;
1927    ELM_WIDGET_CLASS(sc)->focus_direction = NULL;
1928
1929    ELM_LAYOUT_CLASS(sc)->text_set = _elm_multibuttonentry_smart_text_set;
1930    ELM_LAYOUT_CLASS(sc)->text_get = _elm_multibuttonentry_smart_text_get;
1931
1932    ELM_LAYOUT_CLASS(sc)->sizing_eval = _elm_multibuttonentry_smart_sizing_eval;
1933
1934    // ACCESS
1935    if (_elm_config->access_mode)
1936       ELM_WIDGET_CLASS(sc)->focus_next = _elm_multibuttonentry_smart_focus_next;
1937
1938    ELM_WIDGET_CLASS(sc)->access = _elm_multibuttonentry_smart_access;
1939 }
1940
1941 EAPI const Elm_Multibuttonentry_Smart_Class *
1942 elm_multibuttonentry_smart_class_get(void)
1943 {
1944    static Elm_Multibuttonentry_Smart_Class _sc =
1945       ELM_MULTIBUTTONENTRY_SMART_CLASS_INIT_NAME_VERSION
1946       (ELM_MULTIBUTTONENTRY_SMART_NAME);
1947    static const Elm_Multibuttonentry_Smart_Class *class = NULL;
1948    Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
1949
1950    if (class) return class;
1951
1952    _elm_multibuttonentry_smart_set(&_sc);
1953    esc->callbacks = _smart_callbacks;
1954    class = &_sc;
1955
1956    return class;
1957 }
1958
1959 EAPI Evas_Object *
1960 elm_multibuttonentry_add(Evas_Object *parent)
1961 {
1962    Evas_Object *obj;
1963
1964    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1965
1966    obj = elm_widget_add(_elm_multibuttonentry_smart_class_new(), parent);
1967    if (!obj) return NULL;
1968
1969    if (!elm_widget_sub_object_add(parent, obj))
1970      ERR("could not add %p as sub object of %p", obj, parent);
1971
1972    return obj;
1973 }
1974
1975 EAPI Evas_Object *
1976 elm_multibuttonentry_entry_get(const Evas_Object *obj)
1977 {
1978    ELM_MULTIBUTTONENTRY_CHECK(obj) NULL;
1979    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
1980
1981    return sd->entry;
1982 }
1983
1984 EAPI void
1985 elm_multibuttonentry_expanded_set(Evas_Object *obj,
1986                                   Eina_Bool expanded)
1987 {
1988    ELM_MULTIBUTTONENTRY_CHECK(obj);
1989    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
1990
1991    expanded = !!expanded;
1992    if (sd->expanded == expanded) return;
1993    sd->expanded = expanded;
1994
1995    if (elm_object_focus_get(obj)) return;
1996
1997    if (sd->expanded)
1998      _layout_expand(obj);
1999    else
2000      _layout_shrink(obj, EINA_FALSE);
2001 }
2002
2003 EAPI Eina_Bool
2004 elm_multibuttonentry_expanded_get(const Evas_Object *obj)
2005 {
2006    ELM_MULTIBUTTONENTRY_CHECK(obj) EINA_FALSE;
2007    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
2008
2009    return (elm_object_focus_get(obj) || sd->expanded);
2010 }
2011
2012 EAPI void
2013 elm_multibuttonentry_editable_set(Evas_Object *obj,
2014                                   Eina_Bool editable)
2015 {
2016    ELM_MULTIBUTTONENTRY_CHECK(obj);
2017    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
2018
2019    editable = !!editable;
2020    if (sd->editable == editable) return;
2021    sd->editable = editable;
2022
2023    if (sd->editable)
2024      {
2025         if (!(sd->guide && _guide_packed(obj)))
2026           {
2027              elm_box_pack_end(sd->box, sd->entry);
2028              evas_object_show(sd->entry);
2029           }
2030
2031         if (!elm_object_focus_get(obj))
2032           elm_layout_signal_emit(obj, "elm,state,event,block", "");
2033      }
2034    else
2035      {
2036         if (!(sd->guide && _guide_packed(obj)))
2037           {
2038              elm_box_unpack(sd->box, sd->entry);
2039              evas_object_hide(sd->entry);
2040           }
2041
2042         if (!elm_object_focus_get(obj))
2043           elm_layout_signal_emit(obj, "elm,state,event,allow", "");
2044      }
2045 }
2046
2047 EAPI Eina_Bool
2048 elm_multibuttonentry_editable_get(const Evas_Object *obj)
2049 {
2050    ELM_MULTIBUTTONENTRY_CHECK(obj) EINA_FALSE;
2051    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
2052
2053    return sd->editable;
2054 }
2055
2056 EAPI Elm_Object_Item *
2057 elm_multibuttonentry_item_prepend(Evas_Object *obj,
2058                                   const char *label,
2059                                   Evas_Smart_Cb func,
2060                                   const void *data)
2061 {
2062    Elm_Multibuttonentry_Item *it;
2063
2064    ELM_MULTIBUTTONENTRY_CHECK(obj) NULL;
2065    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
2066
2067    if (!label) return NULL;
2068
2069    // if guide text was shown, hide it
2070    if (sd->guide && _guide_packed(obj))
2071      {
2072         elm_box_unpack(sd->box, sd->guide);
2073         evas_object_hide(sd->guide);
2074
2075         if (sd->editable)
2076           {
2077              elm_box_pack_end(sd->box, sd->entry);
2078              evas_object_show(sd->entry);
2079           }
2080      }
2081
2082    it = _item_new(obj, label, func, data);
2083    if (!it) return NULL;
2084
2085    sd->items = eina_list_prepend(sd->items, it);
2086
2087    if (!elm_object_focus_get(obj) && !sd->expanded && sd->boxw)
2088      {
2089 #ifdef _VI_EFFECT
2090         _item_adding_effect_add(obj, it);
2091 #endif
2092         _layout_shrink(obj, EINA_TRUE);
2093      }
2094    else
2095      {
2096 #ifdef _VI_EFFECT
2097         if (sd->boxh && sd->boxw)
2098           _item_adding_effect_add(obj, it);
2099         else
2100           {
2101              if (sd->label && _label_packed(obj))
2102                elm_box_pack_after(sd->box, VIEW(it), sd->label);
2103              else
2104                elm_box_pack_start(sd->box, VIEW(it));
2105              evas_object_show(VIEW(it));
2106           }
2107 #else
2108         if (sd->label && _label_packed(obj))
2109           elm_box_pack_after(sd->box, VIEW(it), sd->label);
2110         else
2111           elm_box_pack_start(sd->box, VIEW(it));
2112         evas_object_show(VIEW(it));
2113 #endif
2114      }
2115
2116 #ifdef _VI_EFFECT
2117    if (!sd->boxh || !sd->boxw)
2118      evas_object_smart_callback_call(obj, SIG_ITEM_ADDED, it);
2119 #else
2120    evas_object_smart_callback_call(obj, SIG_ITEM_ADDED, it);
2121 #endif
2122
2123    return (Elm_Object_Item *)it;
2124 }
2125
2126 EAPI Elm_Object_Item *
2127 elm_multibuttonentry_item_append(Evas_Object *obj,
2128                                  const char *label,
2129                                  Evas_Smart_Cb func,
2130                                  const void *data)
2131 {
2132    Elm_Multibuttonentry_Item *it;
2133
2134    ELM_MULTIBUTTONENTRY_CHECK(obj) NULL;
2135    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
2136
2137    if (!label) return NULL;
2138
2139    // if guide text was shown, hide it
2140    if (sd->guide && _guide_packed(obj))
2141      {
2142         elm_box_unpack(sd->box, sd->guide);
2143         evas_object_hide(sd->guide);
2144
2145         if (sd->editable)
2146           {
2147              elm_box_pack_end(sd->box, sd->entry);
2148              evas_object_show(sd->entry);
2149           }
2150      }
2151
2152    it = _item_new(obj, label, func, data);
2153    if (!it) return NULL;
2154
2155    sd->items = eina_list_append(sd->items, it);
2156
2157    if (!elm_object_focus_get(obj) && !sd->expanded && sd->boxw)
2158      {
2159 #ifdef _VI_EFFECT
2160         _item_adding_effect_add(obj, it);
2161 #endif
2162         _layout_shrink(obj, EINA_TRUE);
2163      }
2164    else
2165      {
2166 #ifdef _VI_EFFECT
2167         if (sd->boxh && sd->boxw)
2168           _item_adding_effect_add(obj, it);
2169         else
2170           {
2171              if (sd->editable)
2172                elm_box_pack_before(sd->box, VIEW(it), sd->entry);
2173              else
2174                elm_box_pack_end(sd->box, VIEW(it));
2175              evas_object_show(VIEW(it));
2176           }
2177 #else
2178         if (sd->editable)
2179           elm_box_pack_before(sd->box, VIEW(it), sd->entry);
2180         else
2181           elm_box_pack_end(sd->box, VIEW(it));
2182         evas_object_show(VIEW(it));
2183 #endif
2184      }
2185
2186 #ifdef _VI_EFFECT
2187    if (!sd->boxh || !sd->boxw)
2188      evas_object_smart_callback_call(obj, SIG_ITEM_ADDED, it);
2189 #else
2190    evas_object_smart_callback_call(obj, SIG_ITEM_ADDED, it);
2191 #endif
2192
2193    return (Elm_Object_Item *)it;
2194 }
2195
2196 EAPI Elm_Object_Item *
2197 elm_multibuttonentry_item_insert_before(Evas_Object *obj,
2198                                         Elm_Object_Item *before,
2199                                         const char *label,
2200                                         Evas_Smart_Cb func,
2201                                         const void *data)
2202 {
2203    Elm_Multibuttonentry_Item *it;
2204
2205    ELM_MULTIBUTTONENTRY_CHECK(obj) NULL;
2206    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
2207
2208    if (!label) return NULL;
2209    if (!before) return NULL;
2210
2211    it = _item_new(obj, label, func, data);
2212    if (!it) return NULL;
2213
2214    sd->items = eina_list_prepend_relative(sd->items, it, before);
2215
2216    if (!elm_object_focus_get(obj) && !sd->expanded && sd->boxw)
2217      {
2218 #ifdef _VI_EFFECT
2219         _item_adding_effect_add(obj, it);
2220 #endif
2221         _layout_shrink(obj, EINA_TRUE);
2222      }
2223    else
2224      {
2225 #ifdef _VI_EFFECT
2226         if (sd->boxh && sd->boxw)
2227           _item_adding_effect_add(obj, it);
2228         else
2229           {
2230              elm_box_pack_before(sd->box, VIEW(it), VIEW(before));
2231              evas_object_show(VIEW(it));
2232           }
2233 #else
2234         elm_box_pack_before(sd->box, VIEW(it), VIEW(before));
2235         evas_object_show(VIEW(it));
2236 #endif
2237      }
2238
2239 #ifdef _VI_EFFECT
2240    if (!sd->boxh || !sd->boxw)
2241      evas_object_smart_callback_call(obj, SIG_ITEM_ADDED, it);
2242 #else
2243    evas_object_smart_callback_call(obj, SIG_ITEM_ADDED, it);
2244 #endif
2245
2246    return (Elm_Object_Item *)it;
2247 }
2248
2249 EAPI Elm_Object_Item *
2250 elm_multibuttonentry_item_insert_after(Evas_Object *obj,
2251                                        Elm_Object_Item *after,
2252                                        const char *label,
2253                                        Evas_Smart_Cb func,
2254                                        const void *data)
2255 {
2256    Elm_Multibuttonentry_Item *it;
2257
2258    ELM_MULTIBUTTONENTRY_CHECK(obj) NULL;
2259    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
2260
2261    if (!label) return NULL;
2262    if (!after) return NULL;
2263
2264    it = _item_new(obj, label, func, data);
2265    if (!it) return NULL;
2266
2267    sd->items = eina_list_append_relative(sd->items, it, after);
2268
2269    if (!elm_object_focus_get(obj) && !sd->expanded && sd->boxw)
2270      {
2271 #ifdef _VI_EFFECT
2272         _item_adding_effect_add(obj, it);
2273 #endif
2274         _layout_shrink(obj, EINA_TRUE);
2275      }
2276    else
2277      {
2278 #ifdef _VI_EFFECT
2279         if (sd->boxw && sd->boxh)
2280           _item_adding_effect_add(obj, it);
2281         else
2282           {
2283              elm_box_pack_after(sd->box, VIEW(it), VIEW(after));
2284              evas_object_show(VIEW(it));
2285           }
2286 #else
2287         elm_box_pack_after(sd->box, VIEW(it), VIEW(after));
2288         evas_object_show(VIEW(it));
2289 #endif
2290      }
2291
2292 #ifdef _VI_EFFECT
2293    if (!sd->boxh || !sd->boxw)
2294      evas_object_smart_callback_call(obj, SIG_ITEM_ADDED, it);
2295 #else
2296    evas_object_smart_callback_call(obj, SIG_ITEM_ADDED, it);
2297 #endif
2298
2299    return (Elm_Object_Item *)it;
2300 }
2301
2302 EAPI const Eina_List *
2303 elm_multibuttonentry_items_get(const Evas_Object *obj)
2304 {
2305    ELM_MULTIBUTTONENTRY_CHECK(obj) NULL;
2306    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
2307
2308    return sd->items;
2309 }
2310
2311 EAPI Evas_Object *
2312 elm_multibuttonentry_item_object_get(const Elm_Object_Item *it)
2313 {
2314    ELM_MULTIBUTTONENTRY_ITEM_CHECK_OR_RETURN(it, NULL);
2315
2316    return VIEW(it);
2317 }
2318
2319 EAPI Elm_Object_Item *
2320 elm_multibuttonentry_first_item_get(const Evas_Object *obj)
2321 {
2322    ELM_MULTIBUTTONENTRY_CHECK(obj) NULL;
2323    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
2324
2325    return eina_list_data_get(sd->items);
2326 }
2327
2328 EAPI Elm_Object_Item *
2329 elm_multibuttonentry_last_item_get(const Evas_Object *obj)
2330 {
2331    ELM_MULTIBUTTONENTRY_CHECK(obj) NULL;
2332    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
2333
2334    return eina_list_data_get(eina_list_last(sd->items));
2335 }
2336
2337 EAPI Elm_Object_Item *
2338 elm_multibuttonentry_selected_item_get(const Evas_Object *obj)
2339 {
2340    ELM_MULTIBUTTONENTRY_CHECK(obj) NULL;
2341    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
2342
2343    return sd->selected_item;
2344 }
2345
2346 EAPI void
2347 elm_multibuttonentry_item_selected_set(Elm_Object_Item *it,
2348                                        Eina_Bool selected)
2349 {
2350    ELM_MULTIBUTTONENTRY_ITEM_CHECK_OR_RETURN(it);
2351    ELM_MULTIBUTTONENTRY_DATA_GET(WIDGET(it), sd);
2352
2353    if (!elm_object_focus_get(WIDGET(it))) return;
2354
2355    if (selected && it != sd->selected_item)
2356      {
2357         evas_object_focus_set(elm_layout_edje_get(VIEW(it)), EINA_TRUE);
2358      }
2359    else if (!selected && it == sd->selected_item)
2360      {
2361         evas_object_focus_set(elm_layout_edje_get(VIEW(it)), EINA_FALSE);
2362
2363         if (sd->editable)
2364           elm_object_focus_set(sd->entry, EINA_TRUE);
2365      }
2366 }
2367
2368 EAPI Eina_Bool
2369 elm_multibuttonentry_item_selected_get(const Elm_Object_Item *it)
2370 {
2371    ELM_MULTIBUTTONENTRY_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
2372    ELM_MULTIBUTTONENTRY_DATA_GET(WIDGET(it), sd);
2373
2374    if (!elm_object_focus_get(WIDGET(it))) return EINA_FALSE;
2375
2376    if (it == sd->selected_item)
2377      return EINA_TRUE;
2378
2379    return EINA_FALSE;
2380 }
2381
2382 EAPI void
2383 elm_multibuttonentry_clear(Evas_Object *obj)
2384 {
2385    Elm_Multibuttonentry_Item *it;
2386
2387    ELM_MULTIBUTTONENTRY_CHECK(obj);
2388    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
2389
2390 #ifdef _VI_EFFECT
2391    EINA_LIST_FREE(sd->items, it)
2392      {
2393         Elm_Transit *trans;
2394         Evas_Object *rect;
2395
2396         trans = (Elm_Transit *)evas_object_data_get(VIEW(it), "transit");
2397         if (trans)
2398           {
2399              elm_transit_del_cb_set(trans, NULL, NULL);
2400              elm_transit_del(trans);
2401           }
2402
2403         rect = (Evas_Object *)evas_object_data_get(VIEW(it), "effect_rect");
2404         if (rect)
2405           {
2406              Ecore_Animator *anim;
2407
2408              anim = (Ecore_Animator*)evas_object_data_get(rect, "animator");
2409              if (anim) ecore_animator_del(anim);
2410
2411              evas_object_del(rect);
2412              evas_object_data_set(VIEW(it), "effect_rect", NULL);
2413
2414              if (sd->editable)
2415                {
2416                   elm_box_pack_end(sd->box, sd->entry);
2417                   evas_object_show(sd->entry);
2418                   if (elm_object_focus_get(WIDGET(it)))
2419                     elm_object_focus_set(sd->entry, EINA_TRUE);
2420                }
2421           }
2422         elm_widget_item_free(it);
2423      }
2424 #else
2425    EINA_LIST_FREE(sd->items, it)
2426       elm_widget_item_free(it);
2427 #endif
2428
2429    sd->items = NULL;
2430    sd->item_be_selected = EINA_FALSE;
2431    sd->expanded_state = EINA_TRUE;
2432
2433    if (sd->end)
2434      {
2435         evas_object_del(sd->end);
2436         sd->end = NULL;
2437      }
2438
2439    if (!sd->items && !elm_object_focus_get(obj) &&
2440        sd->guide && !_guide_packed(obj))
2441      {
2442         if (sd->editable)
2443           {
2444              elm_box_unpack(sd->box, sd->entry);
2445              evas_object_hide(sd->entry);
2446           }
2447
2448         elm_box_pack_end(sd->box, sd->guide);
2449         evas_object_show(sd->guide);
2450      }
2451 }
2452
2453 EAPI Elm_Object_Item *
2454 elm_multibuttonentry_item_prev_get(const Elm_Object_Item *it)
2455 {
2456    Eina_List *l;
2457    Elm_Multibuttonentry_Item *item;
2458
2459    ELM_MULTIBUTTONENTRY_ITEM_CHECK_OR_RETURN(it, NULL);
2460    ELM_MULTIBUTTONENTRY_DATA_GET(WIDGET(it), sd);
2461
2462    EINA_LIST_FOREACH(sd->items, l, item)
2463      {
2464         if (item == (Elm_Multibuttonentry_Item *)it)
2465           {
2466              l = eina_list_prev(l);
2467              if (!l) return NULL;
2468              return eina_list_data_get(l);
2469           }
2470      }
2471    return NULL;
2472 }
2473
2474 EAPI Elm_Object_Item *
2475 elm_multibuttonentry_item_next_get(const Elm_Object_Item *it)
2476 {
2477    Eina_List *l;
2478    Elm_Multibuttonentry_Item *item;
2479
2480    ELM_MULTIBUTTONENTRY_ITEM_CHECK_OR_RETURN(it, NULL);
2481    ELM_MULTIBUTTONENTRY_DATA_GET(WIDGET(it), sd);
2482
2483    EINA_LIST_FOREACH(sd->items, l, item)
2484      {
2485         if (item == (Elm_Multibuttonentry_Item *)it)
2486           {
2487              l = eina_list_next(l);
2488              if (!l) return NULL;
2489              return eina_list_data_get(l);
2490           }
2491      }
2492    return NULL;
2493 }
2494
2495 EAPI void
2496 elm_multibuttonentry_item_filter_append(Evas_Object *obj,
2497                                         Elm_Multibuttonentry_Item_Filter_Cb func,
2498                                         const void *data)
2499 {
2500    Elm_Multibuttonentry_Item_Filter *ft = NULL;
2501
2502    ELM_MULTIBUTTONENTRY_CHECK(obj);
2503    EINA_SAFETY_ON_NULL_RETURN(func);
2504    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
2505
2506    ft = _filter_new(func, data);
2507    if (!ft) return;
2508
2509    sd->filters = eina_list_append(sd->filters, ft);
2510 }
2511
2512 EAPI void
2513 elm_multibuttonentry_item_filter_prepend(Evas_Object *obj,
2514                                          Elm_Multibuttonentry_Item_Filter_Cb func,
2515                                          const void *data)
2516 {
2517    Elm_Multibuttonentry_Item_Filter *ft = NULL;
2518
2519    ELM_MULTIBUTTONENTRY_CHECK(obj);
2520    EINA_SAFETY_ON_NULL_RETURN(func);
2521    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
2522
2523    ft = _filter_new(func, data);
2524    if (!ft) return;
2525
2526    sd->filters = eina_list_prepend(sd->filters, ft);
2527 }
2528
2529 EAPI void
2530 elm_multibuttonentry_item_filter_remove(Evas_Object *obj,
2531                                         Elm_Multibuttonentry_Item_Filter_Cb func,
2532                                         const void *data)
2533 {
2534    Elm_Multibuttonentry_Item_Filter *ft;
2535    Eina_List *l;
2536
2537    ELM_MULTIBUTTONENTRY_CHECK(obj);
2538    EINA_SAFETY_ON_NULL_RETURN(func);
2539    ELM_MULTIBUTTONENTRY_DATA_GET(obj, sd);
2540
2541    EINA_LIST_FOREACH(sd->filters, l, ft)
2542      {
2543         if ((ft->func == func) && (!data || ft->data == data))
2544           {
2545              sd->filters = eina_list_remove_list(sd->filters, l);
2546              free(ft);
2547              return;
2548           }
2549      }
2550 }