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_focus_direction(const Evas_Object *obj,
58 const Evas_Object *base,
60 Evas_Object **direction,
65 void *(*list_data_get)(const Eina_List *list);
67 ELM_CTXPOPUP_DATA_GET(obj, sd);
72 list_data_get = eina_list_data_get;
74 l = eina_list_append(l, sd->box);
75 ret = elm_widget_focus_list_direction_get
76 (obj, base, l, list_data_get, degree, direction, weight);
83 _elm_ctxpopup_smart_event(Evas_Object *obj,
84 Evas_Object *src __UNUSED__,
85 Evas_Callback_Type type,
88 Evas_Event_Key_Down *ev = event_info;
90 ELM_CTXPOPUP_DATA_GET(obj, sd);
92 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
93 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
94 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
96 if (!strcmp(ev->keyname, "Tab"))
98 if (evas_key_modifier_is_set(ev->modifiers, "Shift"))
99 elm_widget_focus_cycle(sd->box, ELM_FOCUS_PREVIOUS);
101 elm_widget_focus_cycle(sd->box, ELM_FOCUS_NEXT);
105 if (strcmp(ev->keyname, "Escape")) return EINA_FALSE;
107 evas_object_hide(obj);
108 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
113 _freeze_on_cb(void *data __UNUSED__,
115 void *event_info __UNUSED__)
117 ELM_CTXPOPUP_DATA_GET(obj, sd);
119 if ((!sd) || (!sd->scr)) return;
120 elm_object_scroll_freeze_push(sd->scr);
124 _freeze_off_cb(void *data __UNUSED__,
126 void *event_info __UNUSED__)
128 ELM_CTXPOPUP_DATA_GET(obj, sd);
130 if ((!sd) || (!sd->scr)) return;
131 elm_object_scroll_freeze_pop(sd->scr);
135 _hold_on_cb(void *data __UNUSED__,
137 void *event_info __UNUSED__)
139 ELM_CTXPOPUP_DATA_GET(obj, sd);
141 if ((!sd) || (!sd->scr)) return;
142 elm_object_scroll_hold_push(sd->scr);
146 _hold_off_cb(void *data __UNUSED__,
148 void *event_info __UNUSED__)
150 ELM_CTXPOPUP_DATA_GET(obj, sd);
152 if ((!sd) || (!sd->scr)) return;
153 elm_object_scroll_hold_pop(sd->scr);
157 _x_pos_adjust(Evas_Coord_Point *pos,
158 Evas_Coord_Point *base_size,
159 Evas_Coord_Rectangle *hover_area)
161 pos->x -= (base_size->x / 2);
163 if (pos->x < hover_area->x)
164 pos->x = hover_area->x;
165 else if ((pos->x + base_size->x) > (hover_area->x + hover_area->w))
166 pos->x = (hover_area->x + hover_area->w) - base_size->x;
168 if (base_size->x > hover_area->w)
169 base_size->x -= (base_size->x - hover_area->w);
171 if (pos->x < hover_area->x)
172 pos->x = hover_area->x;
176 _y_pos_adjust(Evas_Coord_Point *pos,
177 Evas_Coord_Point *base_size,
178 Evas_Coord_Rectangle *hover_area)
180 pos->y -= (base_size->y / 2);
182 if (pos->y < hover_area->y)
183 pos->y = hover_area->y;
184 else if ((pos->y + base_size->y) > (hover_area->y + hover_area->h))
185 pos->y = hover_area->y + hover_area->h - base_size->y;
187 if (base_size->y > hover_area->h)
188 base_size->y -= (base_size->y - hover_area->h);
190 if (pos->y < hover_area->y)
191 pos->y = hover_area->y;
195 _item_select_cb(void *data, Evas_Object *obj __UNUSED__,
196 const char *emission __UNUSED__,
197 const char *source __UNUSED__)
199 Elm_Ctxpopup_Item *item = data;
202 if (elm_widget_item_disabled_get(item)) return;
205 item->func((void*)item->base.data, WIDGET(item), data);
209 _access_info_cb(void *data, Evas_Object *obj __UNUSED__)
211 Elm_Ctxpopup_Item *it = (Elm_Ctxpopup_Item *)data;
212 const char *txt = NULL;
213 Evas_Object *icon = NULL;
214 Eina_Strbuf *buf = NULL;
217 if (!it) return NULL;
219 if ((!txt) && (!icon))
224 else if (!txt) txt = it->label;
225 else if (!icon) icon = it->icon;
229 buf = eina_strbuf_new();
230 eina_strbuf_append(buf, E_("icon "));
231 eina_strbuf_append(buf, txt);
232 str = eina_strbuf_string_steal(buf);
233 eina_strbuf_free(buf);
236 else if ((!txt) && icon) return strdup(E_("icon"));
237 else if (txt && (!icon)) return strdup(txt);
243 _access_state_cb(void *data, Evas_Object *obj __UNUSED__)
245 Elm_Ctxpopup_Item *it = (Elm_Ctxpopup_Item *)data;
246 if (!it) return NULL;
248 if (it->base.disabled)
249 return strdup(E_("State: Disabled"));
255 _access_activate_cb(void *data __UNUSED__,
256 Evas_Object *part_obj __UNUSED__,
257 Elm_Object_Item *item)
259 _item_select_cb(item, NULL, NULL, NULL);
263 _access_widget_item_register(Elm_Ctxpopup_Item *it, Eina_Bool is_access)
267 if (!is_access) _elm_access_widget_item_unregister((Elm_Widget_Item *)it);
270 _elm_access_widget_item_register((Elm_Widget_Item *)it);
272 ai = _elm_access_object_get(it->base.access_obj);
274 _elm_access_callback_set(ai, ELM_ACCESS_INFO, _access_info_cb, it);
275 _elm_access_callback_set(ai, ELM_ACCESS_STATE, _access_state_cb, it);
276 _elm_access_text_set(ai, ELM_ACCESS_TYPE, E_("Contextual Popup"));
277 _elm_access_activate_callback_set(ai, _access_activate_cb, it);
282 _item_new(Elm_Ctxpopup_Item *item,
285 ELM_CTXPOPUP_DATA_GET(WIDGET(item), sd);
288 VIEW(item) = edje_object_add(evas_object_evas_get(sd->box));
289 edje_object_mirrored_set(VIEW(item), elm_widget_mirrored_get(WIDGET(item)));
290 _elm_theme_object_set(WIDGET(item), VIEW(item), "ctxpopup", group_name,
291 elm_widget_style_get(WIDGET(item)));
292 edje_object_signal_callback_add(VIEW(item), "elm,action,click", "",
293 _item_select_cb, item);
294 evas_object_size_hint_align_set(VIEW(item), EVAS_HINT_FILL, EVAS_HINT_FILL);
295 evas_object_show(VIEW(item));
298 if (_elm_config->access_mode) _access_widget_item_register(item, EINA_TRUE);
302 _item_icon_set(Elm_Ctxpopup_Item *item,
306 evas_object_del(item->icon);
311 edje_object_part_swallow(VIEW(item), "elm.swallow.icon", item->icon);
312 edje_object_message_signal_process(VIEW(item));
316 _item_label_set(Elm_Ctxpopup_Item *item,
319 if (!eina_stringshare_replace(&item->label, label))
322 edje_object_part_text_set(VIEW(item), "elm.text", label);
323 edje_object_message_signal_process(VIEW(item));
327 _item_del_pre_hook(Elm_Object_Item *it)
329 Elm_Ctxpopup_Item *ctxpopup_it = (Elm_Ctxpopup_Item *)it;
331 ELM_CTXPOPUP_DATA_GET(WIDGET(ctxpopup_it), sd);
332 if (!sd) return EINA_FALSE;
334 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
336 if (ctxpopup_it->icon)
337 evas_object_del(ctxpopup_it->icon);
338 if (VIEW(ctxpopup_it))
339 evas_object_del(VIEW(ctxpopup_it));
341 eina_stringshare_del(ctxpopup_it->label);
342 sd->items = eina_list_remove(sd->items, ctxpopup_it);
344 if (eina_list_count(sd->items) < 1)
346 evas_object_hide(WIDGET(ctxpopup_it));
349 if (sd->visible) elm_layout_sizing_eval(WIDGET(ctxpopup_it));
355 _items_remove(Elm_Ctxpopup_Smart_Data *sd)
358 Elm_Ctxpopup_Item *item;
360 if (!sd->items) return;
362 EINA_LIST_FOREACH(sd->items, elist, item)
364 _item_del_pre_hook((Elm_Object_Item *)item);
371 _scroller_size_reset(Elm_Ctxpopup_Smart_Data *sd)
373 sd->finished = EINA_FALSE;
379 _item_sizing_eval(Elm_Ctxpopup_Item *item)
381 Evas_Coord min_w = -1, min_h = -1, max_w = -1, max_h = -1;
385 edje_object_size_min_restricted_calc(VIEW(item), &min_w, &min_h, min_w,
387 evas_object_size_hint_min_set(VIEW(item), min_w, min_h);
388 evas_object_size_hint_max_set(VIEW(item), max_w, max_h);
391 static Elm_Ctxpopup_Direction
392 _base_geometry_calc(Evas_Object *obj,
393 Evas_Coord_Rectangle *rect)
395 Elm_Ctxpopup_Direction dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
396 Evas_Coord_Rectangle hover_area;
397 Evas_Coord_Point pos = {0, 0};
398 Evas_Coord_Point arrow_size;
399 Evas_Coord_Point base_size;
400 Evas_Coord_Point max_size;
401 Evas_Coord_Point min_size;
402 Evas_Coord_Point temp;
405 ELM_CTXPOPUP_DATA_GET(obj, sd);
407 if (!rect) return ELM_CTXPOPUP_DIRECTION_DOWN;
409 edje_object_part_geometry_get
410 (sd->arrow, "ctxpopup_arrow", NULL, NULL, &arrow_size.x, &arrow_size.y);
411 evas_object_resize(sd->arrow, arrow_size.x, arrow_size.y);
413 //Initialize Area Rectangle.
414 evas_object_geometry_get
415 (sd->parent, &hover_area.x, &hover_area.y, &hover_area.w,
418 evas_object_geometry_get(obj, &pos.x, &pos.y, NULL, NULL);
421 edje_object_size_min_calc
422 (ELM_WIDGET_DATA(sd)->resize_obj, &base_size.x, &base_size.y);
423 evas_object_smart_calculate(ELM_WIDGET_DATA(sd)->resize_obj);
426 evas_object_size_hint_max_get(obj, &max_size.x, &max_size.y);
427 if ((max_size.x == -1) || (max_size.y == -1))
428 edje_object_size_max_get(sd->layout, &max_size.x, &max_size.y);
430 if ((max_size.y > 0) && (base_size.y > max_size.y))
431 base_size.y = max_size.y;
433 if ((max_size.x > 0) && (base_size.x > max_size.x))
434 base_size.x = max_size.x;
437 evas_object_size_hint_min_get(obj, &min_size.x, &min_size.y);
438 if ((min_size.x == 0) || (min_size.y == 0))
439 edje_object_size_min_get(sd->layout, &min_size.x, &min_size.y);
441 if ((min_size.y > 0) && (base_size.y < min_size.y))
442 base_size.y = min_size.y;
444 if ((min_size.x > 0) && (base_size.x < min_size.x))
445 base_size.x = min_size.x;
447 //Check the Which direction is available.
448 //If find a avaialble direction, it adjusts position and size.
449 for (idx = 0; idx < 4; idx++)
451 switch (sd->dir_priority[idx])
453 case ELM_CTXPOPUP_DIRECTION_UNKNOWN:
455 case ELM_CTXPOPUP_DIRECTION_UP:
456 temp.y = (pos.y - base_size.y);
457 if ((temp.y - arrow_size.y) < hover_area.y)
460 _x_pos_adjust(&pos, &base_size, &hover_area);
461 pos.y -= base_size.y;
462 dir = ELM_CTXPOPUP_DIRECTION_UP;
465 case ELM_CTXPOPUP_DIRECTION_LEFT:
466 temp.x = (pos.x - base_size.x);
467 if ((temp.x - arrow_size.x) < hover_area.x)
470 _y_pos_adjust(&pos, &base_size, &hover_area);
471 pos.x -= base_size.x;
472 dir = ELM_CTXPOPUP_DIRECTION_LEFT;
475 case ELM_CTXPOPUP_DIRECTION_RIGHT:
476 temp.x = (pos.x + base_size.x);
477 if ((temp.x + arrow_size.x) >
478 (hover_area.x + hover_area.w))
481 _y_pos_adjust(&pos, &base_size, &hover_area);
482 dir = ELM_CTXPOPUP_DIRECTION_RIGHT;
485 case ELM_CTXPOPUP_DIRECTION_DOWN:
486 temp.y = (pos.y + base_size.y);
487 if ((temp.y + arrow_size.y) >
488 (hover_area.y + hover_area.h))
491 _x_pos_adjust(&pos, &base_size, &hover_area);
492 dir = ELM_CTXPOPUP_DIRECTION_DOWN;
501 //In this case, all directions are invalid because of lack of space.
504 Evas_Coord length[2];
508 length[0] = pos.y - hover_area.y;
509 length[1] = (hover_area.y + hover_area.h) - pos.y;
511 // ELM_CTXPOPUP_DIRECTION_UP
512 if (length[0] > length[1])
514 _x_pos_adjust(&pos, &base_size, &hover_area);
515 pos.y -= base_size.y;
516 dir = ELM_CTXPOPUP_DIRECTION_UP;
517 if (pos.y < (hover_area.y + arrow_size.y))
519 base_size.y -= ((hover_area.y + arrow_size.y) - pos.y);
520 pos.y = hover_area.y + arrow_size.y;
523 //ELM_CTXPOPUP_DIRECTION_DOWN
526 _x_pos_adjust(&pos, &base_size, &hover_area);
527 dir = ELM_CTXPOPUP_DIRECTION_DOWN;
528 if ((pos.y + arrow_size.y + base_size.y) >
529 (hover_area.y + hover_area.h))
531 ((pos.y + arrow_size.y + base_size.y) -
532 (hover_area.y + hover_area.h));
537 length[0] = pos.x - hover_area.x;
538 length[1] = (hover_area.x + hover_area.w) - pos.x;
540 //ELM_CTXPOPUP_DIRECTION_LEFT
541 if (length[0] > length[1])
543 _y_pos_adjust(&pos, &base_size, &hover_area);
544 pos.x -= base_size.x;
545 dir = ELM_CTXPOPUP_DIRECTION_LEFT;
546 if (pos.x < (hover_area.x + arrow_size.x))
548 base_size.x -= ((hover_area.x + arrow_size.x) - pos.x);
549 pos.x = hover_area.x + arrow_size.x;
552 //ELM_CTXPOPUP_DIRECTION_RIGHT
555 _y_pos_adjust(&pos, &base_size, &hover_area);
556 dir = ELM_CTXPOPUP_DIRECTION_RIGHT;
557 if (pos.x + (arrow_size.x + base_size.x) >
558 hover_area.x + hover_area.w)
560 ((pos.x + arrow_size.x + base_size.x) -
561 (hover_area.x + hover_area.w));
566 //Final position and size.
569 rect->w = base_size.x;
570 rect->h = base_size.y;
576 _arrow_update(Evas_Object *obj,
577 Elm_Ctxpopup_Direction dir,
578 Evas_Coord_Rectangle base_size)
580 Evas_Coord_Rectangle arrow_size;
583 Evas_Coord_Rectangle shadow_left_top, shadow_right_bottom, arrow_padding;
585 ELM_CTXPOPUP_DATA_GET(obj, sd);
587 evas_object_geometry_get(obj, &x, &y, NULL, NULL);
588 evas_object_geometry_get
589 (sd->arrow, NULL, NULL, &arrow_size.w, &arrow_size.h);
591 /* tizen only : since ctxpopup of tizen has shadow, start and end padding of arrow, it should be put together when updating arrow
592 * so there are some differences between open source and tizen */
593 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);
594 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);
595 edje_object_part_geometry_get(ELM_WIDGET_DATA(sd)->resize_obj, "ctxpopup_frame_left_top", NULL, NULL, &arrow_padding.w, &arrow_padding.h);
597 /* arrow is not being kept as sub-object on purpose, here. the
598 * design of the widget does not help with the contrary */
602 case ELM_CTXPOPUP_DIRECTION_RIGHT:
603 edje_object_signal_emit(sd->arrow, "elm,state,left", "elm");
604 edje_object_part_swallow
605 (ELM_WIDGET_DATA(sd)->resize_obj,
606 (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_right" :
607 "elm.swallow.arrow_left"), sd->arrow);
611 if (y <= ((arrow_size.h * 0.5) + base_size.y + shadow_left_top.h + arrow_padding.h))
613 else if (y >= (base_size.y + base_size.h - ((arrow_size.h * 0.5) + shadow_right_bottom.h + arrow_padding.h)))
614 y = base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2));
616 y = y - base_size.y - ((arrow_size.h * 0.5) + shadow_left_top.h + arrow_padding.h);
617 drag = (double)(y) / (double)(base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2)));
618 edje_object_part_drag_value_set
619 (ELM_WIDGET_DATA(sd)->resize_obj,
620 (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_right" :
621 "elm.swallow.arrow_left"), 1, drag);
625 case ELM_CTXPOPUP_DIRECTION_LEFT:
626 edje_object_signal_emit(sd->arrow, "elm,state,right", "elm");
627 edje_object_part_swallow
628 (ELM_WIDGET_DATA(sd)->resize_obj,
629 (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_left" :
630 "elm.swallow.arrow_right"), sd->arrow);
634 if (y <= ((arrow_size.h * 0.5) + base_size.y + shadow_left_top.h + arrow_padding.h))
636 else if (y >= (base_size.y + base_size.h - ((arrow_size.h * 0.5) + shadow_right_bottom.h + arrow_padding.h)))
637 y = base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2));
639 y = y - base_size.y - ((arrow_size.h * 0.5) + shadow_left_top.h + arrow_padding.h);
640 drag = (double)(y) / (double)(base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2)));
641 edje_object_part_drag_value_set
642 (ELM_WIDGET_DATA(sd)->resize_obj,
643 (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_left" :
644 "elm.swallow.arrow_right"), 0, drag);
648 case ELM_CTXPOPUP_DIRECTION_DOWN:
649 edje_object_signal_emit(sd->arrow, "elm,state,top", "elm");
650 edje_object_part_swallow
651 (ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.arrow_up",
656 if (x <= ((arrow_size.w * 0.5) + base_size.x + shadow_left_top.w + arrow_padding.w))
658 else if (x >= (base_size.x + base_size.w - ((arrow_size.w * 0.5) + shadow_right_bottom.w + arrow_padding.w)))
659 x = base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2));
661 x = x - base_size.x - ((arrow_size.w * 0.5) + shadow_left_top.w + arrow_padding.w);
662 drag = (double)(x) / (double)(base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2)));
663 edje_object_part_drag_value_set
664 (ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.arrow_up",
669 case ELM_CTXPOPUP_DIRECTION_UP:
670 edje_object_signal_emit(sd->arrow, "elm,state,bottom", "elm");
671 edje_object_part_swallow
672 (ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.arrow_down",
677 if (x <= ((arrow_size.w * 0.5) + base_size.x + shadow_left_top.w + arrow_padding.w))
679 else if (x >= (base_size.x + base_size.w - ((arrow_size.w * 0.5) + shadow_right_bottom.w + arrow_padding.w)))
680 x = base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2));
682 x = x - base_size.x - ((arrow_size.w * 0.5) + shadow_left_top.w + arrow_padding.w);
683 drag = (double)(x) / (double)(base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2)));
684 edje_object_part_drag_value_set
685 (ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.arrow_down",
694 //should be here for getting accurate geometry value
695 evas_object_smart_calculate(ELM_WIDGET_DATA(sd)->resize_obj);
699 _show_signals_emit(Evas_Object *obj,
700 Elm_Ctxpopup_Direction dir)
702 ELM_CTXPOPUP_DATA_GET(obj, sd);
704 if (!sd->visible) return;
708 case ELM_CTXPOPUP_DIRECTION_UP:
709 edje_object_signal_emit(sd->layout, "elm,state,show,up", "elm");
712 case ELM_CTXPOPUP_DIRECTION_LEFT:
713 edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,show,right" :
714 "elm,state,show,left"), "elm");
717 case ELM_CTXPOPUP_DIRECTION_RIGHT:
718 edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,show,left" :
719 "elm,state,show,right"), "elm");
722 case ELM_CTXPOPUP_DIRECTION_DOWN:
723 edje_object_signal_emit(sd->layout, "elm,state,show,down", "elm");
730 edje_object_signal_emit(sd->bg, "elm,state,show", "elm");
731 // elm_layout_signal_emit(obj, "elm,state,show", "elm");
735 _hide_signals_emit(Evas_Object *obj,
736 Elm_Ctxpopup_Direction dir)
738 ELM_CTXPOPUP_DATA_GET(obj, sd);
740 if (!sd->visible) return;
744 case ELM_CTXPOPUP_DIRECTION_UP:
745 edje_object_signal_emit(sd->layout, "elm,state,hide,up", "elm");
748 case ELM_CTXPOPUP_DIRECTION_LEFT:
749 edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,hide,right" :
750 "elm,state,hide,left"), "elm");
753 case ELM_CTXPOPUP_DIRECTION_RIGHT:
754 edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,hide,left" :
755 "elm,state,hide,right"), "elm");
758 case ELM_CTXPOPUP_DIRECTION_DOWN:
759 edje_object_signal_emit(sd->layout, "elm,state,hide,down", "elm");
766 edje_object_signal_emit(sd->bg, "elm,state,hide", "elm");
770 _base_shift_by_arrow(Evas_Object *arrow,
771 Elm_Ctxpopup_Direction dir,
772 Evas_Coord_Rectangle *rect)
774 Evas_Coord arrow_w, arrow_h;
776 evas_object_geometry_get(arrow, NULL, NULL, &arrow_w, &arrow_h);
780 case ELM_CTXPOPUP_DIRECTION_RIGHT:
784 case ELM_CTXPOPUP_DIRECTION_LEFT:
788 case ELM_CTXPOPUP_DIRECTION_DOWN:
792 case ELM_CTXPOPUP_DIRECTION_UP:
801 //TODO: compress item - different from opensource
803 _compress_item(Evas_Object *obj)
806 Elm_Ctxpopup_Item *item;
808 ELM_CTXPOPUP_DATA_GET(obj, sd);
811 EINA_LIST_FOREACH(sd->items, elist, item)
813 edje_object_signal_emit(item->base.view, "elm,state,compress", "elm");
818 _elm_ctxpopup_smart_sub_object_add(Evas_Object *obj,
821 Elm_Widget_Smart_Class *parent_parent;
823 parent_parent = (Elm_Widget_Smart_Class *)((Evas_Smart_Class *)
824 _elm_ctxpopup_parent_sc)->parent;
826 /* skipping layout's code, which registers size hint changing
827 * callback on sub objects. a hack to make ctxpopup live, as it is,
828 * on the new classing schema. this widget needs a total
830 if (!parent_parent->sub_object_add(obj, sobj))
837 _elm_ctxpopup_smart_sizing_eval(Evas_Object *obj)
840 Elm_Ctxpopup_Item *item;
841 Evas_Coord_Rectangle rect = { 0, 0, 1, 1 };
842 Evas_Coord_Point box_size = { 0, 0 };
843 Evas_Coord_Point _box_size = { 0, 0 };
847 ELM_CTXPOPUP_DATA_GET(obj, sd);
850 EINA_LIST_FOREACH(sd->items, elist, item)
852 _item_sizing_eval(item);
853 evas_object_size_hint_min_get(VIEW(item), &_box_size.x, &_box_size.y);
855 str = edje_object_data_get(VIEW(item), "item_max_size");
859 maxw = maxw * elm_widget_scale_get(obj) * elm_config_scale_get();
861 if (_box_size.x > maxw)
863 edje_object_signal_emit(VIEW(item), "elm,state,text,ellipsis", "elm");
864 edje_object_message_signal_process(VIEW(item));
870 if (_box_size.x > box_size.x)
871 box_size.x = _box_size.x;
872 if (_box_size.y != -1)
873 box_size.y += _box_size.y;
877 if (_box_size.x != -1)
878 box_size.x += _box_size.x;
879 if (_box_size.y > box_size.y)
880 box_size.y = _box_size.y;
884 if (!sd->arrow) return; /* simple way to flag "under deletion" */
886 if ((!sd->content) && (sd->scr))
888 evas_object_size_hint_min_set(sd->box, box_size.x, box_size.y);
889 elm_scroller_content_min_limit(sd->scr, EINA_TRUE, EINA_TRUE);
890 evas_object_size_hint_min_set(sd->scr, box_size.x, box_size.y);
894 sd->dir = _base_geometry_calc(obj, &rect);
896 //TODO: compress item - different from opensource
897 if (!sd->horizontal && !sd->content)
900 _arrow_update(obj, sd->dir, rect);
901 _base_shift_by_arrow(sd->arrow, sd->dir, &rect);
903 //resize scroller according to final size
904 if ((!sd->content) && (sd->scr))
906 elm_scroller_content_min_limit(sd->scr, EINA_FALSE, EINA_FALSE);
907 evas_object_smart_calculate(sd->scr);
910 evas_object_size_hint_min_set(ELM_WIDGET_DATA(sd)->resize_obj, rect.w, rect.h);
911 evas_object_resize(ELM_WIDGET_DATA(sd)->resize_obj, rect.w, rect.h);
913 evas_object_move(sd->layout, rect.x, rect.y);
914 evas_object_resize(sd->layout, rect.w, rect.h);
916 _show_signals_emit(obj, sd->dir);
920 _on_parent_del(void *data,
922 Evas_Object *obj __UNUSED__,
923 void *event_info __UNUSED__)
925 evas_object_del(data);
929 _on_parent_move(void *data,
931 Evas_Object *obj __UNUSED__,
932 void *event_info __UNUSED__)
934 ELM_CTXPOPUP_DATA_GET(data, sd);
937 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
941 _scroller_size_reset(sd);
942 elm_layout_sizing_eval(data);
947 _on_parent_resize(void *data,
949 Evas_Object *obj __UNUSED__,
950 void *event_info __UNUSED__)
952 ELM_CTXPOPUP_DATA_GET(data, sd);
954 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
956 evas_object_hide(data);
957 evas_object_smart_callback_call(data, SIG_DISMISSED, NULL);
961 _parent_detach(Evas_Object *obj)
963 ELM_CTXPOPUP_DATA_GET(obj, sd);
965 if (!sd->parent) return;
967 evas_object_event_callback_del_full
968 (sd->parent, EVAS_CALLBACK_DEL, _on_parent_del, obj);
969 evas_object_event_callback_del_full
970 (sd->parent, EVAS_CALLBACK_MOVE, _on_parent_move, obj);
971 evas_object_event_callback_del_full
972 (sd->parent, EVAS_CALLBACK_RESIZE, _on_parent_resize, obj);
976 _on_content_resized(void *data,
978 Evas_Object *obj __UNUSED__,
979 void *event_info __UNUSED__)
981 ELM_CTXPOPUP_DATA_GET(data, sd);
983 elm_box_recalculate(sd->box);
984 elm_layout_sizing_eval(data);
987 //FIXME: lost the content size when theme hook is called.
989 _elm_ctxpopup_smart_theme(Evas_Object *obj)
992 Elm_Ctxpopup_Item *item;
996 ELM_CTXPOPUP_DATA_GET(obj, sd);
998 if (!ELM_WIDGET_CLASS(_elm_ctxpopup_parent_sc)->theme(obj))
1001 rtl = elm_widget_mirrored_get(obj);
1003 elm_widget_theme_object_set
1004 (obj, sd->bg, "ctxpopup", "bg", elm_widget_style_get(obj));
1005 elm_widget_theme_object_set
1006 (obj, sd->arrow, "ctxpopup", "arrow", elm_widget_style_get(obj));
1007 elm_widget_theme_object_set
1008 (obj, sd->layout, "ctxpopup", "layout", elm_widget_style_get(obj));
1011 EINA_LIST_FOREACH(sd->items, elist, item)
1013 edje_object_mirrored_set(VIEW(item), rtl);
1015 if (item->label && item->icon)
1016 _elm_theme_object_set
1017 (obj, VIEW(item), "ctxpopup", "icon_text_style_item", elm_widget_style_get(obj));
1018 else if (item->label)
1021 _elm_theme_object_set(obj, VIEW(item), "ctxpopup", "text_style_item",
1022 elm_widget_style_get(obj));
1024 _elm_theme_object_set(obj, VIEW(item), "ctxpopup", "text_style_item_horizontal",
1025 elm_widget_style_get(obj));
1027 else if (item->icon)
1028 _elm_theme_object_set
1029 (obj, VIEW(item), "ctxpopup", "icon_style_item", elm_widget_style_get(obj));
1031 edje_object_part_text_set(VIEW(item), "elm.text", item->label);
1033 if (elm_widget_item_disabled_get(item))
1034 edje_object_signal_emit(VIEW(item), "elm,state,disabled", "elm");
1037 * For separator, if the first item has visible separator,
1038 * then it should be aligned with edge of the base part.
1039 * In some cases, it gives improper display. Ex) rounded corner
1040 * So the first item separator should be invisible.
1043 edje_object_signal_emit(VIEW(item), "elm,state,default", "elm");
1045 edje_object_signal_emit(VIEW(item), "elm,state,separator", "elm");
1047 edje_object_message_signal_process(VIEW(item));
1050 if (evas_object_visible_get(sd->bg))
1051 edje_object_signal_emit(sd->bg, "elm,state,show", "elm");
1055 if (!strncmp(elm_object_style_get(obj), "default", strlen("default")))
1056 elm_object_style_set(sd->scr, "ctxpopup");
1058 elm_object_style_set(sd->scr, elm_object_style_get(obj));
1061 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1065 _scroller_size_reset(sd);
1066 _elm_ctxpopup_smart_sizing_eval(obj);
1072 /* kind of a big and tricky override here: an internal box will hold
1073 * the actual content. content aliases won't be of much help here */
1075 _elm_ctxpopup_smart_content_set(Evas_Object *obj,
1077 Evas_Object *content)
1079 Evas_Coord min_w = -1, min_h = -1;
1081 ELM_CTXPOPUP_DATA_GET(obj, sd);
1083 if ((part) && (strcmp(part, "default")))
1084 return ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_set
1085 (obj, part, content);
1087 if (!content) return EINA_FALSE;
1089 if (content == sd->content) return EINA_TRUE;
1091 if (sd->items) elm_ctxpopup_clear(obj);
1092 if (sd->content) evas_object_del(sd->content);
1097 sd->box = elm_box_add(obj);
1098 evas_object_size_hint_weight_set(sd->box, EVAS_HINT_EXPAND,
1100 evas_object_event_callback_add
1101 (sd->box, EVAS_CALLBACK_RESIZE, _on_content_resized, obj);
1102 ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_set
1103 (obj, "elm.swallow.content", sd->box);
1106 evas_object_size_hint_weight_set
1107 (content, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1108 evas_object_size_hint_fill_set
1109 (content, EVAS_HINT_FILL, EVAS_HINT_FILL);
1111 /* since it's going to be a box content, not a layout's... */
1112 evas_object_show(content);
1114 evas_object_size_hint_min_get(content, &min_w, &min_h);
1115 evas_object_size_hint_min_set(sd->box, min_w, min_h);
1116 elm_box_pack_end(sd->box, content);
1118 sd->content = content;
1119 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1121 if (sd->visible) elm_layout_sizing_eval(obj);
1126 static Evas_Object *
1127 _elm_ctxpopup_smart_content_get(const Evas_Object *obj,
1130 ELM_CTXPOPUP_DATA_GET(obj, sd);
1132 if ((part) && (strcmp(part, "default")))
1133 return ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_get
1139 static Evas_Object *
1140 _elm_ctxpopup_smart_content_unset(Evas_Object *obj,
1143 Evas_Object *content;
1145 ELM_CTXPOPUP_DATA_GET(obj, sd);
1147 if ((part) && (strcmp(part, "default")))
1148 return ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_unset
1151 content = sd->content;
1152 if (!content) return NULL;
1154 evas_object_del(sd->box);
1157 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1159 if (sd->visible) elm_layout_sizing_eval(obj);
1165 _item_text_set_hook(Elm_Object_Item *it,
1169 Elm_Ctxpopup_Item *ctxpopup_it;
1171 if ((part) && (strcmp(part, "default"))) return;
1173 ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1175 _item_label_set(ctxpopup_it, label);
1179 _item_text_get_hook(const Elm_Object_Item *it,
1182 Elm_Ctxpopup_Item *ctxpopup_it;
1184 if (part && strcmp(part, "default")) return NULL;
1186 ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1187 return ctxpopup_it->label;
1191 _item_content_set_hook(Elm_Object_Item *it,
1193 Evas_Object *content)
1195 Elm_Ctxpopup_Item *ctxpopup_it;
1197 if ((part) && (strcmp(part, "icon"))) return;
1199 ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1201 ELM_CTXPOPUP_DATA_GET(WIDGET(ctxpopup_it), sd);
1203 _item_icon_set(ctxpopup_it, content);
1204 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1208 _scroller_size_reset(sd);
1209 _elm_ctxpopup_smart_sizing_eval(WIDGET(ctxpopup_it));
1213 static Evas_Object *
1214 _item_content_get_hook(const Elm_Object_Item *it,
1217 Elm_Ctxpopup_Item *ctxpopup_it;
1219 if (part && strcmp(part, "icon")) return NULL;
1221 ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1222 return ctxpopup_it->icon;
1226 _item_disable_hook(Elm_Object_Item *it)
1228 Elm_Ctxpopup_Item *ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1230 ELM_CTXPOPUP_DATA_GET(WIDGET(it), sd);
1233 if (elm_widget_item_disabled_get(it))
1234 edje_object_signal_emit(VIEW(ctxpopup_it), "elm,state,disabled", "elm");
1236 edje_object_signal_emit(VIEW(ctxpopup_it), "elm,state,enabled", "elm");
1240 _item_signal_emit_hook(Elm_Object_Item *it,
1241 const char *emission,
1244 Elm_Ctxpopup_Item *ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1246 edje_object_signal_emit(VIEW(ctxpopup_it), emission, source);
1250 _bg_clicked_cb(void *data,
1251 Evas_Object *obj __UNUSED__,
1252 const char *emission __UNUSED__,
1253 const char *source __UNUSED__)
1255 ELM_CTXPOPUP_DATA_GET(data, sd);
1257 _hide_signals_emit(data, sd->dir);
1261 _on_show(void *data __UNUSED__,
1264 void *event_info __UNUSED__)
1267 Elm_Ctxpopup_Item *item;
1270 ELM_CTXPOPUP_DATA_GET(obj, sd);
1272 if ((!sd->items) && (!sd->content)) return;
1274 sd->visible = EINA_TRUE;
1276 evas_object_show(sd->bg);
1277 evas_object_show(sd->arrow);
1278 evas_object_show(sd->layout);
1280 edje_object_signal_emit(sd->bg, "elm,state,show", "elm");
1281 elm_layout_signal_emit(obj, "elm,state,show", "elm");
1283 EINA_LIST_FOREACH(sd->items, elist, item)
1285 if (item->label && !item->icon)
1288 _elm_theme_object_set(obj, VIEW(item), "ctxpopup", "text_style_item",
1289 elm_widget_style_get(obj));
1291 _elm_theme_object_set(obj, VIEW(item), "ctxpopup", "text_style_item_horizontal",
1292 elm_widget_style_get(obj));
1296 edje_object_signal_emit(VIEW(item), "elm,state,default", "elm");
1298 edje_object_signal_emit(VIEW(item), "elm,state,separator", "elm");
1301 elm_layout_sizing_eval(obj);
1303 elm_object_focus_set(obj, EINA_TRUE);
1307 _on_hide(void *data __UNUSED__,
1310 void *event_info __UNUSED__)
1312 ELM_CTXPOPUP_DATA_GET(obj, sd);
1314 if (!sd->visible) return;
1316 evas_object_hide(sd->bg);
1317 evas_object_hide(sd->arrow);
1318 evas_object_hide(sd->layout);
1320 _scroller_size_reset(sd);
1322 sd->visible = EINA_FALSE;
1326 _on_move(void *data __UNUSED__,
1329 void *event_info __UNUSED__)
1331 ELM_CTXPOPUP_DATA_GET(obj, sd);
1333 if (sd->visible) evas_object_show(sd->arrow);
1335 _scroller_size_reset(sd);
1336 _elm_ctxpopup_smart_sizing_eval(obj);
1340 _hide_finished_cb(void *data,
1341 Evas_Object *obj __UNUSED__,
1342 const char *emission __UNUSED__,
1343 const char *source __UNUSED__)
1345 evas_object_hide(data);
1346 evas_object_smart_callback_call(data, SIG_DISMISSED, NULL);
1350 _scroller_resize(void *data, Evas *e __UNUSED__,
1352 void *event_info __UNUSED__)
1356 ELM_CTXPOPUP_DATA_GET(data, sd);
1358 if (!sd->visible) return;
1359 if (sd->finished) return;
1361 evas_object_geometry_get(obj, 0, 0, &w, &h);
1363 if (w != 0 && h != 0)
1365 if ((w <= sd->max_sc_w) && (h <= sd->max_sc_h))
1367 _elm_ctxpopup_smart_sizing_eval(data);
1368 sd->finished = EINA_TRUE;
1373 if (sd->max_sc_w < w)
1375 if (sd->max_sc_h < h)
1378 _elm_ctxpopup_smart_sizing_eval(data);
1382 _ctxpopup_restack_cb(void *data __UNUSED__,
1385 void *event_info __UNUSED__)
1387 ELM_CTXPOPUP_DATA_GET(obj, sd);
1388 evas_object_stack_below(sd->bg, obj);
1389 evas_object_stack_below(sd->layout, obj);
1393 _list_del(Elm_Ctxpopup_Smart_Data *sd)
1395 if (!sd->scr) return;
1397 edje_object_part_unswallow(ELM_WIDGET_DATA(sd)->resize_obj, sd->scr);
1398 evas_object_del(sd->scr);
1400 evas_object_del(sd->box);
1405 _list_new(Evas_Object *obj)
1407 ELM_CTXPOPUP_DATA_GET(obj, sd);
1411 sd->scr = elm_scroller_add(obj);
1412 elm_object_style_set(sd->scr, "ctxpopup");
1413 evas_object_size_hint_align_set(sd->scr, EVAS_HINT_FILL, EVAS_HINT_FILL);
1414 evas_object_event_callback_add(sd->scr, EVAS_CALLBACK_RESIZE,
1415 _scroller_resize, obj);
1416 edje_object_part_swallow(ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.content", sd->scr);
1421 sd->box = elm_box_add(obj);
1422 evas_object_size_hint_weight_set(sd->box, EVAS_HINT_EXPAND,
1424 evas_object_event_callback_add
1425 (sd->box, EVAS_CALLBACK_RESIZE, _on_content_resized, obj);
1426 ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_set
1427 (obj, "elm.swallow.content", sd->box);
1430 elm_object_content_set(sd->scr, sd->box);
1431 elm_ctxpopup_horizontal_set(obj, sd->horizontal);
1435 _elm_ctxpopup_smart_disable(Evas_Object *obj)
1438 Elm_Object_Item *it;
1440 ELM_CTXPOPUP_DATA_GET(obj, sd);
1442 if (!ELM_WIDGET_CLASS(_elm_ctxpopup_parent_sc)->disable(obj))
1445 EINA_LIST_FOREACH(sd->items, l, it)
1446 elm_object_item_disabled_set(it, elm_widget_disabled_get(obj));
1452 _elm_ctxpopup_smart_add(Evas_Object *obj)
1454 EVAS_SMART_DATA_ALLOC(obj, Elm_Ctxpopup_Smart_Data);
1455 ELM_CTXPOPUP_DATA_GET(obj, sd);
1457 ELM_WIDGET_CLASS(_elm_ctxpopup_parent_sc)->base.add(obj);
1459 elm_layout_theme_set(obj, "ctxpopup", "base", elm_widget_style_get(obj));
1460 elm_layout_signal_callback_add
1461 (obj, "elm,action,hide,finished", "", _hide_finished_cb, obj);
1464 priv->bg = edje_object_add(evas_object_evas_get(obj));
1465 elm_widget_theme_object_set(obj, priv->bg, "ctxpopup", "bg", "default");
1466 edje_object_signal_callback_add
1467 (priv->bg, "elm,action,click", "", _bg_clicked_cb, obj);
1469 evas_object_stack_below(priv->bg, obj);
1472 priv->arrow = edje_object_add(evas_object_evas_get(obj));
1473 elm_widget_theme_object_set
1474 (obj, priv->arrow, "ctxpopup", "arrow", "default");
1476 priv->dir_priority[0] = ELM_CTXPOPUP_DIRECTION_UP;
1477 priv->dir_priority[1] = ELM_CTXPOPUP_DIRECTION_LEFT;
1478 priv->dir_priority[2] = ELM_CTXPOPUP_DIRECTION_RIGHT;
1479 priv->dir_priority[3] = ELM_CTXPOPUP_DIRECTION_DOWN;
1480 priv->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1482 evas_object_event_callback_add
1483 (obj, EVAS_CALLBACK_RESTACK, _ctxpopup_restack_cb, obj);
1485 evas_object_smart_callback_add
1486 (obj, "scroll-freeze-on", _freeze_on_cb, obj);
1487 evas_object_smart_callback_add
1488 (obj, "scroll-freeze-off", _freeze_off_cb, obj);
1489 evas_object_smart_callback_add
1490 (obj, "scroll-hold-on", _hold_on_cb, obj);
1491 evas_object_smart_callback_add
1492 (obj, "scroll-hold-off", _hold_off_cb, obj);
1494 priv->box = elm_box_add(obj);
1495 evas_object_size_hint_weight_set
1496 (priv->box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1498 evas_object_event_callback_add
1499 (priv->box, EVAS_CALLBACK_RESIZE, _on_content_resized, obj);
1501 /* box will be our content placeholder, thus the parent's version call */
1502 ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_set
1503 (obj, "elm.swallow.content", priv->box);
1505 priv->layout = edje_object_add(evas_object_evas_get(obj));
1506 elm_widget_theme_object_set(obj, priv->layout, "ctxpopup", "layout", "default");
1508 edje_object_signal_callback_add
1509 (priv->layout, "elm,action,hide,finished", "", _hide_finished_cb, obj);
1510 edje_object_part_swallow(priv->layout, "swallow", ELM_WIDGET_DATA(sd)->resize_obj);
1511 evas_object_size_hint_weight_set
1512 (priv->layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1514 evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _on_show, NULL);
1515 evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _on_hide, NULL);
1516 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _on_move, NULL);
1518 elm_widget_can_focus_set(obj, EINA_TRUE);
1522 _elm_ctxpopup_smart_del(Evas_Object *obj)
1524 ELM_CTXPOPUP_DATA_GET(obj, sd);
1526 evas_object_event_callback_del_full
1527 (sd->box, EVAS_CALLBACK_RESIZE, _on_content_resized, obj);
1528 _parent_detach(obj);
1530 elm_ctxpopup_clear(obj);
1531 evas_object_del(sd->arrow);
1532 sd->arrow = NULL; /* stops _sizing_eval() from going on on deletion */
1534 evas_object_del(sd->bg);
1537 evas_object_del(sd->layout);
1540 ELM_WIDGET_CLASS(_elm_ctxpopup_parent_sc)->base.del(obj);
1544 _elm_ctxpopup_smart_parent_set(Evas_Object *obj,
1545 Evas_Object *parent)
1547 //default parent is to be hover parent
1548 elm_ctxpopup_hover_parent_set(obj, parent);
1552 _elm_ctxpopup_smart_access(Evas_Object *obj, Eina_Bool is_access)
1554 Eina_List *elist = NULL;
1555 Elm_Ctxpopup_Item *it;
1557 ELM_CTXPOPUP_CHECK(obj);
1558 ELM_CTXPOPUP_DATA_GET(obj, sd);
1560 EINA_LIST_FOREACH(sd->items, elist, it)
1561 _access_widget_item_register(it, is_access);
1565 _elm_ctxpopup_smart_set_user(Elm_Ctxpopup_Smart_Class *sc)
1567 ELM_WIDGET_CLASS(sc)->base.add = _elm_ctxpopup_smart_add;
1568 ELM_WIDGET_CLASS(sc)->base.del = _elm_ctxpopup_smart_del;
1570 ELM_WIDGET_CLASS(sc)->parent_set = _elm_ctxpopup_smart_parent_set;
1571 ELM_WIDGET_CLASS(sc)->disable = _elm_ctxpopup_smart_disable;
1572 ELM_WIDGET_CLASS(sc)->event = _elm_ctxpopup_smart_event;
1573 ELM_WIDGET_CLASS(sc)->theme = _elm_ctxpopup_smart_theme;
1574 ELM_WIDGET_CLASS(sc)->sub_object_add = _elm_ctxpopup_smart_sub_object_add;
1575 ELM_WIDGET_CLASS(sc)->focus_next = _elm_ctxpopup_smart_focus_next;
1576 ELM_WIDGET_CLASS(sc)->focus_direction = _elm_ctxpopup_smart_focus_direction;
1577 ELM_WIDGET_CLASS(sc)->translate = _elm_ctxpopup_smart_translate;
1579 ELM_CONTAINER_CLASS(sc)->content_get = _elm_ctxpopup_smart_content_get;
1580 ELM_CONTAINER_CLASS(sc)->content_set = _elm_ctxpopup_smart_content_set;
1581 ELM_CONTAINER_CLASS(sc)->content_unset = _elm_ctxpopup_smart_content_unset;
1583 ELM_LAYOUT_CLASS(sc)->sizing_eval = _elm_ctxpopup_smart_sizing_eval;
1585 ELM_WIDGET_CLASS(sc)->access = _elm_ctxpopup_smart_access;
1588 EAPI const Elm_Ctxpopup_Smart_Class *
1589 elm_ctxpopup_smart_class_get(void)
1591 static Elm_Ctxpopup_Smart_Class _sc =
1592 ELM_CTXPOPUP_SMART_CLASS_INIT_NAME_VERSION(ELM_CTXPOPUP_SMART_NAME);
1593 static const Elm_Ctxpopup_Smart_Class *class = NULL;
1594 Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
1599 _elm_ctxpopup_smart_set(&_sc);
1600 esc->callbacks = _smart_callbacks;
1607 elm_ctxpopup_add(Evas_Object *parent)
1611 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1613 obj = elm_widget_add(_elm_ctxpopup_smart_class_new(), parent);
1614 if (!obj) return NULL;
1616 if (!elm_widget_sub_object_add(parent, obj))
1617 ERR("could not add %p as sub object of %p", obj, parent);
1619 /* access: parent could be any object such as elm_list which does
1620 not know elc_ctxpopup as its child object in the focus_next(); */
1621 ELM_WIDGET_DATA_GET(obj, sd);
1622 sd->highlight_root = EINA_TRUE;
1628 elm_ctxpopup_hover_parent_set(Evas_Object *obj,
1629 Evas_Object *parent)
1631 Evas_Coord x, y, w, h;
1633 ELM_CTXPOPUP_CHECK(obj);
1634 ELM_CTXPOPUP_DATA_GET(obj, sd);
1636 if (!parent) return;
1638 _parent_detach(obj);
1640 evas_object_event_callback_add
1641 (parent, EVAS_CALLBACK_DEL, _on_parent_del, obj);
1642 evas_object_event_callback_add
1643 (parent, EVAS_CALLBACK_MOVE, _on_parent_move, obj);
1644 evas_object_event_callback_add
1645 (parent, EVAS_CALLBACK_RESIZE, _on_parent_resize, obj);
1647 sd->parent = parent;
1650 evas_object_geometry_get(parent, &x, &y, &w, &h);
1651 evas_object_move(sd->bg, x, y);
1652 evas_object_resize(sd->bg, w, h);
1654 if (sd->visible) elm_layout_sizing_eval(obj);
1658 elm_ctxpopup_hover_parent_get(const Evas_Object *obj)
1660 ELM_CTXPOPUP_CHECK(obj) NULL;
1661 ELM_CTXPOPUP_DATA_GET(obj, sd);
1667 elm_ctxpopup_clear(Evas_Object *obj)
1669 ELM_CTXPOPUP_CHECK(obj);
1670 ELM_CTXPOPUP_DATA_GET(obj, sd);
1674 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1678 elm_ctxpopup_horizontal_set(Evas_Object *obj,
1679 Eina_Bool horizontal)
1682 Elm_Ctxpopup_Item *item;
1685 ELM_CTXPOPUP_CHECK(obj);
1686 ELM_CTXPOPUP_DATA_GET(obj, sd);
1688 sd->horizontal = !!horizontal;
1695 elm_box_horizontal_set(sd->box, EINA_FALSE);
1696 elm_scroller_bounce_set(sd->scr, EINA_FALSE, EINA_TRUE);
1700 elm_box_horizontal_set(sd->box, EINA_TRUE);
1701 elm_scroller_bounce_set(sd->scr, EINA_TRUE, EINA_FALSE);
1704 EINA_LIST_FOREACH(sd->items, elist, item)
1706 if (item->label && !item->icon && !horizontal)
1707 _elm_theme_object_set(obj, VIEW(item), "ctxpopup", "text_style_item",
1708 elm_widget_style_get(obj));
1709 else if (item->label && !item->icon && horizontal)
1710 _elm_theme_object_set(obj, VIEW(item), "ctxpopup", "text_style_item_horizontal",
1711 elm_widget_style_get(obj));
1714 edje_object_signal_emit(VIEW(item), "elm,state,default", "elm");
1716 edje_object_signal_emit(VIEW(item), "elm,state,separator", "elm");
1718 _item_disable_hook((Elm_Object_Item *)item);
1721 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1723 if (sd->visible) elm_layout_sizing_eval(obj);
1727 elm_ctxpopup_horizontal_get(const Evas_Object *obj)
1729 ELM_CTXPOPUP_CHECK(obj) EINA_FALSE;
1730 ELM_CTXPOPUP_DATA_GET(obj, sd);
1732 return sd->horizontal;
1735 EAPI Elm_Object_Item *
1736 elm_ctxpopup_item_append(Evas_Object *obj,
1742 Elm_Ctxpopup_Item *item;
1743 Evas_Object *content;
1745 ELM_CTXPOPUP_CHECK(obj) NULL;
1746 ELM_CTXPOPUP_DATA_GET(obj, sd);
1748 item = elm_widget_item_new(obj, Elm_Ctxpopup_Item);
1749 if (!item) return NULL;
1751 elm_widget_item_del_pre_hook_set(item, _item_del_pre_hook);
1752 elm_widget_item_disable_hook_set(item, _item_disable_hook);
1753 elm_widget_item_text_set_hook_set(item, _item_text_set_hook);
1754 elm_widget_item_text_get_hook_set(item, _item_text_get_hook);
1755 elm_widget_item_content_set_hook_set(item, _item_content_set_hook);
1756 elm_widget_item_content_get_hook_set(item, _item_content_get_hook);
1757 elm_widget_item_signal_emit_hook_set(item, _item_signal_emit_hook);
1759 //The first item is appended.
1760 content = elm_object_content_unset(obj);
1761 if (content) evas_object_del(content);
1767 item->base.data = data;
1770 _item_new(item, "icon_text_style_item");
1773 if (!sd->horizontal)
1774 _item_new(item, "text_style_item");
1776 _item_new(item, "text_style_item_horizontal");
1779 _item_new(item, "icon_style_item");
1781 _item_icon_set(item, icon);
1782 _item_label_set(item, label);
1783 elm_box_pack_end(sd->box, VIEW(item));
1784 sd->items = eina_list_append(sd->items, item);
1786 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1790 _scroller_size_reset(sd);
1791 _elm_ctxpopup_smart_sizing_eval(obj);
1795 return (Elm_Object_Item *)item;
1799 elm_ctxpopup_direction_priority_set(Evas_Object *obj,
1800 Elm_Ctxpopup_Direction first,
1801 Elm_Ctxpopup_Direction second,
1802 Elm_Ctxpopup_Direction third,
1803 Elm_Ctxpopup_Direction fourth)
1805 ELM_CTXPOPUP_CHECK(obj);
1806 ELM_CTXPOPUP_DATA_GET(obj, sd);
1808 sd->dir_priority[0] = first;
1809 sd->dir_priority[1] = second;
1810 sd->dir_priority[2] = third;
1811 sd->dir_priority[3] = fourth;
1813 if (sd->visible) elm_layout_sizing_eval(obj);
1817 elm_ctxpopup_direction_priority_get(Evas_Object *obj,
1818 Elm_Ctxpopup_Direction *first,
1819 Elm_Ctxpopup_Direction *second,
1820 Elm_Ctxpopup_Direction *third,
1821 Elm_Ctxpopup_Direction *fourth)
1823 ELM_CTXPOPUP_CHECK(obj);
1824 ELM_CTXPOPUP_DATA_GET(obj, sd);
1826 if (first) *first = sd->dir_priority[0];
1827 if (second) *second = sd->dir_priority[1];
1828 if (third) *third = sd->dir_priority[2];
1829 if (fourth) *fourth = sd->dir_priority[3];
1832 EAPI Elm_Ctxpopup_Direction
1833 elm_ctxpopup_direction_get(const Evas_Object *obj)
1835 ELM_CTXPOPUP_CHECK(obj) ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1836 ELM_CTXPOPUP_DATA_GET(obj, sd);
1842 elm_ctxpopup_dismiss(Evas_Object *obj)
1844 ELM_CTXPOPUP_CHECK(obj);
1845 ELM_CTXPOPUP_DATA_GET(obj, sd);
1847 _hide_signals_emit(obj, sd->dir);