elementry/multibuttonentry - need to use ELM_WIDGET_ITEM internally.
[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      ELM_WIDGET_ITEM;
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 = WIDGET(item);
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_widget_item_new(obj, Elm_Multibuttonentry_Item);
794    if (item)
795      {
796         Evas_Coord rw, vw;
797         _resize_button(btn, &rw, &vw);
798         item->button = btn;
799         item->data = data;
800         item->rw = rw;
801         item->vw = vw;
802         item->visible = EINA_TRUE;
803
804         switch (pos)
805           {
806              case MULTIBUTTONENTRY_POS_START:
807                 wd->items = eina_list_prepend(wd->items, item);
808                 if (wd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK)
809                   {
810                      elm_widget_sub_object_add(obj, btn);
811                      _shrink_mode_set(obj, 1);
812                   }
813                 else
814                   {
815                      if (wd->label)
816                        elm_box_pack_after(wd->box, btn, wd->label);
817                      else
818                        elm_box_pack_start(wd->box, btn);
819                      if (wd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT)
820                        _set_vis_guidetext(obj);
821                   }
822                 break;
823              case MULTIBUTTONENTRY_POS_END:
824                 wd->items = eina_list_append(wd->items, item);
825                 if (wd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK)
826                   {
827                      elm_widget_sub_object_add(obj, btn);
828                      evas_object_hide(btn);
829                   }
830                 else
831                   {
832                      if (wd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT)
833                        _set_vis_guidetext(obj);
834                      if (wd->entry)
835                        elm_box_pack_before(wd->box, btn, wd->entry);
836                      else
837                        elm_box_pack_end(wd->box, btn);
838                   }
839                 break;
840              case MULTIBUTTONENTRY_POS_BEFORE:
841                 if (reference)
842                      wd->items = eina_list_prepend_relative(wd->items, item, reference);
843                 else
844                      wd->items = eina_list_append(wd->items, item);
845                 if (wd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK)
846                   {
847                      elm_widget_sub_object_add(obj, btn);
848                      evas_object_hide(btn);
849                      _shrink_mode_set(obj, 1);
850                   }
851                 else
852                   {
853                      if (reference)
854                        elm_box_pack_before(wd->box, btn, reference->button);
855                      else
856                        {
857                           if (wd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT)
858                             _set_vis_guidetext(obj);
859                           if (wd->entry)
860                             elm_box_pack_before(wd->box, btn, wd->entry);
861                           else
862                             elm_box_pack_end(wd->box, btn);
863                        }
864                   }
865                 break;
866              case MULTIBUTTONENTRY_POS_AFTER:
867                 if (reference)
868                      wd->items = eina_list_append_relative(wd->items, item, reference);
869                 else
870                      wd->items = eina_list_append(wd->items, item);
871                 if (wd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK)
872                   {
873                      elm_widget_sub_object_add(obj, btn);
874                      _shrink_mode_set(obj, 1);
875                   }
876                 else
877                   {
878                      if (reference)
879                        elm_box_pack_after(wd->box, btn, reference->button);
880                      else
881                        {
882                           if (wd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT)
883                             _set_vis_guidetext(obj);
884                           if (wd->entry)
885                             elm_box_pack_before(wd->box, btn, wd->entry);
886                           else
887                             elm_box_pack_end(wd->box, btn);
888                        }
889                   }
890                 break;
891              default:
892                 break;
893           }
894      }
895    evas_object_smart_callback_call(obj, "item,added", item);
896
897    free(str_utf8);
898
899    return item;
900 }
901
902 static void
903 _add_button(Evas_Object *obj, const char *str)
904 {
905    Widget_Data *wd = elm_widget_data_get(obj);
906    if (!wd) return;
907
908    _add_button_item(obj, str, MULTIBUTTONENTRY_POS_END, NULL, NULL);
909 }
910
911 static Elm_Multibuttonentry_Item_Filter*
912 _filter_new(Elm_Multibuttonentry_Item_Filter_callback func, void *data)
913 {
914    Elm_Multibuttonentry_Item_Filter *item_filter = ELM_NEW(Elm_Multibuttonentry_Item_Filter);
915    if (!item_filter) return NULL;
916
917    item_filter->callback_func= func;
918    item_filter->data = data;
919
920    return item_filter;
921 }
922
923 static void
924 _filter_free(Elm_Multibuttonentry_Item_Filter *item_filter)
925 {
926    free(item_filter);
927 }
928
929 static void
930 _evas_mbe_key_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
931 {
932    Widget_Data *wd = elm_widget_data_get(data);
933    Elm_Multibuttonentry_Item *item = NULL;
934
935    if (!wd || !wd->base || !wd->box) return;
936
937    Evas_Event_Key_Up *ev = (Evas_Event_Key_Up*)event_info;
938
939    if (wd->last_btn_select)
940      {
941         if (wd->current &&
942             ((strcmp(ev->keyname, "BackSpace") == 0) ||
943              (strcmp(ev->keyname, "BackSpace (") == 0)))
944           {
945              item = eina_list_data_get(wd->current);
946              if (item)
947                {
948                   _del_button_item(item);
949                   elm_object_focus_set(wd->entry, EINA_TRUE);
950                }
951           }
952         else if (((!wd->current && (wd->n_str == 0) &&
953                    (strcmp(ev->keyname, "BackSpace") == 0)) ||
954                   (strcmp(ev->keyname, "BackSpace (") == 0)))
955           {
956              item = eina_list_data_get(eina_list_last(wd->items));
957              if (item)
958                _select_button(data, item->button);
959           }
960      }
961    else
962      wd->last_btn_select = EINA_TRUE;
963 }
964
965 static void
966 _entry_key_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
967 {
968    Widget_Data *wd = elm_widget_data_get(data);
969    Evas_Event_Key_Down *ev = (Evas_Event_Key_Down *)event_info;
970
971    if (!wd) return;
972
973    if ((wd->n_str == 1) && (strcmp(ev->keyname, "BackSpace") == 0 || (strcmp(ev->keyname, "BackSpace (") == 0 )))
974      wd->last_btn_select = EINA_FALSE;
975 }
976
977 static void
978 _entry_key_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
979 {
980    Widget_Data *wd = elm_widget_data_get(data);
981    Evas_Event_Key_Up *ev = (Evas_Event_Key_Up *) event_info;
982    const char *str;
983
984    if (!wd || !wd->base || !wd->box) return;
985
986    str = elm_object_text_get(wd->entry);
987
988    if ((strcmp(str, "") != 0) && (strcmp(ev->keyname, "KP_Enter") == 0 || strcmp(ev->keyname, "Return") == 0 ))
989      {
990         _add_button(data, str);
991         wd->n_str = 0;
992      }
993 }
994
995 static void
996 _entry_clicked_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
997 {
998    Widget_Data *wd = elm_widget_data_get(data);
999    if (!wd) return;
1000
1001    _change_current_button_state(data, MULTIBUTTONENTRY_BUTTON_STATE_DEFAULT);
1002    elm_object_focus_set(wd->entry, EINA_TRUE);
1003 }
1004
1005 static void
1006 _entry_focus_in_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1007 {
1008    Widget_Data *wd = elm_widget_data_get(data);
1009    Elm_Multibuttonentry_Item *item = NULL;
1010
1011    if (!wd) return;
1012
1013    if (wd->current)
1014      {
1015         item = eina_list_data_get(wd->current);
1016         elm_object_focus_set(wd->entry, EINA_FALSE);
1017         evas_object_focus_set(item->button, EINA_TRUE);
1018      }
1019 }
1020
1021 static void
1022 _entry_focus_out_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1023 {
1024    Widget_Data *wd = elm_widget_data_get(data);
1025    const char *str;
1026
1027    if (!wd) return;
1028
1029    str = elm_object_text_get(wd->entry);
1030    if (strlen(str))
1031      _add_button(data, str);
1032 }
1033
1034 static void
1035 _entry_changed_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1036 {
1037    Widget_Data *wd = elm_widget_data_get(data);
1038    const char *str;
1039
1040    if (!wd) return;
1041
1042    str = elm_object_text_get(wd->entry);
1043    wd->n_str = strlen(str);
1044 }
1045
1046 static void
1047 _entry_resized_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1048 {
1049    Evas_Coord en_x, en_y, en_w, en_h;
1050    Evas_Coord bx_x, bx_y;
1051
1052    Widget_Data *wd = elm_widget_data_get(data);
1053    if (!wd) return;
1054
1055    evas_object_geometry_get(wd->entry, &en_x, &en_y, &en_w, &en_h);
1056    evas_object_geometry_get(wd->box, &bx_x, &bx_y, NULL, NULL);
1057
1058    elm_widget_show_region_set(wd->box, en_x - bx_x, en_y - bx_y, en_w, en_h, EINA_TRUE);
1059 }
1060
1061 static void
1062 _view_init(Evas_Object *obj)
1063 {
1064    Widget_Data *wd = elm_widget_data_get(obj);
1065
1066    if (!wd) return;
1067
1068    if (!wd->box)
1069      {
1070         wd->box = elm_box_add (obj);
1071         if (!wd->box) return;
1072         elm_widget_sub_object_add(obj, wd->box);
1073         elm_box_layout_set(wd->box, _box_layout_cb, NULL, NULL);
1074         elm_box_homogeneous_set(wd->box, EINA_FALSE);
1075         edje_object_part_swallow(wd->base, "box.swallow", wd->box);
1076      }
1077    if (!wd->label)
1078      {
1079         wd->label = edje_object_add(evas_object_evas_get(obj));
1080         if (!wd->label) return;
1081         _elm_theme_object_set(obj, wd->label, "multibuttonentry", "label", elm_widget_style_get(obj));
1082         _set_label(obj, "");
1083         elm_widget_sub_object_add(obj, wd->label);
1084      }
1085
1086    if (!wd->entry)
1087      {
1088         wd->entry = elm_entry_add (obj);
1089         if (!wd->entry) return;
1090         elm_entry_single_line_set(wd->entry, EINA_TRUE);
1091         elm_object_text_set(wd->entry, "");
1092         elm_entry_cursor_end_set(wd->entry);
1093         evas_object_size_hint_min_set(wd->entry, MIN_W_ENTRY, 0);
1094         evas_object_size_hint_weight_set(wd->entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1095         evas_object_size_hint_align_set(wd->entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
1096         if (wd->box) elm_box_pack_end (wd->box, wd->entry);
1097         evas_object_show(wd->entry);
1098         wd->view_state = MULTIBUTTONENTRY_VIEW_ENTRY;
1099      }
1100
1101    if (!wd->end)
1102      {
1103         const char *end_type;
1104
1105         end_type = edje_object_data_get(wd->base, "closed_button_type");
1106         if (!end_type || !strcmp(end_type, "label"))
1107           {
1108              wd->end = elm_label_add (obj);
1109              if (!wd->end) return;
1110              elm_object_style_set(wd->end, "extended/multibuttonentry_default");
1111              wd->end_type = MULTIBUTTONENTRY_CLOSED_LABEL;
1112           }
1113         else
1114           {
1115              const char *size_str;
1116              wd->end = edje_object_add(evas_object_evas_get(obj));
1117              if (!wd->end) return;
1118              _elm_theme_object_set(obj, wd->end, "multibuttonentry", "closedbutton", elm_widget_style_get(obj));
1119              Evas_Coord button_min_width = 0;
1120              Evas_Coord button_min_height = 0;
1121
1122              size_str = edje_object_data_get(wd->end, "closed_button_width");
1123              if (size_str) button_min_width = (Evas_Coord)atoi(size_str);
1124              size_str = edje_object_data_get(wd->end, "closed_button_height");
1125              if (size_str) button_min_height = (Evas_Coord)atoi(size_str);
1126
1127              wd->end_type = MULTIBUTTONENTRY_CLOSED_IMAGE;
1128              evas_object_size_hint_min_set(wd->end, button_min_width * elm_scale_get(), button_min_height * elm_scale_get());
1129              elm_widget_sub_object_add(obj, wd->end);
1130           }
1131      }
1132 }
1133
1134 static void
1135 _calculate_box_min_size(Evas_Object *box, Evas_Object_Box_Data *priv)
1136 {
1137    Evas_Coord minw, minh, mnw, mnh, ww;
1138    Evas_Coord w, cw = 0, cmaxh = 0;
1139    const Eina_List *l;
1140    Evas_Object_Box_Option *opt;
1141    double wx;
1142
1143    /* FIXME: need to calc max */
1144    minw = 0;
1145    minh = 0;
1146
1147    evas_object_geometry_get(box, NULL, NULL, &w, NULL);
1148    evas_object_size_hint_min_get(box, &minw, NULL);
1149
1150    EINA_LIST_FOREACH(priv->children, l, opt)
1151      {
1152         evas_object_size_hint_min_get(opt->obj, &mnw, &mnh);
1153         evas_object_size_hint_weight_get(opt->obj, &wx, NULL);
1154
1155         if (wx)
1156           {
1157              if (mnw != -1 && (w - cw) >= mnw)
1158                ww = w - cw;
1159              else
1160                ww = w;
1161           }
1162         else
1163            ww = mnw;
1164
1165         if ((cw + mnw) > w)
1166           {
1167              minh += cmaxh;
1168              cw = 0;
1169              cmaxh = 0;
1170           }
1171         cw += ww;
1172         if (cmaxh < mnh) cmaxh = mnh;
1173      }
1174
1175    minh += cmaxh;
1176
1177    evas_object_size_hint_min_set(box, minw, minh);
1178 }
1179
1180 static Evas_Coord
1181 _calculate_item_max_height(Evas_Object *box, Evas_Object_Box_Data *priv, int obj_index)
1182 {
1183    Evas_Coord mnw, mnh, cw = 0, cmaxh = 0, w, ww;
1184    const Eina_List *l;
1185    Evas_Object_Box_Option *opt;
1186    int index = 0;
1187    double wx;
1188
1189    evas_object_geometry_get(box, NULL, NULL, &w, NULL);
1190
1191    EINA_LIST_FOREACH(priv->children, l, opt)
1192      {
1193         evas_object_size_hint_min_get(opt->obj, &mnw, &mnh);
1194         evas_object_size_hint_weight_get(opt->obj, &wx, NULL);
1195
1196         if (wx)
1197           {
1198              if (mnw != -1 && (w - cw) >= mnw)
1199                 ww = w - cw;
1200              else
1201                 ww = w;
1202           }
1203         else
1204            ww = mnw;
1205
1206         if ((cw + ww) > w)
1207           {
1208              if (index > obj_index) return cmaxh;
1209              cw = 0;
1210              cmaxh = 0;
1211           }
1212
1213         cw += ww;
1214         if (cmaxh < mnh) cmaxh = mnh;
1215
1216         index++;
1217      }
1218
1219    return cmaxh;
1220 }
1221
1222 static void
1223 _box_layout_cb(Evas_Object *o, Evas_Object_Box_Data *priv, void *data __UNUSED__)
1224 {
1225    Evas_Coord x, y, w, h, xx, yy;
1226    const Eina_List *l;
1227    Evas_Object *obj;
1228    Evas_Coord minw, minh;
1229    double ax, ay;
1230    Evas_Object_Box_Option *opt;
1231
1232    _calculate_box_min_size(o, priv);
1233
1234    evas_object_geometry_get(o, &x, &y, &w, &h);
1235
1236    evas_object_size_hint_min_get(o, &minw, &minh);
1237    evas_object_size_hint_align_get(o, &ax, &ay);
1238    if (w < minw)
1239      {
1240         x = x + ((w - minw) * (1.0 - ax));
1241         w = minw;
1242      }
1243    if (h < minh)
1244      {
1245         y = y + ((h - minh) * (1.0 - ay));
1246         h = minh;
1247      }
1248
1249    xx = x;
1250    yy = y;
1251
1252    Evas_Coord cw = 0, ch = 0, cmaxh = 0, obj_index = 0;
1253
1254    EINA_LIST_FOREACH(priv->children, l, opt)
1255      {
1256         Evas_Coord mnw, mnh, mxw, mxh;
1257         double wx, wy;
1258         int fw, fh;
1259
1260         obj = opt->obj;
1261         evas_object_size_hint_align_get(obj, &ax, &ay);
1262         evas_object_size_hint_weight_get(obj, &wx, &wy);
1263         evas_object_size_hint_min_get(obj, &mnw, &mnh);
1264         evas_object_size_hint_max_get(obj, &mxw, &mxh);
1265         fw = fh = 0;
1266         if (ax == -1.0) {fw = 1; ax = 0.5;}
1267         if (ay == -1.0) {fh = 1; ay = 0.5;}
1268         Evas_Coord ww, hh, ow, oh;
1269
1270         if (wx)
1271           {
1272              if (mnw != -1 && (w - cw) >= mnw)
1273                 ww = w - cw;
1274              else
1275                 ww = w;
1276           }
1277         else
1278            ww = mnw;
1279         hh = _calculate_item_max_height(o, priv, obj_index);
1280
1281         ow = mnw;
1282         if (fw) ow = ww;
1283         if ((mxw >= 0) && (mxw < ow)) ow = mxw;
1284         oh = mnh;
1285         if (fh) oh = hh;
1286         if ((mxh >= 0) && (mxh < oh)) oh = mxh;
1287
1288         if ((cw + ww) > w)
1289           {
1290              ch += cmaxh;
1291              cw = 0;
1292              cmaxh = 0;
1293           }
1294
1295         evas_object_move(obj,
1296                          xx + cw + (Evas_Coord)(((double)(ww - ow)) * ax),
1297                          yy + ch + (Evas_Coord)(((double)(hh - oh)) * ay));
1298         evas_object_resize(obj, ow, oh);
1299
1300         cw += ww;
1301         if (cmaxh < hh) cmaxh = hh;
1302
1303         obj_index++;
1304      }
1305 }
1306
1307 EAPI Evas_Object *
1308 elm_multibuttonentry_add(Evas_Object *parent)
1309 {
1310    Evas_Object *obj;
1311    Evas *e;
1312    Widget_Data *wd;
1313
1314    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1315
1316    ELM_SET_WIDTYPE(widtype, "multibuttonentry");
1317    elm_widget_type_set(obj, "multibuttonentry");
1318    elm_widget_sub_object_add(parent, obj);
1319    elm_widget_data_set(obj, wd);
1320
1321    elm_widget_del_hook_set(obj, _del_hook);
1322    elm_widget_theme_hook_set(obj, _theme_hook);
1323    elm_widget_event_hook_set(obj, _event_hook);
1324    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
1325    elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
1326
1327    wd->base = edje_object_add(e);
1328    _elm_theme_object_set(obj, wd->base, "multibuttonentry", "base", "default");
1329    elm_widget_resize_object_set(obj, wd->base);
1330    elm_widget_can_focus_set(obj, EINA_TRUE);
1331
1332    wd->view_state = MULTIBUTTONENTRY_VIEW_NONE;
1333    wd->focused = EINA_FALSE;
1334    wd->last_btn_select = EINA_TRUE;
1335    wd->n_str = 0;
1336    wd->rect_for_end= NULL;
1337    wd->add_callback = NULL;
1338    wd->add_callback_data = NULL;
1339
1340    _view_init(obj);
1341    _event_init(obj);
1342
1343    return obj;
1344 }
1345
1346 EAPI Evas_Object *
1347 elm_multibuttonentry_entry_get(const Evas_Object *obj)
1348 {
1349    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1350    Widget_Data *wd = elm_widget_data_get(obj);
1351
1352    if (!wd) return NULL;
1353
1354    return wd->entry;
1355 }
1356
1357 EAPI const char *
1358 elm_multibuttonentry_label_get(const Evas_Object *obj)
1359 {
1360    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1361    Widget_Data *wd = elm_widget_data_get(obj);
1362
1363    if (!wd) return NULL;
1364    if (wd->label) return edje_object_part_text_get(wd->label, "mbe.label");
1365    return NULL;
1366 }
1367
1368 EAPI void
1369 elm_multibuttonentry_label_set(Evas_Object *obj, const char *label)
1370 {
1371    ELM_CHECK_WIDTYPE(obj, widtype);
1372    Widget_Data *wd = elm_widget_data_get(obj);
1373
1374    if (!wd) return;
1375    if (label)
1376      _set_label(obj, label);
1377    else
1378      _set_label(obj, "");
1379 }
1380
1381 EAPI const char *
1382 elm_multibuttonentry_guide_text_get(const Evas_Object *obj)
1383 {
1384    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1385    Widget_Data *wd = elm_widget_data_get(obj);
1386
1387    if (!wd) return NULL;
1388    if (wd->guidetext) return edje_object_part_text_get(wd->guidetext, "elm.text");
1389    return NULL;
1390 }
1391
1392 EAPI void
1393 elm_multibuttonentry_guide_text_set(Evas_Object *obj, const char *guidetext)
1394 {
1395    ELM_CHECK_WIDTYPE(obj, widtype);
1396    Widget_Data *wd = elm_widget_data_get(obj);
1397
1398    if (!wd) return;
1399    if (guidetext)
1400      _set_guidetext(obj, guidetext);
1401    else
1402      _set_guidetext(obj, "");
1403 }
1404
1405 EAPI int
1406 elm_multibuttonentry_shrink_mode_get(const Evas_Object *obj)
1407 {
1408    ELM_CHECK_WIDTYPE(obj, widtype) -1;
1409    Widget_Data *wd = elm_widget_data_get(obj);
1410
1411    if (!wd) return -1;
1412    return wd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK ? 1 : 0;
1413 }
1414
1415 EAPI void
1416 elm_multibuttonentry_shrink_mode_set(Evas_Object *obj, int shrink)
1417 {
1418    ELM_CHECK_WIDTYPE(obj, widtype);
1419    Widget_Data *wd = elm_widget_data_get(obj);
1420
1421    if (!wd || !wd->box ||
1422        ((wd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) ? 1 : 0) == shrink) return;
1423    _shrink_mode_set(obj, shrink);
1424 }
1425
1426 EAPI Elm_Multibuttonentry_Item *
1427 elm_multibuttonentry_item_prepend(Evas_Object *obj, const char *label, void *data)
1428 {
1429    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1430    Widget_Data *wd = elm_widget_data_get(obj);
1431    Elm_Multibuttonentry_Item *item;
1432
1433    if (!wd || !label) return NULL;
1434    item = _add_button_item(obj, label, MULTIBUTTONENTRY_POS_START, NULL, data);
1435    return item;
1436 }
1437
1438 EAPI Elm_Multibuttonentry_Item *
1439 elm_multibuttonentry_item_append(Evas_Object *obj, const char *label, void *data)
1440 {
1441    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1442    Widget_Data *wd = elm_widget_data_get(obj);
1443    Elm_Multibuttonentry_Item *item;
1444
1445    if (!wd || !label) return NULL;
1446    item = _add_button_item(obj, label, MULTIBUTTONENTRY_POS_END, NULL, data);
1447    return item;
1448 }
1449
1450 EAPI Elm_Multibuttonentry_Item *
1451 elm_multibuttonentry_item_insert_before(Evas_Object *obj, Elm_Multibuttonentry_Item *before, const char *label, void *data)
1452 {
1453    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1454    Widget_Data *wd = elm_widget_data_get(obj);
1455    Elm_Multibuttonentry_Item *item;
1456
1457    if (!wd || !label) return NULL;
1458    item = _add_button_item(obj, label, MULTIBUTTONENTRY_POS_BEFORE, before, data);
1459    return item;
1460 }
1461
1462 EAPI Elm_Multibuttonentry_Item *
1463 elm_multibuttonentry_item_insert_after(Evas_Object *obj, Elm_Multibuttonentry_Item *after, const char *label, void *data)
1464 {
1465    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1466    Widget_Data *wd = elm_widget_data_get(obj);
1467    Elm_Multibuttonentry_Item *item;
1468
1469    if (!wd || !label) return NULL;
1470    item = _add_button_item(obj, label, MULTIBUTTONENTRY_POS_AFTER, after, data);
1471    return item;
1472 }
1473
1474 EAPI const Eina_List *
1475 elm_multibuttonentry_items_get(const Evas_Object *obj)
1476 {
1477    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1478    Widget_Data *wd = elm_widget_data_get(obj);
1479
1480    if (!wd) return NULL;
1481    return wd->items;
1482 }
1483
1484 EAPI Elm_Multibuttonentry_Item *
1485 elm_multibuttonentry_first_item_get(const Evas_Object *obj)
1486 {
1487    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1488    Widget_Data *wd = elm_widget_data_get(obj);
1489
1490    if (!wd || !wd->items) return NULL;
1491    return eina_list_data_get(wd->items);
1492 }
1493
1494 EAPI Elm_Multibuttonentry_Item *
1495 elm_multibuttonentry_last_item_get(const Evas_Object *obj)
1496 {
1497    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1498    Widget_Data *wd = elm_widget_data_get(obj);
1499
1500    if (!wd || !wd->items) return NULL;
1501    return eina_list_data_get(eina_list_last(wd->items));
1502 }
1503
1504 EAPI Elm_Multibuttonentry_Item *
1505 elm_multibuttonentry_selected_item_get(const Evas_Object *obj)
1506 {
1507    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1508    Widget_Data *wd = elm_widget_data_get(obj);
1509
1510    if (!wd || !wd->current) return NULL;
1511    return eina_list_data_get(wd->current);
1512 }
1513
1514 EAPI void
1515 elm_multibuttonentry_item_select(Elm_Multibuttonentry_Item *item, Eina_Bool selected)
1516 {
1517    Widget_Data *wd;
1518    Eina_List *l;
1519    Elm_Multibuttonentry_Item *_item;
1520
1521    if (!item) return;
1522    ELM_CHECK_WIDTYPE(WIDGET(item), widtype);
1523    wd = elm_widget_data_get(WIDGET(item));
1524    if (!wd) return;
1525
1526    EINA_LIST_FOREACH(wd->items, l, _item)
1527      {
1528         if (_item == item)
1529           {
1530              if (selected)
1531                _select_button(WIDGET(item), item->button);
1532              else
1533                _select_button(WIDGET(item), NULL);
1534           }
1535      }
1536 }
1537
1538 EAPI void
1539 elm_multibuttonentry_item_unselect_all(Evas_Object *obj)
1540 {
1541    ELM_CHECK_WIDTYPE(obj, widtype);
1542    Widget_Data *wd = elm_widget_data_get(obj);
1543    if (!wd) return;
1544
1545    _select_button(obj, NULL);
1546 }
1547
1548 EAPI void
1549 elm_multibuttonentry_clear(Evas_Object *obj)
1550 {
1551    ELM_CHECK_WIDTYPE(obj, widtype);
1552    Widget_Data *wd = elm_widget_data_get(obj);
1553    if (!wd) return;
1554
1555    if (wd->items)
1556      {
1557         Elm_Multibuttonentry_Item *item;
1558         EINA_LIST_FREE(wd->items, item)
1559           {
1560              elm_box_unpack(wd->box, item->button);
1561              _del_button_obj(obj, item->button);
1562              free(item);
1563           }
1564         wd->items = NULL;
1565      }
1566    wd->current = NULL;
1567    _view_update(obj);
1568 }
1569
1570 EAPI void
1571 elm_multibuttonentry_item_del(Elm_Multibuttonentry_Item *item)
1572 {
1573    if (!item) return;
1574    _del_button_item(item);
1575 }
1576
1577 EAPI const char *
1578 elm_multibuttonentry_item_label_get(const Elm_Multibuttonentry_Item *item)
1579 {
1580    Widget_Data *wd;
1581    Eina_List *l;
1582    Elm_Multibuttonentry_Item *_item;
1583    if (!item) return NULL;
1584    ELM_CHECK_WIDTYPE(WIDGET(item), widtype) NULL;
1585    wd = elm_widget_data_get(WIDGET(item));
1586    if (!wd || !wd->items) return NULL;
1587
1588    EINA_LIST_FOREACH(wd->items, l, _item)
1589      {
1590         if (_item == item)
1591           return edje_object_part_text_get(_item->button, "elm.btn.text");
1592      }
1593
1594    return NULL;
1595 }
1596
1597 EAPI void
1598 elm_multibuttonentry_item_label_set(Elm_Multibuttonentry_Item *item, const char *str)
1599 {
1600    Widget_Data *wd;
1601    Eina_List *l;
1602    Elm_Multibuttonentry_Item *_item;
1603    if (!item || !str) return;
1604    ELM_CHECK_WIDTYPE(WIDGET(item), widtype);
1605    wd = elm_widget_data_get(WIDGET(item));
1606    if (!wd || !wd->items) return;
1607
1608    EINA_LIST_FOREACH(wd->items, l, _item)
1609      if (_item == item)
1610        {
1611           edje_object_part_text_set(_item->button, "elm.btn.text", str);
1612           _resize_button(_item->button, &_item->rw, &_item->vw);
1613           break;
1614        }
1615 }
1616
1617 EAPI Elm_Multibuttonentry_Item *
1618 elm_multibuttonentry_item_prev_get(const Elm_Multibuttonentry_Item *item)
1619 {
1620    Widget_Data *wd;
1621    Eina_List *l;
1622    Elm_Multibuttonentry_Item *_item;
1623    if (!item) return NULL;
1624    ELM_CHECK_WIDTYPE(WIDGET(item), widtype) NULL;
1625    wd = elm_widget_data_get(WIDGET(item));
1626    if (!wd || !wd->items) return NULL;
1627
1628    EINA_LIST_FOREACH(wd->items, l, _item)
1629       if (_item == item)
1630         {
1631            l = eina_list_prev(l);
1632            if (!l) return NULL;
1633            return eina_list_data_get(l);
1634         }
1635    return NULL;
1636 }
1637
1638 EAPI Elm_Multibuttonentry_Item *
1639 elm_multibuttonentry_item_next_get(const Elm_Multibuttonentry_Item *item)
1640 {
1641    Widget_Data *wd;
1642    Eina_List *l;
1643    Elm_Multibuttonentry_Item *_item;
1644
1645    if (!item) return NULL;
1646    ELM_CHECK_WIDTYPE(WIDGET(item), widtype) NULL;
1647    wd = elm_widget_data_get(WIDGET(item));
1648    if (!wd || !wd->items) return NULL;
1649
1650    EINA_LIST_FOREACH(wd->items, l, _item)
1651       if (_item == item)
1652         {
1653            l = eina_list_next(l);
1654            if (!l) return NULL;
1655            return eina_list_data_get(l);
1656         }
1657    return NULL;
1658 }
1659
1660 EAPI void *
1661 elm_multibuttonentry_item_data_get(const Elm_Multibuttonentry_Item *item)
1662 {
1663    if (!item) return NULL;
1664    return item->data;
1665 }
1666
1667 EAPI void
1668 elm_multibuttonentry_item_data_set(Elm_Multibuttonentry_Item *item, void *data)
1669 {
1670    if (!item) return;
1671    item->data = data;
1672 }
1673
1674 EAPI void
1675 elm_multibuttonentry_item_filter_append(Evas_Object *obj, Elm_Multibuttonentry_Item_Filter_callback func, void *data)
1676 {
1677    Elm_Multibuttonentry_Item_Filter *new_item_filter = NULL;
1678    Elm_Multibuttonentry_Item_Filter *_item_filter = NULL;
1679    Eina_List *l;
1680
1681    Widget_Data *wd = elm_widget_data_get(obj);
1682    if (!wd) return;
1683
1684    ELM_CHECK_WIDTYPE(obj, widtype);
1685    EINA_SAFETY_ON_NULL_RETURN(func);
1686
1687    new_item_filter= _filter_new(func, data);
1688    if (!new_item_filter) return;
1689
1690    EINA_LIST_FOREACH(wd->filter_list, l, _item_filter)
1691      {
1692         if ( _item_filter && ((_item_filter->callback_func == func) && (_item_filter->data == data)))
1693           {
1694              printf("Already Registered this item filter!!!!\n");
1695              return;
1696           }
1697      }
1698    wd->filter_list = eina_list_append(wd->filter_list, new_item_filter);
1699 }
1700
1701 EAPI void
1702 elm_multibuttonentry_item_filter_prepend(Evas_Object *obj, Elm_Multibuttonentry_Item_Filter_callback func, void *data)
1703 {
1704    Elm_Multibuttonentry_Item_Filter *new_item_filter = NULL;
1705    Elm_Multibuttonentry_Item_Filter *_item_filter = NULL;
1706    Eina_List *l;
1707    Widget_Data *wd = elm_widget_data_get(obj);
1708    if (!wd) return;
1709
1710    ELM_CHECK_WIDTYPE(obj, widtype);
1711    EINA_SAFETY_ON_NULL_RETURN(func);
1712
1713    new_item_filter = _filter_new(func, data);
1714    if (!new_item_filter) return;
1715
1716    EINA_LIST_FOREACH(wd->filter_list, l, _item_filter)
1717      {
1718         if (_item_filter && ((_item_filter->callback_func == func) && (_item_filter->data == data)))
1719           {
1720              printf("Already Registered this item filter!!!!\n");
1721              return;
1722           }
1723      }
1724    wd->filter_list = eina_list_prepend(wd->filter_list, new_item_filter);
1725 }
1726
1727 EAPI void
1728 elm_multibuttonentry_item_filter_remove(Evas_Object *obj, Elm_Multibuttonentry_Item_Filter_callback func, void *data)
1729 {
1730    Widget_Data *wd;
1731    Eina_List *l;
1732    Elm_Multibuttonentry_Item_Filter *item_filter;
1733
1734    wd = elm_widget_data_get(obj);
1735
1736    EINA_SAFETY_ON_NULL_RETURN(func);
1737
1738    EINA_LIST_FOREACH(wd->filter_list, l, item_filter)
1739      {
1740         if ((item_filter->callback_func == func) && ((!data) || (item_filter->data == data)))
1741           {
1742              wd->filter_list = eina_list_remove_list(wd->filter_list, l);
1743              _filter_free(item_filter);
1744              return;
1745           }
1746      }
1747 }