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