2 # include "elementary_config.h"
5 #define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED
6 #define ELM_INTERFACE_ATSPI_COMPONENT_PROTECTED
7 #define ELM_INTERFACE_ATSPI_WIDGET_ACTION_PROTECTED
8 #define ELM_WIDGET_ITEM_PROTECTED
10 #include <Elementary.h>
13 #include "elm_widget_ctxpopup.h"
15 #define MY_CLASS ELM_CTXPOPUP_CLASS
17 #define MY_CLASS_NAME "Elm_Ctxpopup"
18 #define MY_CLASS_NAME_LEGACY "elm_ctxpopup"
20 EAPI const char ELM_CTXPOPUP_SMART_NAME[] = "elm_ctxpopup";
22 #define ELM_PRIV_CTXPOPUP_SIGNALS(cmd) \
23 cmd(SIG_DISMISSED, "dismissed", "") \
25 ELM_PRIV_CTXPOPUP_SIGNALS(ELM_PRIV_STATIC_VARIABLE_DECLARE);
27 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
28 ELM_PRIV_CTXPOPUP_SIGNALS(ELM_PRIV_SMART_CALLBACKS_DESC)
29 {SIG_WIDGET_LANG_CHANGED, ""}, /**< handled by elm_widget */
30 {SIG_WIDGET_ACCESS_CHANGED, ""}, /**< handled by elm_widget */
31 {SIG_LAYOUT_FOCUSED, ""}, /**< handled by elm_layout */
32 {SIG_LAYOUT_UNFOCUSED, ""}, /**< handled by elm_layout */
35 #undef ELM_PRIV_CTXPOPUP_SIGNALS
37 #define TTS_STR_MENU_POPUP dgettext(PACKAGE, "IDS_SCR_OPT_MENU_POP_UP_TTS")
38 #define TTS_STR_MENU_CLOSE dgettext(PACKAGE, "IDS_ST_BODY_DOUBLE_TAP_TO_CLOSE_THE_MENU_T_TTS")
40 static const char ACCESS_OUTLINE_PART[] = "access.outline";
42 static void _on_move(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED);
43 static void _item_sizing_eval(Elm_Ctxpopup_Item_Data *item);
44 static Eina_Bool _key_action_escape(Evas_Object *obj, const char *params EINA_UNUSED);
45 //TIZEN ONLY(20161014) : Accessibility: scroll the content when highlight frame goes out of view port
46 static void _content_move_down_cb(void *data, Evas_Object *obj, void *ev EINA_UNUSED);
47 static void _content_move_up_cb(void *data, Evas_Object *obj, void *ev EINA_UNUSED);
50 EOLIAN static Eina_Bool
51 _elm_ctxpopup_elm_widget_translate(Eo *obj, Elm_Ctxpopup_Data *sd)
54 Elm_Ctxpopup_Item_Data *it;
58 evas_object_hide(obj);
59 eo_do(obj, eo_event_callback_call(ELM_CTXPOPUP_EVENT_DISMISSED, NULL));
62 EINA_LIST_FOREACH(sd->items, l, it)
63 eo_do(EO_OBJ(it), elm_wdg_item_translate());
65 eo_do_super(obj, MY_CLASS, elm_obj_widget_translate());
71 _access_object_get(const Evas_Object *obj, const char* part)
75 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
77 po = (Evas_Object *)edje_object_part_object_get(wd->resize_obj, part);
78 ao = evas_object_data_get(po, "_part_access_obj");
83 EOLIAN static Eina_Bool
84 _elm_ctxpopup_elm_widget_focus_next(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd, Elm_Focus_Direction dir, Evas_Object **next, Elm_Object_Item **next_item)
86 Eina_List *items = NULL;
92 if (_elm_config->access_mode)
96 ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
97 if (ao) items = eina_list_append(items, ao);
99 /* scroller exists when ctxpopup has an item */
101 items = eina_list_append(items, sd->scr);
103 items = eina_list_append(items, sd->box);
105 _elm_access_auto_highlight_set(EINA_TRUE);
106 ret = elm_widget_focus_list_next_get
107 (obj, items, eina_list_data_get, dir, next, next_item);
108 _elm_access_auto_highlight_set(EINA_FALSE);
113 elm_widget_focus_next_get(sd->box, dir, next, next_item);
114 if (!*next) *next = (Evas_Object *)obj;
119 EOLIAN static Eina_Bool
120 _elm_ctxpopup_elm_widget_focus_next_manager_is(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *_pd EINA_UNUSED)
125 EOLIAN static Eina_Bool
126 _elm_ctxpopup_elm_widget_focus_direction_manager_is(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *_pd EINA_UNUSED)
131 EOLIAN static Eina_Bool
132 _elm_ctxpopup_elm_widget_focus_direction(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd, const Evas_Object *base, double degree, Evas_Object **direction, Elm_Object_Item **direction_item, double *weight)
135 void *(*list_data_get)(const Eina_List *list);
140 list_data_get = eina_list_data_get;
142 l = eina_list_append(l, sd->box);
144 elm_widget_focus_list_direction_get
145 (obj, base, l, list_data_get, degree, direction, direction_item, weight);
152 _key_action_move(Evas_Object *obj, const char *params)
154 ELM_CTXPOPUP_DATA_GET(obj, sd);
155 const char *dir = params;
157 if (!sd->box) return EINA_FALSE;
159 if (!strcmp(dir, "previous"))
160 elm_widget_focus_cycle(sd->box, ELM_FOCUS_PREVIOUS);
161 else if (!strcmp(dir, "next"))
162 elm_widget_focus_cycle(sd->box, ELM_FOCUS_NEXT);
163 else if (!strcmp(dir, "left"))
164 elm_widget_focus_cycle(sd->box, ELM_FOCUS_LEFT);
165 else if (!strcmp(dir, "right"))
166 elm_widget_focus_cycle(sd->box, ELM_FOCUS_RIGHT);
167 else if (!strcmp(dir, "up"))
168 elm_widget_focus_cycle(sd->box, ELM_FOCUS_UP);
169 else if (!strcmp(dir, "down"))
170 elm_widget_focus_cycle(sd->box, ELM_FOCUS_DOWN);
171 else return EINA_FALSE;
177 _x_pos_adjust(Evas_Coord_Point *pos,
178 Evas_Coord_Point *base_size,
179 Evas_Coord_Rectangle *hover_area)
181 pos->x -= (base_size->x / 2);
183 if (pos->x < hover_area->x)
184 pos->x = hover_area->x;
185 else if ((pos->x + base_size->x) > (hover_area->x + hover_area->w))
186 pos->x = (hover_area->x + hover_area->w) - base_size->x;
188 if (base_size->x > hover_area->w)
189 base_size->x -= (base_size->x - hover_area->w);
191 if (pos->x < hover_area->x)
192 pos->x = hover_area->x;
196 _y_pos_adjust(Evas_Coord_Point *pos,
197 Evas_Coord_Point *base_size,
198 Evas_Coord_Rectangle *hover_area)
200 pos->y -= (base_size->y / 2);
202 if (pos->y < hover_area->y)
203 pos->y = hover_area->y;
204 else if ((pos->y + base_size->y) > (hover_area->y + hover_area->h))
205 pos->y = hover_area->y + hover_area->h - base_size->y;
207 if (base_size->y > hover_area->h)
208 base_size->y -= (base_size->y - hover_area->h);
210 if (pos->y < hover_area->y)
211 pos->y = hover_area->y;
215 _item_select_cb(void *data,
216 Evas_Object *obj EINA_UNUSED,
217 void *event_info EINA_UNUSED)
219 Elm_Ctxpopup_Item_Data *item = data;
223 if (eo_do_ret(EO_OBJ(item), tmp, elm_wdg_item_disabled_get()))
225 if (_elm_config->access_mode)
226 elm_access_say(E_("Disabled"));
230 if (item->wcb.org_func_cb)
231 item->wcb.org_func_cb((void*)item->wcb.org_data, WIDGET(item), EO_OBJ(item));
235 _access_info_cb(void *data, Evas_Object *obj EINA_UNUSED)
237 Elm_Ctxpopup_Item_Data *it = (Elm_Ctxpopup_Item_Data *)data;
238 const char *txt = NULL;
239 Evas_Object *icon = NULL;
241 if (!it) return NULL;
246 if (txt) return strdup(txt);
247 if (icon) return strdup(E_("icon"));
252 _access_state_cb(void *data, Evas_Object *obj EINA_UNUSED)
254 Elm_Ctxpopup_Item_Data *it = (Elm_Ctxpopup_Item_Data *)data;
256 if (!it) return NULL;
258 if (eo_do_ret(EO_OBJ(it), tmp, elm_wdg_item_disabled_get()))
259 return strdup(E_("Disabled"));
265 _access_focusable_button_register(Evas_Object *obj, Elm_Ctxpopup_Item_Data *it)
269 ai = _elm_access_info_get(obj);
271 _elm_access_callback_set(ai, ELM_ACCESS_INFO, _access_info_cb, it);
272 _elm_access_callback_set(ai, ELM_ACCESS_STATE, _access_state_cb, it);
273 _elm_access_callback_set(ai, ELM_ACCESS_TYPE, NULL, NULL);
275 it->base->access_obj = obj;
279 _mouse_down_cb(Elm_Ctxpopup_Item_Data *it,
280 Evas *evas EINA_UNUSED,
281 Evas_Object *obj EINA_UNUSED,
282 Evas_Event_Mouse_Down *ev)
284 ELM_CTXPOPUP_DATA_GET(WIDGET(it), sd);
286 if (ev->button != 1) return;
288 //If counter is not zero, it means all other multi down is not released.
289 if (sd->multi_down != 0) return;
290 sd->mouse_down = EINA_TRUE;
291 //******************** TIZEN Only
292 sd->pressed = EINA_TRUE;
293 //****************************
296 //******************** TIZEN Only
298 _mouse_move_cb(Elm_Ctxpopup_Item_Data *it,
299 Evas *evas EINA_UNUSED,
303 ELM_CTXPOPUP_DATA_GET(WIDGET(it), sd);
304 Evas_Event_Mouse_Move *ev = event_info;
306 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
310 edje_object_signal_emit(obj,"elm,action,unpressed", "elm");
311 sd->pressed = EINA_FALSE;
316 Evas_Coord x, y, w, h;
317 evas_object_geometry_get(obj, &x, &y, &w, &h);
318 if ((sd->pressed) && (ELM_RECTS_POINT_OUT(x, y, w, h, ev->cur.canvas.x, ev->cur.canvas.y)))
320 edje_object_signal_emit(obj,"elm,action,unpressed", "elm");
321 sd->pressed = EINA_FALSE;
325 //****************************
328 _mouse_up_cb(Elm_Ctxpopup_Item_Data *it,
329 Evas *evas EINA_UNUSED,
330 Evas_Object *obj EINA_UNUSED,
331 Evas_Event_Mouse_Up *ev)
333 ELM_CTXPOPUP_DATA_GET(WIDGET(it), sd);
335 if (ev->button != 1) return;
337 if (!sd->mouse_down) return;
338 sd->mouse_down = EINA_FALSE;
339 //******************** TIZEN Only
340 sd->pressed = EINA_FALSE;
341 //****************************
345 _multi_down_cb(void *data,
346 Evas *evas EINA_UNUSED,
347 Evas_Object *obj EINA_UNUSED,
348 void *event_info EINA_UNUSED)
350 Elm_Ctxpopup_Item_Data *it = data;
351 ELM_CTXPOPUP_DATA_GET(WIDGET(it), sd);
353 //Emitting signal to inform edje about multi down event.
354 edje_object_signal_emit(VIEW(it), "elm,action,multi,down", "elm");
359 _multi_up_cb(void *data,
360 Evas *evas EINA_UNUSED,
361 Evas_Object *obj EINA_UNUSED,
362 void *event_info EINA_UNUSED)
364 Elm_Ctxpopup_Item_Data *it = data;
365 ELM_CTXPOPUP_DATA_GET(WIDGET(it), sd);
368 if(sd->multi_down == 0)
370 //Emitting signal to inform edje about last multi up event.
371 edje_object_signal_emit(VIEW(it), "elm,action,multi,up", "elm");
376 _item_new(Elm_Ctxpopup_Item_Data *item,
379 ELM_CTXPOPUP_DATA_GET(WIDGET(item), sd);
382 VIEW(item) = edje_object_add(evas_object_evas_get(sd->box));
383 edje_object_mirrored_set(VIEW(item), elm_widget_mirrored_get(WIDGET(item)));
384 _elm_theme_object_set(WIDGET(item), VIEW(item), "ctxpopup", group_name,
385 elm_widget_style_get(WIDGET(item)));
386 evas_object_size_hint_align_set(VIEW(item), EVAS_HINT_FILL, EVAS_HINT_FILL);
387 evas_object_show(VIEW(item));
389 evas_object_event_callback_add
390 (VIEW(item), EVAS_CALLBACK_MOUSE_DOWN, (Evas_Object_Event_Cb)_mouse_down_cb,
392 //******************** TIZEN Only
393 evas_object_event_callback_add
394 (VIEW(item), EVAS_CALLBACK_MOUSE_MOVE, (Evas_Object_Event_Cb)_mouse_move_cb,
396 //****************************
397 evas_object_event_callback_add
398 (VIEW(item), EVAS_CALLBACK_MOUSE_UP, (Evas_Object_Event_Cb)_mouse_up_cb, item);
400 /*Registering Multi down/up events to ignore mouse down/up events untill all
401 multi down/up events are released.*/
402 evas_object_event_callback_add
403 (VIEW(item), EVAS_CALLBACK_MULTI_DOWN, (Evas_Object_Event_Cb)_multi_down_cb,
405 evas_object_event_callback_add
406 (VIEW(item), EVAS_CALLBACK_MULTI_UP, (Evas_Object_Event_Cb)_multi_up_cb,
411 _item_icon_set(Elm_Ctxpopup_Item_Data *item,
415 evas_object_del(item->icon);
420 edje_object_part_swallow(VIEW(item), "elm.swallow.icon", item->icon);
424 _item_label_set(Elm_Ctxpopup_Item_Data *item,
427 if (!eina_stringshare_replace(&item->label, label))
430 ELM_CTXPOPUP_DATA_GET(WIDGET(item), sd);
432 edje_object_part_text_set(VIEW(item), "elm.text", label);
433 if (sd->visible) _item_sizing_eval(item);
437 _item_in_focusable_button(Elm_Ctxpopup_Item_Data *item)
441 bt = elm_button_add(WIDGET(item));
442 elm_object_style_set(bt, "focus");
443 evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
444 elm_object_part_content_set(bt, "elm.swallow.content", VIEW(item));
445 evas_object_smart_callback_add(bt, "clicked", _item_select_cb, item);
446 evas_object_show(bt);
451 EOLIAN static Eina_Bool
452 _elm_ctxpopup_item_elm_widget_item_del_pre(Eo *eo_item EINA_UNUSED, Elm_Ctxpopup_Item_Data *item)
456 ELM_CTXPOPUP_DATA_GET(WIDGET(item), sd);
457 if (!sd) return EINA_FALSE;
460 elm_box_unpack(sd->box, btn);
461 evas_object_smart_callback_del_full(btn, "clicked", _item_select_cb, item);
462 evas_object_del(btn);
464 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
467 evas_object_del(item->icon);
469 evas_object_del(VIEW(item));
471 eina_stringshare_del(item->label);
472 sd->items = eina_list_remove(sd->items, item);
474 if (eina_list_count(sd->items) < 1)
476 evas_object_hide(WIDGET(item));
479 if (sd->visible) elm_layout_sizing_eval(WIDGET(item));
485 _items_remove(Elm_Ctxpopup_Data *sd)
487 Eina_List *l, *l_next;
488 Elm_Ctxpopup_Item_Data *item;
490 if (!sd->items) return;
492 EINA_LIST_FOREACH_SAFE(sd->items, l, l_next, item)
493 eo_do(EO_OBJ(item), elm_wdg_item_del());
499 _item_sizing_eval(Elm_Ctxpopup_Item_Data *item)
501 Evas_Coord min_w = -1, min_h = -1, max_w = -1, max_h = -1;
505 edje_object_signal_emit(VIEW(item), "elm,state,text,default", "elm");
506 edje_object_message_signal_process(VIEW(item));
507 edje_object_size_min_restricted_calc(VIEW(item), &min_w, &min_h, min_w,
509 evas_object_size_hint_min_set(VIEW(item), min_w, min_h);
510 evas_object_size_hint_max_set(VIEW(item), max_w, max_h);
513 static Elm_Ctxpopup_Direction
514 _base_geometry_calc(Evas_Object *obj,
515 Evas_Coord_Rectangle *rect)
517 Elm_Ctxpopup_Direction dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
518 Evas_Coord_Rectangle hover_area;
519 Evas_Coord_Point pos = {0, 0};
520 Evas_Coord_Point arrow_size;
521 Evas_Coord_Point base_size;
522 Evas_Coord_Point max_size;
523 Evas_Coord_Point min_size;
524 Evas_Coord_Point temp;
528 ELM_CTXPOPUP_DATA_GET(obj, sd);
529 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, ELM_CTXPOPUP_DIRECTION_DOWN);
531 if (!rect) return ELM_CTXPOPUP_DIRECTION_DOWN;
533 edje_object_part_geometry_get
534 (sd->arrow, "ctxpopup_arrow", NULL, NULL, &arrow_size.x, &arrow_size.y);
535 evas_object_resize(sd->arrow, arrow_size.x, arrow_size.y);
537 //Initialize Area Rectangle.
538 evas_object_geometry_get
539 (sd->parent, &hover_area.x, &hover_area.y, &hover_area.w,
542 evas_object_geometry_get(obj, &pos.x, &pos.y, NULL, NULL);
545 edje_object_size_min_calc
546 (wd->resize_obj, &base_size.x, &base_size.y);
547 evas_object_smart_calculate(wd->resize_obj);
550 evas_object_size_hint_max_get(obj, &max_size.x, &max_size.y);
551 if ((max_size.x == -1) || (max_size.y == -1))
553 str = edje_object_data_get(sd->layout, "visible_maxw");
555 max_size.x = (int)(atoi(str)
556 * elm_config_scale_get()
557 * elm_object_scale_get(obj)
558 / edje_object_base_scale_get(sd->layout));
559 str = edje_object_data_get(sd->layout, "visible_maxh");
561 max_size.y = (int)(atoi(str)
562 * elm_config_scale_get()
563 * elm_object_scale_get(obj)
564 / edje_object_base_scale_get(sd->layout));
567 if ((max_size.y > 0) && (base_size.y > max_size.y))
568 base_size.y = max_size.y;
570 if ((max_size.x > 0) && (base_size.x > max_size.x))
571 base_size.x = max_size.x;
574 evas_object_size_hint_min_get(obj, &min_size.x, &min_size.y);
575 if ((min_size.x == 0) || (min_size.y == 0))
576 edje_object_size_min_get(sd->layout, &min_size.x, &min_size.y);
578 if ((min_size.y > 0) && (base_size.y < min_size.y))
579 base_size.y = min_size.y;
581 if ((min_size.x > 0) && (base_size.x < min_size.x))
582 base_size.x = min_size.x;
584 //Check the Which direction is available.
585 //If find a avaialble direction, it adjusts position and size.
586 for (idx = 0; idx < 4; idx++)
588 switch (sd->dir_priority[idx])
590 case ELM_CTXPOPUP_DIRECTION_UNKNOWN:
592 case ELM_CTXPOPUP_DIRECTION_UP:
593 temp.y = (pos.y - base_size.y);
594 if ((temp.y - arrow_size.y) < hover_area.y)
597 _x_pos_adjust(&pos, &base_size, &hover_area);
598 pos.y -= base_size.y;
599 dir = ELM_CTXPOPUP_DIRECTION_UP;
602 case ELM_CTXPOPUP_DIRECTION_LEFT:
603 temp.x = (pos.x - base_size.x);
604 if ((temp.x - arrow_size.x) < hover_area.x)
607 _y_pos_adjust(&pos, &base_size, &hover_area);
608 pos.x -= base_size.x;
609 dir = ELM_CTXPOPUP_DIRECTION_LEFT;
612 case ELM_CTXPOPUP_DIRECTION_RIGHT:
613 temp.x = (pos.x + base_size.x);
614 if ((temp.x + arrow_size.x) >
615 (hover_area.x + hover_area.w))
618 _y_pos_adjust(&pos, &base_size, &hover_area);
619 dir = ELM_CTXPOPUP_DIRECTION_RIGHT;
622 case ELM_CTXPOPUP_DIRECTION_DOWN:
623 temp.y = (pos.y + base_size.y);
624 if ((temp.y + arrow_size.y) >
625 (hover_area.y + hover_area.h))
628 _x_pos_adjust(&pos, &base_size, &hover_area);
629 dir = ELM_CTXPOPUP_DIRECTION_DOWN;
638 //In this case, all directions are invalid because of lack of space.
641 Evas_Coord length[2];
645 length[0] = pos.y - hover_area.y;
646 length[1] = (hover_area.y + hover_area.h) - pos.y;
648 // ELM_CTXPOPUP_DIRECTION_UP
649 if (length[0] > length[1])
651 _x_pos_adjust(&pos, &base_size, &hover_area);
652 pos.y -= base_size.y;
653 dir = ELM_CTXPOPUP_DIRECTION_UP;
654 if (pos.y < (hover_area.y + arrow_size.y))
656 base_size.y -= ((hover_area.y + arrow_size.y) - pos.y);
657 pos.y = hover_area.y + arrow_size.y;
660 //ELM_CTXPOPUP_DIRECTION_DOWN
663 _x_pos_adjust(&pos, &base_size, &hover_area);
664 dir = ELM_CTXPOPUP_DIRECTION_DOWN;
665 if ((pos.y + arrow_size.y + base_size.y) >
666 (hover_area.y + hover_area.h))
668 ((pos.y + arrow_size.y + base_size.y) -
669 (hover_area.y + hover_area.h));
674 length[0] = pos.x - hover_area.x;
675 length[1] = (hover_area.x + hover_area.w) - pos.x;
677 //ELM_CTXPOPUP_DIRECTION_LEFT
678 if (length[0] > length[1])
680 _y_pos_adjust(&pos, &base_size, &hover_area);
681 pos.x -= base_size.x;
682 dir = ELM_CTXPOPUP_DIRECTION_LEFT;
683 if (pos.x < (hover_area.x + arrow_size.x))
685 base_size.x -= ((hover_area.x + arrow_size.x) - pos.x);
686 pos.x = hover_area.x + arrow_size.x;
689 //ELM_CTXPOPUP_DIRECTION_RIGHT
692 _y_pos_adjust(&pos, &base_size, &hover_area);
693 dir = ELM_CTXPOPUP_DIRECTION_RIGHT;
694 if (pos.x + (arrow_size.x + base_size.x) >
695 hover_area.x + hover_area.w)
697 ((pos.x + arrow_size.x + base_size.x) -
698 (hover_area.x + hover_area.w));
703 //Final position and size.
706 rect->w = base_size.x;
707 rect->h = base_size.y;
713 _arrow_update(Evas_Object *obj,
714 Elm_Ctxpopup_Direction dir,
715 Evas_Coord_Rectangle base_size)
717 Evas_Coord_Rectangle arrow_size;
720 Evas_Coord_Rectangle shadow_left_top, shadow_right_bottom, arrow_padding;
722 ELM_CTXPOPUP_DATA_GET(obj, sd);
723 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
725 evas_object_geometry_get(obj, &x, &y, NULL, NULL);
726 evas_object_geometry_get
727 (sd->arrow, NULL, NULL, &arrow_size.w, &arrow_size.h);
729 /* tizen only : since ctxpopup of tizen has shadow, start and end padding of arrow, it should be put together when updating arrow
730 * so there are some differences between open source and tizen */
731 edje_object_part_geometry_get(wd->resize_obj, "frame_shadow_left_top_padding", NULL, NULL, &shadow_left_top.w, &shadow_left_top.h);
732 edje_object_part_geometry_get(wd->resize_obj, "frame_shadow_right_bottom_padding", NULL, NULL, &shadow_right_bottom.w, &shadow_right_bottom.h);
733 edje_object_part_geometry_get(wd->resize_obj, "ctxpopup_frame_left_top", NULL, NULL, &arrow_padding.w, &arrow_padding.h);
735 /* arrow is not being kept as sub-object on purpose, here. the
736 * design of the widget does not help with the contrary */
740 case ELM_CTXPOPUP_DIRECTION_RIGHT:
741 edje_object_signal_emit(sd->arrow, "elm,state,left", "elm");
742 edje_object_part_swallow
744 (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_right" :
745 "elm.swallow.arrow_left"), sd->arrow);
749 if (y <= ((arrow_size.h * 0.5) + base_size.y + shadow_left_top.h + arrow_padding.h))
751 else if (y >= (base_size.y + base_size.h - ((arrow_size.h * 0.5) + shadow_right_bottom.h + arrow_padding.h)))
752 y = base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2));
754 y = y - base_size.y - ((arrow_size.h * 0.5) + shadow_left_top.h + arrow_padding.h);
755 drag = (double)(y) / (double)(base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2)));
756 edje_object_part_drag_value_set
758 (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_right" :
759 "elm.swallow.arrow_left"), 1, drag);
763 case ELM_CTXPOPUP_DIRECTION_LEFT:
764 edje_object_signal_emit(sd->arrow, "elm,state,right", "elm");
765 edje_object_part_swallow
767 (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_left" :
768 "elm.swallow.arrow_right"), sd->arrow);
772 if (y <= ((arrow_size.h * 0.5) + base_size.y + shadow_left_top.h + arrow_padding.h))
774 else if (y >= (base_size.y + base_size.h - ((arrow_size.h * 0.5) + shadow_right_bottom.h + arrow_padding.h)))
775 y = base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2));
777 y = y - base_size.y - ((arrow_size.h * 0.5) + shadow_left_top.h + arrow_padding.h);
778 drag = (double)(y) / (double)(base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2)));
779 edje_object_part_drag_value_set
781 (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_left" :
782 "elm.swallow.arrow_right"), 0, drag);
786 case ELM_CTXPOPUP_DIRECTION_DOWN:
787 edje_object_signal_emit(sd->arrow, "elm,state,top", "elm");
788 edje_object_part_swallow
789 (wd->resize_obj, "elm.swallow.arrow_up",
794 if (x <= ((arrow_size.w * 0.5) + base_size.x + shadow_left_top.w + arrow_padding.w))
796 else if (x >= (base_size.x + base_size.w - ((arrow_size.w * 0.5) + shadow_right_bottom.w + arrow_padding.w)))
797 x = base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2));
799 x = x - base_size.x - ((arrow_size.w * 0.5) + shadow_left_top.w + arrow_padding.w);
800 drag = (double)(x) / (double)(base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2)));
801 edje_object_part_drag_value_set
802 (wd->resize_obj, "elm.swallow.arrow_up",
807 case ELM_CTXPOPUP_DIRECTION_UP:
808 edje_object_signal_emit(sd->arrow, "elm,state,bottom", "elm");
809 edje_object_part_swallow
810 (wd->resize_obj, "elm.swallow.arrow_down",
815 if (x <= ((arrow_size.w * 0.5) + base_size.x + shadow_left_top.w + arrow_padding.w))
817 else if (x >= (base_size.x + base_size.w - ((arrow_size.w * 0.5) + shadow_right_bottom.w + arrow_padding.w)))
818 x = base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2));
820 x = x - base_size.x - ((arrow_size.w * 0.5) + shadow_left_top.w + arrow_padding.w);
821 drag = (double)(x) / (double)(base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2)));
822 edje_object_part_drag_value_set
823 (wd->resize_obj, "elm.swallow.arrow_down",
832 //should be here for getting accurate geometry value
833 evas_object_smart_calculate(wd->resize_obj);
837 _show_signals_emit(Evas_Object *obj,
838 Elm_Ctxpopup_Direction dir)
840 ELM_CTXPOPUP_DATA_GET(obj, sd);
842 if (!sd->visible) return;
846 case ELM_CTXPOPUP_DIRECTION_UP:
847 edje_object_signal_emit(sd->layout, "elm,state,show,up", "elm");
850 case ELM_CTXPOPUP_DIRECTION_LEFT:
851 edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,show,right" :
852 "elm,state,show,left"), "elm");
855 case ELM_CTXPOPUP_DIRECTION_RIGHT:
856 edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,show,left" :
857 "elm,state,show,right"), "elm");
860 case ELM_CTXPOPUP_DIRECTION_DOWN:
861 edje_object_signal_emit(sd->layout, "elm,state,show,down", "elm");
868 edje_object_signal_emit(sd->bg, "elm,state,show", "elm");
872 _hide_signals_emit(Evas_Object *obj,
873 Elm_Ctxpopup_Direction dir)
875 ELM_CTXPOPUP_DATA_GET(obj, sd);
877 if (!sd->visible) return;
881 case ELM_CTXPOPUP_DIRECTION_UP:
882 edje_object_signal_emit(sd->layout, "elm,state,hide,up", "elm");
885 case ELM_CTXPOPUP_DIRECTION_LEFT:
886 edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,hide,right" :
887 "elm,state,hide,left"), "elm");
890 case ELM_CTXPOPUP_DIRECTION_RIGHT:
891 edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,hide,left" :
892 "elm,state,hide,right"), "elm");
895 case ELM_CTXPOPUP_DIRECTION_DOWN:
896 edje_object_signal_emit(sd->layout, "elm,state,hide,down", "elm");
903 edje_object_signal_emit(sd->bg, "elm,state,hide", "elm");
907 _base_shift_by_arrow(Evas_Object *obj,
909 Elm_Ctxpopup_Direction dir,
910 Evas_Coord_Rectangle *rect)
912 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
914 Evas_Coord arrow_w, arrow_h, diff_w, diff_h;
915 Evas_Coord_Rectangle shadow_left_top, shadow_right_bottom;
917 evas_object_geometry_get(arrow, NULL, NULL, &arrow_w, &arrow_h);
918 /* tizen only: since ctxpopup of tizen has shadow parts, start and end padding of arrow, it should be put together when shifting ctxpopup by arrow
919 * so there are some differences between opensource and tizen*/
920 edje_object_part_geometry_get(wd->resize_obj, "frame_shadow_left_top_padding", NULL, NULL, &shadow_left_top.w, &shadow_left_top.h);
921 edje_object_part_geometry_get(wd->resize_obj, "frame_shadow_right_bottom_padding", NULL, NULL, &shadow_right_bottom.w, &shadow_right_bottom.h);
926 case ELM_CTXPOPUP_DIRECTION_RIGHT:
927 diff_w = arrow_w - shadow_right_bottom.w;
931 case ELM_CTXPOPUP_DIRECTION_LEFT:
932 diff_w = arrow_w - shadow_left_top.w;
936 case ELM_CTXPOPUP_DIRECTION_DOWN:
937 diff_h = arrow_h - shadow_left_top.h;
941 case ELM_CTXPOPUP_DIRECTION_UP:
942 diff_h = arrow_h - shadow_right_bottom.h;
951 EOLIAN static Eina_Bool
952 _elm_ctxpopup_elm_layout_sub_object_add_enable(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *_pd EINA_UNUSED)
957 EOLIAN static Eina_Bool
958 _elm_ctxpopup_elm_widget_sub_object_add(Eo *obj, Elm_Ctxpopup_Data *_pd EINA_UNUSED, Evas_Object *sobj)
960 Eina_Bool int_ret = EINA_FALSE;
962 eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_sub_object_add(sobj));
968 _elm_ctxpopup_elm_layout_sizing_eval(Eo *obj, Elm_Ctxpopup_Data *sd)
971 Elm_Ctxpopup_Item_Data *item;
972 Evas_Coord_Rectangle rect = { 0, 0, 1, 1 };
973 Evas_Coord_Point box_size = { 0, 0 };
974 Evas_Coord_Point _box_size = { 0, 0 };
976 Evas_Coord x, y, w, h;
979 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
981 if (!sd->parent || !(sd->items || sd->content)) return;
984 EINA_LIST_FOREACH(sd->items, elist, item)
986 _item_sizing_eval(item);
987 evas_object_size_hint_min_get(VIEW(item), &_box_size.x, &_box_size.y);
989 str = edje_object_data_get(VIEW(item), "item_max_size");
993 maxw = maxw * elm_config_scale_get()
994 * elm_widget_scale_get(obj)
995 / edje_object_base_scale_get(VIEW(item));
997 if (_box_size.x > maxw)
999 edje_object_signal_emit(VIEW(item), "elm,state,text,ellipsis", "elm");
1000 edje_object_message_signal_process(VIEW(item));
1004 if (!sd->horizontal)
1006 if (_box_size.x > box_size.x)
1007 box_size.x = _box_size.x;
1008 if (_box_size.y != -1)
1009 box_size.y += _box_size.y;
1013 if (_box_size.x != -1)
1014 box_size.x += _box_size.x;
1015 if (_box_size.y > box_size.y)
1016 box_size.y = _box_size.y;
1020 // if (!sd->arrow) return; /* simple way to flag "under deletion" */
1022 if ((!sd->content) && (sd->scr))
1024 evas_object_size_hint_min_set(sd->box, box_size.x, box_size.y);
1025 elm_scroller_content_min_limit(sd->scr, EINA_TRUE, EINA_TRUE);
1026 evas_object_size_hint_min_set(sd->scr, box_size.x, box_size.y);
1030 sd->dir = _base_geometry_calc(obj, &rect);
1032 _arrow_update(obj, sd->dir, rect);
1033 _base_shift_by_arrow(obj, sd->arrow, sd->dir, &rect);
1035 //resize scroller according to final size
1036 if ((!sd->content) && (sd->scr))
1038 elm_scroller_content_min_limit(sd->scr, EINA_FALSE, EINA_FALSE);
1039 evas_object_smart_calculate(sd->scr);
1042 evas_object_resize(obj, rect.w, rect.h);
1043 evas_object_size_hint_min_set(wd->resize_obj, rect.w, rect.h);
1045 evas_object_resize(sd->layout, rect.w, rect.h);
1046 evas_object_move(sd->layout, rect.x, rect.y);
1048 evas_object_geometry_get(sd->parent, &x, &y, &w, &h);
1049 evas_object_move(sd->bg, x, y);
1050 evas_object_resize(sd->bg, w, h);
1054 _on_parent_del(void *data,
1055 Evas *e EINA_UNUSED,
1056 Evas_Object *obj EINA_UNUSED,
1057 void *event_info EINA_UNUSED)
1059 evas_object_del(data);
1063 _on_parent_move(void *data,
1064 Evas *e EINA_UNUSED,
1065 Evas_Object *obj EINA_UNUSED,
1066 void *event_info EINA_UNUSED)
1068 ELM_CTXPOPUP_DATA_GET(data, sd);
1071 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1074 elm_layout_sizing_eval(data);
1078 _on_parent_resize(void *data,
1079 Evas *e EINA_UNUSED,
1080 Evas_Object *obj EINA_UNUSED,
1081 void *event_info EINA_UNUSED)
1083 ELM_CTXPOPUP_DATA_GET(data, sd);
1084 ELM_WIDGET_DATA_GET_OR_RETURN(data, wd);
1088 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1090 evas_object_hide(data);
1091 eo_do(data, eo_event_callback_call(ELM_CTXPOPUP_EVENT_DISMISSED, NULL));
1095 if (wd->orient_mode == 90 || wd->orient_mode == 270)
1096 elm_widget_theme_object_set
1097 (data, sd->layout, "ctxpopup", "layout/landscape", elm_widget_style_get(data));
1099 elm_widget_theme_object_set
1100 (data, sd->layout, "ctxpopup", "layout", elm_widget_style_get(data));
1101 edje_object_part_swallow(sd->layout, "swallow", wd->resize_obj);
1104 elm_layout_sizing_eval(data);
1106 _show_signals_emit(data, sd->dir);
1111 _parent_detach(Evas_Object *obj)
1113 ELM_CTXPOPUP_DATA_GET(obj, sd);
1115 if (!sd->parent) return;
1117 evas_object_event_callback_del_full
1118 (sd->parent, EVAS_CALLBACK_DEL, _on_parent_del, obj);
1119 evas_object_event_callback_del_full
1120 (sd->parent, EVAS_CALLBACK_MOVE, _on_parent_move, obj);
1121 evas_object_event_callback_del_full
1122 (sd->parent, EVAS_CALLBACK_RESIZE, _on_parent_resize, obj);
1126 _on_content_resized(void *data,
1127 Evas *e EINA_UNUSED,
1128 Evas_Object *obj EINA_UNUSED,
1129 void *event_info EINA_UNUSED)
1131 elm_layout_sizing_eval(data);
1135 _access_outline_activate_cb(void *data,
1136 Evas_Object *part_obj EINA_UNUSED,
1137 Elm_Object_Item *item EINA_UNUSED)
1139 evas_object_hide(data);
1140 eo_do(data, eo_event_callback_call(ELM_CTXPOPUP_EVENT_DISMISSED, NULL));
1144 _access_obj_process(Evas_Object *obj, Eina_Bool is_access)
1147 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1151 ao = _access_object_get(obj, ACCESS_OUTLINE_PART);
1154 ao = _elm_access_edje_object_part_object_register
1155 (obj, wd->resize_obj, ACCESS_OUTLINE_PART);
1157 const char *style = elm_widget_style_get(obj);
1158 if (!strcmp(style, "more/default"))
1160 elm_access_info_set(ao, ELM_ACCESS_TYPE, TTS_STR_MENU_POPUP);
1161 elm_access_info_set(ao, ELM_ACCESS_CONTEXT_INFO, TTS_STR_MENU_CLOSE);
1165 elm_access_info_set(ao, ELM_ACCESS_TYPE, E_("Contextual popup"));
1166 elm_access_info_set(ao, ELM_ACCESS_CONTEXT_INFO, E_("Double tap to close popup"));
1168 _elm_access_activate_callback_set
1169 (_elm_access_info_get(ao), _access_outline_activate_cb, obj);
1174 _elm_access_edje_object_part_object_unregister
1175 (obj, wd->resize_obj, ACCESS_OUTLINE_PART);
1180 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
1182 ELM_CTXPOPUP_DATA_GET(obj, sd);
1183 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1185 edje_object_mirrored_set(sd->layout, rtl);
1186 edje_object_mirrored_set(sd->arrow, rtl);
1187 edje_object_mirrored_set(wd->resize_obj, rtl);
1190 EOLIAN static Eina_Bool
1191 _elm_ctxpopup_elm_widget_event(Eo *obj, Elm_Ctxpopup_Data *sd, Evas_Object *src EINA_UNUSED, Evas_Callback_Type type, void *event_info)
1193 Evas_Event_Key_Down *ev = event_info;
1195 // TIZEN ONLY(20131221) : When access mode, focused ui is disabled.
1196 if (_elm_config->access_mode) return EINA_FALSE;
1198 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
1199 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
1200 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
1202 //FIXME: for this key event, _elm_ctxpopup_smart_focus_next should be done first
1203 if ((!strcmp(ev->key, "Tab")) ||
1204 (!strcmp(ev->key, "ISO_Left_Tab")))
1207 Evas_Object *target = NULL;
1208 Elm_Object_Item *target_item = NULL;
1209 Elm_Focus_Direction dir;
1211 if (evas_key_modifier_is_set(ev->modifiers, "Control") ||
1212 evas_key_modifier_is_set(ev->modifiers, "Alt"))
1214 if (evas_key_modifier_is_set(ev->modifiers, "Shift"))
1215 dir = ELM_FOCUS_PREVIOUS;
1217 dir = ELM_FOCUS_NEXT;
1219 ret = elm_widget_focus_next_get(sd->box, dir, &target, &target_item);
1220 if (ret) elm_widget_focus_steal(target, target_item);
1222 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1226 if (((!strcmp(ev->key, "Left")) ||
1227 (!strcmp(ev->key, "KP_Left")) ||
1228 (!strcmp(ev->key, "Right")) ||
1229 (!strcmp(ev->key, "KP_Right")) ||
1230 (!strcmp(ev->key, "Up")) ||
1231 (!strcmp(ev->key, "KP_Up")) ||
1232 (!strcmp(ev->key, "Down")) ||
1233 (!strcmp(ev->key, "KP_Down"))) && (!ev->string))
1235 double degree = 0.0;
1237 if ((!strcmp(ev->key, "Left")) ||
1238 (!strcmp(ev->key, "KP_Left")))
1240 else if ((!strcmp(ev->key, "Right")) ||
1241 (!strcmp(ev->key, "KP_Right")))
1243 else if ((!strcmp(ev->key, "Up")) ||
1244 (!strcmp(ev->key, "KP_Up")))
1246 else if ((!strcmp(ev->key, "Down")) ||
1247 (!strcmp(ev->key, "KP_Down")))
1250 elm_widget_focus_direction_go(sd->box, degree);
1251 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1254 else if (((!strcmp(ev->key, "Home")) ||
1255 (!strcmp(ev->key, "KP_Home")) ||
1256 (!strcmp(ev->key, "Prior")) ||
1257 (!strcmp(ev->key, "KP_Prior"))) && (!ev->string))
1259 Elm_Ctxpopup_Item_Data *it = eina_list_data_get(sd->items);
1260 Evas_Object *btn = it->btn;
1261 elm_object_focus_set(btn, EINA_TRUE);
1262 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1265 else if (((!strcmp(ev->key, "End")) ||
1266 (!strcmp(ev->key, "KP_End")) ||
1267 (!strcmp(ev->key, "Next")) ||
1268 (!strcmp(ev->key, "KP_Next"))) && (!ev->string))
1270 Elm_Ctxpopup_Item_Data *it = eina_list_data_get(eina_list_last(sd->items));
1271 Evas_Object *btn = it->btn;
1272 elm_object_focus_set(btn, EINA_TRUE);
1273 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1277 // TIZEN ONLY : 20130530 : ctxpopup will be dismissed by user
1278 //if (strcmp(ev->keyname, "Escape")) return EINA_FALSE;
1282 _hide_signals_emit(obj, sd->dir);
1284 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1289 //FIXME: lost the content size when theme hook is called.
1290 EOLIAN static Elm_Theme_Apply
1291 _elm_ctxpopup_elm_widget_theme_apply(Eo *obj, Elm_Ctxpopup_Data *sd)
1294 Elm_Ctxpopup_Item_Data *item;
1298 Elm_Theme_Apply int_ret = ELM_THEME_APPLY_FAILED;
1300 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, ELM_THEME_APPLY_FAILED);
1302 eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_theme_apply());
1303 if (!int_ret) return ELM_THEME_APPLY_FAILED;
1305 rtl = elm_widget_mirrored_get(obj);
1307 elm_widget_theme_object_set
1308 (obj, sd->bg, "ctxpopup", "bg", elm_widget_style_get(obj));
1310 elm_widget_theme_object_set
1311 (obj, sd->arrow, "ctxpopup", "arrow", elm_widget_style_get(obj));
1313 if (wd->orient_mode == 90 || wd->orient_mode == 270)
1314 elm_widget_theme_object_set
1315 (obj, sd->layout, "ctxpopup", "layout/landscape", elm_widget_style_get(obj));
1317 elm_widget_theme_object_set
1318 (obj, sd->layout, "ctxpopup", "layout", elm_widget_style_get(obj));
1319 edje_object_part_swallow(sd->layout, "swallow", wd->resize_obj);
1321 _mirrored_set(obj, rtl);
1324 EINA_LIST_FOREACH(sd->items, elist, item)
1326 edje_object_mirrored_set(VIEW(item), rtl);
1328 if (item->label && item->icon)
1330 if (!sd->horizontal)
1331 _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1332 "icon_text_style_item",
1333 elm_widget_style_get(obj));
1335 _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1336 "icon_text_style_item_horizontal",
1337 elm_widget_style_get(obj));
1339 else if (item->label)
1341 if (!sd->horizontal)
1342 _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1344 elm_widget_style_get(obj));
1346 _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1347 "text_style_item_horizontal",
1348 elm_widget_style_get(obj));
1350 else if (item->icon)
1352 if (!sd->horizontal)
1353 _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1355 elm_widget_style_get(obj));
1357 _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1358 "icon_style_item_horizontal",
1359 elm_widget_style_get(obj));
1363 edje_object_part_text_set(VIEW(item), "elm.text", item->label);
1365 if (eo_do_ret(EO_OBJ(item), tmp, elm_wdg_item_disabled_get()))
1366 edje_object_signal_emit(VIEW(item), "elm,state,disabled", "elm");
1369 * For separator, if the first item has visible separator,
1370 * then it should be aligned with edge of the base part.
1371 * In some cases, it gives improper display. Ex) rounded corner
1372 * So the first item separator should be invisible.
1375 edje_object_signal_emit(VIEW(item), "elm,state,default", "elm");
1377 edje_object_signal_emit(VIEW(item), "elm,state,separator", "elm");
1379 // reset state of text to be default
1380 edje_object_signal_emit(VIEW(item), "elm,state,text,default", "elm");
1381 edje_object_message_signal_process(VIEW(item));
1384 if (evas_object_visible_get(sd->bg))
1385 edje_object_signal_emit(sd->bg, "elm,state,show", "elm");
1389 elm_layout_theme_set(sd->scr, "scroller", "ctxpopup", elm_widget_style_get(obj));
1392 elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
1394 elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
1397 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1400 elm_layout_sizing_eval(obj);
1403 if (_elm_config->access_mode) _access_obj_process(obj, EINA_TRUE);
1408 /* kind of a big and tricky override here: an internal box will hold
1409 * the actual content. content aliases won't be of much help here */
1410 EOLIAN static Eina_Bool
1411 _elm_ctxpopup_elm_container_content_set(Eo *obj, Elm_Ctxpopup_Data *sd, const char *part, Evas_Object *content)
1413 Evas_Coord min_w = -1, min_h = -1;
1414 Eina_Bool int_ret = EINA_TRUE;
1416 if ((part) && (strcmp(part, "default")))
1418 eo_do_super(obj, MY_CLASS, int_ret = elm_obj_container_content_set(part, content));
1422 if (!content) return EINA_FALSE;
1424 if (content == sd->content) return EINA_TRUE;
1426 if (sd->items) elm_ctxpopup_clear(obj);
1427 if (sd->content) evas_object_del(sd->content);
1429 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
1431 evas_object_event_callback_add
1432 (sd->box, EVAS_CALLBACK_RESIZE, _on_content_resized, obj);
1433 edje_object_part_swallow(wd->resize_obj, "elm.swallow.content", sd->box);
1435 evas_object_size_hint_weight_set
1436 (content, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1437 evas_object_size_hint_fill_set
1438 (content, EVAS_HINT_FILL, EVAS_HINT_FILL);
1440 /* since it's going to be a box content, not a layout's... */
1441 evas_object_show(content);
1443 evas_object_size_hint_min_get(content, &min_w, &min_h);
1444 evas_object_size_hint_min_set(sd->box, min_w, min_h);
1445 elm_box_pack_end(sd->box, content);
1447 sd->content = content;
1448 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1450 if (sd->visible) elm_layout_sizing_eval(obj);
1455 EOLIAN static Evas_Object*
1456 _elm_ctxpopup_elm_container_content_get(Eo *obj, Elm_Ctxpopup_Data *sd, const char *part)
1459 if ((part) && (strcmp(part, "default")))
1461 Evas_Object *ret = NULL;
1462 eo_do_super(obj, MY_CLASS, ret = elm_obj_container_content_get(part));
1469 EOLIAN static Evas_Object*
1470 _elm_ctxpopup_elm_container_content_unset(Eo *obj, Elm_Ctxpopup_Data *sd, const char *part)
1472 Evas_Object *content = NULL;
1474 if ((part) && (strcmp(part, "default")))
1476 eo_do_super(obj, MY_CLASS, content = elm_obj_container_content_unset(part));
1480 content = sd->content;
1481 if (!content) return content;
1483 elm_box_unpack(sd->box, content);
1485 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1487 if (sd->visible) elm_layout_sizing_eval(obj);
1493 _elm_ctxpopup_item_elm_widget_item_part_text_set(Eo *eo_ctxpopup_it EINA_UNUSED,
1494 Elm_Ctxpopup_Item_Data *ctxpopup_it,
1498 if ((part) && (strcmp(part, "default"))) return;
1500 _item_label_set(ctxpopup_it, label);
1503 EOLIAN static const char *
1504 _elm_ctxpopup_item_elm_widget_item_part_text_get(Eo *eo_ctxpopup_it EINA_UNUSED,
1505 Elm_Ctxpopup_Item_Data *ctxpopup_it,
1508 if (part && strcmp(part, "default")) return NULL;
1510 return ctxpopup_it->label;
1514 _elm_ctxpopup_item_elm_widget_item_part_content_set(Eo *eo_ctxpopup_it EINA_UNUSED,
1515 Elm_Ctxpopup_Item_Data *ctxpopup_it,
1517 Evas_Object *content)
1519 if ((part) && (strcmp(part, "icon"))) return;
1521 ELM_CTXPOPUP_DATA_GET(WIDGET(ctxpopup_it), sd);
1523 _item_icon_set(ctxpopup_it, content);
1524 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1527 elm_layout_sizing_eval(WIDGET(ctxpopup_it));
1530 EOLIAN static Evas_Object *
1531 _elm_ctxpopup_item_elm_widget_item_part_content_get(Eo *eo_ctxpopup_it EINA_UNUSED,
1532 Elm_Ctxpopup_Item_Data *ctxpopup_it,
1535 if (part && strcmp(part, "icon")) return NULL;
1537 return ctxpopup_it->icon;
1541 _elm_ctxpopup_item_elm_widget_item_disable(Eo *eo_ctxpopup_it,
1542 Elm_Ctxpopup_Item_Data *ctxpopup_it)
1544 ELM_CTXPOPUP_DATA_GET(WIDGET(ctxpopup_it), sd);
1548 if (eo_do_ret(eo_ctxpopup_it, tmp, elm_wdg_item_disabled_get()))
1549 edje_object_signal_emit(VIEW(ctxpopup_it), "elm,state,disabled", "elm");
1551 edje_object_signal_emit(VIEW(ctxpopup_it), "elm,state,enabled", "elm");
1555 _elm_ctxpopup_item_elm_widget_item_signal_emit(Eo *eo_ctxpopup_it EINA_UNUSED,
1556 Elm_Ctxpopup_Item_Data *ctxpopup_it,
1557 const char *emission,
1560 edje_object_signal_emit(VIEW(ctxpopup_it), emission, source);
1564 _elm_ctxpopup_item_elm_widget_item_style_set(Eo *eo_item EINA_UNUSED,
1565 Elm_Ctxpopup_Item_Data *item,
1568 ELM_CTXPOPUP_DATA_GET(WIDGET(item), sd);
1570 if (item->icon && item->label)
1573 _elm_theme_object_set(WIDGET(item), VIEW(item), "ctxpopup", "icon_text_style_item_horizontal", style);
1575 _elm_theme_object_set(WIDGET(item), VIEW(item), "ctxpopup", "icon_text_style_item", style);
1577 else if (item->label)
1580 _elm_theme_object_set(WIDGET(item), VIEW(item), "ctxpopup", "text_style_item_horizontal", style);
1582 _elm_theme_object_set(WIDGET(item), VIEW(item), "ctxpopup", "text_style_item", style);
1584 else if (item->icon)
1587 _elm_theme_object_set(WIDGET(item), VIEW(item), "ctxpopup", "icon_style_item_horizontal", style);
1589 _elm_theme_object_set(WIDGET(item), VIEW(item), "ctxpopup", "icon_style_item", style);
1592 if (sd->visible) elm_layout_sizing_eval(WIDGET(item));
1596 _bg_clicked_cb(void *data,
1597 Evas_Object *obj EINA_UNUSED,
1598 const char *emission EINA_UNUSED,
1599 const char *source EINA_UNUSED)
1601 ELM_CTXPOPUP_DATA_GET(data, sd);
1603 _hide_signals_emit(data, sd->dir);
1607 _on_show(void *data EINA_UNUSED,
1608 Evas *e EINA_UNUSED,
1610 void *event_info EINA_UNUSED)
1613 Elm_Ctxpopup_Item_Data *item;
1616 ELM_CTXPOPUP_DATA_GET(obj, sd);
1617 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1619 if ((!sd->items) && (!sd->content)) return;
1621 sd->visible = EINA_TRUE;
1623 elm_layout_signal_emit(obj, "elm,state,show", "elm");
1625 if (wd->orient_mode == 90 || wd->orient_mode == 270)
1626 elm_widget_theme_object_set
1627 (obj, sd->layout, "ctxpopup", "layout/landscape", elm_widget_style_get(obj));
1629 elm_widget_theme_object_set
1630 (obj, sd->layout, "ctxpopup", "layout", elm_widget_style_get(obj));
1631 edje_object_part_swallow(sd->layout, "swallow", wd->resize_obj);
1633 EINA_LIST_FOREACH(sd->items, elist, item)
1635 if (item->label && !item->icon)
1637 if (!sd->horizontal)
1638 _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1640 elm_widget_style_get(obj));
1642 _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1643 "text_style_item_horizontal",
1644 elm_widget_style_get(obj));
1646 else if (item->label)
1648 if (!sd->horizontal)
1649 _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1651 elm_widget_style_get(obj));
1653 _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1654 "label_style_item_horizontal",
1655 elm_widget_style_get(obj));
1657 else if (item->icon)
1659 if (!sd->horizontal)
1660 _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1662 elm_widget_style_get(obj));
1664 _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
1665 "icon_style_item_horizontal",
1666 elm_widget_style_get(obj));
1670 edje_object_signal_emit(VIEW(item), "elm,state,default", "elm");
1672 edje_object_signal_emit(VIEW(item), "elm,state,separator", "elm");
1675 elm_layout_sizing_eval(obj);
1677 elm_object_focus_set(obj, EINA_TRUE);
1678 _show_signals_emit(obj, sd->dir);
1682 _elm_ctxpopup_item_elm_widget_item_focus_set(Eo *eo_ctxpopup_it EINA_UNUSED,
1683 Elm_Ctxpopup_Item_Data *ctxpopup_it,
1686 elm_object_focus_set(ctxpopup_it->btn, focused);
1689 EOLIAN static Eina_Bool
1690 _elm_ctxpopup_item_elm_widget_item_focus_get(Eo *eo_ctxpopup_it EINA_UNUSED,
1691 Elm_Ctxpopup_Item_Data *ctxpopup_it)
1693 return elm_object_focus_get(ctxpopup_it->btn);
1697 _on_hide(void *data EINA_UNUSED,
1698 Evas *e EINA_UNUSED,
1700 void *event_info EINA_UNUSED)
1702 ELM_CTXPOPUP_DATA_GET(obj, sd);
1704 if (!sd->visible) return;
1706 sd->visible = EINA_FALSE;
1710 _on_move(void *data EINA_UNUSED,
1711 Evas *e EINA_UNUSED,
1713 void *event_info EINA_UNUSED)
1715 ELM_CTXPOPUP_DATA_GET(obj, sd);
1717 if (sd->visible) elm_layout_sizing_eval(obj);
1721 _hide_finished_cb(void *data,
1722 Evas_Object *obj EINA_UNUSED,
1723 const char *emission EINA_UNUSED,
1724 const char *source EINA_UNUSED)
1726 evas_object_hide(data);
1727 eo_do(data, eo_event_callback_call(ELM_CTXPOPUP_EVENT_DISMISSED, NULL));
1730 /* TIZEN_ONLY(20161207): add show finished callback */
1732 _show_finished_cb(void *data,
1733 Evas_Object *obj EINA_UNUSED,
1734 const char *emission EINA_UNUSED,
1735 const char *source EINA_UNUSED)
1737 elm_object_focus_set(data, EINA_TRUE);
1742 _list_del(Eo *obj, Elm_Ctxpopup_Data *sd)
1744 if (!sd->scr) return;
1746 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1748 edje_object_part_unswallow(wd->resize_obj, sd->scr);
1749 evas_object_del(sd->scr);
1751 evas_object_del(sd->box);
1756 _list_new(Evas_Object *obj)
1758 ELM_CTXPOPUP_DATA_GET(obj, sd);
1761 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1763 sd->scr = elm_scroller_add(obj);
1764 elm_layout_theme_set(sd->scr, "scroller", "ctxpopup", elm_widget_style_get(obj));
1765 evas_object_size_hint_align_set(sd->scr, EVAS_HINT_FILL, EVAS_HINT_FILL);
1766 _elm_widget_color_class_parent_set(sd->scr, obj);
1769 elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
1771 elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
1773 edje_object_part_swallow(wd->resize_obj, "elm.swallow.content", sd->scr);
1774 //TIZEN ONLY(20161014) : Accessibility: scroll the content when highlight frame goes out of view port
1775 evas_object_smart_callback_add(sd->scr, "scroll,down", _content_move_down_cb, (void*)obj);
1776 evas_object_smart_callback_add(sd->scr, "scroll,up", _content_move_up_cb, (void*)obj);
1778 elm_object_content_set(sd->scr, sd->box);
1779 elm_ctxpopup_horizontal_set(obj, sd->horizontal);
1782 EOLIAN static Eina_Bool
1783 _elm_ctxpopup_elm_widget_disable(Eo *obj, Elm_Ctxpopup_Data *sd)
1786 Elm_Ctxpopup_Item_Data *it;
1787 Eina_Bool int_ret = EINA_FALSE;
1789 eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_disable());
1790 if (!int_ret) return EINA_FALSE;
1792 EINA_LIST_FOREACH(sd->items, l, it)
1793 elm_object_item_disabled_set(EO_OBJ(it), elm_widget_disabled_get(obj));
1799 _elm_ctxpopup_evas_object_smart_add(Eo *obj, Elm_Ctxpopup_Data *priv)
1801 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
1803 eo_do_super(obj, MY_CLASS, evas_obj_smart_add());
1805 if (!elm_widget_sub_object_parent_add(obj))
1806 ERR("could not add %p as sub object of %p", obj, elm_object_parent_widget_get(obj));
1808 elm_layout_theme_set(obj, "ctxpopup", "base", elm_widget_style_get(obj));
1811 priv->bg = edje_object_add(evas_object_evas_get(obj));
1812 elm_widget_theme_object_set(obj, priv->bg, "ctxpopup", "bg", "default");
1813 edje_object_signal_callback_add
1814 (priv->bg, "elm,action,click", "", _bg_clicked_cb, obj);
1815 evas_object_smart_member_add(priv->bg, obj);
1816 evas_object_stack_below(priv->bg, wd->resize_obj);
1817 _elm_widget_color_class_parent_set(priv->bg, obj);
1820 priv->arrow = edje_object_add(evas_object_evas_get(obj));
1821 elm_widget_theme_object_set
1822 (obj, priv->arrow, "ctxpopup", "arrow", "default");
1823 _elm_widget_color_class_parent_set(priv->arrow, obj);
1825 priv->dir_priority[0] = ELM_CTXPOPUP_DIRECTION_UP;
1826 priv->dir_priority[1] = ELM_CTXPOPUP_DIRECTION_LEFT;
1827 priv->dir_priority[2] = ELM_CTXPOPUP_DIRECTION_RIGHT;
1828 priv->dir_priority[3] = ELM_CTXPOPUP_DIRECTION_DOWN;
1829 priv->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1831 priv->auto_hide = EINA_TRUE;
1832 priv->mouse_down = EINA_FALSE;
1833 priv->multi_down = 0;
1835 priv->box = elm_box_add(obj);
1836 evas_object_size_hint_weight_set
1837 (priv->box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1839 priv->layout = edje_object_add(evas_object_evas_get(obj));
1840 if (wd->orient_mode == 90 || wd->orient_mode == 270)
1841 elm_widget_theme_object_set(obj, priv->layout, "ctxpopup", "layout/landscape", "default");
1843 elm_widget_theme_object_set(obj, priv->layout, "ctxpopup", "layout", "default");
1844 evas_object_smart_member_add(priv->layout, obj);
1845 _elm_widget_color_class_parent_set(priv->layout, obj);
1847 edje_object_signal_callback_add
1848 (priv->layout, "elm,action,hide,finished", "", _hide_finished_cb, obj);
1849 /* TIZEN_ONLY(20161207): Add show finished callback */
1850 edje_object_signal_callback_add
1851 (priv->layout, "elm,action,show,finished", "", _show_finished_cb, obj);
1854 edje_object_part_swallow(priv->layout, "swallow", wd->resize_obj);
1855 evas_object_size_hint_weight_set
1856 (priv->layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1858 evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _on_show, NULL);
1859 evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _on_hide, NULL);
1860 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _on_move, NULL);
1862 _mirrored_set(obj, elm_widget_mirrored_get(obj));
1864 elm_widget_can_focus_set(obj, EINA_TRUE);
1865 elm_ctxpopup_hover_parent_set(obj, elm_object_parent_widget_get(obj));
1867 if (_elm_config->access_mode) _access_obj_process(obj, EINA_TRUE);
1869 /* access: parent could be any object such as elm_list which does
1870 not know elc_ctxpopup as its child object in the focus_next(); */
1872 wd->highlight_root = EINA_TRUE;
1874 //Tizen Only: This should be removed when eo is applied.
1875 wd->on_create = EINA_FALSE;
1879 _elm_ctxpopup_evas_object_smart_del(Eo *obj, Elm_Ctxpopup_Data *sd)
1881 evas_object_event_callback_del_full
1882 (sd->box, EVAS_CALLBACK_RESIZE, _on_content_resized, obj);
1883 _parent_detach(obj);
1892 evas_object_del(sd->box);
1896 evas_object_del(sd->arrow);
1897 sd->arrow = NULL; /* stops _sizing_eval() from going on on deletion */
1899 evas_object_del(sd->bg);
1902 evas_object_del(sd->layout);
1905 eo_do_super(obj, MY_CLASS, evas_obj_smart_del());
1909 _elm_ctxpopup_elm_widget_parent_set(Eo *obj, Elm_Ctxpopup_Data *_pd EINA_UNUSED, Evas_Object *parent)
1911 //default parent is to be hover parent
1912 elm_ctxpopup_hover_parent_set(obj, parent);
1917 _elm_ctxpopup_smart_access(Evas_Object *obj, Eina_Bool is_access)
1919 ELM_CTXPOPUP_CHECK(obj);
1921 _access_obj_process(obj, is_access);
1923 evas_object_smart_callback_call(obj, SIG_ACCESS_CHANGED, NULL);
1926 static Evas_Object *
1927 _elm_ctxpopup_smart_access_object_get(Evas_Object *obj, char *part)
1929 ELM_CTXPOPUP_CHECK(obj) NULL;
1931 return _access_object_get(obj, part);
1936 _elm_ctxpopup_class_constructor(Eo_Class *klass)
1938 evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
1942 elm_ctxpopup_add(Evas_Object *parent)
1944 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1945 Evas_Object *obj = eo_add(MY_CLASS, parent);
1947 /* access: parent could be any object such as elm_list which does
1948 not know elc_ctxpopup as its child object in the focus_next(); */
1949 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
1950 wd->highlight_root = EINA_TRUE;
1956 _elm_ctxpopup_eo_base_constructor(Eo *obj, Elm_Ctxpopup_Data *_pd EINA_UNUSED)
1958 obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
1960 evas_obj_type_set(MY_CLASS_NAME_LEGACY),
1961 evas_obj_smart_callbacks_descriptions_set(_smart_callbacks),
1962 elm_interface_atspi_accessible_role_set(ELM_ATSPI_ROLE_POPUP_MENU));
1969 _elm_ctxpopup_hover_parent_set(Eo *obj, Elm_Ctxpopup_Data *sd, Evas_Object *parent)
1971 Evas_Coord x, y, w, h;
1973 if (!parent) return;
1975 _parent_detach(obj);
1977 evas_object_event_callback_add
1978 (parent, EVAS_CALLBACK_DEL, _on_parent_del, obj);
1979 evas_object_event_callback_add
1980 (parent, EVAS_CALLBACK_MOVE, _on_parent_move, obj);
1981 evas_object_event_callback_add
1982 (parent, EVAS_CALLBACK_RESIZE, _on_parent_resize, obj);
1984 sd->parent = parent;
1987 evas_object_geometry_get(parent, &x, &y, &w, &h);
1988 evas_object_move(sd->bg, x, y);
1989 evas_object_resize(sd->bg, w, h);
1991 if (sd->visible) elm_layout_sizing_eval(obj);
1994 EOLIAN static Evas_Object*
1995 _elm_ctxpopup_hover_parent_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd)
2001 _elm_ctxpopup_clear(Eo *obj, Elm_Ctxpopup_Data *sd)
2005 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
2007 elm_object_content_unset(sd->scr);
2008 edje_object_part_unswallow(wd->resize_obj, sd->scr);
2009 evas_object_del(sd->scr);
2011 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
2015 _elm_ctxpopup_horizontal_set(Eo *obj, Elm_Ctxpopup_Data *sd, Eina_Bool horizontal)
2018 Elm_Ctxpopup_Item_Data *item;
2021 sd->horizontal = !!horizontal;
2028 elm_box_horizontal_set(sd->box, EINA_FALSE);
2029 elm_scroller_bounce_set(sd->scr, EINA_FALSE, EINA_TRUE);
2030 elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
2034 elm_box_horizontal_set(sd->box, EINA_TRUE);
2035 elm_scroller_bounce_set(sd->scr, EINA_TRUE, EINA_FALSE);
2036 elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
2039 EINA_LIST_FOREACH(sd->items, elist, item)
2041 if (item->label && !item->icon)
2043 if (!sd->horizontal)
2044 _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
2046 elm_widget_style_get(obj));
2048 _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
2049 "text_style_item_horizontal",
2050 elm_widget_style_get(obj));
2052 else if (item->label)
2054 if (!sd->horizontal)
2055 _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
2057 elm_widget_style_get(obj));
2059 _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
2060 "label_style_item_horizontal",
2061 elm_widget_style_get(obj));
2063 else if (item->icon)
2065 if (!sd->horizontal)
2066 _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
2068 elm_widget_style_get(obj));
2070 _elm_theme_object_set(obj, VIEW(item), "ctxpopup",
2071 "icon_style_item_horizontal",
2072 elm_widget_style_get(obj));
2075 edje_object_signal_emit(VIEW(item), "elm,state,default", "elm");
2077 edje_object_signal_emit(VIEW(item), "elm,state,separator", "elm");
2079 eo_do(EO_OBJ(item), elm_wdg_item_disable());
2082 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
2084 if (sd->visible) elm_layout_sizing_eval(obj);
2087 EOLIAN static Eina_Bool
2088 _elm_ctxpopup_horizontal_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd)
2090 return sd->horizontal;
2094 _elm_ctxpopup_item_eo_base_constructor(Eo *obj, Elm_Ctxpopup_Item_Data *it)
2096 obj = eo_do_super_ret(obj, ELM_CTXPOPUP_ITEM_CLASS, obj, eo_constructor());
2097 it->base = eo_data_scope_get(obj, ELM_WIDGET_ITEM_CLASS);
2098 //TIZEN ONLY(20150710)ctxpopup: Accessible methods for children_get, extents_get and item name_get
2099 eo_do(obj, elm_interface_atspi_accessible_role_set(ELM_ATSPI_ROLE_MENU_ITEM));
2105 _elm_ctxpopup_item_eo_base_destructor(Eo *eo_ctxpopup_it,
2106 Elm_Ctxpopup_Item_Data *ctxpopup_it EINA_UNUSED)
2108 eo_do_super(eo_ctxpopup_it, ELM_CTXPOPUP_ITEM_CLASS, eo_destructor());
2111 EOLIAN static Elm_Object_Item*
2112 _elm_ctxpopup_item_append(Eo *obj, Elm_Ctxpopup_Data *sd, const char *label, Evas_Object *icon, Evas_Smart_Cb func, const void *data)
2114 Elm_Ctxpopup_Item_Data *it;
2115 Evas_Object *content, *focus_bt;
2120 eo_item = eo_add(ELM_CTXPOPUP_ITEM_CLASS, obj, elm_obj_ctxpopup_item_init(func, data));
2121 if (!eo_item) return NULL;
2123 ELM_CTXPOPUP_ITEM_DATA_GET(eo_item, item);
2125 //The first item is appended.
2126 content = elm_object_content_unset(obj);
2127 if (content) evas_object_del(content);
2134 if (!sd->horizontal)
2135 _item_new(item, "icon_text_style_item");
2137 _item_new(item, "icon_text_style_item_horizontal");
2141 if (!sd->horizontal)
2142 _item_new(item, "text_style_item");
2144 _item_new(item, "text_style_item_horizontal");
2148 if (!sd->horizontal)
2149 _item_new(item, "icon_style_item");
2151 _item_new(item, "icon_style_item_horizontal");
2154 _item_icon_set(item, icon);
2155 _item_label_set(item, label);
2156 focus_bt = _item_in_focusable_button(item);
2157 elm_box_pack_end(sd->box, focus_bt);
2158 sd->items = eina_list_append(sd->items, item);
2159 item->btn = focus_bt;
2160 _elm_widget_color_class_parent_set(VIEW(item), obj);
2162 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
2166 EINA_LIST_FOREACH(sd->items, elist, it)
2169 edje_object_signal_emit(VIEW(it), "elm,state,default", "elm");
2171 edje_object_signal_emit(VIEW(it), "elm,state,separator", "elm");
2173 elm_layout_sizing_eval(obj);
2176 if (_elm_config->access_mode) _access_focusable_button_register(focus_bt, item);
2178 return EO_OBJ(item);
2182 _elm_ctxpopup_direction_priority_set(Eo *obj, Elm_Ctxpopup_Data *sd, Elm_Ctxpopup_Direction first, Elm_Ctxpopup_Direction second, Elm_Ctxpopup_Direction third, Elm_Ctxpopup_Direction fourth)
2184 sd->dir_priority[0] = first;
2185 sd->dir_priority[1] = second;
2186 sd->dir_priority[2] = third;
2187 sd->dir_priority[3] = fourth;
2189 if (sd->visible) elm_layout_sizing_eval(obj);
2193 _elm_ctxpopup_direction_priority_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd, Elm_Ctxpopup_Direction *first, Elm_Ctxpopup_Direction *second, Elm_Ctxpopup_Direction *third, Elm_Ctxpopup_Direction *fourth)
2195 if (first) *first = sd->dir_priority[0];
2196 if (second) *second = sd->dir_priority[1];
2197 if (third) *third = sd->dir_priority[2];
2198 if (fourth) *fourth = sd->dir_priority[3];
2201 EOLIAN static Elm_Ctxpopup_Direction
2202 _elm_ctxpopup_direction_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd)
2208 elm_ctxpopup_direction_available_get(Evas_Object *obj, Elm_Ctxpopup_Direction direction)
2210 ELM_CTXPOPUP_CHECK(obj) EINA_FALSE;
2211 ELM_CTXPOPUP_DATA_GET(obj, sd);
2213 elm_layout_sizing_eval(obj);
2215 if (sd->dir == direction) return EINA_TRUE;
2220 _elm_ctxpopup_dismiss(Eo *obj, Elm_Ctxpopup_Data *sd)
2222 _hide_signals_emit(obj, sd->dir);
2226 _elm_ctxpopup_auto_hide_disabled_set(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd, Eina_Bool disabled)
2228 disabled = !!disabled;
2229 if (sd->auto_hide == !disabled) return;
2230 sd->auto_hide = !disabled;
2233 EOLIAN static Eina_Bool
2234 _elm_ctxpopup_auto_hide_disabled_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd)
2236 return !sd->auto_hide;
2239 // TIZEN_ONLY(20170116): merge eo & header files for different profiles
2240 EOLIAN static const Eina_List*
2241 _elm_ctxpopup_items_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd)
2246 EOLIAN static Elm_Object_Item*
2247 _elm_ctxpopup_first_item_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd)
2249 if (!sd->items) return NULL;
2251 return eina_list_data_get(sd->items);
2254 EOLIAN static Elm_Object_Item*
2255 _elm_ctxpopup_last_item_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd)
2257 if (!sd->items) return NULL;
2259 return eina_list_data_get(eina_list_last(sd->items));
2262 EOLIAN static Elm_Object_Item*
2263 _elm_ctxpopup_item_prepend(Eo *obj, Elm_Ctxpopup_Data *sd, const char *label, Evas_Object *icon, Evas_Smart_Cb func, const void *data)
2265 // the feature not provided for mobile or wearable profile
2269 EOLIAN static Elm_Object_Item *
2270 _elm_ctxpopup_item_prev_get(Eo *eo_item EINA_UNUSED, Elm_Ctxpopup_Item_Data *item)
2274 ELM_CTXPOPUP_DATA_GET(WIDGET(item), sd);
2276 if (!sd->items) return NULL;
2278 l = eina_list_data_find_list(sd->items, eo_item);
2279 if (l && l->prev) return eina_list_data_get(l->prev);
2284 EOLIAN static Elm_Object_Item *
2285 _elm_ctxpopup_item_next_get(Eo *eo_item EINA_UNUSED, Elm_Ctxpopup_Item_Data *item)
2289 ELM_CTXPOPUP_DATA_GET(WIDGET(item), sd);
2291 if (!sd->items) return NULL;
2293 l = eina_list_data_find_list(sd->items, eo_item);
2294 if (l && l->next) return eina_list_data_get(l->next);
2301 _elm_ctxpopup_item_init(Eo *eo_item,
2302 Elm_Ctxpopup_Item_Data *item,
2307 eo_do(eo_item, obj = eo_parent_get());
2309 item->wcb.org_func_cb = func;
2310 item->wcb.org_data = data;
2311 item->wcb.cobj = obj;
2314 //TIZEN ONLY(20160918): name interface added
2315 EOLIAN static const char*
2316 _elm_ctxpopup_elm_interface_atspi_accessible_name_get(Eo *obj, Elm_Ctxpopup_Data *sd EINA_UNUSED)
2319 char *accessible_name = NULL;
2320 const char *style = elm_widget_style_get(obj);
2322 ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
2323 buf = eina_strbuf_new();
2324 if (!strcmp(style, "more/default"))
2325 eina_strbuf_append_printf(buf, "%s", N_("More menu popup"));
2327 eina_strbuf_append_printf(buf, "%s", N_("Alert"));
2328 accessible_name = eina_strbuf_string_steal(buf);
2329 eina_strbuf_free(buf);
2331 eina_stringshare_del(wd->accessible_name);
2332 wd->accessible_name = eina_stringshare_add(accessible_name);
2333 free(accessible_name);
2334 return wd->accessible_name;
2338 EOLIAN static const Elm_Atspi_Action*
2339 _elm_ctxpopup_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd EINA_UNUSED)
2341 static Elm_Atspi_Action atspi_actions[] = {
2342 { "escape", "escape", NULL, _key_action_escape},
2343 { "move,previous", "move", "previous", _key_action_move},
2344 { "move,next", "move", "next", _key_action_move},
2345 { "move,left", "move", "left", _key_action_move},
2346 { "move,right", "move", "right", _key_action_move},
2347 { "move,up", "move", "up", _key_action_move},
2348 { "move,down", "move", "down", _key_action_move},
2349 { NULL, NULL, NULL, NULL }
2351 return &atspi_actions[0];
2354 EOLIAN static Elm_Atspi_State_Set
2355 _elm_ctxpopup_elm_interface_atspi_accessible_state_set_get(Eo *obj, Elm_Ctxpopup_Data *sd)
2357 Elm_Atspi_State_Set ret;
2358 eo_do_super(obj, MY_CLASS, ret = elm_interface_atspi_accessible_state_set_get());
2360 STATE_TYPE_SET(ret, ELM_ATSPI_STATE_MODAL);
2362 if (_elm_object_accessibility_currently_highlighted_get() == (void*)sd->scr)
2363 STATE_TYPE_SET(ret, ELM_ATSPI_STATE_HIGHLIGHTED);
2367 //TIZEN ONLY(20150710): ctxpopup: Accessible methods for children_get, extents_get and item name_get
2369 _elm_ctxpopup_elm_interface_atspi_accessible_children_get(Eo *eo_item EINA_UNUSED, Elm_Ctxpopup_Data *sd)
2371 Eina_List *ret = NULL;
2372 Eina_List *l = NULL;
2373 Elm_Ctxpopup_Item_Data *it;
2375 EINA_LIST_FOREACH(sd->items, l, it)
2376 ret = eina_list_append(ret, EO_OBJ(it));
2382 _elm_ctxpopup_elm_interface_atspi_component_extents_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd, Eina_Bool screen_coords, int *x, int *y, int *w, int *h)
2394 evas_object_geometry_get(sd->scr, x, y, w, h);
2398 Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(sd->scr));
2400 ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
2407 //TIZEN ONLY(20150708): popup and ctxpopup accessibility highlight impementation
2408 EOLIAN static Eina_Bool
2409 _elm_ctxpopup_elm_interface_atspi_component_highlight_grab(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd)
2413 elm_object_accessibility_highlight_set(sd->scr, EINA_TRUE);
2414 ///TIZEN_ONLY(20170717) : expose highlight information on atspi
2415 elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_TRUE);
2422 EOLIAN static Eina_Bool
2423 _elm_ctxpopup_elm_interface_atspi_component_highlight_clear(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Data *sd)
2427 elm_object_accessibility_highlight_set(sd->scr, EINA_FALSE);
2428 ///TIZEN_ONLY(20170717) : expose highlight information on atspi
2429 elm_interface_atspi_accessible_state_changed_signal_emit(obj, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_FALSE);
2437 //TIZEN ONLY(20150710)ctxpopup: Accessible methods for children_get, extents_get and item name_get
2439 _elm_ctxpopup_item_elm_interface_atspi_accessible_name_get(Eo *eo_it EINA_UNUSED, Elm_Ctxpopup_Item_Data *item)
2441 if(item->icon && !item->label)
2443 const char *icon_name = NULL;
2444 eo_do(item->icon, icon_name = elm_interface_atspi_accessible_name_get());
2453 _key_action_escape(Evas_Object *obj, const char *params EINA_UNUSED)
2455 elm_ctxpopup_dismiss(obj);
2460 _item_action_activate(Evas_Object *obj, const char *params EINA_UNUSED)
2462 ELM_CTXPOPUP_ITEM_DATA_GET(obj, item);
2464 if (item->wcb.org_func_cb)
2465 item->wcb.org_func_cb((void*)item->wcb.org_data, WIDGET(item), EO_OBJ(item));
2469 EOLIAN static const Elm_Atspi_Action*
2470 _elm_ctxpopup_item_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, Elm_Ctxpopup_Item_Data *sd EINA_UNUSED)
2472 static Elm_Atspi_Action atspi_actions[] = {
2473 { "activate", "activate", NULL, _item_action_activate},
2474 { NULL, NULL, NULL, NULL }
2476 return &atspi_actions[0];
2479 //TIZEN ONLY(20161014) : Accessibility: scroll the content when highlight frame goes out of view port
2481 _is_item_in_viewport(int viewport_y, int viewport_h, int obj_y, int obj_h)
2483 if ((obj_y + obj_h/2) < viewport_y)
2485 else if ((obj_y + obj_h/2) > viewport_y + viewport_h)
2490 EOLIAN static Eina_Bool
2491 _elm_ctxpopup_item_elm_interface_atspi_component_highlight_grab(Eo *eo_it, Elm_Ctxpopup_Item_Data *it)
2493 Evas_Coord wy, wh, x, y, w, h, bx, by;
2494 ELM_CTXPOPUP_DATA_GET_OR_RETURN_VAL(WIDGET(it), sd, EINA_FALSE);
2496 evas_object_geometry_get(VIEW(it), &x, &y, &w, &h);
2497 eo_do(sd->scr, elm_interface_scrollable_content_viewport_geometry_get(NULL, &wy, NULL, &wh));
2498 int res = _is_item_in_viewport(wy, wh, y, h);
2502 evas_object_geometry_get(sd->box, &bx, &by, NULL, NULL);
2503 evas_smart_objects_calculate(evas_object_evas_get(sd->box));
2509 eo_do(sd->scr, elm_interface_scrollable_content_region_show(x, y, w, h));
2514 eo_do(sd->scr, elm_interface_scrollable_content_region_show(x, y, w, h));
2518 elm_object_accessibility_highlight_set(eo_it, EINA_TRUE);
2519 elm_interface_atspi_accessible_state_changed_signal_emit(eo_it, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_TRUE);
2523 EOLIAN static Eina_Bool
2524 _elm_ctxpopup_item_elm_interface_atspi_component_highlight_clear(Eo *eo_it, Elm_Ctxpopup_Item_Data *it EINA_UNUSED)
2526 elm_object_accessibility_highlight_set(eo_it, EINA_FALSE);
2527 elm_interface_atspi_accessible_state_changed_signal_emit(eo_it, ELM_ATSPI_STATE_HIGHLIGHTED, EINA_FALSE);
2533 _content_move_down_cb(void *data, Evas_Object *obj, void *ev EINA_UNUSED)
2535 if (!_elm_atspi_enabled())
2537 ELM_CTXPOPUP_DATA_GET(data, pd);
2538 Elm_Ctxpopup_Item_Data *it_data;
2539 Evas_Object *highlighted_obj = _elm_object_accessibility_currently_highlighted_get();
2541 if (eo_isa(highlighted_obj, ELM_WIDGET_ITEM_CLASS))
2543 Elm_Widget_Item_Data *id = eo_data_scope_get(highlighted_obj, ELM_WIDGET_ITEM_CLASS);
2544 highlighted_obj = id->view;
2547 Evas_Object *parent = highlighted_obj;
2549 if (eo_isa(highlighted_obj, ELM_WIDGET_CLASS))
2551 while ((parent = elm_widget_parent_get(parent)))
2555 else if (eo_isa(highlighted_obj, EDJE_OBJECT_CLASS))
2557 while ((parent = evas_object_smart_parent_get(parent)))
2561 // TIZEN_ONLY(20160805): set _accessibility_currently_highlighted_obj to NULL in object delete callback
2564 WRN("Improper highlighted object: %p", highlighted_obj);
2571 int obj_x, obj_y, w, h, hx, hy, hw, hh;
2572 eo_do(pd->scr, elm_interface_scrollable_content_viewport_geometry_get(&obj_x, &obj_y, &w, &h));
2573 evas_object_geometry_get(highlighted_obj, &hx, &hy, &hw, &hh);
2575 Elm_Ctxpopup_Item_Data *next_previous_item = NULL;
2576 int viewport_position_result = _is_item_in_viewport(obj_y, h, hy, hh);
2577 if (viewport_position_result > 0)
2579 Eina_List *l = pd->items;
2582 it_data = eina_list_data_get(l);
2583 next_previous_item = it_data;
2584 evas_object_geometry_get(VIEW(next_previous_item), &hx, &hy, &hw, &hh);
2586 if (_is_item_in_viewport(obj_y, h, hy, hh) == 0)
2588 next_previous_item = NULL;
2590 l = eina_list_next(l);
2593 if (next_previous_item)
2595 elm_object_accessibility_highlight_set(EO_OBJ(next_previous_item), EINA_TRUE);
2596 elm_interface_atspi_accessible_state_changed_signal_emit(EO_OBJ(next_previous_item), ELM_ATSPI_STATE_HIGHLIGHTED, EINA_TRUE);
2603 _content_move_up_cb(void *data, Evas_Object *obj, void *ev EINA_UNUSED)
2605 if (!_elm_atspi_enabled())
2607 ELM_CTXPOPUP_DATA_GET(data, pd);
2608 Elm_Ctxpopup_Item_Data *it_data;
2609 Evas_Object *highlighted_obj = _elm_object_accessibility_currently_highlighted_get();
2611 if (eo_isa(highlighted_obj, ELM_WIDGET_ITEM_CLASS))
2613 Elm_Widget_Item_Data *id = eo_data_scope_get(highlighted_obj, ELM_WIDGET_ITEM_CLASS);
2614 highlighted_obj = id->view;
2617 Evas_Object *parent = highlighted_obj;
2619 if (eo_isa(highlighted_obj, ELM_WIDGET_CLASS))
2621 while ((parent = elm_widget_parent_get(parent)))
2625 else if (eo_isa(highlighted_obj, EDJE_OBJECT_CLASS))
2627 while ((parent = evas_object_smart_parent_get(parent)))
2631 // TIZEN_ONLY(20160805): set _accessibility_currently_highlighted_obj to NULL in object delete callback
2634 WRN("Improper highlighted object: %p", highlighted_obj);
2641 int obj_x, obj_y, w, h, hx, hy, hw, hh;
2642 eo_do(pd->scr, elm_interface_scrollable_content_viewport_geometry_get(&obj_x, &obj_y, &w, &h));
2643 evas_object_geometry_get(highlighted_obj, &hx, &hy, &hw, &hh);
2645 Elm_Ctxpopup_Item_Data *next_previous_item = NULL;
2646 int viewport_position_result = _is_item_in_viewport(obj_y, h, hy, hh);
2647 if (viewport_position_result < 0)
2649 Eina_List *l = eina_list_last(pd->items);
2652 it_data = eina_list_data_get(l);
2653 next_previous_item = it_data;
2654 evas_object_geometry_get(VIEW(next_previous_item), &hx, &hy, &hw, &hh);
2656 if (_is_item_in_viewport(obj_y, h, hy, hh) == 0)
2658 next_previous_item = NULL;
2660 l = eina_list_prev(l);
2663 if (next_previous_item)
2665 elm_object_accessibility_highlight_set(EO_OBJ(next_previous_item), EINA_TRUE);
2666 elm_interface_atspi_accessible_state_changed_signal_emit(EO_OBJ(next_previous_item), ELM_ATSPI_STATE_HIGHLIGHTED, EINA_TRUE);
2673 //TIZEN_ONLY ctx_popup: fix accessibility states
2674 EOLIAN static Elm_Atspi_State_Set
2675 _elm_ctxpopup_item_elm_interface_atspi_accessible_state_set_get(Eo *obj, Elm_Ctxpopup_Item_Data *it)
2677 Elm_Atspi_State_Set states;
2678 Eina_Rectangle r1, r2;
2679 Eina_Bool is_showing = EINA_FALSE;
2681 eo_do_super(obj, ELM_CTXPOPUP_ITEM_CLASS, states = elm_interface_atspi_accessible_state_set_get());
2683 // evaluate showing state
2686 evas_object_visible_get(VIEW(it)) &&
2687 _elm_widget_onscreen_is(WIDGET(it)))
2689 ELM_CTXPOPUP_DATA_GET(WIDGET(it), sd);
2691 evas_object_geometry_get(VIEW(it), &r1.x, &r1.y, &r1.w, &r1.h);
2692 evas_object_geometry_get(sd->scr, &r2.x, &r2.y, &r2.w, &r2.h);
2694 if (eina_rectangles_intersect(&r1, &r2))
2695 is_showing = EINA_TRUE;
2699 STATE_TYPE_SET(states, ELM_ATSPI_STATE_SHOWING);
2701 STATE_TYPE_UNSET(states, ELM_ATSPI_STATE_SHOWING);
2706 #include "elm_ctxpopup_item.eo.c"
2707 #include "elm_ctxpopup.eo.c"