[Popup] Upstream merging r69492
[framework/uifw/elementary.git] / src / lib / elc_popup.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 #define ELM_POPUP_ACTION_BUTTON_MAX 3
5 typedef struct _Widget_Data Widget_Data;
6 typedef struct _Elm_Popup_Content_Item Elm_Popup_Content_Item;
7 typedef struct _Action_Area_Data Action_Area_Data;
8
9 struct _Widget_Data
10 {
11    Evas_Object *base;
12    Evas_Object *notify;
13    Evas_Object *title_icon;
14    Evas_Object *content_area;
15    Evas_Object *content_text_obj;
16    Evas_Object *action_area;
17    Evas_Object *box;
18    Evas_Object *scr;
19    Evas_Object *content;
20    Eina_List *items;
21    const char *title_text;
22    Action_Area_Data *buttons[ELM_POPUP_ACTION_BUTTON_MAX];
23    Elm_Wrap_Type content_text_wrap_type;
24    unsigned int button_count;
25    Evas_Coord max_sc_w;
26    Evas_Coord max_sc_h;
27    Eina_Bool scr_size_recalc:1;
28 };
29
30 struct _Elm_Popup_Content_Item
31 {
32    Elm_Widget_Item base;
33    const char *label;
34    Evas_Object *icon;
35    Evas_Smart_Cb func;
36    Eina_Bool disabled:1;
37 };
38
39 struct _Action_Area_Data
40 {
41    Evas_Object *obj;
42    Evas_Object *btn;
43    Eina_Bool delete_me;
44 };
45
46 static const char *widtype = NULL;
47 static void _del_hook(Evas_Object *obj);
48 static void _theme_hook(Evas_Object *obj);
49 static void _text_set_hook(Evas_Object *obj, const char *part,
50                                           const char *label);
51 static const char *_text_get_hook(const Evas_Object *obj,
52                                                  const char *part);
53 static void _content_set_hook(Evas_Object *obj, const char *part,
54                                              Evas_Object *content);
55 static Evas_Object *_content_get_hook(Evas_Object *obj,
56                                                      const char *part);
57 static Evas_Object *_content_unset_hook(Evas_Object *obj,
58                                                        const char *part);
59 static void _item_text_set_hook(Elm_Object_Item *it, const char *part,
60                                 const char *label);
61 static const char *_item_text_get_hook(const Elm_Object_Item *it,
62                                        const char *part);
63 static void _item_content_set_hook(Elm_Object_Item *it, const char *part,
64                                    Evas_Object *content);
65 static Evas_Object *_item_content_unset_hook(const Elm_Object_Item *it,
66                                              const char *part);
67 static Evas_Object *_item_content_get_hook(const Elm_Object_Item *it,
68                                            const char *part);
69 static void _item_disable_hook(Elm_Object_Item *it);
70 static void _item_del_pre_hook(Elm_Object_Item *it);
71 static void _item_signal_emit_hook(Elm_Object_Item *it, const char *emission,
72                                    const char *source);
73 static void _sizing_eval(Evas_Object *obj);
74 static void _block_clicked_cb(void *data, Evas_Object *obj, void *event_info);
75 static void _notify_resize(void *data, Evas *e, Evas_Object *obj,
76                            void *event_info);
77 static void _scroller_resize(void *data, Evas *e, Evas_Object *obj,
78                              void *event_info);
79 static void _timeout(void *data, Evas_Object *obj , void *event_info);
80 static void _sub_del(void *data, Evas_Object *obj, void *event_info);
81 static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
82 static void _restack(void *data, Evas *e, Evas_Object *obj, void *event_info);
83 static void _layout_change_cb(void *data, Evas_Object *obj __UNUSED__,
84                               const char *emission __UNUSED__,
85                               const char *source __UNUSED__);
86 static void _item_new(Elm_Popup_Content_Item *item);
87 static void _remove_items(Widget_Data *wd);
88 static void _list_new(Evas_Object *obj);
89 static void _list_del(Widget_Data *wd);
90 static void _item_sizing_eval(Elm_Popup_Content_Item *item);
91 static void _item_select_cb(void *data, Evas_Object *obj __UNUSED__,
92                             const char *emission __UNUSED__,
93                             const char *source __UNUSED__);
94 static void _scroller_size_calc(Evas_Object *obj);
95 static void _action_button_set(Evas_Object *obj, Evas_Object *btn,
96                                unsigned int idx);
97 static Evas_Object *_action_button_get(Evas_Object *obj, unsigned int idx);
98 static Evas_Object *_action_button_unset(Evas_Object *obj, unsigned int idx);
99 static void _button_remove(Evas_Object *obj, Evas_Object *content,
100                            Eina_Bool delete);
101 static const char SIG_BLOCK_CLICKED[] = "block,clicked";
102 static const char SIG_TIMEOUT[] = "timeout";
103 static const Evas_Smart_Cb_Description _signals[] = {
104        {SIG_BLOCK_CLICKED, ""},
105        {SIG_TIMEOUT, ""},
106        {NULL, NULL}
107 };
108
109 #define ELM_POPUP_CONTENT_ITEM_CHECK_RETURN(it, ...)                        \
110   ELM_WIDGET_ITEM_CHECK_OR_RETURN((Elm_Widget_Item *)it, __VA_ARGS__); \
111   ELM_CHECK_WIDTYPE(WIDGET(item), widtype) __VA_ARGS__;
112
113 static void
114 _layout_set(Evas_Object *obj)
115 {
116    Widget_Data *wd = elm_widget_data_get(obj);
117
118    if (!wd) return;
119    if ((!(wd->title_text)) && (!(wd->title_icon)))
120      elm_object_signal_emit(wd->base, "elm,state,title_area,hidden", "elm");
121    else
122      elm_object_signal_emit(wd->base, "elm,state,title_area,visible", "elm");
123    if (wd->button_count)
124      elm_object_signal_emit(wd->base, "elm,state,action_area,visible", "elm");
125    else
126      elm_object_signal_emit(wd->base, "elm,state,action_area,hidden", "elm");
127 }
128
129 static void
130 _del_hook(Evas_Object *obj)
131 {
132    Widget_Data *wd = elm_widget_data_get(obj);
133
134    if (!wd) return;
135    free(wd);
136 }
137
138 static void
139 _del_pre_hook(Evas_Object *obj)
140 {
141    unsigned int i;
142    Widget_Data *wd = elm_widget_data_get(obj);
143
144    if (!wd) return;
145    evas_object_smart_callback_del(wd->notify, "block,clicked",
146                                   _block_clicked_cb);
147    evas_object_smart_callback_del(wd->notify, "timeout", _timeout);
148    evas_object_event_callback_del(wd->notify, EVAS_CALLBACK_RESIZE,
149                                   _notify_resize);
150    wd->button_count = 0;
151    for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
152      if (wd->buttons[i])
153        {
154           evas_object_del(wd->buttons[i]->btn);
155           free(wd->buttons[i]);
156           wd->buttons[i] = NULL;
157        }
158    if (wd->items)
159      {
160         _remove_items(wd);
161         _list_del(wd);
162      }
163 }
164
165 static void
166 _theme_hook(Evas_Object *obj)
167 {
168    Eina_List *elist;
169    Elm_Popup_Content_Item *item;
170    char buf[128];
171    unsigned int i = 0;
172    Widget_Data *wd = elm_widget_data_get(obj);
173
174    if (!wd) return;
175    elm_layout_theme_set(wd->base, "popup", "base", elm_widget_style_get(obj));
176    _elm_widget_mirrored_reload(obj);
177    _mirrored_set(obj, elm_widget_mirrored_get(obj));
178    if (wd->button_count)
179      {
180         snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
181         elm_layout_theme_set(wd->action_area, "popup", buf,
182                              elm_widget_style_get(obj));
183         for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
184           {
185              if (!wd->buttons[i]) continue;
186              elm_object_style_set(wd->buttons[i]->btn, buf);
187           }
188      }
189    elm_layout_theme_set(wd->content_area, "popup", "content",
190                         elm_widget_style_get(obj));
191    if (wd->content_text_obj)
192      {
193         snprintf(buf, sizeof(buf), "popup/%s", elm_widget_style_get(obj));
194         elm_object_style_set(wd->content_text_obj, buf);
195      }
196    else if (wd->items)
197      {
198         EINA_LIST_FOREACH(wd->items, elist, item)
199           {
200              _elm_theme_object_set(obj, VIEW(item), "popup",
201                                    "item", elm_widget_style_get(obj));
202              if (item->label)
203                {
204                   edje_object_part_text_set(VIEW(item), "elm.text",
205                                             item->label);
206                   edje_object_signal_emit(VIEW(item),
207                                           "elm,state,item,text,visible", "elm");
208                }
209              if (item->icon)
210                edje_object_signal_emit(VIEW(item),
211                                        "elm,state,item,icon,visible", "elm");
212              if (item->disabled)
213                edje_object_signal_emit(VIEW(item),
214                                        "elm,state,item,disabled", "elm");
215              evas_object_show(VIEW(item));
216              edje_object_message_signal_process(VIEW(item));
217           }
218         _scroller_size_calc(obj);
219      }
220    if (wd->title_text)
221      {
222         elm_object_part_text_set(wd->base, "elm.text.title", wd->title_text);
223         elm_object_signal_emit(wd->base, "elm,state,title,text,visible", "elm");
224      }
225    if (wd->title_icon)
226      elm_object_signal_emit(wd->base, "elm,state,title,icon,visible", "elm");
227    _layout_set(obj);
228    edje_object_message_signal_process(elm_layout_edje_get(wd->base));
229    _sizing_eval(obj);
230 }
231
232 static void
233 _item_sizing_eval(Elm_Popup_Content_Item *item)
234 {
235    Evas_Coord min_w = -1, min_h = -1, max_w = -1, max_h = -1;
236
237    edje_object_size_min_restricted_calc(VIEW(item), &min_w, &min_h, min_w,
238                                         min_h);
239    evas_object_size_hint_min_set(VIEW(item), min_w, min_h);
240    evas_object_size_hint_max_set(VIEW(item), max_w, max_h);
241 }
242
243 static void
244 _sizing_eval(Evas_Object *obj)
245 {
246    Eina_List *elist;
247    Elm_Popup_Content_Item *item;
248    Evas_Coord w_box = 0, h_box = 0;
249    Evas_Coord minw_box = 0, minh_box = 0;
250    Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
251    Widget_Data *wd = elm_widget_data_get(obj);
252
253    if (!wd) return;
254    if (wd->items)
255      {
256         EINA_LIST_FOREACH(wd->items, elist, item)
257           {
258              _item_sizing_eval(item);
259              evas_object_size_hint_min_get(VIEW(item), &minw_box,
260                                            &minh_box);
261              if (minw_box > w_box)
262                w_box = minw_box;
263              if (minh_box != -1)
264                h_box += minh_box;
265           }
266         evas_object_size_hint_min_set(wd->box, w_box, h_box);
267         evas_object_size_hint_min_set(wd->scr, w_box, MIN(h_box, wd->max_sc_h));
268         evas_object_size_hint_max_set(wd->scr, w_box, wd->max_sc_h);
269         evas_object_smart_calculate(wd->scr);
270      }
271    edje_object_size_min_calc(elm_layout_edje_get(wd->base), &minw, &minh);
272    evas_object_size_hint_min_set(wd->base, minw, minh);
273    evas_object_size_hint_max_set(wd->base, maxw, maxh);
274    evas_object_size_hint_min_set(obj, minw, minh);
275    evas_object_size_hint_max_set(obj, maxw, maxh);
276    elm_layout_sizing_eval(wd->base);
277 }
278
279 static void
280 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
281                     void *event_info __UNUSED__)
282 {
283    _sizing_eval(data);
284 }
285
286 static void
287 _sub_del(void *data, Evas_Object *obj, void *event_info)
288 {
289    Elm_Popup_Content_Item *item;
290    unsigned int i;
291    Evas_Object *sub = event_info;
292    Widget_Data *wd = elm_widget_data_get(data);
293
294    if (!wd) return;
295    if (obj == data)
296      {
297         if ((item = evas_object_data_get(sub, "_popup_content_item")) != NULL)
298           {
299              if (sub == item->icon)
300                {
301                   edje_object_part_unswallow(VIEW(item), sub);
302                   edje_object_signal_emit(VIEW(item),
303                                           "elm,state,item,icon,hidden", "elm");
304                   item->icon = NULL;
305                }
306           }
307      }
308    else if (obj == wd->content_area)
309      {
310         if (sub == wd->content)
311           {
312              wd->content = NULL;
313              elm_object_part_content_unset(wd->base, "elm.swallow.content");
314              _sizing_eval(data);
315           }
316         else if (sub == wd->content_text_obj)
317           {
318              wd->content_text_obj = NULL;
319              elm_object_part_content_unset(wd->base, "elm.swallow.content");
320              _sizing_eval(data);
321           }
322         else if (sub == wd->scr)
323           {
324              wd->scr = NULL;
325              wd->box = NULL;
326              elm_object_part_content_unset(wd->base, "elm.swallow.content");
327              _sizing_eval(data);
328           }
329      }
330    else if (obj == wd->action_area)
331      {
332         for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
333           {
334              if (wd->buttons[i] && sub == wd->buttons[i]->btn &&
335                       wd->buttons[i]->delete_me == EINA_TRUE)
336                {
337                   _button_remove(data, sub, EINA_FALSE);
338                   break;
339                }
340           }
341      }
342    else if (obj == wd->base)
343      {
344         if (sub == wd->title_icon)
345           {
346              elm_object_signal_emit(wd->base, "elm,state,title,icon,hidden",
347                                     "elm");
348              edje_object_message_signal_process(wd->base);
349              wd->title_icon = NULL;
350           }
351      }
352 }
353
354 static void
355 _block_clicked_cb(void *data, Evas_Object *obj __UNUSED__,
356                   void *event_info __UNUSED__)
357 {
358    Widget_Data *wd = elm_widget_data_get(data);
359
360    if (!wd) return;
361    evas_object_smart_callback_call(data, SIG_BLOCK_CLICKED, NULL);
362 }
363
364 static void
365 _timeout(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
366 {
367    evas_object_hide(data);
368    evas_object_smart_callback_call(data, SIG_TIMEOUT, NULL);
369 }
370
371 static void
372 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
373 {
374    Eina_List *elist;
375    Elm_Popup_Content_Item *item;
376    Widget_Data *wd = elm_widget_data_get(obj);
377
378    if (!wd) return;
379    elm_object_mirrored_set(wd->notify, rtl);
380    if (wd->items)
381      EINA_LIST_FOREACH(wd->items, elist, item)
382        edje_object_mirrored_set(VIEW(item), rtl);
383 }
384
385 static void
386 _layout_change_cb(void *data, Evas_Object *obj __UNUSED__,
387                   const char *emission __UNUSED__,
388                   const char *source __UNUSED__)
389 {
390    Widget_Data *wd = elm_widget_data_get((Evas_Object*)data);
391
392    if (!wd) return;
393    if (wd->base)
394      elm_layout_sizing_eval(wd->base);
395 }
396
397 static void
398 _restack(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
399          void *event_info __UNUSED__)
400 {
401    Widget_Data *wd = elm_widget_data_get(obj);
402
403    if (!wd) return;
404    evas_object_layer_set(wd->notify, evas_object_layer_get(obj));
405 }
406
407 static void
408 _scroller_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj,
409                  void *event_info __UNUSED__)
410 {
411    Evas_Coord w, h;
412    Widget_Data *wd = elm_widget_data_get(data);
413
414    if (!wd || wd->scr_size_recalc) return;
415    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
416    if (w && h)
417      {
418         if ((w <= wd->max_sc_w) && (h <= wd->max_sc_h))
419           {
420              _sizing_eval(data);
421              wd->scr_size_recalc = EINA_TRUE;
422              return;
423           }
424      }
425    if (wd->max_sc_w < w)
426      wd->max_sc_w = w;
427    if (wd->max_sc_h < h)
428      wd->max_sc_h = h;
429    _sizing_eval(data);
430 }
431
432 static void
433 _list_new(Evas_Object *obj)
434 {
435    Widget_Data *wd = elm_widget_data_get(obj);
436
437    if (!wd) return;
438    //Scroller
439    wd->scr = elm_scroller_add(obj);
440    elm_scroller_bounce_set(wd->scr, EINA_FALSE, EINA_TRUE);
441    elm_object_content_set(wd->scr, wd->box);
442    evas_object_size_hint_weight_set(wd->scr, EVAS_HINT_EXPAND,
443                                     EVAS_HINT_EXPAND);
444    evas_object_size_hint_align_set(wd->scr, EVAS_HINT_FILL, EVAS_HINT_FILL);
445    evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_RESIZE,
446                                   _scroller_resize, obj);
447    evas_object_event_callback_add(wd->scr,
448                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
449                                   _changed_size_hints, obj);
450    elm_object_part_content_set(wd->base, "elm.swallow.content", wd->scr);
451
452    //Box
453    wd->box = elm_box_add(obj);
454    evas_object_size_hint_weight_set(wd->box, EVAS_HINT_EXPAND,
455                                     EVAS_HINT_EXPAND);
456    evas_object_size_hint_align_set(wd->box, EVAS_HINT_FILL, EVAS_HINT_FILL);
457
458    elm_object_content_set(wd->scr, wd->box);
459 }
460
461 static void
462 _list_del(Widget_Data *wd)
463 {
464    if (!wd->scr) return;
465    elm_object_part_content_unset(wd->base, "elm.swallow.content");
466    evas_object_event_callback_del(wd->scr, EVAS_CALLBACK_RESIZE,
467                                   _scroller_resize);
468    evas_object_event_callback_del(wd->scr, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
469                                   _changed_size_hints);
470    evas_object_del(wd->scr);
471    wd->scr = NULL;
472    wd->box = NULL;
473 }
474
475 static void
476 _scroller_size_calc(Evas_Object *obj)
477 {
478    Evas_Coord h;
479    Evas_Coord h_title = 0;
480    Evas_Coord h_action_area = 0;
481    Evas_Coord h_content = 0;
482    const char *action_area_height;
483    Widget_Data *wd = elm_widget_data_get(obj);
484
485    if (!wd || !wd->items) return;
486    wd->scr_size_recalc = EINA_FALSE;
487    wd->max_sc_h = -1;
488    wd->max_sc_w = -1;
489    evas_object_geometry_get(wd->notify, NULL, NULL, NULL, &h);
490    if (wd->title_text || wd->title_icon)
491      edje_object_part_geometry_get(elm_layout_edje_get(wd->base),
492                                    "elm.bg.title", NULL, NULL, NULL, &h_title);
493    if (wd->button_count)
494      {
495         action_area_height = edje_object_data_get(
496                  elm_layout_edje_get(wd->action_area), "action_area_height");
497         if (action_area_height) h_action_area = (int)(atoi(action_area_height)
498                  * _elm_config->scale * elm_object_scale_get(obj));
499      }
500    h_content = h - (h_title + h_action_area);
501    wd->max_sc_h = h_content;
502 }
503
504 static void
505 _item_select_cb(void *data, Evas_Object *obj __UNUSED__,
506                 const char *emission __UNUSED__, const char *source __UNUSED__)
507 {
508    Elm_Popup_Content_Item *item = data;
509
510    if (!item || item->disabled) return;
511    if (item->func)
512      item->func((void*)item->base.data, WIDGET(item), data);
513 }
514
515 static void
516 _item_new(Elm_Popup_Content_Item *item)
517 {
518    Widget_Data *wd = elm_widget_data_get(WIDGET(item));
519
520    if (!wd) return;
521    elm_widget_item_text_set_hook_set(item, _item_text_set_hook);
522    elm_widget_item_text_get_hook_set(item, _item_text_get_hook);
523    elm_widget_item_content_set_hook_set(item, _item_content_set_hook);
524    elm_widget_item_content_get_hook_set(item, _item_content_get_hook);
525    elm_widget_item_content_unset_hook_set(item, _item_content_unset_hook);
526    elm_widget_item_disable_hook_set(item, _item_disable_hook);
527    elm_widget_item_del_pre_hook_set(item, _item_del_pre_hook);
528    elm_widget_item_signal_emit_hook_set(item, _item_signal_emit_hook);
529    VIEW(item) = edje_object_add(evas_object_evas_get(wd->base));
530    _elm_theme_object_set(WIDGET(item), VIEW(item), "popup", "item",
531                          elm_widget_style_get(WIDGET(item)));
532    edje_object_mirrored_set(VIEW(item), elm_widget_mirrored_get(WIDGET(item)));
533    edje_object_signal_callback_add(VIEW(item), "elm,action,click", "",
534                                    _item_select_cb, item);
535    evas_object_size_hint_align_set(VIEW(item), EVAS_HINT_FILL,
536                                    EVAS_HINT_FILL);
537    evas_object_show(VIEW(item));
538 }
539
540 static void
541 _remove_items(Widget_Data *wd)
542 {
543    Eina_List *elist;
544    Elm_Popup_Content_Item *item;
545
546    if (!wd->items) return;
547    EINA_LIST_FOREACH(wd->items, elist, item)
548      {
549         if (item->label)
550           eina_stringshare_del(item->label);
551         if (item->icon)
552           {
553              evas_object_del(item->icon);
554              item->icon = NULL;
555           }
556         evas_object_del(VIEW(item));
557         wd->items = eina_list_remove(wd->items, item);
558         free(item);
559      }
560    wd->items = NULL;
561 }
562
563 static void
564 _notify_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
565                void *event_info __UNUSED__)
566 {
567    Widget_Data *wd = elm_widget_data_get(data);
568
569    if (wd->items)
570      _scroller_size_calc(data);
571    _sizing_eval(data);
572 }
573
574 static void
575 _title_text_set(Evas_Object *obj, const char *text)
576 {
577    ELM_CHECK_WIDTYPE(obj, widtype);
578    Eina_Bool title_visibility_old, title_visibility_current;
579    Widget_Data *wd = elm_widget_data_get(obj);
580
581    if (!wd) return;
582    if (wd->title_text == text) return;
583    title_visibility_old = (wd->title_text) || (wd->title_icon);
584    eina_stringshare_replace(&wd->title_text, text);
585    elm_object_part_text_set(wd->base, "elm.text.title", text);
586    if (wd->title_text)
587      elm_object_signal_emit(wd->base, "elm,state,title,text,visible", "elm");
588    else
589      elm_object_signal_emit(wd->base, "elm,state,title,text,hidden", "elm");
590    title_visibility_current = (wd->title_text) || (wd->title_icon);
591    if (title_visibility_old != title_visibility_current)
592      _layout_set(obj);
593    edje_object_message_signal_process(wd->base);
594    _sizing_eval(obj);
595 }
596
597 static void
598 _content_text_set(Evas_Object *obj, const char *text)
599 {
600    ELM_CHECK_WIDTYPE(obj, widtype);
601    Evas_Object *prev_content;
602    char buf[128];
603    Widget_Data *wd = elm_widget_data_get(obj);
604
605    if (!wd) return;
606    if (wd->items)
607      {
608         _remove_items(wd);
609         _list_del(wd);
610      }
611    prev_content = elm_object_part_content_get(wd->content_area,
612                                               "elm.swallow.content");
613    if (prev_content)
614      evas_object_del(prev_content);
615    if (text)
616      {
617         elm_object_part_content_set(wd->base, "elm.swallow.content",
618                                     wd->content_area);
619         wd->content_text_obj = elm_label_add(obj);
620         snprintf(buf, sizeof(buf), "popup/%s",
621                  elm_widget_style_get(obj));
622         elm_object_style_set(wd->content_text_obj, buf);
623         elm_label_line_wrap_set(wd->content_text_obj,
624                                 wd->content_text_wrap_type);
625         elm_object_text_set(wd->content_text_obj, text);
626         evas_object_size_hint_weight_set(wd->content_text_obj, EVAS_HINT_EXPAND,
627                                          0.0);
628         evas_object_size_hint_align_set(wd->content_text_obj, EVAS_HINT_FILL,
629                                         EVAS_HINT_FILL);
630         elm_object_part_content_set(wd->content_area, "elm.swallow.content",
631                                     wd->content_text_obj);
632      }
633    _sizing_eval(obj);
634 }
635
636 static void
637 _text_set_hook(Evas_Object *obj, const char *part,
638                               const char *label)
639 {
640    ELM_CHECK_WIDTYPE(obj, widtype);
641    Widget_Data *wd = elm_widget_data_get(obj);
642
643    if (!wd) return;
644    if (!part || !strcmp(part, "default"))
645      _content_text_set(obj, label);
646    else if (!strcmp(part, "title,text"))
647      _title_text_set(obj, label);
648    else
649      WRN("The part name is invalid! : popup=%p", obj);
650 }
651
652 static const char*
653 _title_text_get(const Evas_Object *obj)
654 {
655    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
656    Widget_Data *wd = elm_widget_data_get(obj);
657
658    if (!wd) return NULL;
659    return wd->title_text;
660 }
661
662 static const char*
663 _content_text_get(const Evas_Object *obj)
664 {
665    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
666    const char *str = NULL;
667    Widget_Data *wd = elm_widget_data_get(obj);
668
669    if (!wd) return NULL;
670    if (wd->content_text_obj)
671      str = elm_object_text_get(wd->content_text_obj);
672    return str;
673 }
674
675 static const char *
676 _text_get_hook(const Evas_Object *obj, const char *part)
677 {
678    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
679    const char *str = NULL;
680    Widget_Data *wd = elm_widget_data_get(obj);
681
682    if (!wd) return NULL;
683    if (!part || !strcmp(part, "default"))
684      str = _content_text_get(obj);
685    else if (!strcmp(part, "title,text"))
686      str = _title_text_get(obj);
687    else
688      WRN("The part name is invalid! : popup=%p", obj);
689    return str;
690 }
691
692 static void
693 _title_icon_set(Evas_Object *obj, Evas_Object *icon)
694 {
695    ELM_CHECK_WIDTYPE(obj, widtype);
696    Eina_Bool title_visibility_old, title_visibility_current;
697    Widget_Data *wd = elm_widget_data_get(obj);
698
699    if (!wd) return;
700    if (wd->title_icon == icon) return;
701    title_visibility_old = (wd->title_text) || (wd->title_icon);
702    if (wd->title_icon)
703      {
704         evas_object_del(wd->title_icon);
705         wd->title_icon = NULL;
706      }
707    wd->title_icon = icon;
708    title_visibility_current = (wd->title_text) || (wd->title_icon);
709    elm_object_part_content_set(wd->base, "elm.swallow.title.icon",
710                                wd->title_icon);
711    if (wd->title_icon)
712      elm_object_signal_emit(wd->base, "elm,state,title,icon,visible", "elm");
713    if (title_visibility_old != title_visibility_current) _layout_set(obj);
714    edje_object_message_signal_process(wd->base);
715    _sizing_eval(obj);
716 }
717
718 static void
719 _content_set(Evas_Object *obj, Evas_Object *content)
720 {
721    ELM_CHECK_WIDTYPE(obj, widtype);
722    Evas_Object *prev_content;
723    Widget_Data *wd = elm_widget_data_get(obj);
724
725    if (!wd) return;
726    if (wd->content && wd->content == content) return;
727    if (wd->items)
728      {
729         _remove_items(wd);
730         _list_del(wd);
731      }
732    prev_content = elm_object_part_content_get(wd->content_area,
733                                               "elm.swallow.content");
734    if (prev_content)
735      evas_object_del(prev_content);
736    wd->content = content;
737    if (content)
738      {
739         elm_object_part_content_set(wd->base, "elm.swallow.content",
740                                     wd->content_area);
741         elm_object_part_content_set(wd->content_area, "elm.swallow.content",
742                                     content);
743      }
744    _sizing_eval(obj);
745 }
746
747 static void
748 _button_remove(Evas_Object *obj, Evas_Object *content, Eina_Bool delete)
749 {
750    unsigned int i = 0, position = 0;
751    char buf[128];
752    Widget_Data *wd = elm_widget_data_get(obj);
753
754    if (!wd->button_count) return;
755    for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
756     {
757        if (wd->buttons[i])
758          {
759             position++;
760             wd->buttons[i]->delete_me = EINA_FALSE;
761             if (wd->buttons[i]->btn == content)
762               {
763                  snprintf(buf, sizeof(buf), "actionbtn%u", position);
764                  elm_object_part_content_unset(wd->action_area, buf);
765                  evas_object_hide(content);
766                  if (delete) evas_object_del(content);
767                  free(wd->buttons[i]);
768                  wd->buttons[i] = NULL;
769                  wd->button_count -= 1;
770                }
771          }
772     }
773    position = 0;
774    for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
775     {
776        if (!wd->buttons[i]) continue;
777        position++;
778        snprintf(buf, sizeof(buf), "actionbtn%u", position);
779        elm_object_part_content_unset(wd->action_area, buf);
780        elm_object_part_content_set(wd->action_area, buf,
781                                    wd->buttons[i]->btn);
782        wd->buttons[i]->delete_me = EINA_TRUE;
783     }
784    if (!wd->button_count)
785     {
786        _layout_set(obj);
787        edje_object_message_signal_process(elm_layout_edje_get(wd->base));
788     }
789    else
790     {
791        snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
792        elm_layout_theme_set(wd->action_area, "popup", buf,
793                             elm_widget_style_get(obj));
794     }
795 }
796
797 static void
798 _action_button_set(Evas_Object *obj, Evas_Object *btn, unsigned int idx)
799 {
800    Action_Area_Data *adata;
801    char buf[128];
802    unsigned int num = idx - 1, i = 0, position = 0;
803    Widget_Data *wd = elm_widget_data_get(obj);
804
805    if (!wd) return;
806    if (num >= ELM_POPUP_ACTION_BUTTON_MAX) return;
807    if (wd->buttons[num])
808      _button_remove(obj, wd->buttons[num]->btn, EINA_TRUE);
809    if (btn)
810      {
811         wd->button_count++;
812         snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
813         elm_layout_theme_set(wd->action_area, "popup", buf,
814                              elm_widget_style_get(obj));
815         adata = ELM_NEW(Action_Area_Data);
816         adata->obj = obj;
817         adata->btn = btn;
818         wd->buttons[num] = adata;
819         /* Adding delete_me state inside action data as unset calls _sub_del
820            too and before setting a new content, the previous one needs to
821            be unset in order to avoid unwanted deletion. This way rearrangement
822             of buttons can be achieved in action area.
823          */
824         for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
825           if (wd->buttons[i])
826             wd->buttons[i]->delete_me = EINA_FALSE;
827         for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
828           {
829              if (!wd->buttons[i]) continue;
830              position++;
831              snprintf(buf, sizeof(buf), "actionbtn%u", position);
832              elm_object_part_content_unset(wd->action_area, buf);
833              elm_object_part_content_set(wd->action_area, buf,
834                                          wd->buttons[i]->btn);
835              /* Setting delete_me to TRUE in order to let _sub_del handle it
836                 if deleted externally and update the buttons array after freeing
837                 action data allocated earlier.
838               */
839              wd->buttons[i]->delete_me = EINA_TRUE;
840           }
841         elm_object_part_content_set(wd->base, "elm.swallow.action_area",
842                                     wd->action_area);
843         if (wd->button_count == 1)
844           _layout_set(obj);
845         edje_object_message_signal_process(wd->base);
846         if (wd->items)
847           _scroller_size_calc(obj);
848         _sizing_eval(obj);
849      }
850 }
851
852 static void
853 _content_set_hook(Evas_Object *obj, const char *part,
854                                  Evas_Object *content)
855 {
856    ELM_CHECK_WIDTYPE(obj, widtype);
857    char buff[3];
858    unsigned int i;
859    Widget_Data *wd = elm_widget_data_get(obj);
860
861    if (!wd) return;
862    if (!part || !strcmp(part, "default"))
863      _content_set(obj, content);
864    else if (!strcmp(part, "title,icon"))
865      _title_icon_set(obj, content);
866    else if (!strncmp(part, "button", 6))
867      {
868         part += 6;
869         for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
870           {
871              snprintf(buff, sizeof(buff), "%u", i+1);
872              if (!strncmp(part, buff, sizeof(buff)))
873                {
874                   _action_button_set(obj, content, i+1);
875                   break;
876                }
877           }
878       }
879    else
880      WRN("The part name is invalid! : popup=%p", obj);
881 }
882
883 static Evas_Object *
884 _title_icon_get(Evas_Object *obj)
885 {
886    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
887    Widget_Data *wd = elm_widget_data_get(obj);
888
889    if (!wd) return NULL;
890    return wd->title_icon;
891 }
892
893 static Evas_Object *
894 _content_get(Evas_Object *obj)
895 {
896    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
897    Widget_Data *wd = elm_widget_data_get(obj);
898
899    if (!wd) return NULL;
900    return wd->content;
901 }
902
903 static Evas_Object *
904 _action_button_get(Evas_Object *obj, unsigned int idx)
905 {
906    unsigned int num = idx - 1;
907    Evas_Object *button = NULL;
908    Widget_Data *wd = elm_widget_data_get(obj);
909
910    if (!wd || !wd->button_count) return NULL;
911    if (wd->buttons[num])
912      button = wd->buttons[num]->btn;
913    return button;
914 }
915
916 static Evas_Object *
917 _content_get_hook(Evas_Object *obj, const char *part)
918 {
919    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
920    Evas_Object *content = NULL;
921    char buff[3];
922    unsigned int i;
923    Widget_Data *wd = elm_widget_data_get(obj);
924
925    if (!wd) return NULL;
926    if (!part || !strcmp(part, "default"))
927      content = _content_get(obj);
928    else if (!strcmp(part, "title,text"))
929      content = _title_icon_get(obj);
930    else if (!strncmp(part, "button", 6))
931      {
932         part += 6;
933         for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
934           {
935              snprintf(buff, sizeof(buff), "%u", i+1);
936              if (!strncmp(part, buff, sizeof(buff)))
937                {
938                   content = _action_button_get(obj, i+1);
939                   break;
940                }
941           }
942       }
943    else
944      WRN("The part name is invalid! : popup=%p", obj);
945    return content;
946 }
947
948 static Evas_Object *
949 _content_unset(Evas_Object *obj)
950 {
951    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
952    Evas_Object *content;
953    Widget_Data *wd = elm_widget_data_get(obj);
954
955    if (!wd || !wd->content) return NULL;
956    content = elm_object_part_content_unset(wd->content_area,
957                                            "elm.swallow.content");
958    wd->content = NULL;
959    _sizing_eval(obj);
960    return content;
961 }
962
963 static Evas_Object *
964 _title_icon_unset(Evas_Object *obj)
965 {
966    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
967    Evas_Object *icon;
968    Widget_Data *wd = elm_widget_data_get(obj);
969
970    if (!wd || !wd->title_icon) return NULL;
971    icon = elm_object_part_content_unset(wd->base, "elm.swallow.title.icon");
972    wd->title_icon = NULL;
973    return icon;
974 }
975
976 static Evas_Object *
977 _action_button_unset(Evas_Object *obj, unsigned int idx)
978 {
979    unsigned int num = idx -1;
980    Evas_Object *button = NULL;
981    Widget_Data *wd = elm_widget_data_get(obj);
982
983    if (!wd) return NULL;
984    if ((!wd->button_count) || (num >= ELM_POPUP_ACTION_BUTTON_MAX))
985      return NULL;
986
987    if (wd->buttons[num])
988      {
989         button = wd->buttons[num]->btn;
990         _button_remove(obj, button, EINA_FALSE);
991       }
992    return button;
993 }
994
995 static Evas_Object *
996 _content_unset_hook(Evas_Object *obj, const char *part)
997 {
998    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
999    Evas_Object *content = NULL;
1000    char buff[3];
1001    unsigned int i;
1002    Widget_Data *wd = elm_widget_data_get(obj);
1003
1004    if (!wd) return NULL;
1005    if (!part || !strcmp(part, "default"))
1006      content = _content_unset(obj);
1007    else if (!strcmp(part, "title,icon"))
1008      content = _title_icon_unset(obj);
1009    else if (!strncmp(part, "button", 6))
1010      {
1011         part += 6;
1012         for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
1013           {
1014              snprintf(buff, sizeof(buff), "%u", i+1);
1015              if (!strncmp(part, buff, sizeof(buff)))
1016                {
1017                   content = _action_button_unset(obj, i+1);
1018                   break;
1019                }
1020           }
1021       }
1022    else
1023      WRN("The part name is invalid! : popup=%p", obj);
1024    return content;
1025 }
1026
1027 static Eina_Bool
1028 _focus_next_hook(const Evas_Object *obj __UNUSED__,
1029                  Elm_Focus_Direction dir __UNUSED__,
1030                  Evas_Object **next __UNUSED__)
1031 {
1032    //TODO: Implement Focus chanin Handling in Popup for action area buttons
1033    return EINA_FALSE;
1034 }
1035
1036 static void
1037 _item_text_set(Elm_Popup_Content_Item *item, const char *label)
1038 {
1039    if (!eina_stringshare_replace(&item->label, label)) return;
1040    edje_object_part_text_set(VIEW(item), "elm.text", label);
1041    if (item->label)
1042      edje_object_signal_emit(VIEW(item),
1043                              "elm,state,item,text,visible", "elm");
1044    else
1045      edje_object_signal_emit(VIEW(item),
1046                              "elm,state,item,text,hidden", "elm");
1047    edje_object_message_signal_process(VIEW(item));
1048 }
1049
1050 static void
1051 _item_text_set_hook(Elm_Object_Item *it, const char *part, const char *label)
1052 {
1053    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1054    Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1055
1056    if ((!part) || (!strcmp(part, "default")))
1057      {
1058         _item_text_set(item, label);
1059         return;
1060      }
1061    WRN("The part name is invalid! : popup=%p", WIDGET(item));
1062 }
1063
1064 static const char *
1065 _item_text_get_hook(const Elm_Object_Item *it, const char *part)
1066 {
1067    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1068    Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1069
1070    if ((!part) || (!strcmp(part, "default")))
1071      return item->label;
1072    WRN("The part name is invalid! : popup=%p", WIDGET(item));
1073    return NULL;
1074 }
1075
1076 static void
1077 _item_icon_set(Elm_Popup_Content_Item *item, Evas_Object *icon)
1078 {
1079    if (item->icon == icon) return;
1080    if (item->icon)
1081      {
1082         elm_widget_sub_object_del(WIDGET(item), item->icon);
1083         evas_object_data_del(item->icon, "_popup_content_item");
1084         evas_object_del(item->icon);
1085      }
1086    item->icon = icon;
1087    if (item->icon)
1088      {
1089         elm_widget_sub_object_add(WIDGET(item), item->icon);
1090         evas_object_data_set(item->icon, "_popup_content_item", item);
1091         edje_object_part_swallow(VIEW(item), "elm.swallow.content",
1092                                  item->icon);
1093         edje_object_signal_emit(VIEW(item),
1094                                 "elm,state,item,icon,visible", "elm");
1095      }
1096    else
1097      edje_object_signal_emit(VIEW(item),
1098                              "elm,state,item,icon,hidden", "elm");
1099    edje_object_message_signal_process(item->base.view);
1100 }
1101
1102 static void
1103 _item_content_set_hook(Elm_Object_Item *it, const char *part,
1104                        Evas_Object *content)
1105 {
1106    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1107    Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1108
1109    if ((!(part)) || (!strcmp(part, "default")))
1110      _item_icon_set(item, content);
1111    else
1112      WRN("The part name is invalid! : popup=%p", WIDGET(item));
1113 }
1114
1115 static Evas_Object *
1116 _item_content_get_hook(const Elm_Object_Item *it,
1117                        const char *part)
1118 {
1119    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1120    Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1121
1122    if ((!(part)) || (!strcmp(part, "default")))
1123      return item->icon;
1124    WRN("The part name is invalid! : popup=%p", WIDGET(item));
1125    return NULL;
1126 }
1127
1128 static Evas_Object *
1129 _item_icon_unset(Elm_Popup_Content_Item *item)
1130 {
1131    Evas_Object *icon = item->icon;
1132
1133    if (!item->icon) return NULL;
1134    elm_widget_sub_object_del(WIDGET(item), icon);
1135    evas_object_data_del(icon, "_popup_content_item");
1136    edje_object_part_unswallow(item->base.view, icon);
1137    edje_object_signal_emit(VIEW(item),
1138                            "elm,state,item,icon,hidden", "elm");
1139    item->icon = NULL;
1140    return icon;
1141 }
1142
1143 static Evas_Object *
1144 _item_content_unset_hook(const Elm_Object_Item *it,
1145                          const char *part)
1146 {
1147    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1148    Evas_Object *content = NULL;
1149    Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1150
1151    if ((!(part)) || (!strcmp(part, "default")))
1152      content = _item_icon_unset(item);
1153    else
1154      WRN("The part name is invalid! : popup=%p", WIDGET(item));
1155    return content;
1156 }
1157
1158 static void
1159 _item_disable_hook(Elm_Object_Item *it)
1160 {
1161    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1162    Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1163    Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1164
1165    if (!wd) return;
1166    if (elm_widget_item_disabled_get(it))
1167      edje_object_signal_emit(VIEW(item), "elm,state,item,disabled", "elm");
1168    else
1169      edje_object_signal_emit(VIEW(item), "elm,state,item,enabled", "elm");
1170 }
1171
1172 static void
1173 _item_del_pre_hook(Elm_Object_Item *it)
1174 {
1175    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1176    Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1177    Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1178
1179    if (!wd) return;
1180    if (item->icon)
1181      evas_object_del(item->icon);
1182    eina_stringshare_del(item->label);
1183    wd->items = eina_list_remove(wd->items, item);
1184    if (!eina_list_count(wd->items))
1185      {
1186         wd->items = NULL;
1187         _list_del(wd);
1188      }
1189 }
1190
1191 static void
1192 _item_signal_emit_hook(Elm_Object_Item *it, const char *emission,
1193                        const char *source)
1194 {
1195    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1196    Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1197
1198    edje_object_signal_emit(VIEW(item), emission, source);
1199 }
1200
1201 EAPI Evas_Object *
1202 elm_popup_add(Evas_Object *parent)
1203 {
1204    Evas_Object *obj;
1205    Evas *e;
1206    int i = 0;
1207    Widget_Data *wd;
1208
1209    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1210    ELM_SET_WIDTYPE(widtype, "popup");
1211    elm_widget_type_set(obj, widtype);
1212    elm_widget_sub_object_add(parent, obj);
1213    elm_widget_data_set(obj, wd);
1214    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
1215    elm_widget_del_hook_set(obj, _del_hook);
1216    elm_widget_theme_hook_set(obj, _theme_hook);
1217    elm_widget_text_set_hook_set(obj, _text_set_hook);
1218    elm_widget_text_get_hook_set(obj, _text_get_hook);
1219    elm_widget_content_set_hook_set(obj, _content_set_hook);
1220    elm_widget_content_get_hook_set(obj, _content_get_hook);
1221    elm_widget_content_unset_hook_set(obj,_content_unset_hook);
1222    elm_widget_focus_next_hook_set(obj, _focus_next_hook);
1223    evas_object_smart_callbacks_descriptions_set(obj, _signals);
1224
1225    wd->notify = elm_notify_add(obj);
1226    elm_widget_resize_object_set(obj, wd->notify);
1227    elm_notify_parent_set(wd->notify, parent);
1228    elm_notify_orient_set(wd->notify, ELM_NOTIFY_ORIENT_CENTER);
1229    elm_notify_allow_events_set(wd->notify, EINA_FALSE);
1230    evas_object_size_hint_weight_set(wd->notify,
1231                                     EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1232    evas_object_size_hint_align_set(wd->notify, EVAS_HINT_FILL, EVAS_HINT_FILL);
1233    elm_object_style_set(wd->notify, "popup");
1234
1235    evas_object_event_callback_add(wd->notify, EVAS_CALLBACK_RESIZE,
1236                                   _notify_resize, obj);
1237    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESTACK, _restack, NULL);
1238    wd->base = elm_layout_add(obj);
1239    evas_object_size_hint_weight_set(wd->base, EVAS_HINT_EXPAND,
1240                                     EVAS_HINT_EXPAND);
1241    evas_object_size_hint_align_set(wd->base, EVAS_HINT_FILL, EVAS_HINT_FILL);
1242
1243    elm_layout_theme_set(wd->base, "popup", "base", elm_widget_style_get(obj));
1244    elm_object_content_set(wd->notify, wd->base);
1245
1246    elm_object_signal_callback_add(wd->base, "elm,state,title_area,visible",
1247                                   "elm", _layout_change_cb, obj);
1248    elm_object_signal_callback_add(wd->base, "elm,state,title_area,hidden",
1249                                   "elm", _layout_change_cb, obj);
1250    elm_object_signal_callback_add(wd->base, "elm,state,action_area,visible",
1251                                   "elm", _layout_change_cb, obj);
1252    elm_object_signal_callback_add(wd->base, "elm,state,action_area,hidden",
1253                                   "elm", _layout_change_cb, obj);
1254    wd->content_area = elm_layout_add(obj);
1255    elm_layout_theme_set(wd->content_area, "popup", "content",
1256                         elm_widget_style_get(obj));
1257    wd->action_area = elm_layout_add(obj);
1258    evas_object_size_hint_weight_set(wd->action_area, EVAS_HINT_EXPAND,
1259                                     EVAS_HINT_EXPAND);
1260    evas_object_size_hint_align_set(wd->action_area, EVAS_HINT_FILL,
1261                                    EVAS_HINT_FILL);
1262    evas_object_event_callback_add(wd->action_area,
1263                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1264                                   _changed_size_hints, obj);
1265    evas_object_event_callback_add(wd->content_area,
1266                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1267                                   _changed_size_hints, obj);
1268    evas_object_smart_callback_add(wd->base, "sub-object-del",
1269                                   _sub_del, obj);
1270    evas_object_smart_callback_add(wd->content_area, "sub-object-del",
1271                                   _sub_del, obj);
1272    evas_object_smart_callback_add(wd->action_area, "sub-object-del",
1273                                   _sub_del, obj);
1274    evas_object_smart_callback_add(obj, "sub-object-del",
1275                                   _sub_del, obj);
1276
1277    wd->content_text_wrap_type = ELM_WRAP_MIXED;
1278    evas_object_smart_callback_add(wd->notify, "block,clicked",
1279                                   _block_clicked_cb, obj);
1280    evas_object_smart_callback_add(wd->notify, "timeout", _timeout, obj);
1281    for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
1282      wd->buttons[i] = NULL;
1283    _layout_set(obj);
1284    //TODO: To use scroller for description also
1285    return obj;
1286 }
1287
1288 EAPI void
1289 elm_popup_content_text_wrap_type_set(Evas_Object *obj, Elm_Wrap_Type wrap)
1290 {
1291    ELM_CHECK_WIDTYPE(obj, widtype);
1292    Evas_Object *content_text_obj;
1293    Widget_Data *wd = elm_widget_data_get(obj);
1294
1295    if (!wd) return;
1296    if (wd->content_text_wrap_type == ELM_WRAP_NONE) return;
1297    //Need to wrap the content text, so not allowing ELM_WRAP_NONE
1298    wd->content_text_wrap_type = wrap;
1299    if (wd->content_text_obj)
1300      {
1301         content_text_obj = elm_object_part_content_get(wd->content_area,
1302                                                        "elm.swallow.content");
1303         elm_label_line_wrap_set(content_text_obj, wrap);
1304      }
1305 }
1306
1307 EAPI Elm_Wrap_Type
1308 elm_popup_content_text_wrap_type_get(const Evas_Object *obj)
1309 {
1310    ELM_CHECK_WIDTYPE(obj, widtype) ELM_WRAP_LAST;
1311    Widget_Data *wd = elm_widget_data_get(obj);
1312
1313    if (!wd) return ELM_WRAP_LAST;
1314    return wd->content_text_wrap_type;
1315 }
1316
1317 EAPI void
1318 elm_popup_orient_set(Evas_Object *obj, Elm_Popup_Orient orient)
1319 {
1320    ELM_CHECK_WIDTYPE(obj, widtype);
1321    Widget_Data *wd = elm_widget_data_get(obj);
1322
1323    if (!wd) return;
1324    if (orient >= ELM_POPUP_ORIENT_LAST) return;
1325    elm_notify_orient_set(wd->notify, (Elm_Notify_Orient)orient);
1326 }
1327
1328 EAPI Elm_Popup_Orient
1329 elm_popup_orient_get(const Evas_Object *obj)
1330 {
1331    ELM_CHECK_WIDTYPE(obj, widtype) -1;
1332    Widget_Data *wd = elm_widget_data_get(obj);
1333
1334    if (!wd) return ELM_POPUP_ORIENT_LAST;
1335    return (Elm_Popup_Orient)elm_notify_orient_get(wd->notify);
1336 }
1337
1338 EAPI void
1339 elm_popup_timeout_set(Evas_Object *obj, double timeout)
1340 {
1341    ELM_CHECK_WIDTYPE(obj, widtype);
1342    Widget_Data *wd = elm_widget_data_get(obj);
1343
1344    if (!wd) return;
1345    elm_notify_timeout_set(wd->notify, timeout);
1346 }
1347
1348 EAPI double
1349 elm_popup_timeout_get(const Evas_Object *obj)
1350 {
1351    ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
1352    Widget_Data *wd = elm_widget_data_get(obj);
1353
1354    if (!wd) return 0.0;
1355    return elm_notify_timeout_get(wd->notify);
1356 }
1357
1358 EAPI void
1359 elm_popup_allow_events_set(Evas_Object *obj, Eina_Bool allow)
1360 {
1361    ELM_CHECK_WIDTYPE(obj, widtype);
1362    Eina_Bool allow_events = !!allow;
1363    Widget_Data *wd = elm_widget_data_get(obj);
1364
1365    if (!wd) return;
1366    elm_notify_allow_events_set(wd->notify, allow_events);
1367 }
1368
1369 EAPI Eina_Bool
1370 elm_popup_allow_events_get(const Evas_Object *obj)
1371 {
1372    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1373    Widget_Data *wd = elm_widget_data_get(obj);
1374
1375    if (!wd) return EINA_FALSE;
1376    return elm_notify_allow_events_get(wd->notify);
1377 }
1378
1379 EAPI Elm_Object_Item *
1380 elm_popup_item_append(Evas_Object *obj, const char *label,
1381                               Evas_Object *icon, Evas_Smart_Cb func,
1382                               const void *data)
1383 {
1384    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1385    Evas_Object *prev_content;
1386    Elm_Popup_Content_Item *item;
1387    Widget_Data *wd = elm_widget_data_get(obj);
1388
1389    if (!wd) return NULL;
1390    item = elm_widget_item_new(obj, Elm_Popup_Content_Item);
1391    if (!item) return NULL;
1392    if (wd->content || wd->content_text_obj)
1393      {
1394         prev_content = elm_object_part_content_get(wd->content_area,
1395                                                    "elm.swallow.content");
1396         if (prev_content)
1397           evas_object_del(prev_content);
1398      }
1399
1400    //The first item is appended.
1401    if (!wd->items)
1402      _list_new(obj);
1403
1404    item->func = func;
1405    item->base.data = data;
1406
1407    _item_new(item);
1408    _item_icon_set(item, icon);
1409    _item_text_set(item, label);
1410    elm_box_pack_end(wd->box, VIEW(item));
1411    wd->items = eina_list_append(wd->items, item);
1412
1413    _scroller_size_calc(obj);
1414    _sizing_eval(obj);
1415    return (Elm_Object_Item *)item;
1416 }