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