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