From: cnook <kimcinoo@gmail.com>
[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) evas_object_del(wd->title_icon);
703
704    wd->title_icon = icon;
705    title_visibility_current = (wd->title_text) || (wd->title_icon);
706    elm_object_part_content_set(wd->base, "elm.swallow.title.icon",
707                                wd->title_icon);
708    if (wd->title_icon)
709      elm_object_signal_emit(wd->base, "elm,state,title,icon,visible", "elm");
710    if (title_visibility_old != title_visibility_current) _layout_set(obj);
711    edje_object_message_signal_process(wd->base);
712    _sizing_eval(obj);
713 }
714
715 static void
716 _content_set(Evas_Object *obj, Evas_Object *content)
717 {
718    ELM_CHECK_WIDTYPE(obj, widtype);
719    Evas_Object *prev_content;
720    Widget_Data *wd = elm_widget_data_get(obj);
721
722    if (!wd) return;
723    if (wd->content && wd->content == content) return;
724    if (wd->items)
725      {
726         _remove_items(wd);
727         _list_del(wd);
728      }
729    prev_content = elm_object_part_content_get(wd->content_area,
730                                               "elm.swallow.content");
731    if (prev_content)
732      evas_object_del(prev_content);
733    wd->content = content;
734    if (content)
735      {
736         elm_object_part_content_set(wd->base, "elm.swallow.content",
737                                     wd->content_area);
738         elm_object_part_content_set(wd->content_area, "elm.swallow.content",
739                                     content);
740      }
741    _sizing_eval(obj);
742 }
743
744 static void
745 _button_remove(Evas_Object *obj, Evas_Object *content, Eina_Bool delete)
746 {
747    unsigned int i = 0, position = 0;
748    char buf[128];
749    Widget_Data *wd = elm_widget_data_get(obj);
750
751    if (!wd->button_count) return;
752    for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
753     {
754        if (wd->buttons[i])
755          {
756             position++;
757             wd->buttons[i]->delete_me = EINA_FALSE;
758             if (wd->buttons[i]->btn == content)
759               {
760                  snprintf(buf, sizeof(buf), "actionbtn%u", position);
761                  elm_object_part_content_unset(wd->action_area, buf);
762                  evas_object_hide(content);
763                  if (delete) evas_object_del(content);
764                  free(wd->buttons[i]);
765                  wd->buttons[i] = NULL;
766                  wd->button_count -= 1;
767                }
768          }
769     }
770    position = 0;
771    for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
772     {
773        if (!wd->buttons[i]) continue;
774        position++;
775        snprintf(buf, sizeof(buf), "actionbtn%u", position);
776        elm_object_part_content_unset(wd->action_area, buf);
777        elm_object_part_content_set(wd->action_area, buf,
778                                    wd->buttons[i]->btn);
779        wd->buttons[i]->delete_me = EINA_TRUE;
780     }
781    if (!wd->button_count)
782     {
783        _layout_set(obj);
784        edje_object_message_signal_process(elm_layout_edje_get(wd->base));
785     }
786    else
787     {
788        snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
789        elm_layout_theme_set(wd->action_area, "popup", buf,
790                             elm_widget_style_get(obj));
791     }
792 }
793
794 static void
795 _action_button_set(Evas_Object *obj, Evas_Object *btn, unsigned int idx)
796 {
797    Action_Area_Data *adata;
798    char buf[128];
799    unsigned int num = idx - 1, i = 0, position = 0;
800    Widget_Data *wd = elm_widget_data_get(obj);
801
802    if (!wd) return;
803    if (num >= ELM_POPUP_ACTION_BUTTON_MAX) return;
804    if (wd->buttons[num])
805      _button_remove(obj, wd->buttons[num]->btn, EINA_TRUE);
806    if (btn)
807      {
808         wd->button_count++;
809         snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
810         elm_layout_theme_set(wd->action_area, "popup", buf,
811                              elm_widget_style_get(obj));
812         adata = ELM_NEW(Action_Area_Data);
813         adata->obj = obj;
814         adata->btn = btn;
815         wd->buttons[num] = adata;
816         /* Adding delete_me state inside action data as unset calls _sub_del
817            too and before setting a new content, the previous one needs to
818            be unset in order to avoid unwanted deletion. This way rearrangement
819             of buttons can be achieved in action area.
820          */
821         for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
822           if (wd->buttons[i])
823             wd->buttons[i]->delete_me = EINA_FALSE;
824         for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
825           {
826              if (!wd->buttons[i]) continue;
827              position++;
828              snprintf(buf, sizeof(buf), "actionbtn%u", position);
829              elm_object_part_content_unset(wd->action_area, buf);
830              elm_object_part_content_set(wd->action_area, buf,
831                                          wd->buttons[i]->btn);
832              /* Setting delete_me to TRUE in order to let _sub_del handle it
833                 if deleted externally and update the buttons array after freeing
834                 action data allocated earlier.
835               */
836              wd->buttons[i]->delete_me = EINA_TRUE;
837           }
838         elm_object_part_content_set(wd->base, "elm.swallow.action_area",
839                                     wd->action_area);
840         if (wd->button_count == 1)
841           _layout_set(obj);
842         edje_object_message_signal_process(wd->base);
843         if (wd->items)
844           _scroller_size_calc(obj);
845         _sizing_eval(obj);
846      }
847 }
848
849 static void
850 _content_set_hook(Evas_Object *obj, const char *part,
851                                  Evas_Object *content)
852 {
853    ELM_CHECK_WIDTYPE(obj, widtype);
854    char buff[3];
855    unsigned int i;
856    Widget_Data *wd = elm_widget_data_get(obj);
857
858    if (!wd) return;
859    if (!part || !strcmp(part, "default"))
860      _content_set(obj, content);
861    else if (!strcmp(part, "title,icon"))
862      _title_icon_set(obj, content);
863    else if (!strncmp(part, "button", 6))
864      {
865         part += 6;
866         for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
867           {
868              snprintf(buff, sizeof(buff), "%u", i+1);
869              if (!strncmp(part, buff, sizeof(buff)))
870                {
871                   _action_button_set(obj, content, i+1);
872                   break;
873                }
874           }
875       }
876    else
877      WRN("The part name is invalid! : popup=%p", obj);
878 }
879
880 static Evas_Object *
881 _title_icon_get(Evas_Object *obj)
882 {
883    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
884    Widget_Data *wd = elm_widget_data_get(obj);
885
886    if (!wd) return NULL;
887    return wd->title_icon;
888 }
889
890 static Evas_Object *
891 _content_get(Evas_Object *obj)
892 {
893    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
894    Widget_Data *wd = elm_widget_data_get(obj);
895
896    if (!wd) return NULL;
897    return wd->content;
898 }
899
900 static Evas_Object *
901 _action_button_get(Evas_Object *obj, unsigned int idx)
902 {
903    unsigned int num = idx - 1;
904    Evas_Object *button = NULL;
905    Widget_Data *wd = elm_widget_data_get(obj);
906
907    if (!wd || !wd->button_count) return NULL;
908    if (wd->buttons[num])
909      button = wd->buttons[num]->btn;
910    return button;
911 }
912
913 static Evas_Object *
914 _content_get_hook(Evas_Object *obj, const char *part)
915 {
916    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
917    Evas_Object *content = NULL;
918    char buff[3];
919    unsigned int i;
920    Widget_Data *wd = elm_widget_data_get(obj);
921
922    if (!wd) return NULL;
923    if (!part || !strcmp(part, "default"))
924      content = _content_get(obj);
925    else if (!strcmp(part, "title,text"))
926      content = _title_icon_get(obj);
927    else if (!strncmp(part, "button", 6))
928      {
929         part += 6;
930         for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
931           {
932              snprintf(buff, sizeof(buff), "%u", i+1);
933              if (!strncmp(part, buff, sizeof(buff)))
934                {
935                   content = _action_button_get(obj, i+1);
936                   break;
937                }
938           }
939       }
940    else
941      WRN("The part name is invalid! : popup=%p", obj);
942    return content;
943 }
944
945 static Evas_Object *
946 _content_unset(Evas_Object *obj)
947 {
948    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
949    Evas_Object *content;
950    Widget_Data *wd = elm_widget_data_get(obj);
951
952    if (!wd || !wd->content) return NULL;
953    content = elm_object_part_content_unset(wd->content_area,
954                                            "elm.swallow.content");
955    wd->content = NULL;
956    _sizing_eval(obj);
957    return content;
958 }
959
960 static Evas_Object *
961 _title_icon_unset(Evas_Object *obj)
962 {
963    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
964    Evas_Object *icon;
965    Widget_Data *wd = elm_widget_data_get(obj);
966
967    if (!wd || !wd->title_icon) return NULL;
968    icon = elm_object_part_content_unset(wd->base, "elm.swallow.title.icon");
969    wd->title_icon = NULL;
970    return icon;
971 }
972
973 static Evas_Object *
974 _action_button_unset(Evas_Object *obj, unsigned int idx)
975 {
976    unsigned int num = idx -1;
977    Evas_Object *button = NULL;
978    Widget_Data *wd = elm_widget_data_get(obj);
979
980    if (!wd) return NULL;
981    if ((!wd->button_count) || (num >= ELM_POPUP_ACTION_BUTTON_MAX))
982      return NULL;
983
984    if (wd->buttons[num])
985      {
986         button = wd->buttons[num]->btn;
987         _button_remove(obj, button, EINA_FALSE);
988       }
989    return button;
990 }
991
992 static Evas_Object *
993 _content_unset_hook(Evas_Object *obj, const char *part)
994 {
995    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
996    Evas_Object *content = NULL;
997    char buff[3];
998    unsigned int i;
999    Widget_Data *wd = elm_widget_data_get(obj);
1000
1001    if (!wd) return NULL;
1002    if (!part || !strcmp(part, "default"))
1003      content = _content_unset(obj);
1004    else if (!strcmp(part, "title,icon"))
1005      content = _title_icon_unset(obj);
1006    else if (!strncmp(part, "button", 6))
1007      {
1008         part += 6;
1009         for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
1010           {
1011              snprintf(buff, sizeof(buff), "%u", i+1);
1012              if (!strncmp(part, buff, sizeof(buff)))
1013                {
1014                   content = _action_button_unset(obj, i+1);
1015                   break;
1016                }
1017           }
1018       }
1019    else
1020      WRN("The part name is invalid! : popup=%p", obj);
1021    return content;
1022 }
1023
1024 static Eina_Bool
1025 _focus_next_hook(const Evas_Object *obj __UNUSED__,
1026                  Elm_Focus_Direction dir __UNUSED__,
1027                  Evas_Object **next __UNUSED__)
1028 {
1029    //TODO: Implement Focus chanin Handling in Popup for action area buttons
1030    return EINA_FALSE;
1031 }
1032 static void
1033 _item_text_set(Elm_Popup_Content_Item *item, const char *label)
1034 {
1035    if (!eina_stringshare_replace(&item->label, label)) return;
1036    edje_object_part_text_set(VIEW(item), "elm.text", label);
1037    if (item->label)
1038      edje_object_signal_emit(VIEW(item),
1039                              "elm,state,item,text,visible", "elm");
1040    else
1041      edje_object_signal_emit(VIEW(item),
1042                              "elm,state,item,text,hidden", "elm");
1043    edje_object_message_signal_process(VIEW(item));
1044 }
1045
1046 static void
1047 _item_text_set_hook(Elm_Object_Item *it, const char *part, const char *label)
1048 {
1049    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1050    Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1051
1052    if ((!part) || (!strcmp(part, "default")))
1053      {
1054         _item_text_set(item, label);
1055         return;
1056      }
1057    WRN("The part name is invalid! : popup=%p", WIDGET(item));
1058 }
1059
1060 static const char *
1061 _item_text_get_hook(const Elm_Object_Item *it, const char *part)
1062 {
1063    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1064    Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1065
1066    if ((!part) || (!strcmp(part, "default")))
1067      return item->label;
1068    WRN("The part name is invalid! : popup=%p", WIDGET(item));
1069    return NULL;
1070 }
1071
1072 static void
1073 _item_icon_set(Elm_Popup_Content_Item *item, Evas_Object *icon)
1074 {
1075    if (item->icon == icon) return;
1076    if (item->icon)
1077      {
1078         evas_object_data_del(item->icon, "_popup_content_item");
1079         evas_object_del(item->icon);
1080      }
1081    item->icon = icon;
1082    if (item->icon)
1083      {
1084         elm_widget_sub_object_add(WIDGET(item), item->icon);
1085         evas_object_data_set(item->icon, "_popup_content_item", item);
1086         edje_object_part_swallow(VIEW(item), "elm.swallow.content",
1087                                  item->icon);
1088         edje_object_signal_emit(VIEW(item),
1089                                 "elm,state,item,icon,visible", "elm");
1090      }
1091    else
1092      edje_object_signal_emit(VIEW(item),
1093                              "elm,state,item,icon,hidden", "elm");
1094    edje_object_message_signal_process(item->base.view);
1095 }
1096
1097 static void
1098 _item_content_set_hook(Elm_Object_Item *it, const char *part,
1099                        Evas_Object *content)
1100 {
1101    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1102    Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1103
1104    if ((!(part)) || (!strcmp(part, "default")))
1105      _item_icon_set(item, content);
1106    else
1107      WRN("The part name is invalid! : popup=%p", WIDGET(item));
1108 }
1109
1110 static Evas_Object *
1111 _item_content_get_hook(const Elm_Object_Item *it,
1112                        const char *part)
1113 {
1114    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1115    Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1116
1117    if ((!(part)) || (!strcmp(part, "default")))
1118      return item->icon;
1119    WRN("The part name is invalid! : popup=%p", WIDGET(item));
1120    return NULL;
1121 }
1122
1123 static Evas_Object *
1124 _item_icon_unset(Elm_Popup_Content_Item *item)
1125 {
1126    Evas_Object *icon = item->icon;
1127
1128    if (!item->icon) return NULL;
1129    elm_widget_sub_object_del(WIDGET(item), icon);
1130    evas_object_data_del(icon, "_popup_content_item");
1131    edje_object_part_unswallow(item->base.view, icon);
1132    edje_object_signal_emit(VIEW(item),
1133                            "elm,state,item,icon,hidden", "elm");
1134    item->icon = NULL;
1135    return icon;
1136 }
1137
1138 static Evas_Object *
1139 _item_content_unset_hook(const Elm_Object_Item *it,
1140                          const char *part)
1141 {
1142    ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1143    Evas_Object *content = NULL;
1144    Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1145
1146    if ((!(part)) || (!strcmp(part, "default")))
1147      content = _item_icon_unset(item);
1148    else
1149      WRN("The part name is invalid! : popup=%p", WIDGET(item));
1150    return content;
1151 }
1152
1153 static void
1154 _item_disable_hook(Elm_Object_Item *it)
1155 {
1156    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1157    Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1158    Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1159
1160    if (!wd) return;
1161    if (elm_widget_item_disabled_get(it))
1162      edje_object_signal_emit(VIEW(item), "elm,state,item,disabled", "elm");
1163    else
1164      edje_object_signal_emit(VIEW(item), "elm,state,item,enabled", "elm");
1165 }
1166
1167 static void
1168 _item_del_pre_hook(Elm_Object_Item *it)
1169 {
1170    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1171    Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1172    Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1173
1174    if (!wd) return;
1175    if (item->icon)
1176      evas_object_del(item->icon);
1177    eina_stringshare_del(item->label);
1178    wd->items = eina_list_remove(wd->items, item);
1179    if (!eina_list_count(wd->items))
1180      {
1181         wd->items = NULL;
1182         _list_del(wd);
1183      }
1184 }
1185
1186 static void
1187 _item_signal_emit_hook(Elm_Object_Item *it, const char *emission,
1188                        const char *source)
1189 {
1190    ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1191    Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1192
1193    edje_object_signal_emit(VIEW(item), emission, source);
1194 }
1195
1196 static void
1197 _popup_show(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
1198                void *event_info __UNUSED__)
1199 {
1200    Widget_Data *wd;
1201
1202    wd = elm_widget_data_get(obj);
1203    if (!wd) return;
1204
1205    evas_object_show(wd->notify);
1206 }
1207
1208 EAPI Evas_Object *
1209 elm_popup_add(Evas_Object *parent)
1210 {
1211    Evas_Object *obj;
1212    Evas *e;
1213    int i = 0;
1214    Widget_Data *wd;
1215
1216    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1217    ELM_SET_WIDTYPE(widtype, "popup");
1218    elm_widget_type_set(obj, widtype);
1219    elm_widget_sub_object_add(parent, obj);
1220    elm_widget_data_set(obj, wd);
1221    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
1222    elm_widget_del_hook_set(obj, _del_hook);
1223    elm_widget_theme_hook_set(obj, _theme_hook);
1224    elm_widget_text_set_hook_set(obj, _text_set_hook);
1225    elm_widget_text_get_hook_set(obj, _text_get_hook);
1226    elm_widget_content_set_hook_set(obj, _content_set_hook);
1227    elm_widget_content_get_hook_set(obj, _content_get_hook);
1228    elm_widget_content_unset_hook_set(obj,_content_unset_hook);
1229    elm_widget_focus_next_hook_set(obj, _focus_next_hook);
1230    evas_object_smart_callbacks_descriptions_set(obj, _signals);
1231
1232    wd->notify = elm_notify_add(obj);
1233    elm_notify_parent_set(wd->notify, parent);
1234    elm_notify_orient_set(wd->notify, ELM_NOTIFY_ORIENT_CENTER);
1235    elm_notify_allow_events_set(wd->notify, EINA_FALSE);
1236    evas_object_size_hint_weight_set(wd->notify,
1237                                     EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1238    evas_object_size_hint_align_set(wd->notify, EVAS_HINT_FILL, EVAS_HINT_FILL);
1239    elm_object_style_set(wd->notify, "popup");
1240
1241    evas_object_event_callback_add(wd->notify, EVAS_CALLBACK_RESIZE,
1242                                   _notify_resize, obj);
1243    evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _popup_show,
1244                                   NULL);
1245    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESTACK, _restack, NULL);
1246    wd->base = elm_layout_add(obj);
1247    evas_object_size_hint_weight_set(wd->base, EVAS_HINT_EXPAND,
1248                                     EVAS_HINT_EXPAND);
1249    evas_object_size_hint_align_set(wd->base, EVAS_HINT_FILL, EVAS_HINT_FILL);
1250
1251    elm_layout_theme_set(wd->base, "popup", "base", elm_widget_style_get(obj));
1252    elm_object_content_set(wd->notify, wd->base);
1253
1254    elm_object_signal_callback_add(wd->base, "elm,state,title_area,visible",
1255                                   "elm", _layout_change_cb, obj);
1256    elm_object_signal_callback_add(wd->base, "elm,state,title_area,hidden",
1257                                   "elm", _layout_change_cb, obj);
1258    elm_object_signal_callback_add(wd->base, "elm,state,action_area,visible",
1259                                   "elm", _layout_change_cb, obj);
1260    elm_object_signal_callback_add(wd->base, "elm,state,action_area,hidden",
1261                                   "elm", _layout_change_cb, obj);
1262    wd->content_area = elm_layout_add(obj);
1263    elm_layout_theme_set(wd->content_area, "popup", "content",
1264                         elm_widget_style_get(obj));
1265    wd->action_area = elm_layout_add(obj);
1266    evas_object_size_hint_weight_set(wd->action_area, EVAS_HINT_EXPAND,
1267                                     EVAS_HINT_EXPAND);
1268    evas_object_size_hint_align_set(wd->action_area, EVAS_HINT_FILL,
1269                                    EVAS_HINT_FILL);
1270    evas_object_event_callback_add(wd->action_area,
1271                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1272                                   _changed_size_hints, obj);
1273    evas_object_event_callback_add(wd->content_area,
1274                                   EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1275                                   _changed_size_hints, obj);
1276    evas_object_smart_callback_add(wd->base, "sub-object-del",
1277                                   _sub_del, obj);
1278    evas_object_smart_callback_add(wd->content_area, "sub-object-del",
1279                                   _sub_del, obj);
1280    evas_object_smart_callback_add(wd->action_area, "sub-object-del",
1281                                   _sub_del, obj);
1282    evas_object_smart_callback_add(obj, "sub-object-del",
1283                                   _sub_del, obj);
1284
1285    wd->content_text_wrap_type = ELM_WRAP_MIXED;
1286    evas_object_smart_callback_add(wd->notify, "block,clicked",
1287                                   _block_clicked_cb, obj);
1288    evas_object_smart_callback_add(wd->notify, "timeout", _timeout, obj);
1289    for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
1290      wd->buttons[i] = NULL;
1291    _layout_set(obj);
1292    //TODO: To use scroller for description also
1293    return obj;
1294 }
1295
1296 EAPI void
1297 elm_popup_content_text_wrap_type_set(Evas_Object *obj, Elm_Wrap_Type wrap)
1298 {
1299    ELM_CHECK_WIDTYPE(obj, widtype);
1300    Evas_Object *content_text_obj;
1301    Widget_Data *wd = elm_widget_data_get(obj);
1302
1303    if (!wd) return;
1304    if (wd->content_text_wrap_type == ELM_WRAP_NONE) return;
1305    //Need to wrap the content text, so not allowing ELM_WRAP_NONE
1306    wd->content_text_wrap_type = wrap;
1307    if (wd->content_text_obj)
1308      {
1309         content_text_obj = elm_object_part_content_get(wd->content_area,
1310                                                        "elm.swallow.content");
1311         elm_label_line_wrap_set(content_text_obj, wrap);
1312      }
1313 }
1314
1315 EAPI Elm_Wrap_Type
1316 elm_popup_content_text_wrap_type_get(const Evas_Object *obj)
1317 {
1318    ELM_CHECK_WIDTYPE(obj, widtype) ELM_WRAP_LAST;
1319    Widget_Data *wd = elm_widget_data_get(obj);
1320
1321    if (!wd) return ELM_WRAP_LAST;
1322    return wd->content_text_wrap_type;
1323 }
1324
1325 EAPI void
1326 elm_popup_orient_set(Evas_Object *obj, Elm_Popup_Orient orient)
1327 {
1328    ELM_CHECK_WIDTYPE(obj, widtype);
1329    Widget_Data *wd = elm_widget_data_get(obj);
1330
1331    if (!wd) return;
1332    if (orient >= ELM_POPUP_ORIENT_LAST) return;
1333    elm_notify_orient_set(wd->notify, (Elm_Notify_Orient)orient);
1334 }
1335
1336 EAPI Elm_Popup_Orient
1337 elm_popup_orient_get(const Evas_Object *obj)
1338 {
1339    ELM_CHECK_WIDTYPE(obj, widtype) -1;
1340    Widget_Data *wd = elm_widget_data_get(obj);
1341
1342    if (!wd) return ELM_POPUP_ORIENT_LAST;
1343    return (Elm_Popup_Orient)elm_notify_orient_get(wd->notify);
1344 }
1345
1346 EAPI void
1347 elm_popup_timeout_set(Evas_Object *obj, double timeout)
1348 {
1349    ELM_CHECK_WIDTYPE(obj, widtype);
1350    Widget_Data *wd = elm_widget_data_get(obj);
1351
1352    if (!wd) return;
1353    elm_notify_timeout_set(wd->notify, timeout);
1354 }
1355
1356 EAPI double
1357 elm_popup_timeout_get(const Evas_Object *obj)
1358 {
1359    ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
1360    Widget_Data *wd = elm_widget_data_get(obj);
1361
1362    if (!wd) return 0.0;
1363    return elm_notify_timeout_get(wd->notify);
1364 }
1365
1366 EAPI void
1367 elm_popup_allow_events_set(Evas_Object *obj, Eina_Bool allow)
1368 {
1369    ELM_CHECK_WIDTYPE(obj, widtype);
1370    Eina_Bool allow_events = !!allow;
1371    Widget_Data *wd = elm_widget_data_get(obj);
1372
1373    if (!wd) return;
1374    elm_notify_allow_events_set(wd->notify, allow_events);
1375 }
1376
1377 EAPI Eina_Bool
1378 elm_popup_allow_events_get(const Evas_Object *obj)
1379 {
1380    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1381    Widget_Data *wd = elm_widget_data_get(obj);
1382
1383    if (!wd) return EINA_FALSE;
1384    return elm_notify_allow_events_get(wd->notify);
1385 }
1386
1387 EAPI Elm_Object_Item *
1388 elm_popup_item_append(Evas_Object *obj, const char *label,
1389                               Evas_Object *icon, Evas_Smart_Cb func,
1390                               const void *data)
1391 {
1392    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1393    Evas_Object *prev_content;
1394    Elm_Popup_Content_Item *item;
1395    Widget_Data *wd = elm_widget_data_get(obj);
1396
1397    if (!wd) return NULL;
1398    item = elm_widget_item_new(obj, Elm_Popup_Content_Item);
1399    if (!item) return NULL;
1400    if (wd->content || wd->content_text_obj)
1401      {
1402         prev_content = elm_object_part_content_get(wd->content_area,
1403                                                    "elm.swallow.content");
1404         if (prev_content)
1405           evas_object_del(prev_content);
1406      }
1407
1408    //The first item is appended.
1409    if (!wd->items)
1410      _list_new(obj);
1411
1412    item->func = func;
1413    item->base.data = data;
1414
1415    _item_new(item);
1416    _item_icon_set(item, icon);
1417    _item_text_set(item, label);
1418    elm_box_pack_end(wd->box, VIEW(item));
1419    wd->items = eina_list_append(wd->items, item);
1420
1421    _scroller_size_calc(obj);
1422    _sizing_eval(obj);
1423    return (Elm_Object_Item *)item;
1424 }