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