[elm_multibuttonentry.c]Bug fix: More than 1 focus at a time in Email App
[framework/uifw/elementary.git] / src / lib / elm_multibuttonentry.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 /**
5  * @defgroup Multibuttonentry Multibuttonentry
6  * @ingroup Elementary
7  *
8  * This is a Multibuttonentry.
9  */
10
11 #define MAX_STR 256
12 #define MIN_W_ENTRY 20
13
14 typedef enum _Multibuttonentry_Pos
15 {
16    MULTIBUTONENTRY_POS_START,
17    MULTIBUTONENTRY_POS_END,
18    MULTIBUTONENTRY_POS_BEFORE,
19    MULTIBUTONENTRY_POS_AFTER,
20    MULTIBUTONENTRY_POS_NUM
21 } Multibuttonentry_Pos;
22
23 typedef enum _Multibuttonentry_Button_State
24 {
25    MULTIBUTONENTRY_BUTTON_STATE_DEFAULT,
26    MULTIBUTONENTRY_BUTTON_STATE_SELECTED,
27    MULTIBUTONENTRY_BUTTON_STATE_NUM
28 } Multibuttonentry_Button_State;
29
30 typedef enum _MultiButtonEntry_Closed_Button_Type {
31    MULTIBUTTONENTRY_CLOSED_IMAGE,
32    MULTIBUTTONENTRY_CLOSED_LABEL
33 } MultiButtonEntry_Closed_Button_Type;
34
35 typedef enum _Multibuttonentry_View_State
36 {
37    MULTIBUTTONENTRY_VIEW_NONE,
38    MULTIBUTTONENTRY_VIEW_GUIDETEXT,
39    MULTIBUTTONENTRY_VIEW_ENTRY,
40    MULTIBUTTONENTRY_VIEW_CONTRACTED
41 } Multibuttonentry_View_State;
42
43 struct _Multibuttonentry_Item {
44    Evas_Object *multibuttonentry;
45    Evas_Object *button;
46    void *data;
47    Evas_Coord vw, rw; // vw: visual width, real width
48    Eina_Bool  visible: 1;
49 };
50
51 typedef struct _Widget_Data Widget_Data;
52 struct _Widget_Data {
53    Evas_Object *base;
54    Evas_Object *box;
55    Evas_Object *entry;
56    Evas_Object *label;
57    Evas_Object *guidetext;
58    Evas_Object *end;   // used to represent the total number of invisible buttons
59
60    Evas_Object *rectForEnd;
61    MultiButtonEntry_Closed_Button_Type end_type;
62
63    Eina_List *items;
64    Eina_List *current;
65    int n_str;
66    Multibuttonentry_View_State view_state;
67
68    Evas_Coord w_box, h_box;
69    int  contracted;
70    Eina_Bool focused: 1;
71    Eina_Bool last_btn_select: 1;
72    Ecore_IMF_Context *imf_context;
73    Elm_Multibuttonentry_Item_Verify_Callback add_callback;
74    void *add_callback_data;
75 };
76
77 static const char *widtype = NULL;
78 static void _del_hook(Evas_Object *obj);
79 static void _theme_hook(Evas_Object *obj);
80 static void _on_focus_hook(void *data __UNUSED__, Evas_Object *obj);
81 static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src, Evas_Callback_Type type, void *event_info);
82 static void _sizing_eval(Evas_Object *obj);
83 static void _changed_size_hint_cb(void *data, Evas *evas, Evas_Object *obj, void *event);
84 static void _resize_cb(void *data, Evas *evas, Evas_Object *obj, void *event);
85 static void _event_init(Evas_Object *obj);
86 static void _contracted_state_set(Evas_Object *obj, int contracted);
87 static void _view_update(Evas_Object *obj);
88 static void _set_label(Evas_Object *obj, const char* str);
89 static void _change_current_button_state(Evas_Object *obj, Multibuttonentry_Button_State state);
90 static void _change_current_button(Evas_Object *obj, Evas_Object *btn);
91 static void _button_clicked(void *data, Evas_Object *obj, const char *emission, const char *source);
92 static void _del_button_obj(Evas_Object *obj, Evas_Object *btn);
93 static void _del_button_item(Elm_Multibuttonentry_Item *item);
94 static void _del_button(Evas_Object *obj);
95 static void _select_button(Evas_Object *obj, Evas_Object *btn);
96 static Elm_Multibuttonentry_Item* _add_button_item(Evas_Object *obj, const char *str, Multibuttonentry_Pos pos, const Elm_Multibuttonentry_Item *reference, void *data);
97 static void _add_button(Evas_Object *obj, char *str);
98 static void _evas_mbe_key_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
99 static void _entry_changed_cb(void *data, Evas_Object *obj, void *event_info);
100 static void _entry_key_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
101 static void _entry_key_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
102 static void _entry_focus_in_cb(void *data, Evas *e, __UNUSED__ void *event_info);
103 static void _entry_focus_out_cb(void *data, Evas *e, __UNUSED__ void *event_info);
104 static void _view_init(Evas_Object *obj);
105 static void _set_vis_guidetext(Evas_Object *obj);
106 static void _calculate_box_min_size(Evas_Object *box, Evas_Object_Box_Data *priv);
107 static Evas_Coord _calculate_item_max_height(Evas_Object *box, Evas_Object_Box_Data *priv, int obj_index);
108 static void _box_layout_cb(Evas_Object *o, Evas_Object_Box_Data *priv, void *data);
109
110 static void
111 _del_hook(Evas_Object *obj)
112 {
113    Widget_Data *wd = elm_widget_data_get(obj);
114    if (!wd) return;
115
116    if (wd->items)
117      {
118         Elm_Multibuttonentry_Item *item;
119         EINA_LIST_FREE(wd->items, item)
120           {
121              _del_button_obj(obj, item->button);
122              free(item);
123           }
124         wd->items = NULL;
125      }
126    wd->current = NULL;
127
128    if (wd->entry) evas_object_del (wd->entry);
129    if (wd->label) evas_object_del (wd->label);
130    if (wd->guidetext) evas_object_del (wd->guidetext);
131    if (wd->end) evas_object_del (wd->end);
132    if (wd->rectForEnd) evas_object_del(wd->rectForEnd);
133 }
134
135 static void
136 _theme_hook(Evas_Object *obj)
137 {
138    Widget_Data *wd = elm_widget_data_get(obj);
139    Eina_List *l;
140    Elm_Multibuttonentry_Item *item;
141    if (!wd) return;
142
143    _elm_theme_object_set(obj, wd->base, "multibuttonentry", "base", elm_widget_style_get(obj));
144    if (wd->box)   edje_object_part_swallow (wd->base, "box.swallow", wd->box);
145    edje_object_scale_set(wd->base, elm_widget_scale_get(obj) * _elm_config->scale);
146
147    EINA_LIST_FOREACH(wd->items, l, item)
148      {
149         if (item->button)
150           _elm_theme_object_set(obj, item->button, "multibuttonentry", "btn", elm_widget_style_get (obj));
151         edje_object_scale_set(item->button, elm_widget_scale_get(obj) * _elm_config->scale);
152      }
153
154    _sizing_eval(obj);
155 }
156
157 static void
158 _on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
159 {
160    Widget_Data *wd = elm_widget_data_get(obj);
161
162    if (!wd) return;
163
164    if (elm_widget_focus_get(obj))
165      {
166         if (wd->imf_context) ecore_imf_context_input_panel_show(wd->imf_context);
167         evas_object_focus_set(obj, EINA_TRUE);
168      }
169    else
170      {
171         wd->focused = EINA_FALSE;
172         _view_update(obj);
173         evas_object_smart_callback_call(obj, "unfocused", NULL);
174         if (wd->imf_context) ecore_imf_context_input_panel_hide(wd->imf_context);
175         evas_object_focus_set(obj, EINA_FALSE);
176      }
177 }
178
179 static Eina_Bool
180 _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
181 {
182    return EINA_TRUE;
183 }
184
185
186 static void
187 _signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
188 {
189    Widget_Data *wd = elm_widget_data_get(obj);
190    if (!wd) return;
191    edje_object_signal_emit(wd->base, emission, source);
192 }
193
194 static void
195 _sizing_eval(Evas_Object *obj)
196 {
197    Widget_Data *wd = elm_widget_data_get(obj);
198    Evas_Coord minw = -1, minh = -1;
199    Evas_Coord left, right, top, bottom;
200    if (!wd) return;
201
202    evas_object_size_hint_min_get(wd->box, &minw, &minh);
203    edje_object_part_geometry_get(wd->base, "top.left.pad", NULL, NULL, &left, &top);
204    edje_object_part_geometry_get(wd->base, "bottom.right.pad", NULL, NULL, &right, &bottom);
205
206    minw += (left + right);
207    minh += (top + bottom);
208
209    evas_object_size_hint_min_set(obj, minw, minh);
210 }
211
212 static void
213 _signal_mouse_clicked(void *data, Evas_Object *obj, const char *emission, const char *source)
214 {
215    Widget_Data *wd = elm_widget_data_get(data);
216    if(!wd || !wd->base) return;
217
218    wd->focused = EINA_TRUE;
219    _view_update(data);
220
221    if (wd->imf_context) ecore_imf_context_input_panel_show(wd->imf_context);
222    evas_object_smart_callback_call(data, "clicked", NULL);
223 }
224
225 static void
226 _changed_size_hint_cb(void *data, Evas *evas, Evas_Object *obj, void *event)
227 {
228    Evas_Object *eo = (Evas_Object *)data;
229    Widget_Data *wd = elm_widget_data_get(data);
230    if (!wd) return;
231    _sizing_eval(eo);
232 }
233
234 static void
235 _resize_cb(void *data, Evas *evas, Evas_Object *obj, void *event)
236 {
237    Widget_Data *wd = elm_widget_data_get(data);
238    Evas_Coord w, h;
239    if (!wd) return;
240
241    evas_object_geometry_get(wd->box, NULL, NULL, &w, &h);
242
243    if (wd->h_box < h) evas_object_smart_callback_call (data, "expanded", NULL);
244    else if (wd->h_box > h) evas_object_smart_callback_call (data, "contracted", NULL);
245    else ;
246
247    wd->w_box = w;
248    wd->h_box = h;
249
250    _view_update(data);
251 }
252
253 static void
254 _event_init(Evas_Object *obj)
255 {
256    Widget_Data *wd = elm_widget_data_get(obj);
257    if (!wd || !wd->base)   return;
258
259    if (wd->base)
260      {
261         edje_object_signal_callback_add(wd->base, "mouse,clicked,1", "*", _signal_mouse_clicked, obj);
262         edje_object_signal_callback_add(wd->base, "clicked", "*", _signal_mouse_clicked, obj);
263         evas_object_event_callback_add(wd->base, EVAS_CALLBACK_KEY_UP, _evas_mbe_key_up_cb, obj);
264      }
265
266    if (wd->box)
267      {
268         evas_object_event_callback_add(wd->box, EVAS_CALLBACK_RESIZE, _resize_cb, obj);
269         evas_object_event_callback_add(wd->box, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hint_cb, obj);
270      }
271
272    if (wd->entry)
273      {
274         evas_object_event_callback_add(wd->entry, EVAS_CALLBACK_KEY_UP, _entry_key_up_cb, obj);
275         evas_object_event_callback_add(wd->entry, EVAS_CALLBACK_KEY_DOWN, _entry_key_down_cb, obj);
276         evas_object_smart_callback_add(wd->entry, "changed", _entry_changed_cb, obj);
277         evas_object_smart_callback_add(wd->entry, "focused", _entry_focus_in_cb, obj);
278         evas_object_smart_callback_add(wd->entry, "unfocused", _entry_focus_out_cb, obj);
279      }
280 }
281
282 static void
283 _set_vis_guidetext(Evas_Object *obj)
284 {
285    Widget_Data *wd = elm_widget_data_get(obj);
286
287    elm_box_unpack(wd->box, wd->guidetext);
288    elm_box_unpack(wd->box, wd->entry);
289    if (wd->view_state == MULTIBUTTONENTRY_VIEW_CONTRACTED) return;
290
291    if (wd && !eina_list_count(wd->items) && wd->guidetext
292        && !elm_widget_focus_get(obj) && !wd->focused)
293      {
294         evas_object_hide(wd->entry);
295         elm_box_pack_end(wd->box, wd->guidetext);
296         evas_object_show(wd->guidetext);
297         wd->view_state = MULTIBUTTONENTRY_VIEW_GUIDETEXT;
298      }
299    else
300      {
301         evas_object_hide(wd->guidetext);
302         elm_box_pack_end(wd->box, wd->entry);
303         evas_object_show(wd->entry);
304         if (elm_widget_focus_get(obj) || wd->focused)
305           if (!wd->current)
306             elm_object_focus(wd->entry);
307         wd->view_state = MULTIBUTTONENTRY_VIEW_ENTRY;
308      }
309    return;
310 }
311
312 static void
313 _contracted_state_set(Evas_Object *obj, int contracted)
314 {
315    Widget_Data *wd = elm_widget_data_get(obj);
316    Eina_List *l;
317    Elm_Multibuttonentry_Item *item;
318    if (!wd || !wd->box) return;
319
320    elm_scrolled_entry_entry_set(wd->entry, "");
321
322    if (wd->view_state == MULTIBUTTONENTRY_VIEW_ENTRY)
323      evas_object_hide(wd->entry);
324    else if (wd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT)
325      evas_object_hide(wd->guidetext);
326    else if (wd->view_state == MULTIBUTTONENTRY_VIEW_CONTRACTED)
327      {
328         evas_object_hide(wd->rectForEnd);
329         evas_object_hide(wd->end);
330         wd->view_state = MULTIBUTTONENTRY_VIEW_NONE;
331      }
332
333    if (contracted == 1)
334      {
335         Evas_Coord w=0, w_tmp=0;
336         Evas_Coord box_inner_item_width_padding = 0;
337
338         elm_box_padding_get(wd->box, &box_inner_item_width_padding, NULL);
339         // unpack all items and entry
340         elm_box_unpack_all(wd->box);
341         EINA_LIST_FOREACH(wd->items, l, item)
342           {
343              if (item)
344                {
345                   evas_object_hide(item->button);
346                   item->visible = EINA_FALSE;
347                }
348           }
349
350         // pack buttons only 1line
351         w = wd->w_box;
352
353         if (wd->label)
354           {
355              elm_box_pack_end(wd->box, wd->label);
356              evas_object_size_hint_min_get(wd->label, &w_tmp, NULL);
357              w -= w_tmp;
358              w -= box_inner_item_width_padding;
359           }
360
361         item = NULL;
362         int count = eina_list_count(wd->items);
363         Evas_Coord button_min_width = 0;
364         /* Evas_Coord button_min_height = 0; */
365         if (wd->end_type == MULTIBUTTONENTRY_CLOSED_IMAGE)
366           {
367              const char *size_str;
368              size_str = edje_object_data_get(wd->end, "closed_button_width");
369              if(size_str) button_min_width = (Evas_Coord)atoi(size_str);
370              /* it use for later
371              size_str = edje_object_data_get(wd->end, "closed_button_height");
372              if(size_str) button_min_width = (Evas_Coord)atoi(size_str);
373               */
374           }
375
376         EINA_LIST_FOREACH(wd->items, l, item)
377           {
378              if (item)
379                {
380                   int w_label_count = 0;
381                   char buf[MAX_STR] = {0,};
382
383                   elm_box_pack_end(wd->box, item->button);
384                   evas_object_show(item->button);
385                   item->visible = EINA_TRUE;
386
387                   w -= item->vw;
388                   w -= box_inner_item_width_padding;
389                   count--;
390
391                   if (wd->end_type == MULTIBUTTONENTRY_CLOSED_LABEL)
392                     {
393                        if (count > 0)
394                          {
395                             snprintf(buf, sizeof(buf), "... + %d", count);
396                             elm_label_label_set(wd->end, buf);
397                             evas_object_size_hint_min_get(wd->end, &w_label_count, NULL);
398                          }
399
400                        if (w < 0 || w < w_label_count)
401                          {
402                             elm_box_unpack(wd->box, item->button);
403                             evas_object_hide(item->button);
404                             item->visible = EINA_FALSE;
405
406                             count++;
407                             snprintf(buf, sizeof(buf), "... + %d", count);
408                             elm_label_label_set(wd->end, buf);
409                             evas_object_size_hint_min_get(wd->end, &w_label_count, NULL);
410
411                             elm_box_pack_end(wd->box, wd->end);
412                             evas_object_show(wd->end);
413
414                             wd->view_state = MULTIBUTTONENTRY_VIEW_CONTRACTED;
415                             evas_object_smart_callback_call(obj, "contracted,state,changed", (void *)1);
416                             break;
417                          }
418                     }
419                   else if (wd->end_type == MULTIBUTTONENTRY_CLOSED_IMAGE)
420                     {
421                        if (w < button_min_width)
422                          {
423                             Evas_Coord rectSize;
424                             Evas_Coord closed_height = 0;
425                             const char *height_str = edje_object_data_get(wd->base, "closed_height");
426                             if(height_str) closed_height = (Evas_Coord)atoi(height_str);
427                             elm_box_unpack(wd->box, item->button);
428                             evas_object_hide(item->button);
429                             item->visible = EINA_FALSE;
430
431                             w += item->vw;
432                             rectSize = w - button_min_width;
433                             if (!wd->rectForEnd)
434                               {
435                                  Evas *e = evas_object_evas_get(obj);
436                                  wd->rectForEnd = evas_object_rectangle_add(e);
437                                  evas_object_color_set(wd->rectForEnd, 0, 0, 0, 0);
438                               }
439                             evas_object_size_hint_min_set(wd->rectForEnd, rectSize, closed_height);
440                             elm_box_pack_end(wd->box, wd->rectForEnd);
441                             evas_object_show(wd->rectForEnd);
442
443                             elm_box_pack_end(wd->box, wd->end);
444                             evas_object_show(wd->end);
445
446                             wd->view_state = MULTIBUTTONENTRY_VIEW_CONTRACTED;
447                             evas_object_smart_callback_call(obj, "contracted,state,changed", (void *)0);
448                             break;
449                          }
450                     }
451                }
452           }
453      }
454    else
455      {
456         // unpack all items and entry
457         elm_box_unpack_all(wd->box);
458         EINA_LIST_FOREACH(wd->items, l, item)
459           {
460              if (item)
461                {
462                   evas_object_hide(item->button);
463                   item->visible = EINA_FALSE;
464                }
465           }
466         evas_object_hide(wd->end);
467
468         if (wd->rectForEnd) evas_object_hide(wd->rectForEnd);
469
470         // pack buttons only 1line
471
472         if (wd->label) elm_box_pack_end(wd->box, wd->label);
473
474         // pack remain btns
475         item = NULL;
476         EINA_LIST_FOREACH(wd->items, l, item)
477           {
478              if (item)
479                {
480                   elm_box_pack_end(wd->box, item->button);
481                   evas_object_show(item->button);
482                   item->visible = EINA_TRUE;
483                }
484           }
485
486         wd->view_state = MULTIBUTTONENTRY_VIEW_NONE;
487         evas_object_smart_callback_call(obj, "contracted,state,changed", (void *)wd->contracted);
488      }
489    if (wd->view_state != MULTIBUTTONENTRY_VIEW_CONTRACTED)
490      {
491         _set_vis_guidetext(obj);
492      }
493 }
494
495 static void
496 _view_update(Evas_Object *obj)
497 {
498    Evas_Coord width = 1, height = 1;
499    Widget_Data *wd = elm_widget_data_get(obj);
500
501    if (!wd || !wd->box || !wd->entry || !(wd->w_box > 0)) return;
502
503    // update label
504    if (wd->label)
505      {
506         elm_box_unpack(wd->box, wd->label);
507         elm_box_pack_start(wd->box, wd->label);
508         evas_object_size_hint_min_get(wd->label, &width, &height);
509      }
510
511    if (wd->guidetext)
512      {
513         Evas_Coord guide_text_width = wd->w_box - width;
514         evas_object_size_hint_min_set(wd->guidetext, guide_text_width, height);
515      }
516
517    // update buttons in contracted mode
518    if (wd->view_state == MULTIBUTTONENTRY_VIEW_CONTRACTED)
519      _contracted_state_set(obj, 1);
520
521    // update guidetext
522    _set_vis_guidetext(obj);
523 }
524
525 static void
526 _set_label(Evas_Object *obj, const char* str)
527 {
528    Widget_Data *wd = elm_widget_data_get(obj);
529    if (!wd || !str) return;
530
531    if (wd->label)
532    {
533       Evas_Coord width, height, sum_width = 0;
534       evas_object_size_hint_min_set(wd->label, 0, 0);
535       evas_object_resize(wd->label, 0, 0);
536       edje_object_part_text_set(wd->label, "mbe.label", str);
537
538       if (!strcmp(str, ""))
539         {
540            /* FIXME: not work yet */
541            edje_object_signal_emit(wd->label, "elm,mbe,clear_text", "");
542            edje_object_part_geometry_get(wd->label, "mbe.label", NULL, NULL, &width, &height);
543            sum_width += width;
544         }
545       else
546         {
547            edje_object_signal_emit(wd->label, "elm,mbe,set_text", "");
548            edje_object_part_geometry_get(wd->label, "mbe.label", NULL, NULL, &width, &height);
549            sum_width += width;
550
551            edje_object_part_geometry_get(wd->label, "mbe.label.left.padding", NULL, NULL, &width, NULL);
552            sum_width += width;
553
554            edje_object_part_geometry_get(wd->label, "mbe.label.right.padding", NULL, NULL, &width, NULL);
555            sum_width += width;
556         }
557       evas_object_size_hint_min_set(wd->label, sum_width, height);
558    }
559    evas_object_show(wd->label);
560    _view_update(obj);
561 }
562
563 static void
564 _set_guidetext(Evas_Object *obj, const char* str)
565 {
566    Widget_Data *wd = elm_widget_data_get(obj);
567    if (!wd || !str)   return;
568
569    if (!wd->guidetext)
570      {
571         if (! (wd->guidetext = edje_object_add (evas_object_evas_get (obj)))) return;
572         _elm_theme_object_set(obj, wd->guidetext, "multibuttonentry", "guidetext", elm_widget_style_get(obj));
573         evas_object_size_hint_weight_set(wd->guidetext, 0.0, EVAS_HINT_EXPAND);
574         evas_object_size_hint_align_set(wd->guidetext, EVAS_HINT_FILL, EVAS_HINT_FILL);
575      }
576
577    if (wd->guidetext) edje_object_part_text_set (wd->guidetext, "elm.text", str);
578    _view_update(obj);
579 }
580
581 static void
582 _change_current_button_state(Evas_Object *obj, Multibuttonentry_Button_State state)
583 {
584    Widget_Data *wd = elm_widget_data_get(obj);
585    Elm_Multibuttonentry_Item *item = NULL;
586    if (!wd) return;
587
588    if (wd->current)
589      item = eina_list_data_get(wd->current);
590
591    if (item && item->button)
592      {
593         switch(state)
594           {
595              case MULTIBUTONENTRY_BUTTON_STATE_DEFAULT:
596                 edje_object_signal_emit(item->button, "default", "");
597                 wd->current = NULL;
598                 break;
599              case MULTIBUTONENTRY_BUTTON_STATE_SELECTED:
600                 edje_object_signal_emit(item->button, "focused", "");
601                 evas_object_smart_callback_call(obj, "item,selected", item);
602                 break;
603              default:
604                 edje_object_signal_emit(item->button, "default", "");
605                 wd->current = NULL;
606                 break;
607           }
608      }
609 }
610
611 static void
612 _change_current_button(Evas_Object *obj, Evas_Object *btn)
613 {
614    Widget_Data *wd = elm_widget_data_get(obj);
615    Eina_List *l;
616    Elm_Multibuttonentry_Item *item;
617    if (!wd) return;
618
619    // change the state of previous button to "default"
620    _change_current_button_state(obj, MULTIBUTONENTRY_BUTTON_STATE_DEFAULT);
621
622    // change the current
623    EINA_LIST_FOREACH(wd->items, l, item)
624      {
625         if (item->button == btn)
626           {
627              wd->current = l;
628              break;
629           }
630      }
631
632    // chagne the state of current button to "focused"
633    _change_current_button_state(obj, MULTIBUTONENTRY_BUTTON_STATE_SELECTED);
634
635 }
636
637 static void
638 _button_clicked(void *data, Evas_Object *obj, const char *emission, const char *source)
639 {
640    Widget_Data *wd = elm_widget_data_get(data);
641
642    Elm_Multibuttonentry_Item *item = NULL;
643    if (!wd || wd->view_state == MULTIBUTTONENTRY_VIEW_CONTRACTED) return;
644
645    _change_current_button(data, obj);
646
647    if (wd->current)
648      if ((item = eina_list_data_get(wd->current)) != NULL)
649        {
650           evas_object_smart_callback_call(data, "item,clicked", item);
651           _select_button(data, item->button);
652        }
653 }
654
655 static void
656 _del_button_obj(Evas_Object *obj, Evas_Object *btn)
657 {
658    Widget_Data *wd = elm_widget_data_get(obj);
659    if (!wd || !btn)   return;
660
661    if (btn)
662      // del button
663      evas_object_del(btn);
664 }
665
666 static void
667 _del_button_item(Elm_Multibuttonentry_Item *item)
668 {
669    Eina_List *l;
670    Elm_Multibuttonentry_Item *_item;
671    if (!item) return;
672    Widget_Data *wd;
673
674    Evas_Object *obj = item->multibuttonentry;
675    wd = elm_widget_data_get(obj);
676    if (!wd) return;
677    EINA_LIST_FOREACH(wd->items, l, _item)
678      {
679         if (_item == item)
680           {
681              wd->items = eina_list_remove(wd->items, _item);
682              elm_box_unpack(wd->box, _item->button);
683
684              evas_object_smart_callback_call(obj, "item,deleted", _item);
685
686              _del_button_obj(obj, _item->button);
687
688              free(_item);
689              if (wd->current == l)
690                wd->current = NULL;
691              break;
692           }
693      }
694    if (wd->view_state == MULTIBUTTONENTRY_VIEW_CONTRACTED)
695      _contracted_state_set(obj, 1);
696
697    if (!eina_list_count(wd->items))
698      _set_vis_guidetext(obj);
699 }
700
701 static void
702 _select_button(Evas_Object *obj, Evas_Object *btn)
703 {
704    Widget_Data *wd = elm_widget_data_get(obj);
705    Elm_Multibuttonentry_Item *item;
706
707    if (!wd) return;
708
709    if (btn)
710      {
711         _change_current_button(obj, btn);
712         if (elm_widget_focus_get(obj))
713           {
714              elm_object_unfocus(wd->entry);
715              evas_object_focus_set(btn, EINA_TRUE);
716           }
717      }
718    else
719      {
720         _change_current_button_state(obj, MULTIBUTONENTRY_BUTTON_STATE_DEFAULT);
721         if (elm_widget_focus_get(obj))
722           elm_object_focus(wd->entry);
723      }
724 }
725
726 static void
727 _resize_button(Evas_Object *btn, Evas_Coord *realw, Evas_Coord *vieww)
728 {
729    Evas_Coord rw, vw;
730    Evas_Coord w_text, h_btn, padding_outer, padding_inner;
731    Evas_Coord w_btn = 0, button_max_width = 0;
732    const char *size_str;
733
734    size_str = edje_object_data_get(btn, "button_max_size");
735    if (size_str) button_max_width = (Evas_Coord)atoi(size_str);
736
737    // decide the size of button
738    edje_object_part_geometry_get(btn, "elm.base", NULL, NULL, NULL, &h_btn);
739    edje_object_part_geometry_get(btn, "elm.btn.text", NULL, NULL, &w_text, NULL);
740    edje_object_part_geometry_get(btn, "left.padding", NULL, NULL, &padding_outer, NULL);
741    edje_object_part_geometry_get(btn, "left.inner.padding", NULL, NULL, &padding_inner, NULL);
742    w_btn = w_text + 2*padding_outer + 2*padding_inner;
743
744    rw = w_btn;
745    vw = (button_max_width < w_btn) ? button_max_width : w_btn;
746
747    //resize btn
748    evas_object_resize(btn, vw, h_btn);
749    evas_object_size_hint_min_set(btn, vw, h_btn);
750
751    if(realw) *realw = rw;
752    if(vieww) *vieww = vw;
753 }
754
755 static Elm_Multibuttonentry_Item*
756 _add_button_item(Evas_Object *obj, const char *str, Multibuttonentry_Pos pos, const Elm_Multibuttonentry_Item *reference, void *data)
757 {
758    Elm_Multibuttonentry_Item *item;
759    Evas_Object *btn;
760    Evas_Coord width, height;
761    const char *str_utf8 = NULL;
762
763    Widget_Data *wd = elm_widget_data_get(obj);
764
765    if (!wd || !wd->box || !wd->entry) return NULL;
766
767    if ((wd->add_callback) && !wd->add_callback(obj, str, data, wd->add_callback_data)) return NULL;
768
769    // add button
770    btn = edje_object_add(evas_object_evas_get(obj));
771    str_utf8 = elm_entry_markup_to_utf8(str);
772
773    _elm_theme_object_set(obj, btn, "multibuttonentry", "btn", elm_widget_style_get(obj));
774    edje_object_part_text_set(btn, "elm.btn.text", str_utf8);
775    edje_object_part_geometry_get(btn, "elm.btn.text", NULL, NULL, &width, &height);
776    evas_object_size_hint_min_set(btn, width, height);
777    edje_object_signal_callback_add(btn, "mouse,clicked,1", "*", _button_clicked, obj);
778    evas_object_size_hint_weight_set(btn, 0.0, 0.0);
779    evas_object_show(btn);
780
781    // append item list
782    item = ELM_NEW(Elm_Multibuttonentry_Item);
783    if (item)
784      {
785         Evas_Coord rw, vw;
786         _resize_button(btn, &rw, &vw);
787         item->multibuttonentry = obj;
788         item->button = btn;
789         item->data = data;
790         item->rw = rw;
791         item->vw = vw;
792         item->visible = EINA_TRUE;
793
794         switch(pos)
795           {
796              case MULTIBUTONENTRY_POS_START:
797                 wd->items = eina_list_prepend(wd->items, item);
798                 if (wd->view_state == MULTIBUTTONENTRY_VIEW_CONTRACTED)
799                   {
800                      elm_widget_sub_object_add(obj, btn);
801                      _contracted_state_set(obj, 1);
802                   }
803                 else
804                   {
805                      if (wd->label)
806                        elm_box_pack_after(wd->box, btn, wd->label);
807                      else
808                        elm_box_pack_start(wd->box, btn);
809                      if (wd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT)
810                        _set_vis_guidetext(obj);
811                   }
812                 break;
813              case MULTIBUTONENTRY_POS_END:
814                 wd->items = eina_list_append(wd->items, item);
815                 if (wd->view_state == MULTIBUTTONENTRY_VIEW_CONTRACTED)
816                   {
817                      elm_widget_sub_object_add(obj, btn);
818                      evas_object_hide(btn);
819                   }
820                 else
821                   {
822                      if (wd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT)
823                        _set_vis_guidetext(obj);
824                      if (wd->entry)
825                        elm_box_pack_before(wd->box, btn, wd->entry);
826                      else
827                        elm_box_pack_end(wd->box, btn);
828                   }
829                 break;
830              case MULTIBUTONENTRY_POS_BEFORE:
831                 if (reference)
832                      wd->items = eina_list_prepend_relative(wd->items, item, reference);
833                 else
834                      wd->items = eina_list_append(wd->items, item);
835                 if (wd->view_state == MULTIBUTTONENTRY_VIEW_CONTRACTED)
836                   {
837                      elm_widget_sub_object_add(obj, btn);
838                      evas_object_hide(btn);
839                      _contracted_state_set(obj, 1);
840                   }
841                 else
842                   {
843                      if (reference)
844                        elm_box_pack_before(wd->box, btn, reference->button);
845                      else
846                        {
847                           if (wd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT)
848                             _set_vis_guidetext(obj);
849                           if (wd->entry)
850                             elm_box_pack_before(wd->box, btn, wd->entry);
851                           else
852                             elm_box_pack_end(wd->box, btn);
853                        }
854                   }
855                 break;
856              case MULTIBUTONENTRY_POS_AFTER:
857                 if (reference)
858                      wd->items = eina_list_append_relative(wd->items, item, reference);
859                 else
860                      wd->items = eina_list_append(wd->items, item);
861                 if (wd->view_state == MULTIBUTTONENTRY_VIEW_CONTRACTED)
862                   {
863                      elm_widget_sub_object_add(obj, btn);
864                      _contracted_state_set(obj, 1);
865                   }
866                 else
867                   {
868                      if (reference)
869                        elm_box_pack_after(wd->box, btn, reference->button);
870                      else
871                        {
872                           if (wd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT)
873                             _set_vis_guidetext(obj);
874                           if (wd->entry)
875                             elm_box_pack_before(wd->box, btn, wd->entry);
876                           else
877                             elm_box_pack_end(wd->box, btn);
878                        }
879                   }
880                 break;
881              default:
882                 break;
883           }
884      }
885    evas_object_smart_callback_call(obj, "item,added", item);
886
887    free(str_utf8);
888
889    return item;
890 }
891
892 static void
893 _add_button(Evas_Object *obj, char *str)
894 {
895    Widget_Data *wd = elm_widget_data_get(obj);
896    if (!wd) return;
897
898    //remove entry text
899    elm_scrolled_entry_entry_set(wd->entry, "");
900
901    // add button
902    _add_button_item(obj, str, MULTIBUTONENTRY_POS_END, NULL, NULL);
903 }
904
905 static void
906 _evas_mbe_key_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
907 {
908    Widget_Data *wd = elm_widget_data_get(data);
909    Elm_Multibuttonentry_Item *item = NULL;
910
911    static char str[MAX_STR];
912
913    if (!wd || !wd->base || !wd->box) return;
914
915    strncpy(str, elm_scrolled_entry_entry_get(wd->entry), MAX_STR);
916    str[MAX_STR - 1] = 0;
917
918    Evas_Event_Key_Up *ev = (Evas_Event_Key_Up*)event_info;
919
920    if (wd->last_btn_select)
921      {
922         if ((wd->current) &&  ( (strcmp (ev->keyname, "BackSpace") == 0) || (strcmp (ev->keyname, "BackSpace (") == 0)))
923           {
924              item = eina_list_data_get(wd->current);
925              if (item)
926                {
927                   _del_button_item(item);
928                   elm_object_focus(wd->entry);
929                }
930           }
931         else if (((!wd->current) && (wd->n_str == 0) && (strcmp (ev->keyname, "BackSpace") == 0) || (strcmp (ev->keyname, "BackSpace (") == 0)))
932           {
933              item = eina_list_data_get(eina_list_last(wd->items));
934              if (item)
935                _select_button(data, item->button);
936           }
937      }
938    else
939      wd->last_btn_select = EINA_TRUE;
940 }
941
942 static void
943 _entry_key_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
944 {
945    Widget_Data *wd = elm_widget_data_get(data);
946    Evas_Event_Key_Down *ev = (Evas_Event_Key_Down *)event_info;
947
948    if (!wd) return;
949
950    if ( (wd->n_str == 1) && (strcmp (ev->keyname, "BackSpace") == 0 || (strcmp (ev->keyname, "BackSpace (") == 0 )))
951      wd->last_btn_select = EINA_FALSE;
952 }
953
954 static void
955 _entry_key_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
956 {
957    Widget_Data *wd = elm_widget_data_get(data);
958    Evas_Event_Key_Up *ev = (Evas_Event_Key_Up *) event_info;
959    static char str[MAX_STR];
960
961    if (!wd || !wd->base || !wd->box) return;
962
963    strncpy(str, elm_scrolled_entry_entry_get(wd->entry), MAX_STR);
964    str[MAX_STR - 1] = 0;
965
966    if ( (strcmp (str, "") != 0) && (strcmp (ev->keyname, "KP_Enter") == 0 || strcmp (ev->keyname, "Return") == 0 ))
967      {
968         _add_button(data, str);
969         wd->n_str = 0;
970         return;
971      }
972 }
973
974 static void
975 _entry_focus_in_cb(void *data, Evas *e, __UNUSED__ void *event_info)
976 {
977    Widget_Data *wd = elm_widget_data_get(data);
978    if (!wd) return;
979
980    _change_current_button_state(data, MULTIBUTONENTRY_BUTTON_STATE_DEFAULT);
981 }
982
983 static void
984 _entry_focus_out_cb(void *data, Evas *e, __UNUSED__ void *event_info)
985 {
986    Widget_Data *wd = elm_widget_data_get(data);
987    if (!wd) return;
988
989    static char str[MAX_STR];
990
991    strncpy(str,elm_scrolled_entry_entry_get(wd->entry), MAX_STR);
992    str[MAX_STR -1] = 0;
993
994    if (strlen(str))
995      _add_button(data, str);
996 }
997
998 static void
999 _entry_changed_cb(void *data, Evas_Object *obj, void *event_info)
1000 {
1001    Widget_Data *wd = elm_widget_data_get(data);
1002    if (!wd) return;
1003
1004    static char str[MAX_STR];
1005
1006    strncpy(str, elm_scrolled_entry_entry_get(wd->entry), MAX_STR);
1007    str[MAX_STR -1] = 0;
1008
1009    wd->n_str =  strlen(str);
1010 }
1011
1012 static void
1013 _view_init(Evas_Object *obj)
1014 {
1015    Widget_Data *wd = elm_widget_data_get(obj);
1016    if (!wd) return;
1017
1018    if (!wd->box)
1019      {
1020         if (! (wd->box = elm_box_add (obj))) return;
1021         elm_widget_sub_object_add(obj, wd->box);
1022         elm_box_layout_set(wd->box, _box_layout_cb, NULL, NULL);
1023         elm_box_homogenous_set(wd->box, EINA_FALSE);
1024         edje_object_part_swallow(wd->base, "box.swallow", wd->box);
1025      }
1026
1027    if (!wd->label)
1028      {
1029         if (!(wd->label = edje_object_add(evas_object_evas_get(obj)))) return;
1030         _elm_theme_object_set(obj, wd->label, "multibuttonentry", "label", elm_widget_style_get(obj));
1031         _set_label(obj, "");
1032         elm_widget_sub_object_add(obj, wd->label);
1033      }
1034
1035    if (!wd->entry)
1036      {
1037         if (! (wd->entry = elm_scrolled_entry_add (obj))) return;
1038         elm_scrolled_entry_single_line_set(wd->entry, EINA_TRUE);
1039         elm_scrolled_entry_entry_set(wd->entry, "");
1040         elm_scrolled_entry_cursor_end_set(wd->entry);
1041         elm_scrolled_entry_input_panel_enabled_set(wd->entry, EINA_FALSE);
1042         evas_object_size_hint_min_set(wd->entry, MIN_W_ENTRY, 0);
1043         evas_object_size_hint_weight_set(wd->entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1044         evas_object_size_hint_align_set(wd->entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
1045         if (wd->box)   elm_box_pack_end (wd->box, wd->entry);
1046         evas_object_show(wd->entry);
1047         wd->view_state = MULTIBUTTONENTRY_VIEW_ENTRY;
1048         wd->imf_context = elm_scrolled_entry_imf_context_get(wd->entry);
1049      }
1050
1051    if (!wd->end)
1052      {
1053         const char *end_type = edje_object_data_get(wd->base, "closed_button_type");
1054         if (!end_type || !strcmp(end_type, "label"))
1055           {
1056              if (! (wd->end = elm_label_add (obj))) return;
1057              elm_object_style_set(wd->end, "extended/multibuttonentry_default");
1058              wd->end_type = MULTIBUTTONENTRY_CLOSED_LABEL;
1059           }
1060         else
1061           {
1062              const char *size_str;
1063              if (!(wd->end = edje_object_add(evas_object_evas_get(obj)))) return;
1064              _elm_theme_object_set(obj, wd->end, "multibuttonentry", "closedbutton", elm_widget_style_get(obj));
1065              Evas_Coord button_min_width = 0;
1066              Evas_Coord button_min_height = 0;
1067
1068              size_str = edje_object_data_get(wd->end, "closed_button_width");
1069              if(size_str) button_min_width = (Evas_Coord)atoi(size_str);
1070              size_str = edje_object_data_get(wd->end, "closed_button_height");
1071              if(size_str) button_min_height = (Evas_Coord)atoi(size_str);
1072
1073              wd->end_type = MULTIBUTTONENTRY_CLOSED_IMAGE;
1074              evas_object_size_hint_min_set(wd->end, button_min_width, button_min_height);
1075              elm_widget_sub_object_add(obj, wd->end);
1076           }
1077      }
1078 }
1079
1080 static void
1081 _calculate_box_min_size(Evas_Object *box, Evas_Object_Box_Data *priv)
1082 {
1083    Evas_Coord minw, minh, maxw, maxh, mnw, mnh, ww;
1084    Evas_Coord w, cw = 0, cmaxh = 0;
1085    const Eina_List *l;
1086    Evas_Object_Box_Option *opt;
1087    double wx;
1088
1089    /* FIXME: need to calc max */
1090    minw = 0;
1091    minh = 0;
1092    maxw = -1;
1093    maxh = -1;
1094
1095    evas_object_geometry_get(box, NULL, NULL, &w, NULL);
1096    evas_object_size_hint_min_get(box, &minw, NULL);
1097
1098    EINA_LIST_FOREACH(priv->children, l, opt)
1099      {
1100         evas_object_size_hint_min_get(opt->obj, &mnw, &mnh);
1101         evas_object_size_hint_weight_get(opt->obj, &wx, NULL);
1102
1103         if(wx)
1104           {
1105              if (mnw != -1 && (w - cw) >= mnw)
1106                 ww = w - cw;
1107              else
1108                 ww = w;
1109           }
1110         else
1111            ww = mnw;
1112
1113         if ((cw + mnw) > w)
1114           {
1115              minh += cmaxh;
1116              cw = 0;
1117              cmaxh = 0;
1118           }
1119         cw += ww;
1120         if (cmaxh < mnh) cmaxh = mnh;
1121      }
1122
1123    minh += cmaxh;
1124
1125    evas_object_size_hint_min_set(box, minw, minh);
1126 }
1127
1128 static Evas_Coord
1129 _calculate_item_max_height(Evas_Object *box, Evas_Object_Box_Data *priv, int obj_index)
1130 {
1131    Evas_Coord mnw, mnh, cw = 0, cmaxh = 0, w, ww;
1132    const Eina_List *l;
1133    Evas_Object_Box_Option *opt;
1134    int index = 0;
1135    double wx;
1136
1137    evas_object_geometry_get(box, NULL, NULL, &w, NULL);
1138
1139    EINA_LIST_FOREACH(priv->children, l, opt)
1140      {
1141         evas_object_size_hint_min_get(opt->obj, &mnw, &mnh);
1142         evas_object_size_hint_weight_get(opt->obj, &wx, NULL);
1143
1144         if(wx)
1145           {
1146              if (mnw != -1 && (w - cw) >= mnw)
1147                 ww = w - cw;
1148              else
1149                 ww = w;
1150           }
1151         else
1152            ww = mnw;
1153
1154         if ((cw + ww) > w)
1155           {
1156              if (index > obj_index) return cmaxh;
1157              cw = 0;
1158              cmaxh = 0;
1159           }
1160
1161         cw += ww;
1162         if (cmaxh < mnh) cmaxh = mnh;
1163
1164         index++;
1165      }
1166
1167    return cmaxh;
1168 }
1169
1170 static void
1171 _box_layout_cb(Evas_Object *o, Evas_Object_Box_Data *priv, void *data)
1172 {
1173    Evas_Coord x, y, w, h, xx, yy;
1174    const Eina_List *l;
1175    Evas_Object *obj;
1176    Evas_Coord minw, minh, wdif, hdif;
1177    int count = 0;
1178    double ax, ay;
1179    Evas_Object_Box_Option *opt;
1180
1181    _calculate_box_min_size(o, priv);
1182
1183    evas_object_geometry_get(o, &x, &y, &w, &h);
1184
1185    evas_object_size_hint_min_get(o, &minw, &minh);
1186    evas_object_size_hint_align_get(o, &ax, &ay);
1187    count = eina_list_count(priv->children);
1188    if (w < minw)
1189      {
1190         x = x + ((w - minw) * (1.0 - ax));
1191         w = minw;
1192      }
1193    if (h < minh)
1194      {
1195         y = y + ((h - minh) * (1.0 - ay));
1196         h = minh;
1197      }
1198
1199    wdif = w - minw;
1200    hdif = h - minh;
1201    xx = x;
1202    yy = y;
1203
1204    Evas_Coord cw = 0, ch = 0, cmaxh = 0, obj_index = 0;
1205
1206    EINA_LIST_FOREACH(priv->children, l, opt)
1207      {
1208         Evas_Coord mnw, mnh, mxw, mxh;
1209         double wx, wy;
1210         int fw, fh, xw, xh;
1211
1212         obj = opt->obj;
1213         evas_object_size_hint_align_get(obj, &ax, &ay);
1214         evas_object_size_hint_weight_get(obj, &wx, &wy);
1215         evas_object_size_hint_min_get(obj, &mnw, &mnh);
1216         evas_object_size_hint_max_get(obj, &mxw, &mxh);
1217         fw = fh = 0;
1218         xw = xh = 0;
1219         if (ax == -1.0) {fw = 1; ax = 0.5;}
1220         if (ay == -1.0) {fh = 1; ay = 0.5;}
1221         if (wx > 0.0) xw = 1;
1222         if (wy > 0.0) xh = 1;
1223         Evas_Coord ww, hh, ow, oh;
1224
1225         if(wx)
1226           {
1227              if (mnw != -1 && (w - cw) >= mnw)
1228                 ww = w - cw;
1229              else
1230                 ww = w;
1231           }
1232         else
1233            ww = mnw;
1234         hh = _calculate_item_max_height(o, priv, obj_index);
1235
1236         ow = mnw;
1237         if (fw) ow = ww;
1238         if ((mxw >= 0) && (mxw < ow)) ow = mxw;
1239         oh = mnh;
1240         if (fh) oh = hh;
1241         if ((mxh >= 0) && (mxh < oh)) oh = mxh;
1242
1243         if ((cw + ww) > w)
1244           {
1245              ch += cmaxh;
1246              cw = 0;
1247              cmaxh = 0;
1248           }
1249
1250         evas_object_move(obj,
1251                          xx + cw + (Evas_Coord)(((double)(ww - ow)) * ax),
1252                          yy + ch + (Evas_Coord)(((double)(hh - oh)) * ay));
1253         evas_object_resize(obj, ow, oh);
1254
1255         cw += ww;
1256         if (cmaxh < hh) cmaxh = hh;
1257
1258         obj_index++;
1259      }
1260 }
1261
1262 /**
1263  * Add a new multibuttonentry to the parent
1264  *
1265  * @param parent The parent object
1266  * @return The new object or NULL if it cannot be created
1267  *
1268  * @ingroup Multibuttonentry
1269  */
1270 EAPI Evas_Object *
1271 elm_multibuttonentry_add(Evas_Object *parent)
1272 {
1273    Evas_Object *obj;
1274    Evas *e;
1275    Widget_Data *wd;
1276    if (!parent) return NULL;
1277
1278    wd = ELM_NEW(Widget_Data);
1279    e = evas_object_evas_get(parent);
1280    if (!e) return NULL;
1281    obj = elm_widget_add(e);
1282    ELM_SET_WIDTYPE(widtype, "multibuttonentry");
1283    elm_widget_type_set(obj, "multibuttonentry");
1284    elm_widget_sub_object_add(parent, obj);
1285    elm_widget_data_set(obj, wd);
1286
1287    elm_widget_del_hook_set(obj, _del_hook);
1288    elm_widget_theme_hook_set(obj, _theme_hook);
1289    elm_widget_event_hook_set(obj, _event_hook);
1290    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
1291    elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
1292
1293    wd->base = edje_object_add(e);
1294    _elm_theme_object_set(obj, wd->base, "multibuttonentry", "base", "default");
1295    elm_widget_resize_object_set(obj, wd->base);
1296    elm_widget_can_focus_set(obj,EINA_TRUE);
1297
1298    wd->view_state = MULTIBUTTONENTRY_VIEW_NONE;
1299    wd->focused = EINA_FALSE;
1300    wd->last_btn_select = EINA_TRUE;
1301    wd->n_str = 0;
1302    wd->rectForEnd = NULL;
1303    wd->imf_context = NULL;
1304    wd->add_callback = NULL;
1305    wd->add_callback_data = NULL;
1306
1307    _view_init(obj);
1308    _event_init(obj);
1309
1310    return obj;
1311 }
1312
1313 /**
1314  * Get the entry of the multibuttonentry object
1315  *
1316  * @param obj The multibuttonentry object
1317  * @return The entry object, or NULL if none
1318  *
1319  * @ingroup Multibuttonentry
1320  */
1321 EAPI Evas_Object *
1322 elm_multibuttonentry_entry_get(Evas_Object *obj)
1323 {
1324    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1325    Widget_Data *wd = elm_widget_data_get(obj);
1326    if (!wd)   return NULL;
1327
1328    return wd->entry;
1329 }
1330
1331 /**
1332  * Get the label
1333  *
1334  * @param obj The multibuttonentry object
1335  * @return The label, or NULL if none
1336  *
1337  * @ingroup Multibuttonentry
1338  */
1339 EAPI const char *
1340 elm_multibuttonentry_label_get(Evas_Object *obj)
1341 {
1342    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1343    Widget_Data *wd = elm_widget_data_get(obj);
1344    if (!wd) return NULL;
1345    if (wd->label) return edje_object_part_text_get(wd->label, "mbe.label");
1346    return NULL;
1347 }
1348
1349 /**
1350  * Set the label
1351  *
1352  * @param obj The multibuttonentry object
1353  * @param label The text label string
1354  *
1355  * @ingroup Multibuttonentry
1356  */
1357 EAPI void
1358 elm_multibuttonentry_label_set(Evas_Object *obj, const char *label)
1359 {
1360    ELM_CHECK_WIDTYPE(obj, widtype);
1361    Widget_Data *wd = elm_widget_data_get(obj);
1362    if (!wd) return;
1363    if (label)
1364      _set_label(obj, label);
1365    else
1366      _set_label(obj, "");
1367 }
1368
1369 /**
1370  * Get the guide text
1371  *
1372  * @param obj The multibuttonentry object
1373  * @return The guide text, or NULL if none
1374  *
1375  * @ingroup Multibuttonentry
1376  */
1377 EAPI const char *
1378 elm_multibuttonentry_guide_text_get(Evas_Object *obj)
1379 {
1380    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1381    Widget_Data *wd = elm_widget_data_get(obj);
1382    if (!wd)   return NULL;
1383    if (wd->guidetext) return edje_object_part_text_get(wd->guidetext, "elm.text");
1384    return NULL;
1385 }
1386
1387 /**
1388  * Set the guide text
1389  *
1390  * @param obj The multibuttonentry object
1391  * @param label The guide text string
1392  *
1393  * @ingroup Multibuttonentry
1394  */
1395 EAPI void
1396 elm_multibuttonentry_guide_text_set(Evas_Object *obj, const char *guidetext)
1397 {
1398    ELM_CHECK_WIDTYPE(obj, widtype);
1399    Widget_Data *wd = elm_widget_data_get(obj);
1400    if (!wd) return;
1401    if (guidetext)
1402       _set_guidetext(obj, guidetext);
1403    else
1404       _set_guidetext(obj, "");
1405
1406 }
1407
1408 /**
1409  * Get the value of contracted state.
1410  *
1411  * @param obj The multibuttonentry object
1412  * @param the value of contracted state.
1413  *
1414  * @ingroup Multibuttonentry
1415  */
1416 EAPI int
1417 elm_multibuttonentry_contracted_state_get(Evas_Object *obj)
1418 {
1419    ELM_CHECK_WIDTYPE(obj, widtype) -1;
1420    Widget_Data *wd = elm_widget_data_get(obj);
1421    if (!wd) return -1;
1422    return wd->view_state == MULTIBUTTONENTRY_VIEW_CONTRACTED ? 1 : 0;
1423 }
1424
1425 /**
1426  * Set/Unset the multibuttonentry to contracted state of single line
1427  *
1428  * @param obj The multibuttonentry object
1429  * @param the value of contracted state. set this to 1 to set the multibuttonentry to contracted state of single line. set this to 0 to unset the contracted state.
1430  *
1431  * @ingroup Multibuttonentry
1432  */
1433 EAPI void
1434 elm_multibuttonentry_contracted_state_set(Evas_Object *obj, int contracted)
1435 {
1436    ELM_CHECK_WIDTYPE(obj, widtype);
1437    Widget_Data *wd = elm_widget_data_get(obj);
1438    if (!wd || !wd->box ||
1439        ((wd->view_state == MULTIBUTTONENTRY_VIEW_CONTRACTED) ? 1 : 0) == contracted) return;
1440    _contracted_state_set(obj, contracted);
1441 }
1442
1443 /**
1444  * Prepend a new item to the multibuttonentry
1445  *
1446  * @param obj The multibuttonentry object
1447  * @param label The label of new item
1448  * @param data The ponter to the data to be attached
1449  * @return A handle to the item added or NULL if not possible
1450  *
1451  * @ingroup Multibuttonentry
1452  */
1453 EAPI Elm_Multibuttonentry_Item *
1454 elm_multibuttonentry_item_add_start(Evas_Object *obj, const char *label, void *data)
1455 {
1456    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1457    Widget_Data *wd = elm_widget_data_get(obj);
1458    Elm_Multibuttonentry_Item *item;
1459    if (!wd || !label) return NULL;
1460    item = _add_button_item(obj, label, MULTIBUTONENTRY_POS_START, NULL, data);
1461    return item;
1462 }
1463
1464 /**
1465  * Append a new item to the multibuttonentry
1466  *
1467  * @param obj The multibuttonentry object
1468  * @param label The label of new item
1469  * @param data The ponter to the data to be attached
1470  * @return A handle to the item added or NULL if not possible
1471  *
1472  * @ingroup Multibuttonentry
1473  */
1474 EAPI Elm_Multibuttonentry_Item *
1475 elm_multibuttonentry_item_add_end(Evas_Object *obj, const char *label, void *data)
1476 {
1477    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1478    Widget_Data *wd = elm_widget_data_get(obj);
1479    Elm_Multibuttonentry_Item *item;
1480    if (!wd || !label) return NULL;
1481    item = _add_button_item(obj, label, MULTIBUTONENTRY_POS_END, NULL, data);
1482    return item;
1483 }
1484
1485 /**
1486  * Add a new item to the multibuttonentry before the indicated object
1487  *
1488  * reference.
1489  * @param obj The multibuttonentry object
1490  * @param label The label of new item
1491  * @param before The item before which to add it
1492  * @param data The ponter to the data to be attached
1493  * @return A handle to the item added or NULL if not possible
1494  *
1495  * @ingroup Multibuttonentry
1496  */
1497 EAPI Elm_Multibuttonentry_Item *
1498 elm_multibuttonentry_item_add_before(Evas_Object *obj, const char *label, Elm_Multibuttonentry_Item *before, void *data)
1499 {
1500    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1501    Widget_Data *wd = elm_widget_data_get(obj);
1502    Elm_Multibuttonentry_Item *item;
1503    if (!wd || !label) return NULL;
1504    item = _add_button_item(obj, label, MULTIBUTONENTRY_POS_BEFORE, before, data);
1505    return item;
1506 }
1507
1508 /**
1509  * Add a new item to the multibuttonentry after the indicated object
1510  *
1511  * @param obj The multibuttonentry object
1512  * @param label The label of new item
1513  * @param after The item after which to add it
1514  * @param data The ponter to the data to be attached
1515  * @return A handle to the item added or NULL if not possible
1516  *
1517  * @ingroup Multibuttonentry
1518  */
1519 EAPI Elm_Multibuttonentry_Item *
1520 elm_multibuttonentry_item_add_after(Evas_Object *obj, const char *label, Elm_Multibuttonentry_Item *after, void *data)
1521 {
1522    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1523    Widget_Data *wd = elm_widget_data_get(obj);
1524    Elm_Multibuttonentry_Item *item;
1525    if (!wd || !label) return NULL;
1526    item = _add_button_item(obj, label, MULTIBUTONENTRY_POS_AFTER, after, data);
1527    return item;
1528 }
1529
1530 /**
1531  * Get a list of items in the multibuttonentry
1532  *
1533  * @param obj The multibuttonentry object
1534  * @return The list of items, or NULL if none
1535  *
1536  * @ingroup Multibuttonentry
1537  */
1538 EAPI const Eina_List *
1539 elm_multibuttonentry_items_get(Evas_Object *obj)
1540 {
1541    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1542    Widget_Data *wd = elm_widget_data_get(obj);
1543    if (!wd) return NULL;
1544    return wd->items;
1545 }
1546
1547 /**
1548  * Get the first item in the multibuttonentry
1549  *
1550  * @param obj The multibuttonentry object
1551  * @return The first item, or NULL if none
1552  *
1553  * @ingroup Multibuttonentry
1554  */
1555 EAPI Elm_Multibuttonentry_Item *
1556 elm_multibuttonentry_item_first_get(Evas_Object *obj)
1557 {
1558    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1559    Widget_Data *wd = elm_widget_data_get(obj);
1560    if (!wd || !wd->items) return NULL;
1561    return eina_list_data_get(wd->items);
1562 }
1563
1564 /**
1565  * Get the last item in the multibuttonentry
1566  *
1567  * @param obj The multibuttonentry object
1568  * @return The last item, or NULL if none
1569  *
1570  * @ingroup Multibuttonentry
1571  */
1572 EAPI Elm_Multibuttonentry_Item *
1573 elm_multibuttonentry_item_last_get(Evas_Object *obj)
1574 {
1575    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1576    Widget_Data *wd = elm_widget_data_get(obj);
1577    if (!wd || !wd->items) return NULL;
1578    return eina_list_data_get(eina_list_last(wd->items));
1579 }
1580
1581 /**
1582  * Get the selected item in the multibuttonentry
1583  *
1584  * @param obj The multibuttonentry object
1585  * @return The selected item, or NULL if none
1586  *
1587  * @ingroup Multibuttonentry
1588  */
1589 EAPI Elm_Multibuttonentry_Item *
1590 elm_multibuttonentry_item_selected_get(Evas_Object *obj)
1591 {
1592    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1593    Widget_Data *wd = elm_widget_data_get(obj);
1594    if (!wd || !wd->current) return NULL;
1595    return eina_list_data_get(wd->current);
1596 }
1597
1598 /**
1599  * Set the selected state of an item
1600  *
1601  * @param item The item
1602  *
1603  * @ingroup Multibuttonentry
1604  */
1605 EAPI void
1606 elm_multibuttonentry_item_selected_set(Elm_Multibuttonentry_Item *item)
1607 {
1608    Widget_Data *wd;
1609    Eina_List *l;
1610    Elm_Multibuttonentry_Item *_item;
1611
1612    if (!item) return;
1613    ELM_CHECK_WIDTYPE(item->multibuttonentry, widtype);
1614    wd = elm_widget_data_get(item->multibuttonentry);
1615    if (!wd) return;
1616
1617    EINA_LIST_FOREACH(wd->items, l, _item)
1618      {
1619         if (_item == item)
1620           _select_button(item->multibuttonentry, item->button);
1621      }
1622 }
1623
1624 /**
1625  * unselect all of items.
1626  *
1627  * @param obj The multibuttonentry object
1628  *
1629  * @ingroup Multibuttonentry
1630  */
1631 EAPI void
1632 elm_multibuttonentry_item_unselect_all(Evas_Object *obj)
1633 {
1634    ELM_CHECK_WIDTYPE(obj, widtype);
1635    Widget_Data *wd = elm_widget_data_get(obj);
1636    if (!wd) return;
1637
1638    _select_button(obj, NULL);
1639 }
1640
1641 /**
1642  * Remove all items in the multibuttonentry.
1643  *
1644  * @param obj The multibuttonentry object
1645  *
1646  * @ingroup Multibuttonentry
1647  */
1648 EAPI void
1649 elm_multibuttonentry_items_del(Evas_Object *obj)
1650 {
1651    ELM_CHECK_WIDTYPE(obj, widtype);
1652    Widget_Data *wd = elm_widget_data_get(obj);
1653    if (!wd) return;
1654
1655    if (wd->items)
1656      {
1657         Elm_Multibuttonentry_Item *item;
1658         EINA_LIST_FREE(wd->items, item)
1659           {
1660              elm_box_unpack(wd->box, item->button);
1661              _del_button_obj(obj, item->button);
1662              free(item);
1663           }
1664         wd->items = NULL;
1665      }
1666    wd->current = NULL;
1667    _view_update(obj);
1668 }
1669
1670 /**
1671  * Delete a given item
1672  *
1673  * @param item The item
1674  *
1675  * @ingroup Multibuttonentry
1676  */
1677 EAPI void
1678 elm_multibuttonentry_item_del(Elm_Multibuttonentry_Item *item)
1679 {
1680    if (!item) return;
1681    _del_button_item(item);
1682 }
1683
1684 /**
1685  * Get the label of a given item
1686  *
1687  * @param item The item
1688  * @return The label of a given item, or NULL if none
1689  *
1690  * @ingroup Multibuttonentry
1691  */
1692 EAPI const char *
1693 elm_multibuttonentry_item_label_get(Elm_Multibuttonentry_Item *item)
1694 {
1695    Widget_Data *wd;
1696    Eina_List *l;
1697    Elm_Multibuttonentry_Item *_item;
1698    if (!item) return NULL;
1699    ELM_CHECK_WIDTYPE(item->multibuttonentry, widtype) NULL;
1700    wd = elm_widget_data_get(item->multibuttonentry);
1701    if (!wd || !wd->items) return NULL;
1702
1703    EINA_LIST_FOREACH(wd->items, l, _item)
1704      {
1705         if (_item == item)
1706           return edje_object_part_text_get(_item->button, "elm.btn.text");
1707      }
1708
1709    return NULL;
1710 }
1711
1712 /**
1713  * Set the label of a given item
1714  *
1715  * @param item The item
1716  * @param label The text label string
1717  *
1718  * @ingroup Multibuttonentry
1719  */
1720 EAPI void
1721 elm_multibuttonentry_item_label_set(Elm_Multibuttonentry_Item *item, const char *str)
1722 {
1723    Widget_Data *wd;
1724    Eina_List *l;
1725    Elm_Multibuttonentry_Item *_item;
1726    if (!item || !str) return;
1727    ELM_CHECK_WIDTYPE(item->multibuttonentry, widtype);
1728    wd = elm_widget_data_get(item->multibuttonentry);
1729    if (!wd || !wd->items) return;
1730
1731    EINA_LIST_FOREACH(wd->items, l, _item)
1732       if (_item == item)
1733         {
1734            edje_object_part_text_set(_item->button, "elm.btn.text", str);
1735            _resize_button(_item->button, &_item->rw, &_item->vw);
1736            break;
1737         }
1738 }
1739
1740 /**
1741  * Get the previous item in the multibuttonentry
1742  *
1743  * @param item The item
1744  * @return The item before the item @p item
1745  *
1746  * @ingroup Multibuttonentry
1747  */
1748 EAPI Elm_Multibuttonentry_Item *
1749 elm_multibuttonentry_item_prev(Elm_Multibuttonentry_Item *item)
1750 {
1751    Widget_Data *wd;
1752    Eina_List *l;
1753    Elm_Multibuttonentry_Item *_item;
1754    if (!item) return NULL;
1755    ELM_CHECK_WIDTYPE(item->multibuttonentry, widtype) NULL;
1756    wd = elm_widget_data_get(item->multibuttonentry);
1757    if (!wd || !wd->items) return NULL;
1758
1759    EINA_LIST_FOREACH(wd->items, l, _item)
1760       if (_item == item)
1761         {
1762            l = eina_list_prev(l);
1763            if (!l) return NULL;
1764            return eina_list_data_get(l);
1765         }
1766    return NULL;
1767 }
1768
1769 /**
1770  * Get the next item in the multibuttonentry
1771  *
1772  * @param item The item
1773  * @return The item after the item @p item
1774  *
1775  * @ingroup Multibuttonentry
1776  */
1777 EAPI Elm_Multibuttonentry_Item *
1778 elm_multibuttonentry_item_next(Elm_Multibuttonentry_Item *item)
1779 {
1780    Widget_Data *wd;
1781    Eina_List *l;
1782    Elm_Multibuttonentry_Item *_item;
1783    if (!item) return NULL;
1784    ELM_CHECK_WIDTYPE(item->multibuttonentry, widtype) NULL;
1785    wd = elm_widget_data_get(item->multibuttonentry);
1786    if (!wd || !wd->items) return NULL;
1787
1788    EINA_LIST_FOREACH(wd->items, l, _item)
1789       if (_item == item)
1790         {
1791            l = eina_list_next(l);
1792            if (!l) return NULL;
1793            return eina_list_data_get(l);
1794         }
1795    return NULL;
1796 }
1797
1798 /**
1799  * Get private data of item
1800  *
1801  * @param item The item
1802  * @return The data pointer stored, or NULL if none was stored
1803  *
1804  * @ingroup Multibuttonentry
1805  */
1806 EAPI void *
1807 elm_multibuttonentry_item_data_get(Elm_Multibuttonentry_Item *item)
1808 {
1809    if (!item) return NULL;
1810    return item->data;
1811 }
1812
1813 /**
1814  * Set private data of item
1815  *
1816  * @param item The item
1817  * @param data The ponter to the data to be attached
1818  *
1819  * @ingroup Multibuttonentry
1820  */
1821 EAPI void
1822 elm_multibuttonentry_item_data_set(Elm_Multibuttonentry_Item *item, void *data)
1823 {
1824    if (!item) return;
1825    item->data = data;
1826 }
1827
1828 /**
1829  * Set the multibuttonentry item_verify_callback function
1830  *
1831  * @param obj The multibuttonentry object
1832  * @param func The function pointer to be called, it it's NULL, callback function will be deleted.
1833  * @param data user data to be passed to the callback function
1834  *
1835  * @ingroup Multibuttonentry
1836  */
1837 EAPI void
1838 elm_multibuttonentry_item_verify_callback_set(Evas_Object *obj, Elm_Multibuttonentry_Item_Verify_Callback func, void *data)
1839 {
1840    ELM_CHECK_WIDTYPE(obj, widtype);
1841    Widget_Data *wd = elm_widget_data_get(obj);
1842    if (!wd) return;
1843
1844    wd->add_callback = func;
1845    wd->add_callback_data = data;
1846 }