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