1 #include <Elementary.h>
3 #include "elm_widget_ctxpopup.h"
5 EAPI const char ELM_CTXPOPUP_SMART_NAME[] = "elm_ctxpopup";
7 static const char SIG_DISMISSED[] = "dismissed";
8 static const char SIG_LANG_CHANGED[] = "language,changed";
10 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
12 {SIG_LANG_CHANGED, ""},
16 EVAS_SMART_SUBCLASS_NEW
17 (ELM_CTXPOPUP_SMART_NAME, _elm_ctxpopup, Elm_Ctxpopup_Smart_Class,
18 Elm_Layout_Smart_Class, elm_layout_smart_class_get, _smart_callbacks);
21 _elm_ctxpopup_smart_translate(Evas_Object *obj)
23 evas_object_hide(obj);
29 _elm_ctxpopup_smart_focus_next(const Evas_Object *obj,
30 Elm_Focus_Direction dir,
33 Eina_List *items = NULL;
34 Eina_List *elist = NULL;
35 Elm_Ctxpopup_Item *it;
37 ELM_CTXPOPUP_DATA_GET(obj, sd);
42 if (eina_list_count(sd->items))
44 EINA_LIST_FOREACH(sd->items, elist, it)
45 items = eina_list_append(items, it->base.access_obj);
47 return elm_widget_focus_list_next_get
48 (obj, items, eina_list_data_get, dir, next);
52 return elm_widget_focus_next_get(sd->box, dir, next);
57 _elm_ctxpopup_smart_event(Evas_Object *obj,
58 Evas_Object *src __UNUSED__,
59 Evas_Callback_Type type,
62 Evas_Event_Key_Down *ev = event_info;
64 ELM_CTXPOPUP_DATA_GET(obj, sd);
66 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
67 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
68 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
70 if (!strcmp(ev->keyname, "Tab"))
72 if (evas_key_modifier_is_set(ev->modifiers, "Shift"))
73 elm_widget_focus_cycle(sd->box, ELM_FOCUS_PREVIOUS);
75 elm_widget_focus_cycle(sd->box, ELM_FOCUS_NEXT);
79 if (strcmp(ev->keyname, "Escape")) return EINA_FALSE;
81 evas_object_hide(obj);
82 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
87 _freeze_on_cb(void *data __UNUSED__,
89 void *event_info __UNUSED__)
91 ELM_CTXPOPUP_DATA_GET(obj, sd);
93 if ((!sd) || (!sd->scr)) return;
94 elm_object_scroll_freeze_push(sd->scr);
98 _freeze_off_cb(void *data __UNUSED__,
100 void *event_info __UNUSED__)
102 ELM_CTXPOPUP_DATA_GET(obj, sd);
104 if ((!sd) || (!sd->scr)) return;
105 elm_object_scroll_freeze_pop(sd->scr);
109 _hold_on_cb(void *data __UNUSED__,
111 void *event_info __UNUSED__)
113 ELM_CTXPOPUP_DATA_GET(obj, sd);
115 if ((!sd) || (!sd->scr)) return;
116 elm_object_scroll_hold_push(sd->scr);
120 _hold_off_cb(void *data __UNUSED__,
122 void *event_info __UNUSED__)
124 ELM_CTXPOPUP_DATA_GET(obj, sd);
126 if ((!sd) || (!sd->scr)) return;
127 elm_object_scroll_hold_pop(sd->scr);
131 _x_pos_adjust(Evas_Coord_Point *pos,
132 Evas_Coord_Point *base_size,
133 Evas_Coord_Rectangle *hover_area)
135 pos->x -= (base_size->x / 2);
137 if (pos->x < hover_area->x)
138 pos->x = hover_area->x;
139 else if ((pos->x + base_size->x) > (hover_area->x + hover_area->w))
140 pos->x = (hover_area->x + hover_area->w) - base_size->x;
142 if (base_size->x > hover_area->w)
143 base_size->x -= (base_size->x - hover_area->w);
145 if (pos->x < hover_area->x)
146 pos->x = hover_area->x;
150 _y_pos_adjust(Evas_Coord_Point *pos,
151 Evas_Coord_Point *base_size,
152 Evas_Coord_Rectangle *hover_area)
154 pos->y -= (base_size->y / 2);
156 if (pos->y < hover_area->y)
157 pos->y = hover_area->y;
158 else if ((pos->y + base_size->y) > (hover_area->y + hover_area->h))
159 pos->y = hover_area->y + hover_area->h - base_size->y;
161 if (base_size->y > hover_area->h)
162 base_size->y -= (base_size->y - hover_area->h);
164 if (pos->y < hover_area->y)
165 pos->y = hover_area->y;
169 _item_select_cb(void *data, Evas_Object *obj __UNUSED__,
170 const char *emission __UNUSED__,
171 const char *source __UNUSED__)
173 Elm_Ctxpopup_Item *item = data;
176 if (elm_widget_item_disabled_get(item)) return;
179 item->func((void*)item->base.data, WIDGET(item), data);
183 _access_info_cb(void *data, Evas_Object *obj __UNUSED__)
185 Elm_Ctxpopup_Item *it = (Elm_Ctxpopup_Item *)data;
186 const char *txt = NULL;
187 Evas_Object *icon = NULL;
188 Eina_Strbuf *buf = NULL;
191 if (!it) return NULL;
193 if ((!txt) && (!icon))
198 else if (!txt) txt = it->label;
199 else if (!icon) icon = it->icon;
203 buf = eina_strbuf_new();
204 eina_strbuf_append(buf, E_("icon "));
205 eina_strbuf_append(buf, txt);
206 str = eina_strbuf_string_steal(buf);
207 eina_strbuf_free(buf);
210 else if ((!txt) && icon) return strdup(E_("icon"));
211 else if (txt && (!icon)) return strdup(txt);
217 _access_state_cb(void *data, Evas_Object *obj __UNUSED__)
219 Elm_Ctxpopup_Item *it = (Elm_Ctxpopup_Item *)data;
220 if (!it) return NULL;
222 if (it->base.disabled)
223 return strdup(E_("State: Disabled"));
229 _access_activate_cb(void *data __UNUSED__,
230 Evas_Object *part_obj __UNUSED__,
231 Elm_Object_Item *item)
233 _item_select_cb(item, NULL, NULL, NULL);
237 _access_widget_item_register(Elm_Ctxpopup_Item *it, Eina_Bool is_access)
241 if (!is_access) _elm_access_widget_item_unregister((Elm_Widget_Item *)it);
244 _elm_access_widget_item_register((Elm_Widget_Item *)it);
246 ai = _elm_access_object_get(it->base.access_obj);
248 _elm_access_callback_set(ai, ELM_ACCESS_INFO, _access_info_cb, it);
249 _elm_access_callback_set(ai, ELM_ACCESS_STATE, _access_state_cb, it);
250 _elm_access_text_set(ai, ELM_ACCESS_TYPE, E_("Contextual Popup"));
251 _elm_access_activate_callback_set(ai, _access_activate_cb, it);
256 _item_new(Elm_Ctxpopup_Item *item,
259 ELM_CTXPOPUP_DATA_GET(WIDGET(item), sd);
262 VIEW(item) = edje_object_add(evas_object_evas_get(sd->box));
263 edje_object_mirrored_set(VIEW(item), elm_widget_mirrored_get(WIDGET(item)));
264 _elm_theme_object_set(WIDGET(item), VIEW(item), "ctxpopup", group_name,
265 elm_widget_style_get(WIDGET(item)));
266 edje_object_signal_callback_add(VIEW(item), "elm,action,click", "",
267 _item_select_cb, item);
268 evas_object_size_hint_align_set(VIEW(item), EVAS_HINT_FILL, EVAS_HINT_FILL);
269 evas_object_show(VIEW(item));
272 if (_elm_config->access_mode) _access_widget_item_register(item, EINA_TRUE);
276 _item_icon_set(Elm_Ctxpopup_Item *item,
280 evas_object_del(item->icon);
285 edje_object_part_swallow(VIEW(item), "elm.swallow.icon", item->icon);
286 edje_object_message_signal_process(VIEW(item));
290 _item_label_set(Elm_Ctxpopup_Item *item,
293 if (!eina_stringshare_replace(&item->label, label))
296 edje_object_part_text_set(VIEW(item), "elm.text", label);
297 edje_object_message_signal_process(VIEW(item));
301 _item_del_pre_hook(Elm_Object_Item *it)
303 Elm_Ctxpopup_Item *ctxpopup_it = (Elm_Ctxpopup_Item *)it;
305 ELM_CTXPOPUP_DATA_GET(WIDGET(ctxpopup_it), sd);
306 if (!sd) return EINA_FALSE;
308 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
310 if (ctxpopup_it->icon)
311 evas_object_del(ctxpopup_it->icon);
312 if (VIEW(ctxpopup_it))
313 evas_object_del(VIEW(ctxpopup_it));
315 eina_stringshare_del(ctxpopup_it->label);
316 sd->items = eina_list_remove(sd->items, ctxpopup_it);
318 if (eina_list_count(sd->items) < 1)
320 evas_object_hide(WIDGET(ctxpopup_it));
323 if (sd->visible) elm_layout_sizing_eval(WIDGET(ctxpopup_it));
329 _items_remove(Elm_Ctxpopup_Smart_Data *sd)
332 Elm_Ctxpopup_Item *item;
334 if (!sd->items) return;
336 EINA_LIST_FOREACH(sd->items, elist, item)
338 _item_del_pre_hook((Elm_Object_Item *)item);
345 _scroller_size_reset(Elm_Ctxpopup_Smart_Data *sd)
347 sd->finished = EINA_FALSE;
353 _item_sizing_eval(Elm_Ctxpopup_Item *item)
355 Evas_Coord min_w = -1, min_h = -1, max_w = -1, max_h = -1;
359 edje_object_size_min_restricted_calc(VIEW(item), &min_w, &min_h, min_w,
361 evas_object_size_hint_min_set(VIEW(item), min_w, min_h);
362 evas_object_size_hint_max_set(VIEW(item), max_w, max_h);
365 static Elm_Ctxpopup_Direction
366 _base_geometry_calc(Evas_Object *obj,
367 Evas_Coord_Rectangle *rect)
369 Elm_Ctxpopup_Direction dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
370 Evas_Coord_Rectangle hover_area;
371 Evas_Coord_Point pos = {0, 0};
372 Evas_Coord_Point arrow_size;
373 Evas_Coord_Point base_size;
374 Evas_Coord_Point max_size;
375 Evas_Coord_Point min_size;
376 Evas_Coord_Point temp;
379 ELM_CTXPOPUP_DATA_GET(obj, sd);
381 if (!rect) return ELM_CTXPOPUP_DIRECTION_DOWN;
383 edje_object_part_geometry_get
384 (sd->arrow, "ctxpopup_arrow", NULL, NULL, &arrow_size.x, &arrow_size.y);
385 evas_object_resize(sd->arrow, arrow_size.x, arrow_size.y);
387 //Initialize Area Rectangle.
388 evas_object_geometry_get
389 (sd->parent, &hover_area.x, &hover_area.y, &hover_area.w,
392 evas_object_geometry_get(obj, &pos.x, &pos.y, NULL, NULL);
395 edje_object_size_min_calc
396 (ELM_WIDGET_DATA(sd)->resize_obj, &base_size.x, &base_size.y);
397 evas_object_smart_calculate(ELM_WIDGET_DATA(sd)->resize_obj);
400 evas_object_size_hint_max_get(obj, &max_size.x, &max_size.y);
401 if ((max_size.x == -1) || (max_size.y == -1))
402 edje_object_size_max_get(sd->layout, &max_size.x, &max_size.y);
404 if ((max_size.y > 0) && (base_size.y > max_size.y))
405 base_size.y = max_size.y;
407 if ((max_size.x > 0) && (base_size.x > max_size.x))
408 base_size.x = max_size.x;
411 evas_object_size_hint_min_get(obj, &min_size.x, &min_size.y);
412 if ((min_size.x == 0) || (min_size.y == 0))
413 edje_object_size_min_get(sd->layout, &min_size.x, &min_size.y);
415 if ((min_size.y > 0) && (base_size.y < min_size.y))
416 base_size.y = min_size.y;
418 if ((min_size.x > 0) && (base_size.x < min_size.x))
419 base_size.x = min_size.x;
421 //Check the Which direction is available.
422 //If find a avaialble direction, it adjusts position and size.
423 for (idx = 0; idx < 4; idx++)
425 switch (sd->dir_priority[idx])
427 case ELM_CTXPOPUP_DIRECTION_UNKNOWN:
429 case ELM_CTXPOPUP_DIRECTION_UP:
430 temp.y = (pos.y - base_size.y);
431 if ((temp.y - arrow_size.y) < hover_area.y)
434 _x_pos_adjust(&pos, &base_size, &hover_area);
435 pos.y -= base_size.y;
436 dir = ELM_CTXPOPUP_DIRECTION_UP;
439 case ELM_CTXPOPUP_DIRECTION_LEFT:
440 temp.x = (pos.x - base_size.x);
441 if ((temp.x - arrow_size.x) < hover_area.x)
444 _y_pos_adjust(&pos, &base_size, &hover_area);
445 pos.x -= base_size.x;
446 dir = ELM_CTXPOPUP_DIRECTION_LEFT;
449 case ELM_CTXPOPUP_DIRECTION_RIGHT:
450 temp.x = (pos.x + base_size.x);
451 if ((temp.x + arrow_size.x) >
452 (hover_area.x + hover_area.w))
455 _y_pos_adjust(&pos, &base_size, &hover_area);
456 dir = ELM_CTXPOPUP_DIRECTION_RIGHT;
459 case ELM_CTXPOPUP_DIRECTION_DOWN:
460 temp.y = (pos.y + base_size.y);
461 if ((temp.y + arrow_size.y) >
462 (hover_area.y + hover_area.h))
465 _x_pos_adjust(&pos, &base_size, &hover_area);
466 dir = ELM_CTXPOPUP_DIRECTION_DOWN;
475 //In this case, all directions are invalid because of lack of space.
478 Evas_Coord length[2];
482 length[0] = pos.y - hover_area.y;
483 length[1] = (hover_area.y + hover_area.h) - pos.y;
485 // ELM_CTXPOPUP_DIRECTION_UP
486 if (length[0] > length[1])
488 _x_pos_adjust(&pos, &base_size, &hover_area);
489 pos.y -= base_size.y;
490 dir = ELM_CTXPOPUP_DIRECTION_UP;
491 if (pos.y < (hover_area.y + arrow_size.y))
493 base_size.y -= ((hover_area.y + arrow_size.y) - pos.y);
494 pos.y = hover_area.y + arrow_size.y;
497 //ELM_CTXPOPUP_DIRECTION_DOWN
500 _x_pos_adjust(&pos, &base_size, &hover_area);
501 dir = ELM_CTXPOPUP_DIRECTION_DOWN;
502 if ((pos.y + arrow_size.y + base_size.y) >
503 (hover_area.y + hover_area.h))
505 ((pos.y + arrow_size.y + base_size.y) -
506 (hover_area.y + hover_area.h));
511 length[0] = pos.x - hover_area.x;
512 length[1] = (hover_area.x + hover_area.w) - pos.x;
514 //ELM_CTXPOPUP_DIRECTION_LEFT
515 if (length[0] > length[1])
517 _y_pos_adjust(&pos, &base_size, &hover_area);
518 pos.x -= base_size.x;
519 dir = ELM_CTXPOPUP_DIRECTION_LEFT;
520 if (pos.x < (hover_area.x + arrow_size.x))
522 base_size.x -= ((hover_area.x + arrow_size.x) - pos.x);
523 pos.x = hover_area.x + arrow_size.x;
526 //ELM_CTXPOPUP_DIRECTION_RIGHT
529 _y_pos_adjust(&pos, &base_size, &hover_area);
530 dir = ELM_CTXPOPUP_DIRECTION_RIGHT;
531 if (pos.x + (arrow_size.x + base_size.x) >
532 hover_area.x + hover_area.w)
534 ((pos.x + arrow_size.x + base_size.x) -
535 (hover_area.x + hover_area.w));
540 //Final position and size.
543 rect->w = base_size.x;
544 rect->h = base_size.y;
550 _arrow_update(Evas_Object *obj,
551 Elm_Ctxpopup_Direction dir,
552 Evas_Coord_Rectangle base_size)
554 Evas_Coord_Rectangle arrow_size;
557 Evas_Coord_Rectangle shadow_left_top, shadow_right_bottom, arrow_padding;
559 ELM_CTXPOPUP_DATA_GET(obj, sd);
561 evas_object_geometry_get(obj, &x, &y, NULL, NULL);
562 evas_object_geometry_get
563 (sd->arrow, NULL, NULL, &arrow_size.w, &arrow_size.h);
565 /* tizen only : since ctxpopup of tizen has shadow, start and end padding of arrow, it should be put together when updating arrow
566 * so there are some differences between open source and tizen */
567 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);
568 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);
569 edje_object_part_geometry_get(ELM_WIDGET_DATA(sd)->resize_obj, "ctxpopup_frame_left_top", NULL, NULL, &arrow_padding.w, &arrow_padding.h);
571 /* arrow is not being kept as sub-object on purpose, here. the
572 * design of the widget does not help with the contrary */
576 case ELM_CTXPOPUP_DIRECTION_RIGHT:
577 edje_object_signal_emit(sd->arrow, "elm,state,left", "elm");
578 edje_object_part_swallow
579 (ELM_WIDGET_DATA(sd)->resize_obj,
580 (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_right" :
581 "elm.swallow.arrow_left"), sd->arrow);
585 if (y <= ((arrow_size.h * 0.5) + base_size.y + shadow_left_top.h + arrow_padding.h))
587 else if (y >= (base_size.y + base_size.h - ((arrow_size.h * 0.5) + shadow_right_bottom.h + arrow_padding.h)))
588 y = base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2));
590 y = y - base_size.y - ((arrow_size.h * 0.5) + shadow_left_top.h + arrow_padding.h);
591 drag = (double)(y) / (double)(base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2)));
592 edje_object_part_drag_value_set
593 (ELM_WIDGET_DATA(sd)->resize_obj,
594 (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_right" :
595 "elm.swallow.arrow_left"), 1, drag);
599 case ELM_CTXPOPUP_DIRECTION_LEFT:
600 edje_object_signal_emit(sd->arrow, "elm,state,right", "elm");
601 edje_object_part_swallow
602 (ELM_WIDGET_DATA(sd)->resize_obj,
603 (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_left" :
604 "elm.swallow.arrow_right"), sd->arrow);
608 if (y <= ((arrow_size.h * 0.5) + base_size.y + shadow_left_top.h + arrow_padding.h))
610 else if (y >= (base_size.y + base_size.h - ((arrow_size.h * 0.5) + shadow_right_bottom.h + arrow_padding.h)))
611 y = base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2));
613 y = y - base_size.y - ((arrow_size.h * 0.5) + shadow_left_top.h + arrow_padding.h);
614 drag = (double)(y) / (double)(base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2)));
615 edje_object_part_drag_value_set
616 (ELM_WIDGET_DATA(sd)->resize_obj,
617 (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_left" :
618 "elm.swallow.arrow_right"), 0, drag);
622 case ELM_CTXPOPUP_DIRECTION_DOWN:
623 edje_object_signal_emit(sd->arrow, "elm,state,top", "elm");
624 edje_object_part_swallow
625 (ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.arrow_up",
630 if (x <= ((arrow_size.w * 0.5) + base_size.x + shadow_left_top.w + arrow_padding.w))
632 else if (x >= (base_size.x + base_size.w - ((arrow_size.w * 0.5) + shadow_right_bottom.w + arrow_padding.w)))
633 x = base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2));
635 x = x - base_size.x - ((arrow_size.w * 0.5) + shadow_left_top.w + arrow_padding.w);
636 drag = (double)(x) / (double)(base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2)));
637 edje_object_part_drag_value_set
638 (ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.arrow_up",
643 case ELM_CTXPOPUP_DIRECTION_UP:
644 edje_object_signal_emit(sd->arrow, "elm,state,bottom", "elm");
645 edje_object_part_swallow
646 (ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.arrow_down",
651 if (x <= ((arrow_size.w * 0.5) + base_size.x + shadow_left_top.w + arrow_padding.w))
653 else if (x >= (base_size.x + base_size.w - ((arrow_size.w * 0.5) + shadow_right_bottom.w + arrow_padding.w)))
654 x = base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2));
656 x = x - base_size.x - ((arrow_size.w * 0.5) + shadow_left_top.w + arrow_padding.w);
657 drag = (double)(x) / (double)(base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2)));
658 edje_object_part_drag_value_set
659 (ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.arrow_down",
668 //should be here for getting accurate geometry value
669 evas_object_smart_calculate(ELM_WIDGET_DATA(sd)->resize_obj);
673 _show_signals_emit(Evas_Object *obj,
674 Elm_Ctxpopup_Direction dir)
676 ELM_CTXPOPUP_DATA_GET(obj, sd);
678 if (!sd->visible) return;
682 case ELM_CTXPOPUP_DIRECTION_UP:
683 edje_object_signal_emit(sd->layout, "elm,state,show,up", "elm");
686 case ELM_CTXPOPUP_DIRECTION_LEFT:
687 edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,show,right" :
688 "elm,state,show,left"), "elm");
691 case ELM_CTXPOPUP_DIRECTION_RIGHT:
692 edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,show,left" :
693 "elm,state,show,right"), "elm");
696 case ELM_CTXPOPUP_DIRECTION_DOWN:
697 edje_object_signal_emit(sd->layout, "elm,state,show,down", "elm");
704 edje_object_signal_emit(sd->bg, "elm,state,show", "elm");
705 // elm_layout_signal_emit(obj, "elm,state,show", "elm");
709 _hide_signals_emit(Evas_Object *obj,
710 Elm_Ctxpopup_Direction dir)
712 ELM_CTXPOPUP_DATA_GET(obj, sd);
714 if (!sd->visible) return;
718 case ELM_CTXPOPUP_DIRECTION_UP:
719 edje_object_signal_emit(sd->layout, "elm,state,hide,up", "elm");
722 case ELM_CTXPOPUP_DIRECTION_LEFT:
723 edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,hide,right" :
724 "elm,state,hide,left"), "elm");
727 case ELM_CTXPOPUP_DIRECTION_RIGHT:
728 edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,hide,left" :
729 "elm,state,hide,right"), "elm");
732 case ELM_CTXPOPUP_DIRECTION_DOWN:
733 edje_object_signal_emit(sd->layout, "elm,state,hide,down", "elm");
740 edje_object_signal_emit(sd->bg, "elm,state,hide", "elm");
744 _base_shift_by_arrow(Evas_Object *arrow,
745 Elm_Ctxpopup_Direction dir,
746 Evas_Coord_Rectangle *rect)
748 Evas_Coord arrow_w, arrow_h;
750 evas_object_geometry_get(arrow, NULL, NULL, &arrow_w, &arrow_h);
754 case ELM_CTXPOPUP_DIRECTION_RIGHT:
758 case ELM_CTXPOPUP_DIRECTION_LEFT:
762 case ELM_CTXPOPUP_DIRECTION_DOWN:
766 case ELM_CTXPOPUP_DIRECTION_UP:
775 //TODO: compress item - different from opensource
777 _compress_item(Evas_Object *obj)
780 Elm_Ctxpopup_Item *item;
782 ELM_CTXPOPUP_DATA_GET(obj, sd);
785 EINA_LIST_FOREACH(sd->items, elist, item)
787 edje_object_signal_emit(item->base.view, "elm,state,compress", "elm");
792 _elm_ctxpopup_smart_sub_object_add(Evas_Object *obj,
795 Elm_Widget_Smart_Class *parent_parent;
797 parent_parent = (Elm_Widget_Smart_Class *)((Evas_Smart_Class *)
798 _elm_ctxpopup_parent_sc)->parent;
800 /* skipping layout's code, which registers size hint changing
801 * callback on sub objects. a hack to make ctxpopup live, as it is,
802 * on the new classing schema. this widget needs a total
804 if (!parent_parent->sub_object_add(obj, sobj))
811 _elm_ctxpopup_smart_sizing_eval(Evas_Object *obj)
814 Elm_Ctxpopup_Item *item;
815 Evas_Coord_Rectangle rect = { 0, 0, 1, 1 };
816 Evas_Coord_Point box_size = { 0, 0 };
817 Evas_Coord_Point _box_size = { 0, 0 };
821 ELM_CTXPOPUP_DATA_GET(obj, sd);
824 EINA_LIST_FOREACH(sd->items, elist, item)
826 _item_sizing_eval(item);
827 evas_object_size_hint_min_get(VIEW(item), &_box_size.x, &_box_size.y);
829 str = edje_object_data_get(VIEW(item), "item_max_size");
833 maxw = maxw * elm_widget_scale_get(obj) * elm_config_scale_get();
835 if (_box_size.x > maxw)
837 edje_object_signal_emit(VIEW(item), "elm,state,text,ellipsis", "elm");
838 edje_object_message_signal_process(VIEW(item));
844 if (_box_size.x > box_size.x)
845 box_size.x = _box_size.x;
846 if (_box_size.y != -1)
847 box_size.y += _box_size.y;
851 if (_box_size.x != -1)
852 box_size.x += _box_size.x;
853 if (_box_size.y > box_size.y)
854 box_size.y = _box_size.y;
858 if (!sd->arrow) return; /* simple way to flag "under deletion" */
860 if ((!sd->content) && (sd->scr))
862 evas_object_size_hint_min_set(sd->box, box_size.x, box_size.y);
863 elm_scroller_content_min_limit(sd->scr, EINA_TRUE, EINA_TRUE);
864 evas_object_size_hint_min_set(sd->scr, box_size.x, box_size.y);
868 sd->dir = _base_geometry_calc(obj, &rect);
870 //TODO: compress item - different from opensource
871 if (!sd->horizontal && !sd->content)
874 _arrow_update(obj, sd->dir, rect);
875 _base_shift_by_arrow(sd->arrow, sd->dir, &rect);
877 //resize scroller according to final size
878 if ((!sd->content) && (sd->scr))
880 elm_scroller_content_min_limit(sd->scr, EINA_FALSE, EINA_FALSE);
881 evas_object_smart_calculate(sd->scr);
884 evas_object_size_hint_min_set(ELM_WIDGET_DATA(sd)->resize_obj, rect.w, rect.h);
885 evas_object_resize(ELM_WIDGET_DATA(sd)->resize_obj, rect.w, rect.h);
887 evas_object_move(sd->layout, rect.x, rect.y);
888 evas_object_resize(sd->layout, rect.w, rect.h);
890 _show_signals_emit(obj, sd->dir);
894 _on_parent_del(void *data,
896 Evas_Object *obj __UNUSED__,
897 void *event_info __UNUSED__)
899 evas_object_del(data);
903 _on_parent_move(void *data,
905 Evas_Object *obj __UNUSED__,
906 void *event_info __UNUSED__)
908 ELM_CTXPOPUP_DATA_GET(data, sd);
911 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
915 _scroller_size_reset(sd);
916 elm_layout_sizing_eval(data);
921 _on_parent_resize(void *data,
923 Evas_Object *obj __UNUSED__,
924 void *event_info __UNUSED__)
926 ELM_CTXPOPUP_DATA_GET(data, sd);
928 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
930 evas_object_hide(data);
931 evas_object_smart_callback_call(data, SIG_DISMISSED, NULL);
935 _parent_detach(Evas_Object *obj)
937 ELM_CTXPOPUP_DATA_GET(obj, sd);
939 if (!sd->parent) return;
941 evas_object_event_callback_del_full
942 (sd->parent, EVAS_CALLBACK_DEL, _on_parent_del, obj);
943 evas_object_event_callback_del_full
944 (sd->parent, EVAS_CALLBACK_MOVE, _on_parent_move, obj);
945 evas_object_event_callback_del_full
946 (sd->parent, EVAS_CALLBACK_RESIZE, _on_parent_resize, obj);
950 _on_content_resized(void *data,
952 Evas_Object *obj __UNUSED__,
953 void *event_info __UNUSED__)
955 ELM_CTXPOPUP_DATA_GET(data, sd);
957 elm_box_recalculate(sd->box);
958 elm_layout_sizing_eval(data);
961 //FIXME: lost the content size when theme hook is called.
963 _elm_ctxpopup_smart_theme(Evas_Object *obj)
966 Elm_Ctxpopup_Item *item;
970 ELM_CTXPOPUP_DATA_GET(obj, sd);
972 if (!ELM_WIDGET_CLASS(_elm_ctxpopup_parent_sc)->theme(obj))
975 rtl = elm_widget_mirrored_get(obj);
977 elm_widget_theme_object_set
978 (obj, sd->bg, "ctxpopup", "bg", elm_widget_style_get(obj));
979 elm_widget_theme_object_set
980 (obj, sd->arrow, "ctxpopup", "arrow", elm_widget_style_get(obj));
981 elm_widget_theme_object_set
982 (obj, sd->layout, "ctxpopup", "layout", elm_widget_style_get(obj));
985 EINA_LIST_FOREACH(sd->items, elist, item)
987 edje_object_mirrored_set(VIEW(item), rtl);
989 if (item->label && item->icon)
990 _elm_theme_object_set
991 (obj, VIEW(item), "ctxpopup", "icon_text_style_item", elm_widget_style_get(obj));
992 else if (item->label)
995 _elm_theme_object_set(obj, VIEW(item), "ctxpopup", "text_style_item",
996 elm_widget_style_get(obj));
998 _elm_theme_object_set(obj, VIEW(item), "ctxpopup", "text_style_item_horizontal",
999 elm_widget_style_get(obj));
1001 else if (item->icon)
1002 _elm_theme_object_set
1003 (obj, VIEW(item), "ctxpopup", "icon_style_item", elm_widget_style_get(obj));
1005 edje_object_part_text_set(VIEW(item), "elm.text", item->label);
1007 if (elm_widget_item_disabled_get(item))
1008 edje_object_signal_emit(VIEW(item), "elm,state,disabled", "elm");
1011 * For separator, if the first item has visible separator,
1012 * then it should be aligned with edge of the base part.
1013 * In some cases, it gives improper display. Ex) rounded corner
1014 * So the first item separator should be invisible.
1017 edje_object_signal_emit(VIEW(item), "elm,state,default", "elm");
1019 edje_object_signal_emit(VIEW(item), "elm,state,separator", "elm");
1021 edje_object_message_signal_process(VIEW(item));
1024 if (evas_object_visible_get(sd->bg))
1025 edje_object_signal_emit(sd->bg, "elm,state,show", "elm");
1029 if (!strncmp(elm_object_style_get(obj), "default", strlen("default")))
1030 elm_object_style_set(sd->scr, "ctxpopup");
1032 elm_object_style_set(sd->scr, elm_object_style_get(obj));
1035 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1039 _scroller_size_reset(sd);
1040 _elm_ctxpopup_smart_sizing_eval(obj);
1046 /* kind of a big and tricky override here: an internal box will hold
1047 * the actual content. content aliases won't be of much help here */
1049 _elm_ctxpopup_smart_content_set(Evas_Object *obj,
1051 Evas_Object *content)
1053 Evas_Coord min_w = -1, min_h = -1;
1055 ELM_CTXPOPUP_DATA_GET(obj, sd);
1057 if ((part) && (strcmp(part, "default")))
1058 return ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_set
1059 (obj, part, content);
1061 if (!content) return EINA_FALSE;
1063 if (content == sd->content) return EINA_TRUE;
1065 if (sd->items) elm_ctxpopup_clear(obj);
1066 if (sd->content) evas_object_del(sd->content);
1071 sd->box = elm_box_add(obj);
1072 evas_object_size_hint_weight_set(sd->box, EVAS_HINT_EXPAND,
1074 evas_object_event_callback_add
1075 (sd->box, EVAS_CALLBACK_RESIZE, _on_content_resized, obj);
1076 ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_set
1077 (obj, "elm.swallow.content", sd->box);
1080 evas_object_size_hint_weight_set
1081 (content, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1082 evas_object_size_hint_fill_set
1083 (content, EVAS_HINT_FILL, EVAS_HINT_FILL);
1085 /* since it's going to be a box content, not a layout's... */
1086 evas_object_show(content);
1088 evas_object_size_hint_min_get(content, &min_w, &min_h);
1089 evas_object_size_hint_min_set(sd->box, min_w, min_h);
1090 elm_box_pack_end(sd->box, content);
1092 sd->content = content;
1093 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1095 if (sd->visible) elm_layout_sizing_eval(obj);
1100 static Evas_Object *
1101 _elm_ctxpopup_smart_content_get(const Evas_Object *obj,
1104 ELM_CTXPOPUP_DATA_GET(obj, sd);
1106 if ((part) && (strcmp(part, "default")))
1107 return ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_get
1113 static Evas_Object *
1114 _elm_ctxpopup_smart_content_unset(Evas_Object *obj,
1117 Evas_Object *content;
1119 ELM_CTXPOPUP_DATA_GET(obj, sd);
1121 if ((part) && (strcmp(part, "default")))
1122 return ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_unset
1125 content = sd->content;
1126 if (!content) return NULL;
1128 evas_object_del(sd->box);
1131 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1133 if (sd->visible) elm_layout_sizing_eval(obj);
1139 _item_text_set_hook(Elm_Object_Item *it,
1143 Elm_Ctxpopup_Item *ctxpopup_it;
1145 if ((part) && (strcmp(part, "default"))) return;
1147 ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1149 _item_label_set(ctxpopup_it, label);
1153 _item_text_get_hook(const Elm_Object_Item *it,
1156 Elm_Ctxpopup_Item *ctxpopup_it;
1158 if (part && strcmp(part, "default")) return NULL;
1160 ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1161 return ctxpopup_it->label;
1165 _item_content_set_hook(Elm_Object_Item *it,
1167 Evas_Object *content)
1169 Elm_Ctxpopup_Item *ctxpopup_it;
1171 if ((part) && (strcmp(part, "icon"))) return;
1173 ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1175 ELM_CTXPOPUP_DATA_GET(WIDGET(ctxpopup_it), sd);
1177 _item_icon_set(ctxpopup_it, content);
1178 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1182 _scroller_size_reset(sd);
1183 _elm_ctxpopup_smart_sizing_eval(WIDGET(ctxpopup_it));
1187 static Evas_Object *
1188 _item_content_get_hook(const Elm_Object_Item *it,
1191 Elm_Ctxpopup_Item *ctxpopup_it;
1193 if (part && strcmp(part, "icon")) return NULL;
1195 ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1196 return ctxpopup_it->icon;
1200 _item_disable_hook(Elm_Object_Item *it)
1202 Elm_Ctxpopup_Item *ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1204 ELM_CTXPOPUP_DATA_GET(WIDGET(it), sd);
1207 if (elm_widget_item_disabled_get(it))
1208 edje_object_signal_emit(VIEW(ctxpopup_it), "elm,state,disabled", "elm");
1210 edje_object_signal_emit(VIEW(ctxpopup_it), "elm,state,enabled", "elm");
1214 _item_signal_emit_hook(Elm_Object_Item *it,
1215 const char *emission,
1218 Elm_Ctxpopup_Item *ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1220 edje_object_signal_emit(VIEW(ctxpopup_it), emission, source);
1224 _bg_clicked_cb(void *data,
1225 Evas_Object *obj __UNUSED__,
1226 const char *emission __UNUSED__,
1227 const char *source __UNUSED__)
1229 ELM_CTXPOPUP_DATA_GET(data, sd);
1231 _hide_signals_emit(data, sd->dir);
1235 _on_show(void *data __UNUSED__,
1238 void *event_info __UNUSED__)
1241 Elm_Ctxpopup_Item *item;
1244 ELM_CTXPOPUP_DATA_GET(obj, sd);
1246 if ((!sd->items) && (!sd->content)) return;
1248 sd->visible = EINA_TRUE;
1250 evas_object_show(sd->bg);
1251 evas_object_show(sd->arrow);
1252 evas_object_show(sd->layout);
1254 edje_object_signal_emit(sd->bg, "elm,state,show", "elm");
1255 elm_layout_signal_emit(obj, "elm,state,show", "elm");
1257 EINA_LIST_FOREACH(sd->items, elist, item)
1259 if (item->label && !item->icon)
1262 _elm_theme_object_set(obj, VIEW(item), "ctxpopup", "text_style_item",
1263 elm_widget_style_get(obj));
1265 _elm_theme_object_set(obj, VIEW(item), "ctxpopup", "text_style_item_horizontal",
1266 elm_widget_style_get(obj));
1270 edje_object_signal_emit(VIEW(item), "elm,state,default", "elm");
1272 edje_object_signal_emit(VIEW(item), "elm,state,separator", "elm");
1275 elm_layout_sizing_eval(obj);
1277 elm_object_focus_set(obj, EINA_TRUE);
1281 _on_hide(void *data __UNUSED__,
1284 void *event_info __UNUSED__)
1286 ELM_CTXPOPUP_DATA_GET(obj, sd);
1288 if (!sd->visible) return;
1290 evas_object_hide(sd->bg);
1291 evas_object_hide(sd->arrow);
1292 evas_object_hide(sd->layout);
1294 _scroller_size_reset(sd);
1296 sd->visible = EINA_FALSE;
1300 _on_move(void *data __UNUSED__,
1303 void *event_info __UNUSED__)
1305 ELM_CTXPOPUP_DATA_GET(obj, sd);
1307 if (sd->visible) evas_object_show(sd->arrow);
1309 _scroller_size_reset(sd);
1310 _elm_ctxpopup_smart_sizing_eval(obj);
1314 _hide_finished_cb(void *data,
1315 Evas_Object *obj __UNUSED__,
1316 const char *emission __UNUSED__,
1317 const char *source __UNUSED__)
1319 evas_object_hide(data);
1320 evas_object_smart_callback_call(data, SIG_DISMISSED, NULL);
1324 _scroller_resize(void *data, Evas *e __UNUSED__,
1326 void *event_info __UNUSED__)
1330 ELM_CTXPOPUP_DATA_GET(data, sd);
1332 if (!sd->visible) return;
1333 if (sd->finished) return;
1335 evas_object_geometry_get(obj, 0, 0, &w, &h);
1337 if (w != 0 && h != 0)
1339 if ((w <= sd->max_sc_w) && (h <= sd->max_sc_h))
1341 _elm_ctxpopup_smart_sizing_eval(data);
1342 sd->finished = EINA_TRUE;
1347 if (sd->max_sc_w < w)
1349 if (sd->max_sc_h < h)
1352 _elm_ctxpopup_smart_sizing_eval(data);
1356 _ctxpopup_restack_cb(void *data __UNUSED__,
1359 void *event_info __UNUSED__)
1361 ELM_CTXPOPUP_DATA_GET(obj, sd);
1362 evas_object_stack_below(sd->bg, obj);
1363 evas_object_stack_below(sd->layout, obj);
1367 _list_del(Elm_Ctxpopup_Smart_Data *sd)
1369 if (!sd->scr) return;
1371 edje_object_part_unswallow(ELM_WIDGET_DATA(sd)->resize_obj, sd->scr);
1372 evas_object_del(sd->scr);
1374 evas_object_del(sd->box);
1379 _list_new(Evas_Object *obj)
1381 ELM_CTXPOPUP_DATA_GET(obj, sd);
1385 sd->scr = elm_scroller_add(obj);
1386 elm_object_style_set(sd->scr, "ctxpopup");
1387 evas_object_size_hint_align_set(sd->scr, EVAS_HINT_FILL, EVAS_HINT_FILL);
1388 evas_object_event_callback_add(sd->scr, EVAS_CALLBACK_RESIZE,
1389 _scroller_resize, obj);
1390 edje_object_part_swallow(ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.content", sd->scr);
1395 sd->box = elm_box_add(obj);
1396 evas_object_size_hint_weight_set(sd->box, EVAS_HINT_EXPAND,
1398 evas_object_event_callback_add
1399 (sd->box, EVAS_CALLBACK_RESIZE, _on_content_resized, obj);
1400 ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_set
1401 (obj, "elm.swallow.content", sd->box);
1404 elm_object_content_set(sd->scr, sd->box);
1405 elm_ctxpopup_horizontal_set(obj, sd->horizontal);
1409 _elm_ctxpopup_smart_disable(Evas_Object *obj)
1412 Elm_Object_Item *it;
1414 ELM_CTXPOPUP_DATA_GET(obj, sd);
1416 if (!ELM_WIDGET_CLASS(_elm_ctxpopup_parent_sc)->disable(obj))
1419 EINA_LIST_FOREACH(sd->items, l, it)
1420 elm_object_item_disabled_set(it, elm_widget_disabled_get(obj));
1426 _elm_ctxpopup_smart_add(Evas_Object *obj)
1428 EVAS_SMART_DATA_ALLOC(obj, Elm_Ctxpopup_Smart_Data);
1429 ELM_CTXPOPUP_DATA_GET(obj, sd);
1431 ELM_WIDGET_CLASS(_elm_ctxpopup_parent_sc)->base.add(obj);
1433 elm_layout_theme_set(obj, "ctxpopup", "base", elm_widget_style_get(obj));
1434 elm_layout_signal_callback_add
1435 (obj, "elm,action,hide,finished", "", _hide_finished_cb, obj);
1438 priv->bg = edje_object_add(evas_object_evas_get(obj));
1439 elm_widget_theme_object_set(obj, priv->bg, "ctxpopup", "bg", "default");
1440 edje_object_signal_callback_add
1441 (priv->bg, "elm,action,click", "", _bg_clicked_cb, obj);
1443 evas_object_stack_below(priv->bg, obj);
1446 priv->arrow = edje_object_add(evas_object_evas_get(obj));
1447 elm_widget_theme_object_set
1448 (obj, priv->arrow, "ctxpopup", "arrow", "default");
1450 priv->dir_priority[0] = ELM_CTXPOPUP_DIRECTION_UP;
1451 priv->dir_priority[1] = ELM_CTXPOPUP_DIRECTION_LEFT;
1452 priv->dir_priority[2] = ELM_CTXPOPUP_DIRECTION_RIGHT;
1453 priv->dir_priority[3] = ELM_CTXPOPUP_DIRECTION_DOWN;
1454 priv->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1456 evas_object_event_callback_add
1457 (obj, EVAS_CALLBACK_RESTACK, _ctxpopup_restack_cb, obj);
1459 evas_object_smart_callback_add
1460 (obj, "scroll-freeze-on", _freeze_on_cb, obj);
1461 evas_object_smart_callback_add
1462 (obj, "scroll-freeze-off", _freeze_off_cb, obj);
1463 evas_object_smart_callback_add
1464 (obj, "scroll-hold-on", _hold_on_cb, obj);
1465 evas_object_smart_callback_add
1466 (obj, "scroll-hold-off", _hold_off_cb, obj);
1468 priv->box = elm_box_add(obj);
1469 evas_object_size_hint_weight_set
1470 (priv->box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1472 evas_object_event_callback_add
1473 (priv->box, EVAS_CALLBACK_RESIZE, _on_content_resized, obj);
1475 /* box will be our content placeholder, thus the parent's version call */
1476 ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_set
1477 (obj, "elm.swallow.content", priv->box);
1479 priv->layout = edje_object_add(evas_object_evas_get(obj));
1480 elm_widget_theme_object_set(obj, priv->layout, "ctxpopup", "layout", "default");
1482 edje_object_signal_callback_add
1483 (priv->layout, "elm,action,hide,finished", "", _hide_finished_cb, obj);
1484 edje_object_part_swallow(priv->layout, "swallow", ELM_WIDGET_DATA(sd)->resize_obj);
1485 evas_object_size_hint_weight_set
1486 (priv->layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1488 evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _on_show, NULL);
1489 evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _on_hide, NULL);
1490 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _on_move, NULL);
1492 elm_widget_can_focus_set(obj, EINA_TRUE);
1496 _elm_ctxpopup_smart_del(Evas_Object *obj)
1498 ELM_CTXPOPUP_DATA_GET(obj, sd);
1500 evas_object_event_callback_del_full
1501 (sd->box, EVAS_CALLBACK_RESIZE, _on_content_resized, obj);
1502 _parent_detach(obj);
1504 elm_ctxpopup_clear(obj);
1505 evas_object_del(sd->arrow);
1506 sd->arrow = NULL; /* stops _sizing_eval() from going on on deletion */
1508 evas_object_del(sd->bg);
1511 evas_object_del(sd->layout);
1514 ELM_WIDGET_CLASS(_elm_ctxpopup_parent_sc)->base.del(obj);
1518 _elm_ctxpopup_smart_parent_set(Evas_Object *obj,
1519 Evas_Object *parent)
1521 //default parent is to be hover parent
1522 elm_ctxpopup_hover_parent_set(obj, parent);
1526 _elm_ctxpopup_smart_access(Evas_Object *obj, Eina_Bool is_access)
1528 Eina_List *elist = NULL;
1529 Elm_Ctxpopup_Item *it;
1531 ELM_CTXPOPUP_CHECK(obj);
1532 ELM_CTXPOPUP_DATA_GET(obj, sd);
1534 EINA_LIST_FOREACH(sd->items, elist, it)
1535 _access_widget_item_register(it, is_access);
1539 _elm_ctxpopup_smart_set_user(Elm_Ctxpopup_Smart_Class *sc)
1541 ELM_WIDGET_CLASS(sc)->base.add = _elm_ctxpopup_smart_add;
1542 ELM_WIDGET_CLASS(sc)->base.del = _elm_ctxpopup_smart_del;
1544 ELM_WIDGET_CLASS(sc)->parent_set = _elm_ctxpopup_smart_parent_set;
1545 ELM_WIDGET_CLASS(sc)->disable = _elm_ctxpopup_smart_disable;
1546 ELM_WIDGET_CLASS(sc)->event = _elm_ctxpopup_smart_event;
1547 ELM_WIDGET_CLASS(sc)->theme = _elm_ctxpopup_smart_theme;
1548 ELM_WIDGET_CLASS(sc)->sub_object_add = _elm_ctxpopup_smart_sub_object_add;
1549 ELM_WIDGET_CLASS(sc)->focus_next = _elm_ctxpopup_smart_focus_next;
1550 ELM_WIDGET_CLASS(sc)->focus_direction = NULL;
1551 ELM_WIDGET_CLASS(sc)->translate = _elm_ctxpopup_smart_translate;
1553 ELM_CONTAINER_CLASS(sc)->content_get = _elm_ctxpopup_smart_content_get;
1554 ELM_CONTAINER_CLASS(sc)->content_set = _elm_ctxpopup_smart_content_set;
1555 ELM_CONTAINER_CLASS(sc)->content_unset = _elm_ctxpopup_smart_content_unset;
1557 ELM_LAYOUT_CLASS(sc)->sizing_eval = _elm_ctxpopup_smart_sizing_eval;
1559 ELM_WIDGET_CLASS(sc)->access = _elm_ctxpopup_smart_access;
1562 EAPI const Elm_Ctxpopup_Smart_Class *
1563 elm_ctxpopup_smart_class_get(void)
1565 static Elm_Ctxpopup_Smart_Class _sc =
1566 ELM_CTXPOPUP_SMART_CLASS_INIT_NAME_VERSION(ELM_CTXPOPUP_SMART_NAME);
1567 static const Elm_Ctxpopup_Smart_Class *class = NULL;
1568 Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
1573 _elm_ctxpopup_smart_set(&_sc);
1574 esc->callbacks = _smart_callbacks;
1581 elm_ctxpopup_add(Evas_Object *parent)
1585 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1587 obj = elm_widget_add(_elm_ctxpopup_smart_class_new(), parent);
1588 if (!obj) return NULL;
1590 if (!elm_widget_sub_object_add(parent, obj))
1591 ERR("could not add %p as sub object of %p", obj, parent);
1593 /* access: parent could be any object such as elm_list which does
1594 not know elc_ctxpopup as its child object in the focus_next(); */
1595 ELM_WIDGET_DATA_GET(obj, sd);
1596 sd->highlight_root = EINA_TRUE;
1602 elm_ctxpopup_hover_parent_set(Evas_Object *obj,
1603 Evas_Object *parent)
1605 Evas_Coord x, y, w, h;
1607 ELM_CTXPOPUP_CHECK(obj);
1608 ELM_CTXPOPUP_DATA_GET(obj, sd);
1610 if (!parent) return;
1612 _parent_detach(obj);
1614 evas_object_event_callback_add
1615 (parent, EVAS_CALLBACK_DEL, _on_parent_del, obj);
1616 evas_object_event_callback_add
1617 (parent, EVAS_CALLBACK_MOVE, _on_parent_move, obj);
1618 evas_object_event_callback_add
1619 (parent, EVAS_CALLBACK_RESIZE, _on_parent_resize, obj);
1621 sd->parent = parent;
1624 evas_object_geometry_get(parent, &x, &y, &w, &h);
1625 evas_object_move(sd->bg, x, y);
1626 evas_object_resize(sd->bg, w, h);
1628 if (sd->visible) elm_layout_sizing_eval(obj);
1632 elm_ctxpopup_hover_parent_get(const Evas_Object *obj)
1634 ELM_CTXPOPUP_CHECK(obj) NULL;
1635 ELM_CTXPOPUP_DATA_GET(obj, sd);
1641 elm_ctxpopup_clear(Evas_Object *obj)
1643 ELM_CTXPOPUP_CHECK(obj);
1644 ELM_CTXPOPUP_DATA_GET(obj, sd);
1648 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1652 elm_ctxpopup_horizontal_set(Evas_Object *obj,
1653 Eina_Bool horizontal)
1656 Elm_Ctxpopup_Item *item;
1659 ELM_CTXPOPUP_CHECK(obj);
1660 ELM_CTXPOPUP_DATA_GET(obj, sd);
1662 sd->horizontal = !!horizontal;
1669 elm_box_horizontal_set(sd->box, EINA_FALSE);
1670 elm_scroller_bounce_set(sd->scr, EINA_FALSE, EINA_TRUE);
1674 elm_box_horizontal_set(sd->box, EINA_TRUE);
1675 elm_scroller_bounce_set(sd->scr, EINA_TRUE, EINA_FALSE);
1678 EINA_LIST_FOREACH(sd->items, elist, item)
1680 if (item->label && !item->icon && !horizontal)
1681 _elm_theme_object_set(obj, VIEW(item), "ctxpopup", "text_style_item",
1682 elm_widget_style_get(obj));
1683 else if (item->label && !item->icon && horizontal)
1684 _elm_theme_object_set(obj, VIEW(item), "ctxpopup", "text_style_item_horizontal",
1685 elm_widget_style_get(obj));
1688 edje_object_signal_emit(VIEW(item), "elm,state,default", "elm");
1690 edje_object_signal_emit(VIEW(item), "elm,state,separator", "elm");
1692 _item_disable_hook((Elm_Object_Item *)item);
1695 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1697 if (sd->visible) elm_layout_sizing_eval(obj);
1701 elm_ctxpopup_horizontal_get(const Evas_Object *obj)
1703 ELM_CTXPOPUP_CHECK(obj) EINA_FALSE;
1704 ELM_CTXPOPUP_DATA_GET(obj, sd);
1706 return sd->horizontal;
1709 EAPI Elm_Object_Item *
1710 elm_ctxpopup_item_append(Evas_Object *obj,
1716 Elm_Ctxpopup_Item *item;
1717 Evas_Object *content;
1719 ELM_CTXPOPUP_CHECK(obj) NULL;
1720 ELM_CTXPOPUP_DATA_GET(obj, sd);
1722 item = elm_widget_item_new(obj, Elm_Ctxpopup_Item);
1723 if (!item) return NULL;
1725 elm_widget_item_del_pre_hook_set(item, _item_del_pre_hook);
1726 elm_widget_item_disable_hook_set(item, _item_disable_hook);
1727 elm_widget_item_text_set_hook_set(item, _item_text_set_hook);
1728 elm_widget_item_text_get_hook_set(item, _item_text_get_hook);
1729 elm_widget_item_content_set_hook_set(item, _item_content_set_hook);
1730 elm_widget_item_content_get_hook_set(item, _item_content_get_hook);
1731 elm_widget_item_signal_emit_hook_set(item, _item_signal_emit_hook);
1733 //The first item is appended.
1734 content = elm_object_content_unset(obj);
1735 if (content) evas_object_del(content);
1741 item->base.data = data;
1744 _item_new(item, "icon_text_style_item");
1747 if (!sd->horizontal)
1748 _item_new(item, "text_style_item");
1750 _item_new(item, "text_style_item_horizontal");
1753 _item_new(item, "icon_style_item");
1755 _item_icon_set(item, icon);
1756 _item_label_set(item, label);
1757 elm_box_pack_end(sd->box, VIEW(item));
1758 sd->items = eina_list_append(sd->items, item);
1760 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1764 _scroller_size_reset(sd);
1765 _elm_ctxpopup_smart_sizing_eval(obj);
1769 return (Elm_Object_Item *)item;
1773 elm_ctxpopup_direction_priority_set(Evas_Object *obj,
1774 Elm_Ctxpopup_Direction first,
1775 Elm_Ctxpopup_Direction second,
1776 Elm_Ctxpopup_Direction third,
1777 Elm_Ctxpopup_Direction fourth)
1779 ELM_CTXPOPUP_CHECK(obj);
1780 ELM_CTXPOPUP_DATA_GET(obj, sd);
1782 sd->dir_priority[0] = first;
1783 sd->dir_priority[1] = second;
1784 sd->dir_priority[2] = third;
1785 sd->dir_priority[3] = fourth;
1787 if (sd->visible) elm_layout_sizing_eval(obj);
1791 elm_ctxpopup_direction_priority_get(Evas_Object *obj,
1792 Elm_Ctxpopup_Direction *first,
1793 Elm_Ctxpopup_Direction *second,
1794 Elm_Ctxpopup_Direction *third,
1795 Elm_Ctxpopup_Direction *fourth)
1797 ELM_CTXPOPUP_CHECK(obj);
1798 ELM_CTXPOPUP_DATA_GET(obj, sd);
1800 if (first) *first = sd->dir_priority[0];
1801 if (second) *second = sd->dir_priority[1];
1802 if (third) *third = sd->dir_priority[2];
1803 if (fourth) *fourth = sd->dir_priority[3];
1806 EAPI Elm_Ctxpopup_Direction
1807 elm_ctxpopup_direction_get(const Evas_Object *obj)
1809 ELM_CTXPOPUP_CHECK(obj) ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1810 ELM_CTXPOPUP_DATA_GET(obj, sd);
1816 elm_ctxpopup_dismiss(Evas_Object *obj)
1818 ELM_CTXPOPUP_CHECK(obj);
1819 ELM_CTXPOPUP_DATA_GET(obj, sd);
1821 _hide_signals_emit(obj, sd->dir);