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