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