Merge "fix bug : IME doesn't show in facebook > Message > Compose"
[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))
172           {
173              ecore_imf_context_input_panel_show(imf_context);
174              elm_object_focus(wd->entry);
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
741    size_str = edje_object_data_get(btn, "button_max_size");
742    if (size_str) button_max_width = (Evas_Coord)atoi(size_str);
743
744    // decide the size of button
745    edje_object_part_geometry_get(btn, "elm.base", NULL, NULL, NULL, &h_btn);
746    edje_object_part_geometry_get(btn, "elm.btn.text", NULL, NULL, &w_text, NULL);
747    edje_object_part_geometry_get(btn, "left.padding", NULL, NULL, &padding_outer, NULL);
748    edje_object_part_geometry_get(btn, "left.inner.padding", NULL, NULL, &padding_inner, NULL);
749    w_btn = w_text + 2*padding_outer + 2*padding_inner;
750
751    rw = w_btn;
752    vw = (button_max_width < w_btn) ? button_max_width : w_btn;
753
754    //resize btn
755    evas_object_resize(btn, vw, h_btn);
756    evas_object_size_hint_min_set(btn, vw, h_btn);
757
758    if(realw) *realw = rw;
759    if(vieww) *vieww = vw;
760 }
761
762 static Elm_Multibuttonentry_Item*
763 _add_button_item(Evas_Object *obj, const char *str, Multibuttonentry_Pos pos, const Elm_Multibuttonentry_Item *reference, void *data)
764 {
765    Elm_Multibuttonentry_Item *item;
766    Evas_Object *btn;
767    Evas_Coord width, height;
768    char *str_utf8 = NULL;
769
770    Widget_Data *wd = elm_widget_data_get(obj);
771
772    if (!wd || !wd->box || !wd->entry) return NULL;
773
774    if ((wd->add_callback) && !wd->add_callback(obj, str, data, wd->add_callback_data)) return NULL;
775
776    //entry is cleared when text is made to button
777    elm_entry_entry_set(wd->entry, "");
778
779    // add button
780    btn = edje_object_add(evas_object_evas_get(obj));
781    str_utf8 = elm_entry_markup_to_utf8(str);
782
783    _elm_theme_object_set(obj, btn, "multibuttonentry", "btn", elm_widget_style_get(obj));
784    edje_object_part_text_set(btn, "elm.btn.text", str_utf8);
785    edje_object_part_geometry_get(btn, "elm.btn.text", NULL, NULL, &width, &height);
786    evas_object_size_hint_min_set(btn, width, height);
787    edje_object_signal_callback_add(btn, "mouse,clicked,1", "*", _button_clicked, obj);
788    evas_object_size_hint_weight_set(btn, 0.0, 0.0);
789    evas_object_show(btn);
790
791    // append item list
792    item = ELM_NEW(Elm_Multibuttonentry_Item);
793    if (item)
794      {
795         Evas_Coord rw, vw;
796         _resize_button(btn, &rw, &vw);
797         item->multibuttonentry = obj;
798         item->button = btn;
799         item->data = data;
800         item->rw = rw;
801         item->vw = vw;
802         item->visible = EINA_TRUE;
803
804         switch(pos)
805           {
806              case MULTIBUTONENTRY_POS_START:
807                 wd->items = eina_list_prepend(wd->items, item);
808                 if (wd->view_state == MULTIBUTTONENTRY_VIEW_CONTRACTED)
809                   {
810                      elm_widget_sub_object_add(obj, btn);
811                      _contracted_state_set(obj, 1);
812                   }
813                 else
814                   {
815                      if (wd->label)
816                        elm_box_pack_after(wd->box, btn, wd->label);
817                      else
818                        elm_box_pack_start(wd->box, btn);
819                      if (wd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT)
820                        _set_vis_guidetext(obj);
821                   }
822                 break;
823              case MULTIBUTONENTRY_POS_END:
824                 wd->items = eina_list_append(wd->items, item);
825                 if (wd->view_state == MULTIBUTTONENTRY_VIEW_CONTRACTED)
826                   {
827                      elm_widget_sub_object_add(obj, btn);
828                      evas_object_hide(btn);
829                   }
830                 else
831                   {
832                      if (wd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT)
833                        _set_vis_guidetext(obj);
834                      if (wd->entry)
835                        elm_box_pack_before(wd->box, btn, wd->entry);
836                      else
837                        elm_box_pack_end(wd->box, btn);
838                   }
839                 break;
840              case MULTIBUTONENTRY_POS_BEFORE:
841                 if (reference)
842                      wd->items = eina_list_prepend_relative(wd->items, item, reference);
843                 else
844                      wd->items = eina_list_append(wd->items, item);
845                 if (wd->view_state == MULTIBUTTONENTRY_VIEW_CONTRACTED)
846                   {
847                      elm_widget_sub_object_add(obj, btn);
848                      evas_object_hide(btn);
849                      _contracted_state_set(obj, 1);
850                   }
851                 else
852                   {
853                      if (reference)
854                        elm_box_pack_before(wd->box, btn, reference->button);
855                      else
856                        {
857                           if (wd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT)
858                             _set_vis_guidetext(obj);
859                           if (wd->entry)
860                             elm_box_pack_before(wd->box, btn, wd->entry);
861                           else
862                             elm_box_pack_end(wd->box, btn);
863                        }
864                   }
865                 break;
866              case MULTIBUTONENTRY_POS_AFTER:
867                 if (reference)
868                      wd->items = eina_list_append_relative(wd->items, item, reference);
869                 else
870                      wd->items = eina_list_append(wd->items, item);
871                 if (wd->view_state == MULTIBUTTONENTRY_VIEW_CONTRACTED)
872                   {
873                      elm_widget_sub_object_add(obj, btn);
874                      _contracted_state_set(obj, 1);
875                   }
876                 else
877                   {
878                      if (reference)
879                        elm_box_pack_after(wd->box, btn, reference->button);
880                      else
881                        {
882                           if (wd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT)
883                             _set_vis_guidetext(obj);
884                           if (wd->entry)
885                             elm_box_pack_before(wd->box, btn, wd->entry);
886                           else
887                             elm_box_pack_end(wd->box, btn);
888                        }
889                   }
890                 break;
891              default:
892                 break;
893           }
894      }
895    evas_object_smart_callback_call(obj, "item,added", item);
896
897    free(str_utf8);
898
899    return item;
900 }
901
902 static void
903 _add_button(Evas_Object *obj, char *str)
904 {
905    Widget_Data *wd = elm_widget_data_get(obj);
906    if (!wd) return;
907
908    // add button
909    _add_button_item(obj, str, MULTIBUTONENTRY_POS_END, NULL, NULL);
910 }
911
912 static void
913 _evas_mbe_key_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
914 {
915    Widget_Data *wd = elm_widget_data_get(data);
916    Elm_Multibuttonentry_Item *item = NULL;
917
918    static char str[MAX_STR];
919
920    if (!wd || !wd->base || !wd->box) return;
921
922    strncpy(str, elm_entry_entry_get(wd->entry), MAX_STR);
923    str[MAX_STR - 1] = 0;
924
925    Evas_Event_Key_Up *ev = (Evas_Event_Key_Up*)event_info;
926
927    if (wd->last_btn_select)
928      {
929         if ((wd->current) &&  ( (strcmp (ev->keyname, "BackSpace") == 0) || (strcmp (ev->keyname, "BackSpace (") == 0)))
930           {
931              item = eina_list_data_get(wd->current);
932              if (item)
933                {
934                   _del_button_item(item);
935                   elm_object_focus(wd->entry);
936                }
937           }
938         else if ((((!wd->current) && (wd->n_str == 0) && (strcmp (ev->keyname, "BackSpace") == 0))
939                   || (strcmp (ev->keyname, "BackSpace (") == 0)))
940           {
941              item = eina_list_data_get(eina_list_last(wd->items));
942              if (item)
943                _select_button(data, item->button);
944           }
945      }
946    else
947      wd->last_btn_select = EINA_TRUE;
948 }
949
950 static void
951 _entry_key_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
952 {
953    Widget_Data *wd = elm_widget_data_get(data);
954    Evas_Event_Key_Down *ev = (Evas_Event_Key_Down *)event_info;
955
956    if (!wd) return;
957
958    if ( (wd->n_str == 1) && (strcmp (ev->keyname, "BackSpace") == 0 || (strcmp (ev->keyname, "BackSpace (") == 0 )))
959      wd->last_btn_select = EINA_FALSE;
960 }
961
962 static void
963 _entry_key_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
964 {
965    Widget_Data *wd = elm_widget_data_get(data);
966    Evas_Event_Key_Up *ev = (Evas_Event_Key_Up *) event_info;
967    static char str[MAX_STR];
968
969    if (!wd || !wd->base || !wd->box) return;
970
971    strncpy(str, elm_entry_entry_get(wd->entry), MAX_STR);
972    str[MAX_STR - 1] = 0;
973
974    if ( (strcmp (str, "") != 0) && (strcmp (ev->keyname, "KP_Enter") == 0 || strcmp (ev->keyname, "Return") == 0 ))
975      {
976         _add_button(data, str);
977         wd->n_str = 0;
978         return;
979      }
980 }
981
982 static void
983 _entry_focus_in_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
984 {
985    Widget_Data *wd = elm_widget_data_get(data);
986    if (!wd) return;
987
988    _change_current_button_state(data, MULTIBUTONENTRY_BUTTON_STATE_DEFAULT);
989 }
990
991 static void
992 _entry_focus_out_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
993 {
994    Widget_Data *wd = elm_widget_data_get(data);
995    if (!wd) return;
996
997    static char str[MAX_STR];
998
999    strncpy(str,elm_entry_entry_get(wd->entry), MAX_STR);
1000    str[MAX_STR -1] = 0;
1001
1002    if (strlen(str))
1003      _add_button(data, str);
1004 }
1005
1006 static void
1007 _entry_changed_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1008 {
1009    Widget_Data *wd = elm_widget_data_get(data);
1010    if (!wd) return;
1011
1012    static char str[MAX_STR];
1013
1014    strncpy(str, elm_entry_entry_get(wd->entry), MAX_STR);
1015    str[MAX_STR -1] = 0;
1016
1017    wd->n_str =  strlen(str);
1018 }
1019
1020 static void
1021 _view_init(Evas_Object *obj)
1022 {
1023    Widget_Data *wd = elm_widget_data_get(obj);
1024    if (!wd) return;
1025
1026    if (!wd->box)
1027      {
1028         if (! (wd->box = elm_box_add (obj))) return;
1029         elm_widget_sub_object_add(obj, wd->box);
1030         elm_box_layout_set(wd->box, _box_layout_cb, NULL, NULL);
1031         elm_box_homogeneous_set(wd->box, EINA_FALSE);
1032         edje_object_part_swallow(wd->base, "box.swallow", wd->box);
1033      }
1034
1035    if (!wd->label)
1036      {
1037         if (!(wd->label = edje_object_add(evas_object_evas_get(obj)))) return;
1038         _elm_theme_object_set(obj, wd->label, "multibuttonentry", "label", elm_widget_style_get(obj));
1039         _set_label(obj, "");
1040         elm_widget_sub_object_add(obj, wd->label);
1041      }
1042
1043    if (!wd->entry)
1044      {
1045         if (! (wd->entry = elm_entry_add (obj))) return;
1046         elm_entry_scrollable_set(wd->entry, EINA_TRUE);
1047         elm_entry_single_line_set(wd->entry, EINA_TRUE);
1048         elm_entry_entry_set(wd->entry, "");
1049         elm_entry_cursor_end_set(wd->entry);
1050         elm_entry_input_panel_enabled_set(wd->entry, EINA_FALSE);
1051         evas_object_size_hint_min_set(wd->entry, MIN_W_ENTRY, 0);
1052         evas_object_size_hint_weight_set(wd->entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1053         evas_object_size_hint_align_set(wd->entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
1054         if (wd->box)   elm_box_pack_end (wd->box, wd->entry);
1055         evas_object_show(wd->entry);
1056         wd->view_state = MULTIBUTTONENTRY_VIEW_ENTRY;
1057      }
1058
1059    if (!wd->end)
1060      {
1061         const char *end_type = edje_object_data_get(wd->base, "closed_button_type");
1062         if (!end_type || !strcmp(end_type, "label"))
1063           {
1064              if (! (wd->end = elm_label_add (obj))) return;
1065              elm_object_style_set(wd->end, "extended/multibuttonentry_default");
1066              wd->end_type = MULTIBUTTONENTRY_CLOSED_LABEL;
1067           }
1068         else
1069           {
1070              const char *size_str;
1071              if (!(wd->end = edje_object_add(evas_object_evas_get(obj)))) return;
1072              _elm_theme_object_set(obj, wd->end, "multibuttonentry", "closedbutton", elm_widget_style_get(obj));
1073              Evas_Coord button_min_width = 0;
1074              Evas_Coord button_min_height = 0;
1075
1076              size_str = edje_object_data_get(wd->end, "closed_button_width");
1077              if(size_str) button_min_width = (Evas_Coord)atoi(size_str);
1078              size_str = edje_object_data_get(wd->end, "closed_button_height");
1079              if(size_str) button_min_height = (Evas_Coord)atoi(size_str);
1080
1081              wd->end_type = MULTIBUTTONENTRY_CLOSED_IMAGE;
1082              evas_object_size_hint_min_set(wd->end, button_min_width, button_min_height);
1083              elm_widget_sub_object_add(obj, wd->end);
1084           }
1085      }
1086 }
1087
1088 static void
1089 _calculate_box_min_size(Evas_Object *box, Evas_Object_Box_Data *priv)
1090 {
1091    Evas_Coord minw, minh, maxw, maxh, mnw, mnh, ww;
1092    Evas_Coord w, cw = 0, cmaxh = 0;
1093    const Eina_List *l;
1094    Evas_Object_Box_Option *opt;
1095    double wx;
1096
1097    /* FIXME: need to calc max */
1098    minw = 0;
1099    minh = 0;
1100    maxw = -1;
1101    maxh = -1;
1102
1103    evas_object_geometry_get(box, NULL, NULL, &w, NULL);
1104    evas_object_size_hint_min_get(box, &minw, NULL);
1105
1106    EINA_LIST_FOREACH(priv->children, l, opt)
1107      {
1108         evas_object_size_hint_min_get(opt->obj, &mnw, &mnh);
1109         evas_object_size_hint_weight_get(opt->obj, &wx, NULL);
1110
1111         if(wx)
1112           {
1113              if (mnw != -1 && (w - cw) >= mnw)
1114                 ww = w - cw;
1115              else
1116                 ww = w;
1117           }
1118         else
1119            ww = mnw;
1120
1121         if ((cw + mnw) > w)
1122           {
1123              minh += cmaxh;
1124              cw = 0;
1125              cmaxh = 0;
1126           }
1127         cw += ww;
1128         if (cmaxh < mnh) cmaxh = mnh;
1129      }
1130
1131    minh += cmaxh;
1132
1133    evas_object_size_hint_min_set(box, minw, minh);
1134 }
1135
1136 static Evas_Coord
1137 _calculate_item_max_height(Evas_Object *box, Evas_Object_Box_Data *priv, int obj_index)
1138 {
1139    Evas_Coord mnw, mnh, cw = 0, cmaxh = 0, w, ww;
1140    const Eina_List *l;
1141    Evas_Object_Box_Option *opt;
1142    int index = 0;
1143    double wx;
1144
1145    evas_object_geometry_get(box, NULL, NULL, &w, NULL);
1146
1147    EINA_LIST_FOREACH(priv->children, l, opt)
1148      {
1149         evas_object_size_hint_min_get(opt->obj, &mnw, &mnh);
1150         evas_object_size_hint_weight_get(opt->obj, &wx, NULL);
1151
1152         if(wx)
1153           {
1154              if (mnw != -1 && (w - cw) >= mnw)
1155                 ww = w - cw;
1156              else
1157                 ww = w;
1158           }
1159         else
1160            ww = mnw;
1161
1162         if ((cw + ww) > w)
1163           {
1164              if (index > obj_index) return cmaxh;
1165              cw = 0;
1166              cmaxh = 0;
1167           }
1168
1169         cw += ww;
1170         if (cmaxh < mnh) cmaxh = mnh;
1171
1172         index++;
1173      }
1174
1175    return cmaxh;
1176 }
1177
1178 static void
1179 _box_layout_cb(Evas_Object *o, Evas_Object_Box_Data *priv, void *data __UNUSED__)
1180 {
1181    Evas_Coord x, y, w, h, xx, yy;
1182    const Eina_List *l;
1183    Evas_Object *obj;
1184    Evas_Coord minw, minh, wdif, hdif;
1185    int count = 0;
1186    double ax, ay;
1187    Evas_Object_Box_Option *opt;
1188
1189    _calculate_box_min_size(o, priv);
1190
1191    evas_object_geometry_get(o, &x, &y, &w, &h);
1192
1193    evas_object_size_hint_min_get(o, &minw, &minh);
1194    evas_object_size_hint_align_get(o, &ax, &ay);
1195    count = eina_list_count(priv->children);
1196    if (w < minw)
1197      {
1198         x = x + ((w - minw) * (1.0 - ax));
1199         w = minw;
1200      }
1201    if (h < minh)
1202      {
1203         y = y + ((h - minh) * (1.0 - ay));
1204         h = minh;
1205      }
1206
1207    wdif = w - minw;
1208    hdif = h - minh;
1209    xx = x;
1210    yy = y;
1211
1212    Evas_Coord cw = 0, ch = 0, cmaxh = 0, obj_index = 0;
1213
1214    EINA_LIST_FOREACH(priv->children, l, opt)
1215      {
1216         Evas_Coord mnw, mnh, mxw, mxh;
1217         double wx, wy;
1218         int fw, fh, xw, xh;
1219
1220         obj = opt->obj;
1221         evas_object_size_hint_align_get(obj, &ax, &ay);
1222         evas_object_size_hint_weight_get(obj, &wx, &wy);
1223         evas_object_size_hint_min_get(obj, &mnw, &mnh);
1224         evas_object_size_hint_max_get(obj, &mxw, &mxh);
1225         fw = fh = 0;
1226         xw = xh = 0;
1227         if (ax == -1.0) {fw = 1; ax = 0.5;}
1228         if (ay == -1.0) {fh = 1; ay = 0.5;}
1229         if (wx > 0.0) xw = 1;
1230         if (wy > 0.0) xh = 1;
1231         Evas_Coord ww, hh, ow, oh;
1232
1233         if(wx)
1234           {
1235              if (mnw != -1 && (w - cw) >= mnw)
1236                 ww = w - cw;
1237              else
1238                 ww = w;
1239           }
1240         else
1241            ww = mnw;
1242         hh = _calculate_item_max_height(o, priv, obj_index);
1243
1244         ow = mnw;
1245         if (fw) ow = ww;
1246         if ((mxw >= 0) && (mxw < ow)) ow = mxw;
1247         oh = mnh;
1248         if (fh) oh = hh;
1249         if ((mxh >= 0) && (mxh < oh)) oh = mxh;
1250
1251         if ((cw + ww) > w)
1252           {
1253              ch += cmaxh;
1254              cw = 0;
1255              cmaxh = 0;
1256           }
1257
1258         evas_object_move(obj,
1259                          xx + cw + (Evas_Coord)(((double)(ww - ow)) * ax),
1260                          yy + ch + (Evas_Coord)(((double)(hh - oh)) * ay));
1261         evas_object_resize(obj, ow, oh);
1262
1263         cw += ww;
1264         if (cmaxh < hh) cmaxh = hh;
1265
1266         obj_index++;
1267      }
1268 }
1269
1270 /**
1271  * Add a new multibuttonentry to the parent
1272  *
1273  * @param parent The parent object
1274  * @return The new object or NULL if it cannot be created
1275  *
1276  * @ingroup Multibuttonentry
1277  */
1278 EAPI Evas_Object *
1279 elm_multibuttonentry_add(Evas_Object *parent)
1280 {
1281    Evas_Object *obj;
1282    Evas *e;
1283    Widget_Data *wd;
1284    if (!parent) return NULL;
1285
1286    wd = ELM_NEW(Widget_Data);
1287    e = evas_object_evas_get(parent);
1288    if (!e) return NULL;
1289    obj = elm_widget_add(e);
1290    ELM_SET_WIDTYPE(widtype, "multibuttonentry");
1291    elm_widget_type_set(obj, "multibuttonentry");
1292    elm_widget_sub_object_add(parent, obj);
1293    elm_widget_data_set(obj, wd);
1294
1295    elm_widget_del_hook_set(obj, _del_hook);
1296    elm_widget_theme_hook_set(obj, _theme_hook);
1297    elm_widget_event_hook_set(obj, _event_hook);
1298    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
1299    elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
1300
1301    wd->base = edje_object_add(e);
1302    _elm_theme_object_set(obj, wd->base, "multibuttonentry", "base", "default");
1303    elm_widget_resize_object_set(obj, wd->base);
1304    elm_widget_can_focus_set(obj,EINA_TRUE);
1305
1306    wd->view_state = MULTIBUTTONENTRY_VIEW_NONE;
1307    wd->focused = EINA_FALSE;
1308    wd->last_btn_select = EINA_TRUE;
1309    wd->n_str = 0;
1310    wd->rectForEnd = NULL;
1311    wd->add_callback = NULL;
1312    wd->add_callback_data = NULL;
1313
1314    _view_init(obj);
1315    _event_init(obj);
1316
1317    return obj;
1318 }
1319
1320 /**
1321  * Get the entry of the multibuttonentry object
1322  *
1323  * @param obj The multibuttonentry object
1324  * @return The entry object, or NULL if none
1325  *
1326  * @ingroup Multibuttonentry
1327  */
1328 EAPI Evas_Object *
1329 elm_multibuttonentry_entry_get(Evas_Object *obj)
1330 {
1331    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1332    Widget_Data *wd = elm_widget_data_get(obj);
1333    if (!wd)   return NULL;
1334
1335    return wd->entry;
1336 }
1337
1338 /**
1339  * Get the label
1340  *
1341  * @param obj The multibuttonentry object
1342  * @return The label, or NULL if none
1343  *
1344  * @ingroup Multibuttonentry
1345  */
1346 EAPI const char *
1347 elm_multibuttonentry_label_get(Evas_Object *obj)
1348 {
1349    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1350    Widget_Data *wd = elm_widget_data_get(obj);
1351    if (!wd) return NULL;
1352    if (wd->label) return edje_object_part_text_get(wd->label, "mbe.label");
1353    return NULL;
1354 }
1355
1356 /**
1357  * Set the label
1358  *
1359  * @param obj The multibuttonentry object
1360  * @param label The text label string
1361  *
1362  * @ingroup Multibuttonentry
1363  */
1364 EAPI void
1365 elm_multibuttonentry_label_set(Evas_Object *obj, const char *label)
1366 {
1367    ELM_CHECK_WIDTYPE(obj, widtype);
1368    Widget_Data *wd = elm_widget_data_get(obj);
1369    if (!wd) return;
1370    if (label)
1371      _set_label(obj, label);
1372    else
1373      _set_label(obj, "");
1374 }
1375
1376 /**
1377  * Get the guide text
1378  *
1379  * @param obj The multibuttonentry object
1380  * @return The guide text, or NULL if none
1381  *
1382  * @ingroup Multibuttonentry
1383  */
1384 EAPI const char *
1385 elm_multibuttonentry_guide_text_get(Evas_Object *obj)
1386 {
1387    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1388    Widget_Data *wd = elm_widget_data_get(obj);
1389    if (!wd)   return NULL;
1390    if (wd->guidetext) return edje_object_part_text_get(wd->guidetext, "elm.text");
1391    return NULL;
1392 }
1393
1394 /**
1395  * Set the guide text
1396  *
1397  * @param obj The multibuttonentry object
1398  * @param label The guide text string
1399  *
1400  * @ingroup Multibuttonentry
1401  */
1402 EAPI void
1403 elm_multibuttonentry_guide_text_set(Evas_Object *obj, const char *guidetext)
1404 {
1405    ELM_CHECK_WIDTYPE(obj, widtype);
1406    Widget_Data *wd = elm_widget_data_get(obj);
1407    if (!wd) return;
1408    if (guidetext)
1409       _set_guidetext(obj, guidetext);
1410    else
1411       _set_guidetext(obj, "");
1412
1413 }
1414
1415 /**
1416  * Get the value of contracted state.
1417  *
1418  * @param obj The multibuttonentry object
1419  * @param the value of contracted state.
1420  *
1421  * @ingroup Multibuttonentry
1422  */
1423 EAPI int
1424 elm_multibuttonentry_contracted_state_get(Evas_Object *obj)
1425 {
1426    ELM_CHECK_WIDTYPE(obj, widtype) -1;
1427    Widget_Data *wd = elm_widget_data_get(obj);
1428    if (!wd) return -1;
1429    return wd->view_state == MULTIBUTTONENTRY_VIEW_CONTRACTED ? 1 : 0;
1430 }
1431
1432 /**
1433  * Set/Unset the multibuttonentry to contracted state of single line
1434  *
1435  * @param obj The multibuttonentry object
1436  * @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.
1437  *
1438  * @ingroup Multibuttonentry
1439  */
1440 EAPI void
1441 elm_multibuttonentry_contracted_state_set(Evas_Object *obj, int contracted)
1442 {
1443    ELM_CHECK_WIDTYPE(obj, widtype);
1444    Widget_Data *wd = elm_widget_data_get(obj);
1445    if (!wd || !wd->box ||
1446        ((wd->view_state == MULTIBUTTONENTRY_VIEW_CONTRACTED) ? 1 : 0) == contracted) return;
1447    _contracted_state_set(obj, contracted);
1448 }
1449
1450 /**
1451  * Prepend a new item to the multibuttonentry
1452  *
1453  * @param obj The multibuttonentry object
1454  * @param label The label of new item
1455  * @param data The ponter to the data to be attached
1456  * @return A handle to the item added or NULL if not possible
1457  *
1458  * @ingroup Multibuttonentry
1459  */
1460 EAPI Elm_Multibuttonentry_Item *
1461 elm_multibuttonentry_item_add_start(Evas_Object *obj, const char *label, void *data)
1462 {
1463    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1464    Widget_Data *wd = elm_widget_data_get(obj);
1465    Elm_Multibuttonentry_Item *item;
1466    if (!wd || !label) return NULL;
1467    item = _add_button_item(obj, label, MULTIBUTONENTRY_POS_START, NULL, data);
1468    return item;
1469 }
1470
1471 /**
1472  * Append a new item to the multibuttonentry
1473  *
1474  * @param obj The multibuttonentry object
1475  * @param label The label of new item
1476  * @param data The ponter to the data to be attached
1477  * @return A handle to the item added or NULL if not possible
1478  *
1479  * @ingroup Multibuttonentry
1480  */
1481 EAPI Elm_Multibuttonentry_Item *
1482 elm_multibuttonentry_item_add_end(Evas_Object *obj, const char *label, void *data)
1483 {
1484    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1485    Widget_Data *wd = elm_widget_data_get(obj);
1486    Elm_Multibuttonentry_Item *item;
1487    if (!wd || !label) return NULL;
1488    item = _add_button_item(obj, label, MULTIBUTONENTRY_POS_END, NULL, data);
1489    return item;
1490 }
1491
1492 /**
1493  * Add a new item to the multibuttonentry before the indicated object
1494  *
1495  * reference.
1496  * @param obj The multibuttonentry object
1497  * @param label The label of new item
1498  * @param before The item before which to add it
1499  * @param data The ponter to the data to be attached
1500  * @return A handle to the item added or NULL if not possible
1501  *
1502  * @ingroup Multibuttonentry
1503  */
1504 EAPI Elm_Multibuttonentry_Item *
1505 elm_multibuttonentry_item_add_before(Evas_Object *obj, const char *label, Elm_Multibuttonentry_Item *before, void *data)
1506 {
1507    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1508    Widget_Data *wd = elm_widget_data_get(obj);
1509    Elm_Multibuttonentry_Item *item;
1510    if (!wd || !label) return NULL;
1511    item = _add_button_item(obj, label, MULTIBUTONENTRY_POS_BEFORE, before, data);
1512    return item;
1513 }
1514
1515 /**
1516  * Add a new item to the multibuttonentry after the indicated object
1517  *
1518  * @param obj The multibuttonentry object
1519  * @param label The label of new item
1520  * @param after The item after which to add it
1521  * @param data The ponter to the data to be attached
1522  * @return A handle to the item added or NULL if not possible
1523  *
1524  * @ingroup Multibuttonentry
1525  */
1526 EAPI Elm_Multibuttonentry_Item *
1527 elm_multibuttonentry_item_add_after(Evas_Object *obj, const char *label, Elm_Multibuttonentry_Item *after, void *data)
1528 {
1529    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1530    Widget_Data *wd = elm_widget_data_get(obj);
1531    Elm_Multibuttonentry_Item *item;
1532    if (!wd || !label) return NULL;
1533    item = _add_button_item(obj, label, MULTIBUTONENTRY_POS_AFTER, after, data);
1534    return item;
1535 }
1536
1537 /**
1538  * Get a list of items in the multibuttonentry
1539  *
1540  * @param obj The multibuttonentry object
1541  * @return The list of items, or NULL if none
1542  *
1543  * @ingroup Multibuttonentry
1544  */
1545 EAPI const Eina_List *
1546 elm_multibuttonentry_items_get(Evas_Object *obj)
1547 {
1548    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1549    Widget_Data *wd = elm_widget_data_get(obj);
1550    if (!wd) return NULL;
1551    return wd->items;
1552 }
1553
1554 /**
1555  * Get the first item in the multibuttonentry
1556  *
1557  * @param obj The multibuttonentry object
1558  * @return The first item, or NULL if none
1559  *
1560  * @ingroup Multibuttonentry
1561  */
1562 EAPI Elm_Multibuttonentry_Item *
1563 elm_multibuttonentry_item_first_get(Evas_Object *obj)
1564 {
1565    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1566    Widget_Data *wd = elm_widget_data_get(obj);
1567    if (!wd || !wd->items) return NULL;
1568    return eina_list_data_get(wd->items);
1569 }
1570
1571 /**
1572  * Get the last item in the multibuttonentry
1573  *
1574  * @param obj The multibuttonentry object
1575  * @return The last item, or NULL if none
1576  *
1577  * @ingroup Multibuttonentry
1578  */
1579 EAPI Elm_Multibuttonentry_Item *
1580 elm_multibuttonentry_item_last_get(Evas_Object *obj)
1581 {
1582    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1583    Widget_Data *wd = elm_widget_data_get(obj);
1584    if (!wd || !wd->items) return NULL;
1585    return eina_list_data_get(eina_list_last(wd->items));
1586 }
1587
1588 /**
1589  * Get the selected item in the multibuttonentry
1590  *
1591  * @param obj The multibuttonentry object
1592  * @return The selected item, or NULL if none
1593  *
1594  * @ingroup Multibuttonentry
1595  */
1596 EAPI Elm_Multibuttonentry_Item *
1597 elm_multibuttonentry_item_selected_get(Evas_Object *obj)
1598 {
1599    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1600    Widget_Data *wd = elm_widget_data_get(obj);
1601    if (!wd || !wd->current) return NULL;
1602    return eina_list_data_get(wd->current);
1603 }
1604
1605 /**
1606  * Set the selected state of an item
1607  *
1608  * @param item The item
1609  *
1610  * @ingroup Multibuttonentry
1611  */
1612 EAPI void
1613 elm_multibuttonentry_item_selected_set(Elm_Multibuttonentry_Item *item)
1614 {
1615    Widget_Data *wd;
1616    Eina_List *l;
1617    Elm_Multibuttonentry_Item *_item;
1618
1619    if (!item) return;
1620    ELM_CHECK_WIDTYPE(item->multibuttonentry, widtype);
1621    wd = elm_widget_data_get(item->multibuttonentry);
1622    if (!wd) return;
1623
1624    EINA_LIST_FOREACH(wd->items, l, _item)
1625      {
1626         if (_item == item)
1627           _select_button(item->multibuttonentry, item->button);
1628      }
1629 }
1630
1631 /**
1632  * unselect all of items.
1633  *
1634  * @param obj The multibuttonentry object
1635  *
1636  * @ingroup Multibuttonentry
1637  */
1638 EAPI void
1639 elm_multibuttonentry_item_unselect_all(Evas_Object *obj)
1640 {
1641    ELM_CHECK_WIDTYPE(obj, widtype);
1642    Widget_Data *wd = elm_widget_data_get(obj);
1643    if (!wd) return;
1644
1645    _select_button(obj, NULL);
1646 }
1647
1648 /**
1649  * Remove all items in the multibuttonentry.
1650  *
1651  * @param obj The multibuttonentry object
1652  *
1653  * @ingroup Multibuttonentry
1654  */
1655 EAPI void
1656 elm_multibuttonentry_items_del(Evas_Object *obj)
1657 {
1658    ELM_CHECK_WIDTYPE(obj, widtype);
1659    Widget_Data *wd = elm_widget_data_get(obj);
1660    if (!wd) return;
1661
1662    if (wd->items)
1663      {
1664         Elm_Multibuttonentry_Item *item;
1665         EINA_LIST_FREE(wd->items, item)
1666           {
1667              elm_box_unpack(wd->box, item->button);
1668              _del_button_obj(obj, item->button);
1669              free(item);
1670           }
1671         wd->items = NULL;
1672      }
1673    wd->current = NULL;
1674    _view_update(obj);
1675 }
1676
1677 /**
1678  * Delete a given item
1679  *
1680  * @param item The item
1681  *
1682  * @ingroup Multibuttonentry
1683  */
1684 EAPI void
1685 elm_multibuttonentry_item_del(Elm_Multibuttonentry_Item *item)
1686 {
1687    if (!item) return;
1688    _del_button_item(item);
1689 }
1690
1691 /**
1692  * Get the label of a given item
1693  *
1694  * @param item The item
1695  * @return The label of a given item, or NULL if none
1696  *
1697  * @ingroup Multibuttonentry
1698  */
1699 EAPI const char *
1700 elm_multibuttonentry_item_label_get(Elm_Multibuttonentry_Item *item)
1701 {
1702    Widget_Data *wd;
1703    Eina_List *l;
1704    Elm_Multibuttonentry_Item *_item;
1705    if (!item) return NULL;
1706    ELM_CHECK_WIDTYPE(item->multibuttonentry, widtype) NULL;
1707    wd = elm_widget_data_get(item->multibuttonentry);
1708    if (!wd || !wd->items) return NULL;
1709
1710    EINA_LIST_FOREACH(wd->items, l, _item)
1711      {
1712         if (_item == item)
1713           return edje_object_part_text_get(_item->button, "elm.btn.text");
1714      }
1715
1716    return NULL;
1717 }
1718
1719 /**
1720  * Set the label of a given item
1721  *
1722  * @param item The item
1723  * @param label The text label string
1724  *
1725  * @ingroup Multibuttonentry
1726  */
1727 EAPI void
1728 elm_multibuttonentry_item_label_set(Elm_Multibuttonentry_Item *item, const char *str)
1729 {
1730    Widget_Data *wd;
1731    Eina_List *l;
1732    Elm_Multibuttonentry_Item *_item;
1733    if (!item || !str) return;
1734    ELM_CHECK_WIDTYPE(item->multibuttonentry, widtype);
1735    wd = elm_widget_data_get(item->multibuttonentry);
1736    if (!wd || !wd->items) return;
1737
1738    EINA_LIST_FOREACH(wd->items, l, _item)
1739       if (_item == item)
1740         {
1741            edje_object_part_text_set(_item->button, "elm.btn.text", str);
1742            _resize_button(_item->button, &_item->rw, &_item->vw);
1743            break;
1744         }
1745 }
1746
1747 /**
1748  * Get the previous item in the multibuttonentry
1749  *
1750  * @param item The item
1751  * @return The item before the item @p item
1752  *
1753  * @ingroup Multibuttonentry
1754  */
1755 EAPI Elm_Multibuttonentry_Item *
1756 elm_multibuttonentry_item_prev(Elm_Multibuttonentry_Item *item)
1757 {
1758    Widget_Data *wd;
1759    Eina_List *l;
1760    Elm_Multibuttonentry_Item *_item;
1761    if (!item) return NULL;
1762    ELM_CHECK_WIDTYPE(item->multibuttonentry, widtype) NULL;
1763    wd = elm_widget_data_get(item->multibuttonentry);
1764    if (!wd || !wd->items) return NULL;
1765
1766    EINA_LIST_FOREACH(wd->items, l, _item)
1767       if (_item == item)
1768         {
1769            l = eina_list_prev(l);
1770            if (!l) return NULL;
1771            return eina_list_data_get(l);
1772         }
1773    return NULL;
1774 }
1775
1776 /**
1777  * Get the next item in the multibuttonentry
1778  *
1779  * @param item The item
1780  * @return The item after the item @p item
1781  *
1782  * @ingroup Multibuttonentry
1783  */
1784 EAPI Elm_Multibuttonentry_Item *
1785 elm_multibuttonentry_item_next(Elm_Multibuttonentry_Item *item)
1786 {
1787    Widget_Data *wd;
1788    Eina_List *l;
1789    Elm_Multibuttonentry_Item *_item;
1790    if (!item) return NULL;
1791    ELM_CHECK_WIDTYPE(item->multibuttonentry, widtype) NULL;
1792    wd = elm_widget_data_get(item->multibuttonentry);
1793    if (!wd || !wd->items) return NULL;
1794
1795    EINA_LIST_FOREACH(wd->items, l, _item)
1796       if (_item == item)
1797         {
1798            l = eina_list_next(l);
1799            if (!l) return NULL;
1800            return eina_list_data_get(l);
1801         }
1802    return NULL;
1803 }
1804
1805 /**
1806  * Get private data of item
1807  *
1808  * @param item The item
1809  * @return The data pointer stored, or NULL if none was stored
1810  *
1811  * @ingroup Multibuttonentry
1812  */
1813 EAPI void *
1814 elm_multibuttonentry_item_data_get(Elm_Multibuttonentry_Item *item)
1815 {
1816    if (!item) return NULL;
1817    return item->data;
1818 }
1819
1820 /**
1821  * Set private data of item
1822  *
1823  * @param item The item
1824  * @param data The ponter to the data to be attached
1825  *
1826  * @ingroup Multibuttonentry
1827  */
1828 EAPI void
1829 elm_multibuttonentry_item_data_set(Elm_Multibuttonentry_Item *item, void *data)
1830 {
1831    if (!item) return;
1832    item->data = data;
1833 }
1834
1835 /**
1836  * Set the multibuttonentry item_verify_callback function
1837  *
1838  * @param obj The multibuttonentry object
1839  * @param func The function pointer to be called, it it's NULL, callback function will be deleted.
1840  * @param data user data to be passed to the callback function
1841  *
1842  * @ingroup Multibuttonentry
1843  */
1844 EAPI void
1845 elm_multibuttonentry_item_verify_callback_set(Evas_Object *obj, Elm_Multibuttonentry_Item_Verify_Callback func, void *data)
1846 {
1847    ELM_CHECK_WIDTYPE(obj, widtype);
1848    Widget_Data *wd = elm_widget_data_get(obj);
1849    if (!wd) return;
1850
1851    wd->add_callback = func;
1852    wd->add_callback_data = data;
1853 }