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