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