Initialize Tizen 2.3
[framework/uifw/elementary.git] / mobile / src / lib / elc_ctxpopup.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include "elm_widget_ctxpopup.h"
4
5 #define OUTLINE_TEXT "Contextual popup is opened, double tap to close the popup"
6
7 EAPI const char ELM_CTXPOPUP_SMART_NAME[] = "elm_ctxpopup";
8
9 static const char ACCESS_OUTLINE_PART[] = "access.outline";
10
11 static const char SIG_DISMISSED[] = "dismissed";
12 static const char SIG_LANG_CHANGED[] = "language,changed";
13 static const char SIG_ACCESS_CHANGED[] = "access,changed";
14
15 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
16    {SIG_DISMISSED, ""},
17    {SIG_LANG_CHANGED, ""},
18    {SIG_ACCESS_CHANGED, ""},
19    {NULL, NULL}
20 };
21
22 EVAS_SMART_SUBCLASS_NEW
23   (ELM_CTXPOPUP_SMART_NAME, _elm_ctxpopup, Elm_Ctxpopup_Smart_Class,
24    Elm_Layout_Smart_Class, elm_layout_smart_class_get, _smart_callbacks);
25
26 static Eina_Bool
27 _elm_ctxpopup_smart_translate(Evas_Object *obj)
28 {
29    ELM_CTXPOPUP_DATA_GET(obj, sd);
30    Elm_Ctxpopup_Item *it;
31    Eina_List *l;
32
33    evas_object_hide(obj);
34
35    EINA_LIST_FOREACH(sd->items, l, it)
36      elm_widget_item_translate(it);
37
38    return EINA_TRUE;
39 }
40
41 static Evas_Object *
42 _access_object_get(const Evas_Object *obj, const char* part)
43 {
44    Evas_Object *po, *ao;
45    ELM_CTXPOPUP_DATA_GET(obj, sd);
46
47    po = (Evas_Object *)edje_object_part_object_get(ELM_WIDGET_DATA(sd)->resize_obj, part);
48    ao = evas_object_data_get(po, "_part_access_obj");
49
50    return ao;
51 }
52
53 static Eina_Bool
54 _elm_ctxpopup_smart_focus_next(const Evas_Object *obj,
55                                Elm_Focus_Direction dir,
56                                Evas_Object **next)
57 {
58    Eina_List *items = NULL;
59    Evas_Object *ao;
60
61    ELM_CTXPOPUP_DATA_GET(obj, sd);
62
63    if (!sd)
64      return EINA_FALSE;
65
66    if (_elm_config->access_mode)
67      {
68         ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
69         if (ao) items = eina_list_append(items, ao);
70
71         /* scroller exists when ctxpopup has an item */
72         if (sd->scr)
73            items = eina_list_append(items, sd->scr);
74         else
75            items = eina_list_append(items, sd->box);
76
77         return elm_widget_focus_list_next_get
78                  (obj, items, eina_list_data_get, dir, next);
79      }
80    else
81      {
82         if (!elm_widget_focus_next_get(sd->box, dir, next))
83           {
84              elm_widget_focused_object_clear(sd->box);
85              elm_widget_focus_next_get(sd->box, dir, next);
86              return EINA_TRUE;
87           }
88
89         return elm_widget_focus_list_next_get
90                  (obj, items, eina_list_data_get, dir, next);
91      }
92 }
93
94 static Eina_Bool
95 _elm_ctxpopup_smart_focus_direction(const Evas_Object *obj,
96                                     const Evas_Object *base,
97                                     double degree,
98                                     Evas_Object **direction,
99                                     double *weight)
100 {
101    Eina_Bool ret;
102    Eina_List *l = NULL;
103    void *(*list_data_get)(const Eina_List *list);
104
105    ELM_CTXPOPUP_DATA_GET(obj, sd);
106
107    if (!sd)
108      return EINA_FALSE;
109
110    list_data_get = eina_list_data_get;
111
112    l = eina_list_append(l, sd->box);
113    ret = elm_widget_focus_list_direction_get
114       (obj, base, l, list_data_get, degree, direction, weight);
115    eina_list_free(l);
116
117    return ret;
118 }
119
120 static void
121 _freeze_on_cb(void *data __UNUSED__,
122               Evas_Object *obj,
123               void *event_info __UNUSED__)
124 {
125    ELM_CTXPOPUP_DATA_GET(obj, sd);
126
127    if ((!sd) || (!sd->scr)) return;
128    elm_object_scroll_freeze_push(sd->scr);
129 }
130
131 static void
132 _freeze_off_cb(void *data __UNUSED__,
133                Evas_Object *obj,
134                void *event_info __UNUSED__)
135 {
136    ELM_CTXPOPUP_DATA_GET(obj, sd);
137
138    if ((!sd) || (!sd->scr)) return;
139    elm_object_scroll_freeze_pop(sd->scr);
140 }
141
142 static void
143 _hold_on_cb(void *data __UNUSED__,
144             Evas_Object *obj,
145             void *event_info __UNUSED__)
146 {
147    ELM_CTXPOPUP_DATA_GET(obj, sd);
148
149    if ((!sd) || (!sd->scr)) return;
150    elm_object_scroll_hold_push(sd->scr);
151 }
152
153 static void
154 _hold_off_cb(void *data __UNUSED__,
155              Evas_Object *obj,
156              void *event_info __UNUSED__)
157 {
158    ELM_CTXPOPUP_DATA_GET(obj, sd);
159
160    if ((!sd) || (!sd->scr)) return;
161    elm_object_scroll_hold_pop(sd->scr);
162 }
163
164 static void
165 _x_pos_adjust(Evas_Coord_Point *pos,
166               Evas_Coord_Point *base_size,
167               Evas_Coord_Rectangle *hover_area)
168 {
169    pos->x -= (base_size->x / 2);
170
171    if (pos->x < hover_area->x)
172      pos->x = hover_area->x;
173    else if ((pos->x + base_size->x) > (hover_area->x + hover_area->w))
174      pos->x = (hover_area->x + hover_area->w) - base_size->x;
175
176    if (base_size->x > hover_area->w)
177      base_size->x -= (base_size->x - hover_area->w);
178
179    if (pos->x < hover_area->x)
180      pos->x = hover_area->x;
181 }
182
183 static void
184 _y_pos_adjust(Evas_Coord_Point *pos,
185               Evas_Coord_Point *base_size,
186               Evas_Coord_Rectangle *hover_area)
187 {
188    pos->y -= (base_size->y / 2);
189
190    if (pos->y < hover_area->y)
191      pos->y = hover_area->y;
192    else if ((pos->y + base_size->y) > (hover_area->y + hover_area->h))
193      pos->y = hover_area->y + hover_area->h - base_size->y;
194
195    if (base_size->y > hover_area->h)
196      base_size->y -= (base_size->y - hover_area->h);
197
198    if (pos->y < hover_area->y)
199      pos->y = hover_area->y;
200 }
201
202 static void
203 _item_select_cb(void *data,
204                 Evas_Object *obj __UNUSED__,
205                 void *event_info __UNUSED__)
206 {
207    Elm_Ctxpopup_Item *item = data;
208
209    if (!item) return;
210    if (elm_widget_item_disabled_get(item)) return;
211
212    if (item->func)
213      item->func((void*)item->base.data, WIDGET(item), data);
214 }
215
216 static char *
217 _access_info_cb(void *data, Evas_Object *obj __UNUSED__)
218 {
219    Elm_Ctxpopup_Item *it = (Elm_Ctxpopup_Item *)data;
220    const char *txt = NULL;
221    Evas_Object *icon = NULL;
222
223    if (!it) return NULL;
224
225    txt = it->label;
226    icon = it->icon;
227
228    if (txt) return strdup(txt);
229    if (icon) return strdup(E_("icon"));
230    return NULL;
231 }
232
233 static char *
234 _access_state_cb(void *data, Evas_Object *obj __UNUSED__)
235 {
236    Elm_Ctxpopup_Item *it = (Elm_Ctxpopup_Item *)data;
237    if (!it) return NULL;
238
239    if (it->base.disabled)
240      return strdup(E_("State: Disabled"));
241
242    return NULL;
243 }
244
245 static char *
246 _access_type_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__)
247 {
248    return strdup(E_("Contextual Popup"));
249 }
250
251 static void
252 _access_activate_cb(void *data __UNUSED__,
253                     Evas_Object *part_obj __UNUSED__,
254                     Elm_Object_Item *item)
255 {
256    _item_select_cb(item, NULL, NULL);
257 }
258
259 static void
260 _access_focusable_button_register(Evas_Object *obj, Elm_Ctxpopup_Item *it)
261 {
262    Elm_Access_Info *ai;
263
264    ai = _elm_access_object_get(obj);
265
266    _elm_access_callback_set(ai, ELM_ACCESS_INFO, _access_info_cb, it);
267    _elm_access_callback_set(ai, ELM_ACCESS_STATE, _access_state_cb, it);
268    _elm_access_callback_set(ai, ELM_ACCESS_TYPE, _access_type_cb, NULL);
269    _elm_access_activate_callback_set(ai, _access_activate_cb, it);
270
271    ((Elm_Widget_Item *)it)->access_obj = obj;
272 }
273
274 static void
275 _item_new(Elm_Ctxpopup_Item *item,
276           char *group_name)
277 {
278    ELM_CTXPOPUP_DATA_GET(WIDGET(item), sd);
279    if (!sd) return;
280
281    VIEW(item) = edje_object_add(evas_object_evas_get(sd->box));
282    edje_object_mirrored_set(VIEW(item), elm_widget_mirrored_get(WIDGET(item)));
283    _elm_theme_object_set(WIDGET(item), VIEW(item), "ctxpopup", group_name,
284                          elm_widget_style_get(WIDGET(item)));
285    evas_object_size_hint_align_set(VIEW(item), EVAS_HINT_FILL, EVAS_HINT_FILL);
286    evas_object_show(VIEW(item));
287 }
288
289 static void
290 _item_icon_set(Elm_Ctxpopup_Item *item,
291                Evas_Object *icon)
292 {
293    if (item->icon)
294      evas_object_del(item->icon);
295
296    item->icon = icon;
297    if (!icon) return;
298
299    edje_object_part_swallow(VIEW(item), "elm.swallow.icon", item->icon);
300    edje_object_message_signal_process(VIEW(item));
301 }
302
303 static void
304 _item_label_set(Elm_Ctxpopup_Item *item,
305                 const char *label)
306 {
307    if (!eina_stringshare_replace(&item->label, label))
308      return;
309
310    edje_object_part_text_set(VIEW(item), "elm.text", label);
311    edje_object_message_signal_process(VIEW(item));
312 }
313
314 static Evas_Object *
315 _item_in_focusable_button(Elm_Ctxpopup_Item *item)
316 {
317    Evas_Object *bt;
318
319    bt = elm_button_add(WIDGET(item));
320    elm_object_style_set(bt, "focus");
321    evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
322    elm_object_part_content_set(bt, "elm.swallow.content", VIEW(item));
323    evas_object_smart_callback_add(bt, "clicked", _item_select_cb, item);
324    evas_object_show(bt);
325
326    return bt;
327 }
328
329 static Eina_Bool
330 _item_del_pre_hook(Elm_Object_Item *it)
331 {
332    Elm_Ctxpopup_Item *ctxpopup_it = (Elm_Ctxpopup_Item *)it;
333
334    ELM_CTXPOPUP_DATA_GET(WIDGET(ctxpopup_it), sd);
335    if (!sd) return EINA_FALSE;
336
337    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
338
339    if (ctxpopup_it->icon)
340      evas_object_del(ctxpopup_it->icon);
341    if (VIEW(ctxpopup_it))
342      evas_object_del(VIEW(ctxpopup_it));
343
344    eina_stringshare_del(ctxpopup_it->label);
345    sd->items = eina_list_remove(sd->items, ctxpopup_it);
346
347    if (eina_list_count(sd->items) < 1)
348      {
349         evas_object_hide(WIDGET(ctxpopup_it));
350         return EINA_TRUE;
351      }
352    if (sd->visible) elm_layout_sizing_eval(WIDGET(ctxpopup_it));
353
354    return EINA_TRUE;
355 }
356
357 static void
358 _items_remove(Elm_Ctxpopup_Smart_Data *sd)
359 {
360    Eina_List *elist;
361    Elm_Ctxpopup_Item *item;
362
363    if (!sd->items) return;
364
365    EINA_LIST_FOREACH(sd->items, elist, item)
366      elm_widget_item_del(item);
367
368    sd->items = NULL;
369 }
370
371 static void
372 _scroller_size_reset(Elm_Ctxpopup_Smart_Data *sd)
373 {
374    sd->finished = EINA_FALSE;
375    sd->max_sc_h = -1;
376    sd->max_sc_w = -1;
377 }
378
379 static void
380 _item_sizing_eval(Elm_Ctxpopup_Item *item)
381 {
382    Evas_Coord min_w = -1, min_h = -1, max_w = -1, max_h = -1;
383
384    if (!item) return;
385
386    edje_object_size_min_restricted_calc(VIEW(item), &min_w, &min_h, min_w,
387                                         min_h);
388    evas_object_size_hint_min_set(VIEW(item), min_w, min_h);
389    evas_object_size_hint_max_set(VIEW(item), max_w, max_h);
390 }
391
392 static Elm_Ctxpopup_Direction
393 _base_geometry_calc(Evas_Object *obj,
394                     Evas_Coord_Rectangle *rect)
395 {
396    Elm_Ctxpopup_Direction dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
397    Evas_Coord_Rectangle hover_area;
398    Evas_Coord_Point pos = {0, 0};
399    Evas_Coord_Point arrow_size;
400    Evas_Coord_Point base_size;
401    Evas_Coord_Point max_size;
402    Evas_Coord_Point min_size;
403    Evas_Coord_Point temp;
404    int idx;
405
406    ELM_CTXPOPUP_DATA_GET(obj, sd);
407
408    if (!rect) return ELM_CTXPOPUP_DIRECTION_DOWN;
409
410    edje_object_part_geometry_get
411      (sd->arrow, "ctxpopup_arrow", NULL, NULL, &arrow_size.x, &arrow_size.y);
412    evas_object_resize(sd->arrow, arrow_size.x, arrow_size.y);
413
414    //Initialize Area Rectangle.
415    evas_object_geometry_get
416      (sd->parent, &hover_area.x, &hover_area.y, &hover_area.w,
417      &hover_area.h);
418
419    evas_object_geometry_get(obj, &pos.x, &pos.y, NULL, NULL);
420
421    //recalc the edje
422    edje_object_size_min_calc
423      (ELM_WIDGET_DATA(sd)->resize_obj, &base_size.x, &base_size.y);
424    evas_object_smart_calculate(ELM_WIDGET_DATA(sd)->resize_obj);
425
426    //Limit to Max Size
427    evas_object_size_hint_max_get(obj, &max_size.x, &max_size.y);
428    if ((max_size.x == -1) || (max_size.y == -1))
429      edje_object_size_max_get(sd->layout, &max_size.x, &max_size.y);
430
431    if ((max_size.y > 0) && (base_size.y > max_size.y))
432      base_size.y = max_size.y;
433
434    if ((max_size.x > 0) && (base_size.x > max_size.x))
435      base_size.x = max_size.x;
436
437    //Limit to Min Size
438    evas_object_size_hint_min_get(obj, &min_size.x, &min_size.y);
439    if ((min_size.x == 0) || (min_size.y == 0))
440      edje_object_size_min_get(sd->layout, &min_size.x, &min_size.y);
441
442    if ((min_size.y > 0) && (base_size.y < min_size.y))
443      base_size.y = min_size.y;
444
445    if ((min_size.x > 0) && (base_size.x < min_size.x))
446      base_size.x = min_size.x;
447
448    //Check the Which direction is available.
449    //If find a avaialble direction, it adjusts position and size.
450    for (idx = 0; idx < 4; idx++)
451      {
452         switch (sd->dir_priority[idx])
453           {
454            case ELM_CTXPOPUP_DIRECTION_UNKNOWN:
455
456            case ELM_CTXPOPUP_DIRECTION_UP:
457              temp.y = (pos.y - base_size.y);
458              if ((temp.y - arrow_size.y) < hover_area.y)
459                continue;
460
461              _x_pos_adjust(&pos, &base_size, &hover_area);
462              pos.y -= base_size.y;
463              dir = ELM_CTXPOPUP_DIRECTION_UP;
464              break;
465
466            case ELM_CTXPOPUP_DIRECTION_LEFT:
467              temp.x = (pos.x - base_size.x);
468              if ((temp.x - arrow_size.x) < hover_area.x)
469                continue;
470
471              _y_pos_adjust(&pos, &base_size, &hover_area);
472              pos.x -= base_size.x;
473              dir = ELM_CTXPOPUP_DIRECTION_LEFT;
474              break;
475
476            case ELM_CTXPOPUP_DIRECTION_RIGHT:
477              temp.x = (pos.x + base_size.x);
478              if ((temp.x + arrow_size.x) >
479                  (hover_area.x + hover_area.w))
480                continue;
481
482              _y_pos_adjust(&pos, &base_size, &hover_area);
483              dir = ELM_CTXPOPUP_DIRECTION_RIGHT;
484              break;
485
486            case ELM_CTXPOPUP_DIRECTION_DOWN:
487              temp.y = (pos.y + base_size.y);
488              if ((temp.y + arrow_size.y) >
489                  (hover_area.y + hover_area.h))
490                continue;
491
492              _x_pos_adjust(&pos, &base_size, &hover_area);
493              dir = ELM_CTXPOPUP_DIRECTION_DOWN;
494              break;
495
496            default:
497              continue;
498           }
499         break;
500      }
501
502    //In this case, all directions are invalid because of lack of space.
503    if (idx == 4)
504      {
505         Evas_Coord length[2];
506
507         if (!sd->horizontal)
508           {
509              length[0] = pos.y - hover_area.y;
510              length[1] = (hover_area.y + hover_area.h) - pos.y;
511
512              // ELM_CTXPOPUP_DIRECTION_UP
513              if (length[0] > length[1])
514                {
515                   _x_pos_adjust(&pos, &base_size, &hover_area);
516                   pos.y -= base_size.y;
517                   dir = ELM_CTXPOPUP_DIRECTION_UP;
518                   if (pos.y < (hover_area.y + arrow_size.y))
519                     {
520                        base_size.y -= ((hover_area.y + arrow_size.y) - pos.y);
521                        pos.y = hover_area.y + arrow_size.y;
522                     }
523                }
524              //ELM_CTXPOPUP_DIRECTION_DOWN
525              else
526                {
527                   _x_pos_adjust(&pos, &base_size, &hover_area);
528                   dir = ELM_CTXPOPUP_DIRECTION_DOWN;
529                   if ((pos.y + arrow_size.y + base_size.y) >
530                       (hover_area.y + hover_area.h))
531                     base_size.y -=
532                       ((pos.y + arrow_size.y + base_size.y) -
533                        (hover_area.y + hover_area.h));
534                }
535           }
536         else
537           {
538              length[0] = pos.x - hover_area.x;
539              length[1] = (hover_area.x + hover_area.w) - pos.x;
540
541              //ELM_CTXPOPUP_DIRECTION_LEFT
542              if (length[0] > length[1])
543                {
544                   _y_pos_adjust(&pos, &base_size, &hover_area);
545                   pos.x -= base_size.x;
546                   dir = ELM_CTXPOPUP_DIRECTION_LEFT;
547                   if (pos.x < (hover_area.x + arrow_size.x))
548                     {
549                        base_size.x -= ((hover_area.x + arrow_size.x) - pos.x);
550                        pos.x = hover_area.x + arrow_size.x;
551                     }
552                }
553              //ELM_CTXPOPUP_DIRECTION_RIGHT
554              else
555                {
556                   _y_pos_adjust(&pos, &base_size, &hover_area);
557                   dir = ELM_CTXPOPUP_DIRECTION_RIGHT;
558                   if (pos.x + (arrow_size.x + base_size.x) >
559                       hover_area.x + hover_area.w)
560                     base_size.x -=
561                       ((pos.x + arrow_size.x + base_size.x) -
562                        (hover_area.x + hover_area.w));
563                }
564           }
565      }
566
567    //Final position and size.
568    rect->x = pos.x;
569    rect->y = pos.y;
570    rect->w = base_size.x;
571    rect->h = base_size.y;
572
573    return dir;
574 }
575
576 static void
577 _arrow_update(Evas_Object *obj,
578               Elm_Ctxpopup_Direction dir,
579               Evas_Coord_Rectangle base_size)
580 {
581    Evas_Coord_Rectangle arrow_size;
582    Evas_Coord x, y;
583    double drag;
584    Evas_Coord_Rectangle shadow_left_top, shadow_right_bottom, arrow_padding;
585
586    ELM_CTXPOPUP_DATA_GET(obj, sd);
587
588    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
589    evas_object_geometry_get
590      (sd->arrow, NULL, NULL, &arrow_size.w, &arrow_size.h);
591
592    /* tizen only : since ctxpopup of tizen has shadow, start and end padding of arrow, it should be put together when updating arrow
593     * so there are some differences between open source and tizen */
594    edje_object_part_geometry_get(ELM_WIDGET_DATA(sd)->resize_obj, "frame_shadow_left_top_padding", NULL, NULL, &shadow_left_top.w, &shadow_left_top.h);
595    edje_object_part_geometry_get(ELM_WIDGET_DATA(sd)->resize_obj, "frame_shadow_right_bottom_padding", NULL, NULL, &shadow_right_bottom.w, &shadow_right_bottom.h);
596    edje_object_part_geometry_get(ELM_WIDGET_DATA(sd)->resize_obj, "ctxpopup_frame_left_top", NULL, NULL, &arrow_padding.w, &arrow_padding.h);
597
598    /* arrow is not being kept as sub-object on purpose, here. the
599     * design of the widget does not help with the contrary */
600
601    switch (dir)
602      {
603       case ELM_CTXPOPUP_DIRECTION_RIGHT:
604         edje_object_signal_emit(sd->arrow, "elm,state,left", "elm");
605         edje_object_part_swallow
606            (ELM_WIDGET_DATA(sd)->resize_obj,
607             (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_right" :
608              "elm.swallow.arrow_left"), sd->arrow);
609
610         if (base_size.h > 0)
611           {
612              if (y <= ((arrow_size.h * 0.5) + base_size.y + shadow_left_top.h + arrow_padding.h))
613                y = 0;
614              else if (y >= (base_size.y + base_size.h - ((arrow_size.h * 0.5) + shadow_right_bottom.h + arrow_padding.h)))
615                y = base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2));
616              else
617                y = y - base_size.y - ((arrow_size.h * 0.5) + shadow_left_top.h + arrow_padding.h);
618              drag = (double)(y) / (double)(base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2)));
619              edje_object_part_drag_value_set
620                 (ELM_WIDGET_DATA(sd)->resize_obj,
621                  (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_right" :
622                   "elm.swallow.arrow_left"), 1, drag);
623           }
624         break;
625
626       case ELM_CTXPOPUP_DIRECTION_LEFT:
627         edje_object_signal_emit(sd->arrow, "elm,state,right", "elm");
628         edje_object_part_swallow
629            (ELM_WIDGET_DATA(sd)->resize_obj,
630             (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_left" :
631              "elm.swallow.arrow_right"), sd->arrow);
632
633         if (base_size.h > 0)
634           {
635              if (y <= ((arrow_size.h * 0.5) + base_size.y + shadow_left_top.h + arrow_padding.h))
636                y = 0;
637              else if (y >= (base_size.y + base_size.h - ((arrow_size.h * 0.5) + shadow_right_bottom.h + arrow_padding.h)))
638                y = base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2));
639              else
640                y = y - base_size.y - ((arrow_size.h * 0.5) + shadow_left_top.h + arrow_padding.h);
641              drag = (double)(y) / (double)(base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2)));
642              edje_object_part_drag_value_set
643                 (ELM_WIDGET_DATA(sd)->resize_obj,
644                  (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_left" :
645                   "elm.swallow.arrow_right"), 0, drag);
646           }
647         break;
648
649       case ELM_CTXPOPUP_DIRECTION_DOWN:
650         edje_object_signal_emit(sd->arrow, "elm,state,top", "elm");
651         edje_object_part_swallow
652           (ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.arrow_up",
653           sd->arrow);
654
655         if (base_size.w > 0)
656           {
657              if (x <= ((arrow_size.w * 0.5) + base_size.x + shadow_left_top.w + arrow_padding.w))
658                x = 0;
659              else if (x >= (base_size.x + base_size.w - ((arrow_size.w * 0.5) + shadow_right_bottom.w + arrow_padding.w)))
660                x = base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2));
661              else
662                x = x - base_size.x - ((arrow_size.w * 0.5) + shadow_left_top.w + arrow_padding.w);
663              drag = (double)(x) / (double)(base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2)));
664              edje_object_part_drag_value_set
665                (ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.arrow_up",
666                drag, 1);
667           }
668         break;
669
670       case ELM_CTXPOPUP_DIRECTION_UP:
671         edje_object_signal_emit(sd->arrow, "elm,state,bottom", "elm");
672         edje_object_part_swallow
673           (ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.arrow_down",
674           sd->arrow);
675
676         if (base_size.w > 0)
677           {
678              if (x <= ((arrow_size.w * 0.5) + base_size.x + shadow_left_top.w + arrow_padding.w))
679                x = 0;
680              else if (x >= (base_size.x + base_size.w - ((arrow_size.w * 0.5) + shadow_right_bottom.w + arrow_padding.w)))
681                x = base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2));
682              else
683                x = x - base_size.x - ((arrow_size.w * 0.5) + shadow_left_top.w + arrow_padding.w);
684              drag = (double)(x) / (double)(base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2)));
685              edje_object_part_drag_value_set
686                (ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.arrow_down",
687                drag, 0);
688           }
689         break;
690
691       default:
692         break;
693      }
694
695    //should be here for getting accurate geometry value
696    evas_object_smart_calculate(ELM_WIDGET_DATA(sd)->resize_obj);
697 }
698
699 static void
700 _show_signals_emit(Evas_Object *obj,
701                    Elm_Ctxpopup_Direction dir)
702 {
703    ELM_CTXPOPUP_DATA_GET(obj, sd);
704
705    if (!sd->visible) return;
706
707    switch (dir)
708      {
709       case ELM_CTXPOPUP_DIRECTION_UP:
710         edje_object_signal_emit(sd->layout, "elm,state,show,up", "elm");
711         break;
712
713       case ELM_CTXPOPUP_DIRECTION_LEFT:
714         edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,show,right" :
715                "elm,state,show,left"), "elm");
716         break;
717
718       case ELM_CTXPOPUP_DIRECTION_RIGHT:
719         edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,show,left" :
720                "elm,state,show,right"), "elm");
721         break;
722
723       case ELM_CTXPOPUP_DIRECTION_DOWN:
724         edje_object_signal_emit(sd->layout, "elm,state,show,down", "elm");
725         break;
726
727       default:
728         break;
729      }
730
731    edje_object_signal_emit(sd->bg, "elm,state,show", "elm");
732 }
733
734 static void
735 _hide_signals_emit(Evas_Object *obj,
736                    Elm_Ctxpopup_Direction dir)
737 {
738    ELM_CTXPOPUP_DATA_GET(obj, sd);
739
740    if (!sd->visible) return;
741
742    switch (dir)
743      {
744       case ELM_CTXPOPUP_DIRECTION_UP:
745         edje_object_signal_emit(sd->layout, "elm,state,hide,up", "elm");
746         break;
747
748       case ELM_CTXPOPUP_DIRECTION_LEFT:
749         edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,hide,right" :
750                "elm,state,hide,left"), "elm");
751         break;
752
753       case ELM_CTXPOPUP_DIRECTION_RIGHT:
754         edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,hide,left" :
755                "elm,state,hide,right"), "elm");
756         break;
757
758       case ELM_CTXPOPUP_DIRECTION_DOWN:
759         edje_object_signal_emit(sd->layout, "elm,state,hide,down", "elm");
760         break;
761
762       default:
763         break;
764      }
765
766    edje_object_signal_emit(sd->bg, "elm,state,hide", "elm");
767 }
768
769 static void
770 _base_shift_by_arrow(Evas_Object *arrow,
771                      Elm_Ctxpopup_Direction dir,
772                      Evas_Coord_Rectangle *rect)
773 {
774    Evas_Coord arrow_w, arrow_h;
775
776    evas_object_geometry_get(arrow, NULL, NULL, &arrow_w, &arrow_h);
777
778    switch (dir)
779      {
780       case ELM_CTXPOPUP_DIRECTION_RIGHT:
781         rect->x += arrow_w;
782         break;
783
784       case ELM_CTXPOPUP_DIRECTION_LEFT:
785         rect->x -= arrow_w;
786         break;
787
788       case ELM_CTXPOPUP_DIRECTION_DOWN:
789         rect->y += arrow_h;
790         break;
791
792       case ELM_CTXPOPUP_DIRECTION_UP:
793         rect->y -= arrow_h;
794         break;
795
796       default:
797          break;
798      }
799 }
800
801 static Eina_Bool
802 _elm_ctxpopup_smart_sub_object_add(Evas_Object *obj,
803                                    Evas_Object *sobj)
804 {
805    Elm_Widget_Smart_Class *parent_parent;
806
807    parent_parent = (Elm_Widget_Smart_Class *)((Evas_Smart_Class *)
808                                               _elm_ctxpopup_parent_sc)->parent;
809
810    /* skipping layout's code, which registers size hint changing
811     * callback on sub objects. a hack to make ctxpopup live, as it is,
812     * on the new classing schema. this widget needs a total
813     * rewrite. */
814    if (!parent_parent->sub_object_add(obj, sobj))
815      return EINA_FALSE;
816
817    return EINA_TRUE;
818 }
819
820 static void
821 _elm_ctxpopup_smart_sizing_eval(Evas_Object *obj)
822 {
823    Eina_List *elist;
824    Elm_Ctxpopup_Item *item;
825    Evas_Coord_Rectangle rect = { 0, 0, 1, 1 };
826    Evas_Coord_Point box_size = { 0, 0 };
827    Evas_Coord_Point _box_size = { 0, 0 };
828    Evas_Coord maxw = 0;
829    const char *str;
830
831    ELM_CTXPOPUP_DATA_GET(obj, sd);
832
833    //Box, Scroller
834    EINA_LIST_FOREACH(sd->items, elist, item)
835      {
836         _item_sizing_eval(item);
837         evas_object_size_hint_min_get(VIEW(item), &_box_size.x, &_box_size.y);
838
839         str = edje_object_data_get(VIEW(item), "item_max_size");
840         if (str)
841           {
842              maxw = atoi(str);
843              maxw = maxw * elm_widget_scale_get(obj) * elm_config_scale_get();
844
845              if (_box_size.x > maxw)
846                {
847                   edje_object_signal_emit(VIEW(item), "elm,state,text,ellipsis", "elm");
848                   edje_object_message_signal_process(VIEW(item));
849                }
850           }
851
852         if (!sd->horizontal)
853           {
854              if (_box_size.x > box_size.x)
855                box_size.x = _box_size.x;
856              if (_box_size.y != -1)
857                box_size.y += _box_size.y;
858           }
859         else
860           {
861              if (_box_size.x != -1)
862                box_size.x += _box_size.x;
863              if (_box_size.y > box_size.y)
864                box_size.y = _box_size.y;
865           }
866      }
867
868 //   if (!sd->arrow) return;  /* simple way to flag "under deletion" */
869
870    if ((!sd->content) && (sd->scr))
871      {
872         evas_object_size_hint_min_set(sd->box, box_size.x, box_size.y);
873         elm_scroller_content_min_limit(sd->scr, EINA_TRUE, EINA_TRUE);
874         evas_object_size_hint_min_set(sd->scr, box_size.x, box_size.y);
875      }
876
877    //Base
878    sd->dir = _base_geometry_calc(obj, &rect);
879
880    if (sd->arrow)
881      {
882         _arrow_update(obj, sd->dir, rect);
883         _base_shift_by_arrow(sd->arrow, sd->dir, &rect);
884      }
885    //resize scroller according to final size
886    if ((!sd->content) && (sd->scr))
887      {
888         elm_scroller_content_min_limit(sd->scr, EINA_FALSE, EINA_FALSE);
889         evas_object_smart_calculate(sd->scr);
890      }
891
892    evas_object_size_hint_min_set(ELM_WIDGET_DATA(sd)->resize_obj, rect.w, rect.h);
893    evas_object_resize(ELM_WIDGET_DATA(sd)->resize_obj, rect.w, rect.h);
894
895    evas_object_move(sd->layout, rect.x, rect.y);
896    evas_object_resize(sd->layout, rect.w, rect.h);
897
898    _show_signals_emit(obj, sd->dir);
899 }
900
901 static void
902 _on_parent_del(void *data,
903                Evas *e __UNUSED__,
904                Evas_Object *obj __UNUSED__,
905                void *event_info __UNUSED__)
906 {
907    evas_object_del(data);
908 }
909
910 static void
911 _on_parent_move(void *data,
912                 Evas *e __UNUSED__,
913                 Evas_Object *obj __UNUSED__,
914                 void *event_info __UNUSED__)
915 {
916    ELM_CTXPOPUP_DATA_GET(data, sd);
917
918
919    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
920
921    if (sd->visible)
922      {
923         _scroller_size_reset(sd);
924         elm_layout_sizing_eval(data);
925      }
926 }
927
928 static void
929 _on_parent_resize(void *data,
930                   Evas *e __UNUSED__,
931                   Evas_Object *obj __UNUSED__,
932                   void *event_info __UNUSED__)
933 {
934    ELM_CTXPOPUP_DATA_GET(data, sd);
935
936    _hide_signals_emit(data, sd->dir);
937
938    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
939
940    evas_object_hide(data);
941    evas_object_smart_callback_call(data, SIG_DISMISSED, NULL);
942 }
943
944 static void
945 _parent_detach(Evas_Object *obj)
946 {
947    ELM_CTXPOPUP_DATA_GET(obj, sd);
948
949    if (!sd->parent) return;
950
951    evas_object_event_callback_del_full
952      (sd->parent, EVAS_CALLBACK_DEL, _on_parent_del, obj);
953    evas_object_event_callback_del_full
954      (sd->parent, EVAS_CALLBACK_MOVE, _on_parent_move, obj);
955    evas_object_event_callback_del_full
956      (sd->parent, EVAS_CALLBACK_RESIZE, _on_parent_resize, obj);
957 }
958
959 static void
960 _on_content_resized(void *data,
961                     Evas *e __UNUSED__,
962                     Evas_Object *obj __UNUSED__,
963                     void *event_info __UNUSED__)
964 {
965    ELM_CTXPOPUP_DATA_GET(data, sd);
966
967    elm_box_recalculate(sd->box);
968    elm_layout_sizing_eval(data);
969 }
970
971 static void
972 _access_outline_activate_cb(void *data,
973                         Evas_Object *part_obj __UNUSED__,
974                         Elm_Object_Item *item __UNUSED__)
975 {
976    evas_object_hide(data);
977    evas_object_smart_callback_call(data, SIG_DISMISSED, NULL);
978 }
979
980 static void
981 _access_obj_process(Evas_Object *obj, Eina_Bool is_access)
982 {
983    Evas_Object *ao;
984    ELM_CTXPOPUP_DATA_GET(obj, sd);
985
986    if (is_access)
987      {
988         ao = _elm_access_edje_object_part_object_register
989                (obj, ELM_WIDGET_DATA(sd)->resize_obj, ACCESS_OUTLINE_PART);
990         _elm_access_text_set(_elm_access_object_get(ao),
991                              ELM_ACCESS_TYPE, E_(OUTLINE_TEXT));
992         _elm_access_activate_callback_set
993           (_elm_access_object_get(ao), _access_outline_activate_cb, obj);
994      }
995    else
996      {
997         _elm_access_edje_object_part_object_unregister
998                (obj, ELM_WIDGET_DATA(sd)->resize_obj, ACCESS_OUTLINE_PART);
999      }
1000 }
1001
1002 static Eina_Bool
1003 _elm_ctxpopup_smart_event(Evas_Object *obj,
1004                           Evas_Object *src __UNUSED__,
1005                           Evas_Callback_Type type,
1006                           void *event_info)
1007 {
1008    Evas_Event_Key_Down *ev = event_info;
1009
1010    ELM_CTXPOPUP_DATA_GET(obj, sd);
1011
1012    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
1013    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
1014    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
1015
1016    if (!strcmp(ev->keyname, "Tab"))
1017      {
1018         if (evas_key_modifier_is_set(ev->modifiers, "Shift"))
1019           elm_widget_focus_cycle(sd->box, ELM_FOCUS_PREVIOUS);
1020         else
1021           elm_widget_focus_cycle(sd->box, ELM_FOCUS_NEXT);
1022         return EINA_TRUE;
1023      }
1024
1025    if (((!strcmp(ev->keyname, "Left")) ||
1026         (!strcmp(ev->keyname, "KP_Left")) ||
1027         (!strcmp(ev->keyname, "Right")) ||
1028         (!strcmp(ev->keyname, "KP_Right")) ||
1029         (!strcmp(ev->keyname, "Up")) ||
1030         (!strcmp(ev->keyname, "KP_Up")) ||
1031         (!strcmp(ev->keyname, "Down")) ||
1032         (!strcmp(ev->keyname, "KP_Down"))) && (!ev->string))
1033      {
1034         double degree = 0.0;
1035
1036         if ((!strcmp(ev->keyname, "Left")) ||
1037             (!strcmp(ev->keyname, "KP_Left")))
1038           degree = 270.0;
1039         else if ((!strcmp(ev->keyname, "Right")) ||
1040                  (!strcmp(ev->keyname, "KP_Right")))
1041           degree = 90.0;
1042         else if ((!strcmp(ev->keyname, "Up")) ||
1043                  (!strcmp(ev->keyname, "KP_Up")))
1044           degree = 0.0;
1045         else if ((!strcmp(ev->keyname, "Down")) ||
1046                  (!strcmp(ev->keyname, "KP_Down")))
1047           degree = 180.0;
1048
1049         elm_widget_focus_direction_go(sd->box, degree);
1050         ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1051         return EINA_TRUE;
1052      }
1053
1054    // TIZEN ONLY : 20130530 : ctxpopup will be dismissed by user
1055    //if (strcmp(ev->keyname, "Escape")) return EINA_FALSE;
1056    return EINA_FALSE;
1057
1058 /*
1059    _hide_signals_emit(obj, sd->dir);
1060
1061    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1062    return EINA_TRUE;
1063 */
1064 }
1065
1066 //FIXME: lost the content size when theme hook is called.
1067 static Eina_Bool
1068 _elm_ctxpopup_smart_theme(Evas_Object *obj)
1069 {
1070    Eina_List *elist;
1071    Elm_Ctxpopup_Item *item;
1072    int idx = 0, orientation = -1;
1073    Eina_Bool rtl;
1074
1075    ELM_CTXPOPUP_DATA_GET(obj, sd);
1076
1077    if (!ELM_WIDGET_CLASS(_elm_ctxpopup_parent_sc)->theme(obj))
1078      return EINA_FALSE;
1079
1080    rtl = elm_widget_mirrored_get(obj);
1081
1082    elm_widget_theme_object_set
1083      (obj, sd->bg, "ctxpopup", "bg", elm_widget_style_get(obj));
1084
1085    if (edje_object_part_exists(elm_layout_edje_get(obj), "elm.swallow.arrow_up") ||
1086     edje_object_part_exists(elm_layout_edje_get(obj), "elm.swallow.arrow_down") ||
1087     edje_object_part_exists(elm_layout_edje_get(obj), "elm.swallow.arrow_left") ||
1088     edje_object_part_exists(elm_layout_edje_get(obj), "elm.swallow.arrow_right"))
1089      {
1090         elm_widget_theme_object_set
1091           (obj, sd->arrow, "ctxpopup", "arrow", elm_widget_style_get(obj));
1092      }
1093    else
1094      {
1095         evas_object_del(sd->arrow);
1096         sd->arrow = NULL;
1097      }
1098
1099    orientation = sd->orientation;
1100    if (orientation == 90 || orientation == 270)
1101      elm_widget_theme_object_set
1102        (obj, sd->layout, "ctxpopup", "layout/landscape", elm_widget_style_get(obj));
1103    else
1104      elm_widget_theme_object_set
1105        (obj, sd->layout, "ctxpopup", "layout", elm_widget_style_get(obj));
1106
1107    //Items
1108    EINA_LIST_FOREACH(sd->items, elist, item)
1109      {
1110         edje_object_mirrored_set(VIEW(item), rtl);
1111
1112         if (item->label && item->icon)
1113           _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1114                                 "icon_text_style_item",
1115                                 elm_widget_style_get(obj));
1116         else if (item->label)
1117           {
1118              if(!sd->horizontal)
1119                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1120                                      "text_style_item",
1121                                      elm_widget_style_get(obj));
1122              else
1123                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1124                                      "text_style_item_horizontal",
1125                                      elm_widget_style_get(obj));
1126           }
1127         else if (item->icon)
1128           _elm_theme_object_set
1129              (obj, VIEW(item), "ctxpopup", "icon_style_item",
1130               elm_widget_style_get(obj));
1131         if (item->label)
1132           edje_object_part_text_set(VIEW(item), "elm.text", item->label);
1133
1134         if (elm_widget_item_disabled_get(item))
1135           edje_object_signal_emit(VIEW(item), "elm,state,disabled", "elm");
1136
1137        /*
1138         *  For separator, if the first item has visible separator,
1139         *  then it should be aligned with edge of the base part.
1140         *  In some cases, it gives improper display. Ex) rounded corner
1141         *  So the first item separator should be invisible.
1142         */
1143         if ((idx++) == 0)
1144           edje_object_signal_emit(VIEW(item), "elm,state,default", "elm");
1145         else
1146           edje_object_signal_emit(VIEW(item), "elm,state,separator", "elm");
1147
1148         edje_object_message_signal_process(VIEW(item));
1149      }
1150
1151    if (evas_object_visible_get(sd->bg))
1152      edje_object_signal_emit(sd->bg, "elm,state,show", "elm");
1153
1154    if (sd->scr)
1155      {
1156         if (!strncmp(elm_object_style_get(obj), "default", strlen("default")))
1157           elm_object_style_set(sd->scr, "ctxpopup");
1158         else
1159           elm_object_style_set(sd->scr, elm_object_style_get(obj));
1160
1161         if (sd->horizontal)
1162           elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
1163         else
1164           elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
1165      }
1166
1167    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1168
1169    if (sd->visible)
1170      {
1171         _scroller_size_reset(sd);
1172         _elm_ctxpopup_smart_sizing_eval(obj);
1173      }
1174
1175    /* access */
1176   if (_elm_config->access_mode) _access_obj_process(obj, EINA_TRUE);
1177
1178    return EINA_TRUE;
1179 }
1180
1181 /* kind of a big and tricky override here: an internal box will hold
1182  * the actual content. content aliases won't be of much help here */
1183 static Eina_Bool
1184 _elm_ctxpopup_smart_content_set(Evas_Object *obj,
1185                                 const char *part,
1186                                 Evas_Object *content)
1187 {
1188    Evas_Coord min_w = -1, min_h = -1;
1189
1190    ELM_CTXPOPUP_DATA_GET(obj, sd);
1191
1192    if ((part) && (strcmp(part, "default")))
1193      return ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_set
1194               (obj, part, content);
1195
1196    if (!content) return EINA_FALSE;
1197
1198    if (content == sd->content) return EINA_TRUE;
1199
1200    if (sd->items) elm_ctxpopup_clear(obj);
1201    if (sd->content) evas_object_del(sd->content);
1202
1203    //box
1204    if (!sd->box)
1205      {
1206         sd->box = elm_box_add(obj);
1207         evas_object_size_hint_weight_set(sd->box, EVAS_HINT_EXPAND,
1208                                          EVAS_HINT_EXPAND);
1209         evas_object_event_callback_add
1210            (sd->box, EVAS_CALLBACK_RESIZE, _on_content_resized, obj);
1211         ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_set
1212            (obj, "elm.swallow.content", sd->box);
1213      }
1214
1215    evas_object_size_hint_weight_set
1216      (content, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1217    evas_object_size_hint_fill_set
1218      (content, EVAS_HINT_FILL, EVAS_HINT_FILL);
1219
1220    /* since it's going to be a box content, not a layout's... */
1221    evas_object_show(content);
1222
1223    evas_object_size_hint_min_get(content, &min_w, &min_h);
1224    evas_object_size_hint_min_set(sd->box, min_w, min_h);
1225    elm_box_pack_end(sd->box, content);
1226
1227    sd->content = content;
1228    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1229
1230    if (sd->visible) elm_layout_sizing_eval(obj);
1231
1232    return EINA_TRUE;
1233 }
1234
1235 static Evas_Object *
1236 _elm_ctxpopup_smart_content_get(const Evas_Object *obj,
1237                                 const char *part)
1238 {
1239    ELM_CTXPOPUP_DATA_GET(obj, sd);
1240
1241    if ((part) && (strcmp(part, "default")))
1242      return ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_get
1243               (obj, part);
1244
1245    return sd->content;
1246 }
1247
1248 static Evas_Object *
1249 _elm_ctxpopup_smart_content_unset(Evas_Object *obj,
1250                                   const char *part)
1251 {
1252    Evas_Object *content;
1253
1254    ELM_CTXPOPUP_DATA_GET(obj, sd);
1255
1256    if ((part) && (strcmp(part, "default")))
1257      return ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_unset
1258               (obj, part);
1259
1260    content = sd->content;
1261    if (!content) return NULL;
1262
1263    evas_object_del(sd->box);
1264    sd->box = NULL;
1265    sd->content = NULL;
1266    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1267
1268    if (sd->visible) elm_layout_sizing_eval(obj);
1269
1270    return content;
1271 }
1272
1273 static void
1274 _item_text_set_hook(Elm_Object_Item *it,
1275                     const char *part,
1276                     const char *label)
1277 {
1278    Elm_Ctxpopup_Item *ctxpopup_it;
1279
1280    if ((part) && (strcmp(part, "default"))) return;
1281
1282    ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1283
1284    _item_label_set(ctxpopup_it, label);
1285 }
1286
1287 static const char *
1288 _item_text_get_hook(const Elm_Object_Item *it,
1289                     const char *part)
1290 {
1291    Elm_Ctxpopup_Item *ctxpopup_it;
1292
1293    if (part && strcmp(part, "default")) return NULL;
1294
1295    ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1296    return ctxpopup_it->label;
1297 }
1298
1299 static void
1300 _item_content_set_hook(Elm_Object_Item *it,
1301                        const char *part,
1302                        Evas_Object *content)
1303 {
1304    Elm_Ctxpopup_Item *ctxpopup_it;
1305
1306    if ((part) && (strcmp(part, "icon"))) return;
1307
1308    ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1309
1310    ELM_CTXPOPUP_DATA_GET(WIDGET(ctxpopup_it), sd);
1311
1312    _item_icon_set(ctxpopup_it, content);
1313    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1314
1315    if (sd->visible)
1316      {
1317         _scroller_size_reset(sd);
1318         _elm_ctxpopup_smart_sizing_eval(WIDGET(ctxpopup_it));
1319      }
1320 }
1321
1322 static Evas_Object *
1323 _item_content_get_hook(const Elm_Object_Item *it,
1324                        const char *part)
1325 {
1326    Elm_Ctxpopup_Item *ctxpopup_it;
1327
1328    if (part && strcmp(part, "icon")) return NULL;
1329
1330    ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1331    return ctxpopup_it->icon;
1332 }
1333
1334 static void
1335 _item_disable_hook(Elm_Object_Item *it)
1336 {
1337    Elm_Ctxpopup_Item *ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1338
1339    ELM_CTXPOPUP_DATA_GET(WIDGET(it), sd);
1340    if (!sd) return;
1341
1342    if (elm_widget_item_disabled_get(it))
1343      edje_object_signal_emit(VIEW(ctxpopup_it), "elm,state,disabled", "elm");
1344    else
1345      edje_object_signal_emit(VIEW(ctxpopup_it), "elm,state,enabled", "elm");
1346 }
1347
1348 static void
1349 _item_signal_emit_hook(Elm_Object_Item *it,
1350                        const char *emission,
1351                        const char *source)
1352 {
1353    Elm_Ctxpopup_Item *ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1354
1355    edje_object_signal_emit(VIEW(ctxpopup_it), emission, source);
1356 }
1357
1358 static void
1359 _bg_clicked_cb(void *data,
1360                Evas_Object *obj __UNUSED__,
1361                const char *emission __UNUSED__,
1362                const char *source __UNUSED__)
1363 {
1364    ELM_CTXPOPUP_DATA_GET(data, sd);
1365
1366    _hide_signals_emit(data, sd->dir);
1367 }
1368
1369 static void
1370 _on_show(void *data __UNUSED__,
1371          Evas *e __UNUSED__,
1372          Evas_Object *obj,
1373          void *event_info __UNUSED__)
1374 {
1375    Eina_List *elist;
1376    Elm_Ctxpopup_Item *item;
1377    int idx = 0;
1378
1379    ELM_CTXPOPUP_DATA_GET(obj, sd);
1380    ELM_WIDGET_DATA_GET(obj, wsd);
1381
1382    if ((!sd->items) && (!sd->content)) return;
1383
1384    sd->visible = EINA_TRUE;
1385
1386    evas_object_show(sd->bg);
1387    if (sd->arrow)
1388      evas_object_show(sd->arrow);
1389    evas_object_show(sd->layout);
1390
1391    edje_object_signal_emit(sd->bg, "elm,state,show", "elm");
1392    elm_layout_signal_emit(obj, "elm,state,show", "elm");
1393
1394    if (wsd->orient_mode == 90 || wsd->orient_mode == 270)
1395      elm_widget_theme_object_set
1396        (obj, sd->layout, "ctxpopup", "layout/landscape", elm_widget_style_get(obj));
1397    else
1398      elm_widget_theme_object_set
1399        (obj, sd->layout, "ctxpopup", "layout", elm_widget_style_get(obj));
1400
1401    EINA_LIST_FOREACH(sd->items, elist, item)
1402      {
1403         if (item->label && !item->icon)
1404           {
1405              if(!sd->horizontal)
1406                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1407                                      "text_style_item",
1408                                      elm_widget_style_get(obj));
1409              else
1410                _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1411                                      "text_style_item_horizontal",
1412                                      elm_widget_style_get(obj));
1413           }
1414
1415         if (idx++ == 0)
1416           edje_object_signal_emit(VIEW(item), "elm,state,default", "elm");
1417         else
1418           edje_object_signal_emit(VIEW(item), "elm,state,separator", "elm");
1419      }
1420
1421    elm_layout_sizing_eval(obj);
1422
1423    elm_object_focus_set(obj, EINA_TRUE);
1424 }
1425
1426 static void
1427 _on_hide(void *data __UNUSED__,
1428          Evas *e __UNUSED__,
1429          Evas_Object *obj,
1430          void *event_info __UNUSED__)
1431 {
1432    ELM_CTXPOPUP_DATA_GET(obj, sd);
1433
1434    if (!sd->visible) return;
1435
1436    evas_object_hide(sd->bg);
1437    if (sd->arrow)
1438      evas_object_hide(sd->arrow);
1439    evas_object_hide(sd->layout);
1440
1441    _scroller_size_reset(sd);
1442
1443    sd->visible = EINA_FALSE;
1444 }
1445
1446 static void
1447 _on_move(void *data __UNUSED__,
1448          Evas *e __UNUSED__,
1449          Evas_Object *obj,
1450          void *event_info __UNUSED__)
1451 {
1452    ELM_CTXPOPUP_DATA_GET(obj, sd);
1453
1454    if (sd->visible && sd->arrow) evas_object_show(sd->arrow);
1455
1456    _scroller_size_reset(sd);
1457    _elm_ctxpopup_smart_sizing_eval(obj);
1458 }
1459
1460 static void
1461 _hide_finished_cb(void *data,
1462                   Evas_Object *obj __UNUSED__,
1463                   const char *emission __UNUSED__,
1464                   const char *source __UNUSED__)
1465 {
1466    evas_object_hide(data);
1467    evas_object_smart_callback_call(data, SIG_DISMISSED, NULL);
1468 }
1469
1470 static void
1471 _scroller_resize(void *data, Evas *e __UNUSED__,
1472                  Evas_Object *obj,
1473                  void *event_info __UNUSED__)
1474 {
1475    Evas_Coord w, h;
1476
1477    ELM_CTXPOPUP_DATA_GET(data, sd);
1478    if (!sd) return;
1479    if (!sd->visible) return;
1480    if (sd->finished) return;
1481
1482    evas_object_geometry_get(obj, 0, 0, &w, &h);
1483
1484    if (w != 0 && h != 0)
1485      {
1486         if ((w <= sd->max_sc_w) && (h <= sd->max_sc_h))
1487           {
1488              _elm_ctxpopup_smart_sizing_eval(data);
1489              sd->finished = EINA_TRUE;
1490              return;
1491           }
1492      }
1493
1494    if (sd->max_sc_w < w)
1495      sd->max_sc_w = w;
1496    if (sd->max_sc_h < h)
1497      sd->max_sc_h = h;
1498
1499    _elm_ctxpopup_smart_sizing_eval(data);
1500 }
1501
1502 static void
1503 _ctxpopup_restack_cb(void *data __UNUSED__,
1504                      Evas *e __UNUSED__,
1505                      Evas_Object *obj,
1506                      void *event_info __UNUSED__)
1507 {
1508    ELM_CTXPOPUP_DATA_GET(obj, sd);
1509    evas_object_stack_below(sd->bg, obj);
1510    evas_object_stack_below(sd->layout, obj);
1511 }
1512
1513 static void
1514 _list_del(Elm_Ctxpopup_Smart_Data *sd)
1515 {
1516    if (!sd->scr) return;
1517
1518    edje_object_part_unswallow(ELM_WIDGET_DATA(sd)->resize_obj, sd->scr);
1519    evas_object_del(sd->scr);
1520    sd->scr = NULL;
1521    evas_object_del(sd->box);
1522    sd->box = NULL;
1523 }
1524
1525 static void
1526 _list_new(Evas_Object *obj)
1527 {
1528    ELM_CTXPOPUP_DATA_GET(obj, sd);
1529    if (!sd) return;
1530
1531    //scroller
1532    sd->scr = elm_scroller_add(obj);
1533    elm_object_style_set(sd->scr, "ctxpopup");
1534    evas_object_size_hint_align_set(sd->scr, EVAS_HINT_FILL, EVAS_HINT_FILL);
1535
1536    if (sd->horizontal)
1537      elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
1538    else
1539      elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
1540
1541    evas_object_event_callback_add(sd->scr, EVAS_CALLBACK_RESIZE,
1542                                   _scroller_resize, obj);
1543    edje_object_part_swallow(ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.content", sd->scr);
1544
1545    //box
1546    if (!sd->box)
1547      {
1548         sd->box = elm_box_add(obj);
1549         evas_object_size_hint_weight_set(sd->box, EVAS_HINT_EXPAND,
1550                                          EVAS_HINT_EXPAND);
1551         evas_object_event_callback_add
1552            (sd->box, EVAS_CALLBACK_RESIZE, _on_content_resized, obj);
1553         ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_set
1554            (obj, "elm.swallow.content", sd->box);
1555      }
1556
1557    elm_object_content_set(sd->scr, sd->box);
1558    elm_ctxpopup_horizontal_set(obj, sd->horizontal);
1559 }
1560
1561 static Eina_Bool
1562 _elm_ctxpopup_smart_disable(Evas_Object *obj)
1563 {
1564    Eina_List *l;
1565    Elm_Object_Item *it;
1566
1567    ELM_CTXPOPUP_DATA_GET(obj, sd);
1568
1569    if (!ELM_WIDGET_CLASS(_elm_ctxpopup_parent_sc)->disable(obj))
1570      return EINA_FALSE;
1571
1572    EINA_LIST_FOREACH(sd->items, l, it)
1573      elm_object_item_disabled_set(it, elm_widget_disabled_get(obj));
1574
1575    return EINA_TRUE;
1576 }
1577
1578 static void
1579 _elm_ctxpopup_smart_add(Evas_Object *obj)
1580 {
1581    EVAS_SMART_DATA_ALLOC(obj, Elm_Ctxpopup_Smart_Data);
1582    ELM_CTXPOPUP_DATA_GET(obj, sd);
1583
1584    ELM_WIDGET_CLASS(_elm_ctxpopup_parent_sc)->base.add(obj);
1585
1586    elm_layout_theme_set(obj, "ctxpopup", "base", elm_widget_style_get(obj));
1587    elm_layout_signal_callback_add
1588      (obj, "elm,action,hide,finished", "", _hide_finished_cb, obj);
1589
1590    //Background
1591    priv->bg = edje_object_add(evas_object_evas_get(obj));
1592    elm_widget_theme_object_set(obj, priv->bg, "ctxpopup", "bg", "default");
1593    edje_object_signal_callback_add
1594      (priv->bg, "elm,action,click", "", _bg_clicked_cb, obj);
1595
1596    evas_object_stack_below(priv->bg, obj);
1597
1598    //Arrow
1599    priv->arrow = edje_object_add(evas_object_evas_get(obj));
1600    elm_widget_theme_object_set
1601      (obj, priv->arrow, "ctxpopup", "arrow", "default");
1602
1603    priv->dir_priority[0] = ELM_CTXPOPUP_DIRECTION_UP;
1604    priv->dir_priority[1] = ELM_CTXPOPUP_DIRECTION_LEFT;
1605    priv->dir_priority[2] = ELM_CTXPOPUP_DIRECTION_RIGHT;
1606    priv->dir_priority[3] = ELM_CTXPOPUP_DIRECTION_DOWN;
1607    priv->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1608
1609    evas_object_event_callback_add
1610       (obj, EVAS_CALLBACK_RESTACK, _ctxpopup_restack_cb, obj);
1611
1612    evas_object_smart_callback_add
1613       (obj, "scroll-freeze-on", _freeze_on_cb, obj);
1614    evas_object_smart_callback_add
1615       (obj, "scroll-freeze-off", _freeze_off_cb, obj);
1616    evas_object_smart_callback_add
1617       (obj, "scroll-hold-on", _hold_on_cb, obj);
1618    evas_object_smart_callback_add
1619       (obj, "scroll-hold-off", _hold_off_cb, obj);
1620
1621    priv->box = elm_box_add(obj);
1622    evas_object_size_hint_weight_set
1623      (priv->box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1624
1625    evas_object_event_callback_add
1626      (priv->box, EVAS_CALLBACK_RESIZE, _on_content_resized, obj);
1627
1628    /* box will be our content placeholder, thus the parent's version call */
1629    ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_set
1630      (obj, "elm.swallow.content", priv->box);
1631
1632    priv->layout = edje_object_add(evas_object_evas_get(obj));
1633    elm_widget_theme_object_set(obj, priv->layout, "ctxpopup", "layout", "default");
1634
1635    edje_object_signal_callback_add
1636      (priv->layout, "elm,action,hide,finished", "", _hide_finished_cb, obj);
1637    edje_object_part_swallow(priv->layout, "swallow", ELM_WIDGET_DATA(sd)->resize_obj);
1638    evas_object_size_hint_weight_set
1639      (priv->layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1640
1641    evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _on_show, NULL);
1642    evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _on_hide, NULL);
1643    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _on_move, NULL);
1644
1645    elm_widget_can_focus_set(obj, EINA_TRUE);
1646
1647    /* access */
1648    if (_elm_config->access_mode) _access_obj_process(obj, EINA_TRUE);
1649 }
1650
1651 static void
1652 _elm_ctxpopup_smart_del(Evas_Object *obj)
1653 {
1654    ELM_CTXPOPUP_DATA_GET(obj, sd);
1655
1656    evas_object_event_callback_del_full
1657      (sd->box, EVAS_CALLBACK_RESIZE, _on_content_resized, obj);
1658    _parent_detach(obj);
1659
1660    elm_ctxpopup_clear(obj);
1661
1662    if (sd->arrow)
1663      {
1664         evas_object_del(sd->arrow);
1665         sd->arrow = NULL; /* stops _sizing_eval() from going on on deletion */
1666      }
1667
1668    evas_object_del(sd->bg);
1669    sd->bg = NULL;
1670
1671    evas_object_del(sd->layout);
1672    sd->layout = NULL;
1673
1674    ELM_WIDGET_CLASS(_elm_ctxpopup_parent_sc)->base.del(obj);
1675 }
1676
1677 static void
1678 _elm_ctxpopup_smart_parent_set(Evas_Object *obj,
1679                                Evas_Object *parent)
1680 {
1681    //default parent is to be hover parent
1682    elm_ctxpopup_hover_parent_set(obj, parent);
1683 }
1684
1685 static void
1686 _elm_ctxpopup_smart_access(Evas_Object *obj, Eina_Bool is_access)
1687 {
1688    ELM_CTXPOPUP_CHECK(obj);
1689
1690    _access_obj_process(obj, is_access);
1691
1692    evas_object_smart_callback_call(obj, SIG_ACCESS_CHANGED, NULL);
1693 }
1694
1695 static void
1696 _elm_ctxpopup_smart_set_user(Elm_Ctxpopup_Smart_Class *sc)
1697 {
1698    ELM_WIDGET_CLASS(sc)->base.add = _elm_ctxpopup_smart_add;
1699    ELM_WIDGET_CLASS(sc)->base.del = _elm_ctxpopup_smart_del;
1700
1701    ELM_WIDGET_CLASS(sc)->parent_set = _elm_ctxpopup_smart_parent_set;
1702    ELM_WIDGET_CLASS(sc)->disable = _elm_ctxpopup_smart_disable;
1703    ELM_WIDGET_CLASS(sc)->event = _elm_ctxpopup_smart_event;
1704    ELM_WIDGET_CLASS(sc)->theme = _elm_ctxpopup_smart_theme;
1705    ELM_WIDGET_CLASS(sc)->translate = _elm_ctxpopup_smart_translate;
1706    ELM_WIDGET_CLASS(sc)->sub_object_add = _elm_ctxpopup_smart_sub_object_add;
1707    ELM_WIDGET_CLASS(sc)->focus_next = _elm_ctxpopup_smart_focus_next;
1708    ELM_WIDGET_CLASS(sc)->focus_direction = _elm_ctxpopup_smart_focus_direction;
1709
1710    ELM_CONTAINER_CLASS(sc)->content_get = _elm_ctxpopup_smart_content_get;
1711    ELM_CONTAINER_CLASS(sc)->content_set = _elm_ctxpopup_smart_content_set;
1712    ELM_CONTAINER_CLASS(sc)->content_unset = _elm_ctxpopup_smart_content_unset;
1713
1714    ELM_LAYOUT_CLASS(sc)->sizing_eval = _elm_ctxpopup_smart_sizing_eval;
1715
1716    ELM_WIDGET_CLASS(sc)->access = _elm_ctxpopup_smart_access;
1717 }
1718
1719 EAPI const Elm_Ctxpopup_Smart_Class *
1720 elm_ctxpopup_smart_class_get(void)
1721 {
1722    static Elm_Ctxpopup_Smart_Class _sc =
1723      ELM_CTXPOPUP_SMART_CLASS_INIT_NAME_VERSION(ELM_CTXPOPUP_SMART_NAME);
1724    static const Elm_Ctxpopup_Smart_Class *class = NULL;
1725    Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
1726
1727    if (class)
1728      return class;
1729
1730    _elm_ctxpopup_smart_set(&_sc);
1731    esc->callbacks = _smart_callbacks;
1732    class = &_sc;
1733
1734    return class;
1735 }
1736
1737 EAPI Evas_Object *
1738 elm_ctxpopup_add(Evas_Object *parent)
1739 {
1740    Evas_Object *obj;
1741
1742    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1743
1744    obj = elm_widget_add(_elm_ctxpopup_smart_class_new(), parent);
1745    if (!obj) return NULL;
1746
1747    if (!elm_widget_sub_object_add(parent, obj))
1748      ERR("could not add %p as sub object of %p", obj, parent);
1749
1750    /* access: parent could be any object such as elm_list which does
1751       not know elc_ctxpopup as its child object in the focus_next(); */
1752    ELM_WIDGET_DATA_GET(obj, sd);
1753    ELM_CTXPOPUP_DATA_GET(obj, sd1);
1754
1755    sd->highlight_root = EINA_TRUE;
1756    sd1->orientation = sd->orient_mode;
1757
1758    _elm_widget_orient_signal_emit(obj);
1759
1760    if (sd1->orientation == 90 || sd1->orientation == 270)
1761      elm_widget_theme_object_set
1762        (obj, sd1->layout, "ctxpopup", "layout/landscape", elm_widget_style_get(obj));
1763    else
1764      elm_widget_theme_object_set
1765        (obj, sd1->layout, "ctxpopup", "layout", elm_widget_style_get(obj));
1766
1767    return obj;
1768 }
1769
1770 EAPI void
1771 elm_ctxpopup_hover_parent_set(Evas_Object *obj,
1772                               Evas_Object *parent)
1773 {
1774    Evas_Coord x, y, w, h;
1775
1776    ELM_CTXPOPUP_CHECK(obj);
1777    ELM_CTXPOPUP_DATA_GET(obj, sd);
1778
1779    if (!parent) return;
1780
1781    _parent_detach(obj);
1782
1783    evas_object_event_callback_add
1784      (parent, EVAS_CALLBACK_DEL, _on_parent_del, obj);
1785    evas_object_event_callback_add
1786      (parent, EVAS_CALLBACK_MOVE, _on_parent_move, obj);
1787    evas_object_event_callback_add
1788      (parent, EVAS_CALLBACK_RESIZE, _on_parent_resize, obj);
1789
1790    sd->parent = parent;
1791
1792    //Update Background
1793    evas_object_geometry_get(parent, &x, &y, &w, &h);
1794    evas_object_move(sd->bg, x, y);
1795    evas_object_resize(sd->bg, w, h);
1796
1797    if (sd->visible) elm_layout_sizing_eval(obj);
1798 }
1799
1800 EAPI Evas_Object *
1801 elm_ctxpopup_hover_parent_get(const Evas_Object *obj)
1802 {
1803    ELM_CTXPOPUP_CHECK(obj) NULL;
1804    ELM_CTXPOPUP_DATA_GET(obj, sd);
1805
1806    return sd->parent;
1807 }
1808
1809 EAPI void
1810 elm_ctxpopup_clear(Evas_Object *obj)
1811 {
1812    ELM_CTXPOPUP_CHECK(obj);
1813    ELM_CTXPOPUP_DATA_GET(obj, sd);
1814
1815    _items_remove(sd);
1816    _list_del(sd);
1817    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1818 }
1819
1820 EAPI void
1821 elm_ctxpopup_horizontal_set(Evas_Object *obj,
1822                             Eina_Bool horizontal)
1823 {
1824    Eina_List *elist;
1825    Elm_Ctxpopup_Item *item;
1826    int idx = 0;
1827
1828    ELM_CTXPOPUP_CHECK(obj);
1829    ELM_CTXPOPUP_DATA_GET(obj, sd);
1830
1831    sd->horizontal = !!horizontal;
1832
1833    if (!sd->scr)
1834       return;
1835
1836   if (!horizontal)
1837      {
1838         elm_box_horizontal_set(sd->box, EINA_FALSE);
1839         elm_scroller_bounce_set(sd->scr, EINA_FALSE, EINA_TRUE);
1840      }
1841    else
1842      {
1843         elm_box_horizontal_set(sd->box, EINA_TRUE);
1844         elm_scroller_bounce_set(sd->scr, EINA_TRUE, EINA_FALSE);
1845      }
1846
1847    EINA_LIST_FOREACH(sd->items, elist, item)
1848      {
1849         if (item->label && !item->icon && !horizontal)
1850           _elm_theme_object_set(obj, VIEW(item), "ctxpopup", "text_style_item",
1851                                 elm_widget_style_get(obj));
1852         else if (item->label && !item->icon && horizontal)
1853           _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1854                                 "text_style_item_horizontal",
1855                                 elm_widget_style_get(obj));
1856
1857         if (idx++ == 0)
1858           edje_object_signal_emit(VIEW(item), "elm,state,default", "elm");
1859         else
1860           edje_object_signal_emit(VIEW(item), "elm,state,separator", "elm");
1861
1862         _item_disable_hook((Elm_Object_Item *)item);
1863      }
1864
1865    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1866
1867    if (sd->visible) elm_layout_sizing_eval(obj);
1868 }
1869
1870 EAPI Eina_Bool
1871 elm_ctxpopup_horizontal_get(const Evas_Object *obj)
1872 {
1873    ELM_CTXPOPUP_CHECK(obj) EINA_FALSE;
1874    ELM_CTXPOPUP_DATA_GET(obj, sd);
1875
1876    return sd->horizontal;
1877 }
1878
1879 EAPI Elm_Object_Item *
1880 elm_ctxpopup_item_append(Evas_Object *obj,
1881                          const char *label,
1882                          Evas_Object *icon,
1883                          Evas_Smart_Cb func,
1884                          const void *data)
1885 {
1886    Elm_Ctxpopup_Item *item;
1887    Evas_Object *content, *focus_bt;
1888
1889    ELM_CTXPOPUP_CHECK(obj) NULL;
1890    ELM_CTXPOPUP_DATA_GET(obj, sd);
1891
1892    item = elm_widget_item_new(obj, Elm_Ctxpopup_Item);
1893    if (!item) return NULL;
1894
1895    elm_widget_item_del_pre_hook_set(item, _item_del_pre_hook);
1896    elm_widget_item_disable_hook_set(item, _item_disable_hook);
1897    elm_widget_item_text_set_hook_set(item, _item_text_set_hook);
1898    elm_widget_item_text_get_hook_set(item, _item_text_get_hook);
1899    elm_widget_item_content_set_hook_set(item, _item_content_set_hook);
1900    elm_widget_item_content_get_hook_set(item, _item_content_get_hook);
1901    elm_widget_item_signal_emit_hook_set(item, _item_signal_emit_hook);
1902
1903    //The first item is appended.
1904    content = elm_object_content_unset(obj);
1905    if (content) evas_object_del(content);
1906
1907    if (!sd->items)
1908      _list_new(obj);
1909
1910    item->func = func;
1911    item->base.data = data;
1912
1913    if (icon && label)
1914      _item_new(item, "icon_text_style_item");
1915    else if (label)
1916      {
1917         if (!sd->horizontal)
1918           _item_new(item, "text_style_item");
1919         else
1920           _item_new(item, "text_style_item_horizontal");
1921      }
1922    else
1923      _item_new(item, "icon_style_item");
1924
1925    _item_icon_set(item, icon);
1926    _item_label_set(item, label);
1927    focus_bt = _item_in_focusable_button(item);
1928    elm_box_pack_end(sd->box, focus_bt);
1929    sd->items = eina_list_append(sd->items, item);
1930
1931    sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1932
1933    if (sd->visible)
1934      {
1935         _scroller_size_reset(sd);
1936         _elm_ctxpopup_smart_sizing_eval(obj);
1937      }
1938
1939
1940    if (_elm_config->access_mode) _access_focusable_button_register(focus_bt, item);
1941
1942    return (Elm_Object_Item *)item;
1943 }
1944
1945 EAPI void
1946 elm_ctxpopup_direction_priority_set(Evas_Object *obj,
1947                                     Elm_Ctxpopup_Direction first,
1948                                     Elm_Ctxpopup_Direction second,
1949                                     Elm_Ctxpopup_Direction third,
1950                                     Elm_Ctxpopup_Direction fourth)
1951 {
1952    ELM_CTXPOPUP_CHECK(obj);
1953    ELM_CTXPOPUP_DATA_GET(obj, sd);
1954
1955    sd->dir_priority[0] = first;
1956    sd->dir_priority[1] = second;
1957    sd->dir_priority[2] = third;
1958    sd->dir_priority[3] = fourth;
1959
1960    if (sd->visible) elm_layout_sizing_eval(obj);
1961 }
1962
1963 EAPI void
1964 elm_ctxpopup_direction_priority_get(Evas_Object *obj,
1965                                     Elm_Ctxpopup_Direction *first,
1966                                     Elm_Ctxpopup_Direction *second,
1967                                     Elm_Ctxpopup_Direction *third,
1968                                     Elm_Ctxpopup_Direction *fourth)
1969 {
1970    ELM_CTXPOPUP_CHECK(obj);
1971    ELM_CTXPOPUP_DATA_GET(obj, sd);
1972
1973    if (first) *first = sd->dir_priority[0];
1974    if (second) *second = sd->dir_priority[1];
1975    if (third) *third = sd->dir_priority[2];
1976    if (fourth) *fourth = sd->dir_priority[3];
1977 }
1978
1979 EAPI Elm_Ctxpopup_Direction
1980 elm_ctxpopup_direction_get(const Evas_Object *obj)
1981 {
1982    ELM_CTXPOPUP_CHECK(obj) ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1983    ELM_CTXPOPUP_DATA_GET(obj, sd);
1984
1985    return sd->dir;
1986 }
1987
1988 EAPI void
1989 elm_ctxpopup_dismiss(Evas_Object *obj)
1990 {
1991    ELM_CTXPOPUP_CHECK(obj);
1992    ELM_CTXPOPUP_DATA_GET(obj, sd);
1993
1994    _hide_signals_emit(obj, sd->dir);
1995 }