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