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);
27 _elm_ctxpopup_smart_focus_next(const Evas_Object *obj,
28 Elm_Focus_Direction dir,
31 Eina_List *items = NULL;
32 Eina_List *elist = NULL;
33 Elm_Ctxpopup_Item *it;
35 ELM_CTXPOPUP_DATA_GET(obj, sd);
40 if (eina_list_count(sd->items))
42 EINA_LIST_FOREACH(sd->items, elist, it)
43 items = eina_list_append(items, it->base.access_obj);
45 return elm_widget_focus_list_next_get
46 (obj, items, eina_list_data_get, dir, next);
50 return elm_widget_focus_next_get(sd->box, dir, next);
55 _elm_ctxpopup_smart_event(Evas_Object *obj,
56 Evas_Object *src __UNUSED__,
57 Evas_Callback_Type type,
60 Evas_Event_Key_Down *ev = event_info;
62 ELM_CTXPOPUP_DATA_GET(obj, sd);
64 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
65 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
66 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
68 if (!strcmp(ev->keyname, "Tab"))
70 if (evas_key_modifier_is_set(ev->modifiers, "Shift"))
71 elm_widget_focus_cycle(sd->box, ELM_FOCUS_PREVIOUS);
73 elm_widget_focus_cycle(sd->box, ELM_FOCUS_NEXT);
77 if (strcmp(ev->keyname, "Escape")) return EINA_FALSE;
79 evas_object_hide(obj);
80 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
85 _freeze_on_cb(void *data __UNUSED__,
87 void *event_info __UNUSED__)
89 ELM_CTXPOPUP_DATA_GET(obj, sd);
91 if ((!sd) || (!sd->scr)) return;
92 elm_object_scroll_freeze_push(sd->scr);
96 _freeze_off_cb(void *data __UNUSED__,
98 void *event_info __UNUSED__)
100 ELM_CTXPOPUP_DATA_GET(obj, sd);
102 if ((!sd) || (!sd->scr)) return;
103 elm_object_scroll_freeze_pop(sd->scr);
107 _hold_on_cb(void *data __UNUSED__,
109 void *event_info __UNUSED__)
111 ELM_CTXPOPUP_DATA_GET(obj, sd);
113 if ((!sd) || (!sd->scr)) return;
114 elm_object_scroll_hold_push(sd->scr);
118 _hold_off_cb(void *data __UNUSED__,
120 void *event_info __UNUSED__)
122 ELM_CTXPOPUP_DATA_GET(obj, sd);
124 if ((!sd) || (!sd->scr)) return;
125 elm_object_scroll_hold_pop(sd->scr);
129 _x_pos_adjust(Evas_Coord_Point *pos,
130 Evas_Coord_Point *base_size,
131 Evas_Coord_Rectangle *hover_area)
133 pos->x -= (base_size->x / 2);
135 if (pos->x < hover_area->x)
136 pos->x = hover_area->x;
137 else if ((pos->x + base_size->x) > (hover_area->x + hover_area->w))
138 pos->x = (hover_area->x + hover_area->w) - base_size->x;
140 if (base_size->x > hover_area->w)
141 base_size->x -= (base_size->x - hover_area->w);
143 if (pos->x < hover_area->x)
144 pos->x = hover_area->x;
148 _y_pos_adjust(Evas_Coord_Point *pos,
149 Evas_Coord_Point *base_size,
150 Evas_Coord_Rectangle *hover_area)
152 pos->y -= (base_size->y / 2);
154 if (pos->y < hover_area->y)
155 pos->y = hover_area->y;
156 else if ((pos->y + base_size->y) > (hover_area->y + hover_area->h))
157 pos->y = hover_area->y + hover_area->h - base_size->y;
159 if (base_size->y > hover_area->h)
160 base_size->y -= (base_size->y - hover_area->h);
162 if (pos->y < hover_area->y)
163 pos->y = hover_area->y;
167 _item_select_cb(void *data, Evas_Object *obj __UNUSED__,
168 const char *emission __UNUSED__,
169 const char *source __UNUSED__)
171 Elm_Ctxpopup_Item *item = data;
174 if (elm_widget_item_disabled_get(item)) return;
177 item->func((void*)item->base.data, WIDGET(item), data);
181 _access_info_cb(void *data, Evas_Object *obj __UNUSED__)
183 Elm_Ctxpopup_Item *it = (Elm_Ctxpopup_Item *)data;
184 const char *txt = NULL;
185 Evas_Object *icon = NULL;
186 Eina_Strbuf *buf = NULL;
189 if (!it) return NULL;
191 if ((!txt) && (!icon))
196 else if (!txt) txt = it->label;
197 else if (!icon) icon = it->icon;
201 buf = eina_strbuf_new();
202 eina_strbuf_append(buf, E_("icon "));
203 eina_strbuf_append(buf, txt);
204 str = eina_strbuf_string_steal(buf);
205 eina_strbuf_free(buf);
208 else if ((!txt) && icon) return strdup(E_("icon"));
209 else if (txt && (!icon)) return strdup(txt);
215 _access_state_cb(void *data, Evas_Object *obj __UNUSED__)
217 Elm_Ctxpopup_Item *it = (Elm_Ctxpopup_Item *)data;
218 if (!it) return NULL;
220 if (it->base.disabled)
221 return strdup(E_("State: Disabled"));
227 _access_activate_cb(void *data __UNUSED__,
228 Evas_Object *part_obj __UNUSED__,
229 Elm_Object_Item *item)
231 _item_select_cb(item, NULL, NULL, NULL);
235 _access_widget_item_register(Elm_Ctxpopup_Item *it, Eina_Bool is_access)
239 if (!is_access) _elm_access_widget_item_unregister((Elm_Widget_Item *)it);
242 _elm_access_widget_item_register((Elm_Widget_Item *)it);
244 ai = _elm_access_object_get(it->base.access_obj);
246 _elm_access_callback_set(ai, ELM_ACCESS_INFO, _access_info_cb, it);
247 _elm_access_callback_set(ai, ELM_ACCESS_STATE, _access_state_cb, it);
248 _elm_access_text_set(ai, ELM_ACCESS_TYPE, E_("Contextual Popup"));
249 _elm_access_activate_callback_set(ai, _access_activate_cb, it);
254 _item_new(Elm_Ctxpopup_Item *item,
257 ELM_CTXPOPUP_DATA_GET(WIDGET(item), sd);
260 VIEW(item) = edje_object_add(evas_object_evas_get(sd->box));
261 edje_object_mirrored_set(VIEW(item), elm_widget_mirrored_get(WIDGET(item)));
262 _elm_theme_object_set(WIDGET(item), VIEW(item), "ctxpopup", group_name,
263 elm_widget_style_get(WIDGET(item)));
264 edje_object_signal_callback_add(VIEW(item), "elm,action,click", "",
265 _item_select_cb, item);
266 evas_object_size_hint_align_set(VIEW(item), EVAS_HINT_FILL, EVAS_HINT_FILL);
267 evas_object_show(VIEW(item));
270 if (_elm_config->access_mode) _access_widget_item_register(item, EINA_TRUE);
274 _item_icon_set(Elm_Ctxpopup_Item *item,
278 evas_object_del(item->icon);
283 edje_object_part_swallow(VIEW(item), "elm.swallow.icon", item->icon);
284 edje_object_message_signal_process(VIEW(item));
288 _item_label_set(Elm_Ctxpopup_Item *item,
291 if (!eina_stringshare_replace(&item->label, label))
294 edje_object_part_text_set(VIEW(item), "elm.text", label);
295 edje_object_message_signal_process(VIEW(item));
299 _item_del_pre_hook(Elm_Object_Item *it)
301 Elm_Ctxpopup_Item *ctxpopup_it = (Elm_Ctxpopup_Item *)it;
303 ELM_CTXPOPUP_DATA_GET(WIDGET(ctxpopup_it), sd);
304 if (!sd) return EINA_FALSE;
306 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
308 if (ctxpopup_it->icon)
309 evas_object_del(ctxpopup_it->icon);
310 if (VIEW(ctxpopup_it))
311 evas_object_del(VIEW(ctxpopup_it));
313 eina_stringshare_del(ctxpopup_it->label);
314 sd->items = eina_list_remove(sd->items, ctxpopup_it);
316 if (eina_list_count(sd->items) < 1)
318 evas_object_hide(WIDGET(ctxpopup_it));
321 if (sd->visible) elm_layout_sizing_eval(WIDGET(ctxpopup_it));
327 _items_remove(Elm_Ctxpopup_Smart_Data *sd)
330 Elm_Ctxpopup_Item *item;
332 if (!sd->items) return;
334 EINA_LIST_FOREACH(sd->items, elist, item)
336 _item_del_pre_hook((Elm_Object_Item *)item);
343 _scroller_size_reset(Elm_Ctxpopup_Smart_Data *sd)
345 sd->finished = EINA_FALSE;
351 _item_sizing_eval(Elm_Ctxpopup_Item *item)
353 Evas_Coord min_w = -1, min_h = -1, max_w = -1, max_h = -1;
357 edje_object_size_min_restricted_calc(VIEW(item), &min_w, &min_h, min_w,
359 evas_object_size_hint_min_set(VIEW(item), min_w, min_h);
360 evas_object_size_hint_max_set(VIEW(item), max_w, max_h);
363 static Elm_Ctxpopup_Direction
364 _base_geometry_calc(Evas_Object *obj,
365 Evas_Coord_Rectangle *rect)
367 Elm_Ctxpopup_Direction dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
368 Evas_Coord_Rectangle hover_area;
369 Evas_Coord_Point pos = {0, 0};
370 Evas_Coord_Point arrow_size;
371 Evas_Coord_Point base_size;
372 Evas_Coord_Point max_size;
373 Evas_Coord_Point min_size;
374 Evas_Coord_Point temp;
377 ELM_CTXPOPUP_DATA_GET(obj, sd);
379 if (!rect) return ELM_CTXPOPUP_DIRECTION_DOWN;
381 edje_object_part_geometry_get
382 (sd->arrow, "ctxpopup_arrow", NULL, NULL, &arrow_size.x, &arrow_size.y);
383 evas_object_resize(sd->arrow, arrow_size.x, arrow_size.y);
385 //Initialize Area Rectangle.
386 evas_object_geometry_get
387 (sd->parent, &hover_area.x, &hover_area.y, &hover_area.w,
390 evas_object_geometry_get(obj, &pos.x, &pos.y, NULL, NULL);
393 edje_object_size_min_calc
394 (ELM_WIDGET_DATA(sd)->resize_obj, &base_size.x, &base_size.y);
395 evas_object_smart_calculate(ELM_WIDGET_DATA(sd)->resize_obj);
398 evas_object_size_hint_max_get(obj, &max_size.x, &max_size.y);
399 if ((max_size.x == -1) || (max_size.y == -1))
400 edje_object_size_max_get(sd->layout, &max_size.x, &max_size.y);
402 if ((max_size.y > 0) && (base_size.y > max_size.y))
403 base_size.y = max_size.y;
405 if ((max_size.x > 0) && (base_size.x > max_size.x))
406 base_size.x = max_size.x;
409 evas_object_size_hint_min_get(obj, &min_size.x, &min_size.y);
410 if ((min_size.x == 0) || (min_size.y == 0))
411 edje_object_size_min_get(sd->layout, &min_size.x, &min_size.y);
413 if ((min_size.y > 0) && (base_size.y < min_size.y))
414 base_size.y = min_size.y;
416 if ((min_size.x > 0) && (base_size.x < min_size.x))
417 base_size.x = min_size.x;
419 //Check the Which direction is available.
420 //If find a avaialble direction, it adjusts position and size.
421 for (idx = 0; idx < 4; idx++)
423 switch (sd->dir_priority[idx])
425 case ELM_CTXPOPUP_DIRECTION_UNKNOWN:
427 case ELM_CTXPOPUP_DIRECTION_UP:
428 temp.y = (pos.y - base_size.y);
429 if ((temp.y - arrow_size.y) < hover_area.y)
432 _x_pos_adjust(&pos, &base_size, &hover_area);
433 pos.y -= base_size.y;
434 dir = ELM_CTXPOPUP_DIRECTION_UP;
437 case ELM_CTXPOPUP_DIRECTION_LEFT:
438 temp.x = (pos.x - base_size.x);
439 if ((temp.x - arrow_size.x) < hover_area.x)
442 _y_pos_adjust(&pos, &base_size, &hover_area);
443 pos.x -= base_size.x;
444 dir = ELM_CTXPOPUP_DIRECTION_LEFT;
447 case ELM_CTXPOPUP_DIRECTION_RIGHT:
448 temp.x = (pos.x + base_size.x);
449 if ((temp.x + arrow_size.x) >
450 (hover_area.x + hover_area.w))
453 _y_pos_adjust(&pos, &base_size, &hover_area);
454 dir = ELM_CTXPOPUP_DIRECTION_RIGHT;
457 case ELM_CTXPOPUP_DIRECTION_DOWN:
458 temp.y = (pos.y + base_size.y);
459 if ((temp.y + arrow_size.y) >
460 (hover_area.y + hover_area.h))
463 _x_pos_adjust(&pos, &base_size, &hover_area);
464 dir = ELM_CTXPOPUP_DIRECTION_DOWN;
473 //In this case, all directions are invalid because of lack of space.
476 Evas_Coord length[2];
480 length[0] = pos.y - hover_area.y;
481 length[1] = (hover_area.y + hover_area.h) - pos.y;
483 // ELM_CTXPOPUP_DIRECTION_UP
484 if (length[0] > length[1])
486 _x_pos_adjust(&pos, &base_size, &hover_area);
487 pos.y -= base_size.y;
488 dir = ELM_CTXPOPUP_DIRECTION_UP;
489 if (pos.y < (hover_area.y + arrow_size.y))
491 base_size.y -= ((hover_area.y + arrow_size.y) - pos.y);
492 pos.y = hover_area.y + arrow_size.y;
495 //ELM_CTXPOPUP_DIRECTION_DOWN
498 _x_pos_adjust(&pos, &base_size, &hover_area);
499 dir = ELM_CTXPOPUP_DIRECTION_DOWN;
500 if ((pos.y + arrow_size.y + base_size.y) >
501 (hover_area.y + hover_area.h))
503 ((pos.y + arrow_size.y + base_size.y) -
504 (hover_area.y + hover_area.h));
509 length[0] = pos.x - hover_area.x;
510 length[1] = (hover_area.x + hover_area.w) - pos.x;
512 //ELM_CTXPOPUP_DIRECTION_LEFT
513 if (length[0] > length[1])
515 _y_pos_adjust(&pos, &base_size, &hover_area);
516 pos.x -= base_size.x;
517 dir = ELM_CTXPOPUP_DIRECTION_LEFT;
518 if (pos.x < (hover_area.x + arrow_size.x))
520 base_size.x -= ((hover_area.x + arrow_size.x) - pos.x);
521 pos.x = hover_area.x + arrow_size.x;
524 //ELM_CTXPOPUP_DIRECTION_RIGHT
527 _y_pos_adjust(&pos, &base_size, &hover_area);
528 dir = ELM_CTXPOPUP_DIRECTION_RIGHT;
529 if (pos.x + (arrow_size.x + base_size.x) >
530 hover_area.x + hover_area.w)
532 ((pos.x + arrow_size.x + base_size.x) -
533 (hover_area.x + hover_area.w));
538 //Final position and size.
541 rect->w = base_size.x;
542 rect->h = base_size.y;
548 _arrow_update(Evas_Object *obj,
549 Elm_Ctxpopup_Direction dir,
550 Evas_Coord_Rectangle base_size)
552 Evas_Coord_Rectangle arrow_size;
555 Evas_Coord_Rectangle shadow_left_top, shadow_right_bottom, arrow_padding;
557 ELM_CTXPOPUP_DATA_GET(obj, sd);
559 evas_object_geometry_get(obj, &x, &y, NULL, NULL);
560 evas_object_geometry_get
561 (sd->arrow, NULL, NULL, &arrow_size.w, &arrow_size.h);
563 /* tizen only : since ctxpopup of tizen has shadow, start and end padding of arrow, it should be put together when updating arrow
564 * so there are some differences between open source and tizen */
565 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);
566 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);
567 edje_object_part_geometry_get(ELM_WIDGET_DATA(sd)->resize_obj, "ctxpopup_frame_left_top", NULL, NULL, &arrow_padding.w, &arrow_padding.h);
569 /* arrow is not being kept as sub-object on purpose, here. the
570 * design of the widget does not help with the contrary */
574 case ELM_CTXPOPUP_DIRECTION_RIGHT:
575 edje_object_signal_emit(sd->arrow, "elm,state,left", "elm");
576 edje_object_part_swallow
577 (ELM_WIDGET_DATA(sd)->resize_obj,
578 (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_right" :
579 "elm.swallow.arrow_left"), sd->arrow);
583 if (y <= ((arrow_size.h * 0.5) + base_size.y + shadow_left_top.h + arrow_padding.h))
585 else if (y >= (base_size.y + base_size.h - ((arrow_size.h * 0.5) + shadow_right_bottom.h + arrow_padding.h)))
586 y = base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2));
588 y = y - base_size.y - ((arrow_size.h * 0.5) + shadow_left_top.h + arrow_padding.h);
589 drag = (double)(y) / (double)(base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2)));
590 edje_object_part_drag_value_set
591 (ELM_WIDGET_DATA(sd)->resize_obj,
592 (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_right" :
593 "elm.swallow.arrow_left"), 1, drag);
597 case ELM_CTXPOPUP_DIRECTION_LEFT:
598 edje_object_signal_emit(sd->arrow, "elm,state,right", "elm");
599 edje_object_part_swallow
600 (ELM_WIDGET_DATA(sd)->resize_obj,
601 (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_left" :
602 "elm.swallow.arrow_right"), sd->arrow);
606 if (y <= ((arrow_size.h * 0.5) + base_size.y + shadow_left_top.h + arrow_padding.h))
608 else if (y >= (base_size.y + base_size.h - ((arrow_size.h * 0.5) + shadow_right_bottom.h + arrow_padding.h)))
609 y = base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2));
611 y = y - base_size.y - ((arrow_size.h * 0.5) + shadow_left_top.h + arrow_padding.h);
612 drag = (double)(y) / (double)(base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2)));
613 edje_object_part_drag_value_set
614 (ELM_WIDGET_DATA(sd)->resize_obj,
615 (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_left" :
616 "elm.swallow.arrow_right"), 0, drag);
620 case ELM_CTXPOPUP_DIRECTION_DOWN:
621 edje_object_signal_emit(sd->arrow, "elm,state,top", "elm");
622 edje_object_part_swallow
623 (ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.arrow_up",
628 if (x <= ((arrow_size.w * 0.5) + base_size.x + shadow_left_top.w + arrow_padding.w))
630 else if (x >= (base_size.x + base_size.w - ((arrow_size.w * 0.5) + shadow_right_bottom.w + arrow_padding.w)))
631 x = base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2));
633 x = x - base_size.x - ((arrow_size.w * 0.5) + shadow_left_top.w + arrow_padding.w);
634 drag = (double)(x) / (double)(base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2)));
635 edje_object_part_drag_value_set
636 (ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.arrow_up",
641 case ELM_CTXPOPUP_DIRECTION_UP:
642 edje_object_signal_emit(sd->arrow, "elm,state,bottom", "elm");
643 edje_object_part_swallow
644 (ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.arrow_down",
649 if (x <= ((arrow_size.w * 0.5) + base_size.x + shadow_left_top.w + arrow_padding.w))
651 else if (x >= (base_size.x + base_size.w - ((arrow_size.w * 0.5) + shadow_right_bottom.w + arrow_padding.w)))
652 x = base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2));
654 x = x - base_size.x - ((arrow_size.w * 0.5) + shadow_left_top.w + arrow_padding.w);
655 drag = (double)(x) / (double)(base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2)));
656 edje_object_part_drag_value_set
657 (ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.arrow_down",
666 //should be here for getting accurate geometry value
667 evas_object_smart_calculate(ELM_WIDGET_DATA(sd)->resize_obj);
671 _show_signals_emit(Evas_Object *obj,
672 Elm_Ctxpopup_Direction dir)
674 ELM_CTXPOPUP_DATA_GET(obj, sd);
676 if (!sd->visible) return;
680 case ELM_CTXPOPUP_DIRECTION_UP:
681 edje_object_signal_emit(sd->layout, "elm,state,show,up", "elm");
684 case ELM_CTXPOPUP_DIRECTION_LEFT:
685 edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,show,right" :
686 "elm,state,show,left"), "elm");
689 case ELM_CTXPOPUP_DIRECTION_RIGHT:
690 edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,show,left" :
691 "elm,state,show,right"), "elm");
694 case ELM_CTXPOPUP_DIRECTION_DOWN:
695 edje_object_signal_emit(sd->layout, "elm,state,show,down", "elm");
702 edje_object_signal_emit(sd->bg, "elm,state,show", "elm");
703 // elm_layout_signal_emit(obj, "elm,state,show", "elm");
707 _hide_signals_emit(Evas_Object *obj,
708 Elm_Ctxpopup_Direction dir)
710 ELM_CTXPOPUP_DATA_GET(obj, sd);
712 if (!sd->visible) return;
716 case ELM_CTXPOPUP_DIRECTION_UP:
717 edje_object_signal_emit(sd->layout, "elm,state,hide,up", "elm");
720 case ELM_CTXPOPUP_DIRECTION_LEFT:
721 edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,hide,right" :
722 "elm,state,hide,left"), "elm");
725 case ELM_CTXPOPUP_DIRECTION_RIGHT:
726 edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,hide,left" :
727 "elm,state,hide,right"), "elm");
730 case ELM_CTXPOPUP_DIRECTION_DOWN:
731 edje_object_signal_emit(sd->layout, "elm,state,hide,down", "elm");
738 edje_object_signal_emit(sd->bg, "elm,state,hide", "elm");
742 _base_shift_by_arrow(Evas_Object *arrow,
743 Elm_Ctxpopup_Direction dir,
744 Evas_Coord_Rectangle *rect)
746 Evas_Coord arrow_w, arrow_h;
748 evas_object_geometry_get(arrow, NULL, NULL, &arrow_w, &arrow_h);
752 case ELM_CTXPOPUP_DIRECTION_RIGHT:
756 case ELM_CTXPOPUP_DIRECTION_LEFT:
760 case ELM_CTXPOPUP_DIRECTION_DOWN:
764 case ELM_CTXPOPUP_DIRECTION_UP:
773 //TODO: compress item - different from opensource
775 _compress_item(Evas_Object *obj)
778 Elm_Ctxpopup_Item *item;
780 ELM_CTXPOPUP_DATA_GET(obj, sd);
783 EINA_LIST_FOREACH(sd->items, elist, item)
785 edje_object_signal_emit(item->base.view, "elm,state,compress", "elm");
790 _elm_ctxpopup_smart_sub_object_add(Evas_Object *obj,
793 Elm_Widget_Smart_Class *parent_parent;
795 parent_parent = (Elm_Widget_Smart_Class *)((Evas_Smart_Class *)
796 _elm_ctxpopup_parent_sc)->parent;
798 /* skipping layout's code, which registers size hint changing
799 * callback on sub objects. a hack to make ctxpopup live, as it is,
800 * on the new classing schema. this widget needs a total
802 if (!parent_parent->sub_object_add(obj, sobj))
809 _elm_ctxpopup_smart_sizing_eval(Evas_Object *obj)
812 Elm_Ctxpopup_Item *item;
813 Evas_Coord_Rectangle rect = { 0, 0, 1, 1 };
814 Evas_Coord_Point box_size = { 0, 0 };
815 Evas_Coord_Point _box_size = { 0, 0 };
819 ELM_CTXPOPUP_DATA_GET(obj, sd);
822 EINA_LIST_FOREACH(sd->items, elist, item)
824 _item_sizing_eval(item);
825 evas_object_size_hint_min_get(VIEW(item), &_box_size.x, &_box_size.y);
827 str = edje_object_data_get(VIEW(item), "item_max_size");
831 maxw = maxw * elm_widget_scale_get(obj) * elm_config_scale_get();
833 if (_box_size.x > maxw)
835 edje_object_signal_emit(VIEW(item), "elm,state,text,ellipsis", "elm");
836 edje_object_message_signal_process(VIEW(item));
842 if (_box_size.x > box_size.x)
843 box_size.x = _box_size.x;
844 if (_box_size.y != -1)
845 box_size.y += _box_size.y;
849 if (_box_size.x != -1)
850 box_size.x += _box_size.x;
851 if (_box_size.y > box_size.y)
852 box_size.y = _box_size.y;
856 if (!sd->arrow) return; /* simple way to flag "under deletion" */
858 if ((!sd->content) && (sd->scr))
860 evas_object_size_hint_min_set(sd->box, box_size.x, box_size.y);
861 elm_scroller_content_min_limit(sd->scr, EINA_TRUE, EINA_TRUE);
862 evas_object_size_hint_min_set(sd->scr, box_size.x, box_size.y);
866 sd->dir = _base_geometry_calc(obj, &rect);
868 //TODO: compress item - different from opensource
869 if (!sd->horizontal && !sd->content)
872 _arrow_update(obj, sd->dir, rect);
873 _base_shift_by_arrow(sd->arrow, sd->dir, &rect);
875 //resize scroller according to final size
876 if ((!sd->content) && (sd->scr))
878 elm_scroller_content_min_limit(sd->scr, EINA_FALSE, EINA_FALSE);
879 evas_object_smart_calculate(sd->scr);
882 evas_object_size_hint_min_set(ELM_WIDGET_DATA(sd)->resize_obj, rect.w, rect.h);
883 evas_object_resize(ELM_WIDGET_DATA(sd)->resize_obj, rect.w, rect.h);
885 evas_object_move(sd->layout, rect.x, rect.y);
886 evas_object_resize(sd->layout, rect.w, rect.h);
888 _show_signals_emit(obj, sd->dir);
892 _on_parent_del(void *data,
894 Evas_Object *obj __UNUSED__,
895 void *event_info __UNUSED__)
897 evas_object_del(data);
901 _on_parent_move(void *data,
903 Evas_Object *obj __UNUSED__,
904 void *event_info __UNUSED__)
906 ELM_CTXPOPUP_DATA_GET(data, sd);
909 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
913 _scroller_size_reset(sd);
914 elm_layout_sizing_eval(data);
919 _on_parent_resize(void *data,
921 Evas_Object *obj __UNUSED__,
922 void *event_info __UNUSED__)
924 ELM_CTXPOPUP_DATA_GET(data, sd);
926 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
928 evas_object_hide(data);
929 evas_object_smart_callback_call(data, SIG_DISMISSED, NULL);
933 _parent_detach(Evas_Object *obj)
935 ELM_CTXPOPUP_DATA_GET(obj, sd);
937 if (!sd->parent) return;
939 evas_object_event_callback_del_full
940 (sd->parent, EVAS_CALLBACK_DEL, _on_parent_del, obj);
941 evas_object_event_callback_del_full
942 (sd->parent, EVAS_CALLBACK_MOVE, _on_parent_move, obj);
943 evas_object_event_callback_del_full
944 (sd->parent, EVAS_CALLBACK_RESIZE, _on_parent_resize, obj);
948 _on_content_resized(void *data,
950 Evas_Object *obj __UNUSED__,
951 void *event_info __UNUSED__)
953 ELM_CTXPOPUP_DATA_GET(data, sd);
955 elm_box_recalculate(sd->box);
956 elm_layout_sizing_eval(data);
959 //FIXME: lost the content size when theme hook is called.
961 _elm_ctxpopup_smart_theme(Evas_Object *obj)
964 Elm_Ctxpopup_Item *item;
968 ELM_CTXPOPUP_DATA_GET(obj, sd);
970 if (!ELM_WIDGET_CLASS(_elm_ctxpopup_parent_sc)->theme(obj))
973 rtl = elm_widget_mirrored_get(obj);
975 elm_widget_theme_object_set
976 (obj, sd->bg, "ctxpopup", "bg", elm_widget_style_get(obj));
977 elm_widget_theme_object_set
978 (obj, sd->arrow, "ctxpopup", "arrow", elm_widget_style_get(obj));
979 elm_widget_theme_object_set
980 (obj, sd->layout, "ctxpopup", "layout", elm_widget_style_get(obj));
983 EINA_LIST_FOREACH(sd->items, elist, item)
985 edje_object_mirrored_set(VIEW(item), rtl);
987 if (item->label && item->icon)
988 _elm_theme_object_set
989 (obj, VIEW(item), "ctxpopup", "icon_text_style_item", elm_widget_style_get(obj));
990 else if (item->label)
993 _elm_theme_object_set(obj, VIEW(item), "ctxpopup", "text_style_item",
994 elm_widget_style_get(obj));
996 _elm_theme_object_set(obj, VIEW(item), "ctxpopup", "text_style_item_horizontal",
997 elm_widget_style_get(obj));
1000 _elm_theme_object_set
1001 (obj, VIEW(item), "ctxpopup", "icon_style_item", elm_widget_style_get(obj));
1003 edje_object_part_text_set(VIEW(item), "elm.text", item->label);
1005 if (elm_widget_item_disabled_get(item))
1006 edje_object_signal_emit(VIEW(item), "elm,state,disabled", "elm");
1009 * For separator, if the first item has visible separator,
1010 * then it should be aligned with edge of the base part.
1011 * In some cases, it gives improper display. Ex) rounded corner
1012 * So the first item separator should be invisible.
1015 edje_object_signal_emit(VIEW(item), "elm,state,default", "elm");
1017 edje_object_signal_emit(VIEW(item), "elm,state,separator", "elm");
1019 edje_object_message_signal_process(VIEW(item));
1022 if (evas_object_visible_get(sd->bg))
1023 edje_object_signal_emit(sd->bg, "elm,state,show", "elm");
1027 if (!strncmp(elm_object_style_get(obj), "default", strlen("default")))
1028 elm_object_style_set(sd->scr, "ctxpopup");
1030 elm_object_style_set(sd->scr, elm_object_style_get(obj));
1033 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1037 _scroller_size_reset(sd);
1038 _elm_ctxpopup_smart_sizing_eval(obj);
1044 /* kind of a big and tricky override here: an internal box will hold
1045 * the actual content. content aliases won't be of much help here */
1047 _elm_ctxpopup_smart_content_set(Evas_Object *obj,
1049 Evas_Object *content)
1051 Evas_Coord min_w = -1, min_h = -1;
1053 ELM_CTXPOPUP_DATA_GET(obj, sd);
1055 if ((part) && (strcmp(part, "default")))
1056 return ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_set
1057 (obj, part, content);
1059 if (!content) return EINA_FALSE;
1061 if (content == sd->content) return EINA_TRUE;
1063 if (sd->items) elm_ctxpopup_clear(obj);
1064 if (sd->content) evas_object_del(sd->content);
1069 sd->box = elm_box_add(obj);
1070 evas_object_size_hint_weight_set(sd->box, EVAS_HINT_EXPAND,
1072 evas_object_event_callback_add
1073 (sd->box, EVAS_CALLBACK_RESIZE, _on_content_resized, obj);
1074 ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_set
1075 (obj, "elm.swallow.content", sd->box);
1078 evas_object_size_hint_weight_set
1079 (content, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1080 evas_object_size_hint_fill_set
1081 (content, EVAS_HINT_FILL, EVAS_HINT_FILL);
1083 /* since it's going to be a box content, not a layout's... */
1084 evas_object_show(content);
1086 evas_object_size_hint_min_get(content, &min_w, &min_h);
1087 evas_object_size_hint_min_set(sd->box, min_w, min_h);
1088 elm_box_pack_end(sd->box, content);
1090 sd->content = content;
1091 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1093 if (sd->visible) elm_layout_sizing_eval(obj);
1098 static Evas_Object *
1099 _elm_ctxpopup_smart_content_get(const Evas_Object *obj,
1102 ELM_CTXPOPUP_DATA_GET(obj, sd);
1104 if ((part) && (strcmp(part, "default")))
1105 return ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_get
1111 static Evas_Object *
1112 _elm_ctxpopup_smart_content_unset(Evas_Object *obj,
1115 Evas_Object *content;
1117 ELM_CTXPOPUP_DATA_GET(obj, sd);
1119 if ((part) && (strcmp(part, "default")))
1120 return ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_unset
1123 content = sd->content;
1124 if (!content) return NULL;
1126 evas_object_del(sd->box);
1129 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1131 if (sd->visible) elm_layout_sizing_eval(obj);
1137 _item_text_set_hook(Elm_Object_Item *it,
1141 Elm_Ctxpopup_Item *ctxpopup_it;
1143 if ((part) && (strcmp(part, "default"))) return;
1145 ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1147 _item_label_set(ctxpopup_it, label);
1151 _item_text_get_hook(const Elm_Object_Item *it,
1154 Elm_Ctxpopup_Item *ctxpopup_it;
1156 if (part && strcmp(part, "default")) return NULL;
1158 ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1159 return ctxpopup_it->label;
1163 _item_content_set_hook(Elm_Object_Item *it,
1165 Evas_Object *content)
1167 Elm_Ctxpopup_Item *ctxpopup_it;
1169 if ((part) && (strcmp(part, "icon"))) return;
1171 ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1173 ELM_CTXPOPUP_DATA_GET(WIDGET(ctxpopup_it), sd);
1175 _item_icon_set(ctxpopup_it, content);
1176 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1180 _scroller_size_reset(sd);
1181 _elm_ctxpopup_smart_sizing_eval(WIDGET(ctxpopup_it));
1185 static Evas_Object *
1186 _item_content_get_hook(const Elm_Object_Item *it,
1189 Elm_Ctxpopup_Item *ctxpopup_it;
1191 if (part && strcmp(part, "icon")) return NULL;
1193 ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1194 return ctxpopup_it->icon;
1198 _item_disable_hook(Elm_Object_Item *it)
1200 Elm_Ctxpopup_Item *ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1202 ELM_CTXPOPUP_DATA_GET(WIDGET(it), sd);
1205 if (elm_widget_item_disabled_get(it))
1206 edje_object_signal_emit(VIEW(ctxpopup_it), "elm,state,disabled", "elm");
1208 edje_object_signal_emit(VIEW(ctxpopup_it), "elm,state,enabled", "elm");
1212 _item_signal_emit_hook(Elm_Object_Item *it,
1213 const char *emission,
1216 Elm_Ctxpopup_Item *ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1218 edje_object_signal_emit(VIEW(ctxpopup_it), emission, source);
1222 _bg_clicked_cb(void *data,
1223 Evas_Object *obj __UNUSED__,
1224 const char *emission __UNUSED__,
1225 const char *source __UNUSED__)
1227 ELM_CTXPOPUP_DATA_GET(data, sd);
1229 _hide_signals_emit(data, sd->dir);
1233 _on_show(void *data __UNUSED__,
1236 void *event_info __UNUSED__)
1239 Elm_Ctxpopup_Item *item;
1242 ELM_CTXPOPUP_DATA_GET(obj, sd);
1244 if ((!sd->items) && (!sd->content)) return;
1246 sd->visible = EINA_TRUE;
1248 evas_object_show(sd->bg);
1249 evas_object_show(sd->arrow);
1250 evas_object_show(sd->layout);
1252 edje_object_signal_emit(sd->bg, "elm,state,show", "elm");
1253 elm_layout_signal_emit(obj, "elm,state,show", "elm");
1255 EINA_LIST_FOREACH(sd->items, elist, item)
1257 if (item->label && !item->icon)
1260 _elm_theme_object_set(obj, VIEW(item), "ctxpopup", "text_style_item",
1261 elm_widget_style_get(obj));
1263 _elm_theme_object_set(obj, VIEW(item), "ctxpopup", "text_style_item_horizontal",
1264 elm_widget_style_get(obj));
1268 edje_object_signal_emit(VIEW(item), "elm,state,default", "elm");
1270 edje_object_signal_emit(VIEW(item), "elm,state,separator", "elm");
1273 elm_layout_sizing_eval(obj);
1275 elm_object_focus_set(obj, EINA_TRUE);
1279 _on_hide(void *data __UNUSED__,
1282 void *event_info __UNUSED__)
1284 ELM_CTXPOPUP_DATA_GET(obj, sd);
1286 if (!sd->visible) return;
1288 evas_object_hide(sd->bg);
1289 evas_object_hide(sd->arrow);
1290 evas_object_hide(sd->layout);
1292 _scroller_size_reset(sd);
1294 sd->visible = EINA_FALSE;
1298 _on_move(void *data __UNUSED__,
1301 void *event_info __UNUSED__)
1303 ELM_CTXPOPUP_DATA_GET(obj, sd);
1305 if (sd->visible) evas_object_show(sd->arrow);
1307 _scroller_size_reset(sd);
1308 _elm_ctxpopup_smart_sizing_eval(obj);
1312 _hide_finished_cb(void *data,
1313 Evas_Object *obj __UNUSED__,
1314 const char *emission __UNUSED__,
1315 const char *source __UNUSED__)
1317 evas_object_hide(data);
1318 evas_object_smart_callback_call(data, SIG_DISMISSED, NULL);
1322 _scroller_resize(void *data, Evas *e __UNUSED__,
1324 void *event_info __UNUSED__)
1328 ELM_CTXPOPUP_DATA_GET(data, sd);
1330 if (!sd->visible) return;
1331 if (sd->finished) return;
1333 evas_object_geometry_get(obj, 0, 0, &w, &h);
1335 if (w != 0 && h != 0)
1337 if ((w <= sd->max_sc_w) && (h <= sd->max_sc_h))
1339 _elm_ctxpopup_smart_sizing_eval(data);
1340 sd->finished = EINA_TRUE;
1345 if (sd->max_sc_w < w)
1347 if (sd->max_sc_h < h)
1350 _elm_ctxpopup_smart_sizing_eval(data);
1354 _ctxpopup_restack_cb(void *data __UNUSED__,
1357 void *event_info __UNUSED__)
1359 ELM_CTXPOPUP_DATA_GET(obj, sd);
1360 evas_object_stack_below(sd->bg, obj);
1361 evas_object_stack_below(sd->layout, obj);
1365 _list_del(Elm_Ctxpopup_Smart_Data *sd)
1367 if (!sd->scr) return;
1369 edje_object_part_unswallow(ELM_WIDGET_DATA(sd)->resize_obj, sd->scr);
1370 evas_object_del(sd->scr);
1372 evas_object_del(sd->box);
1377 _list_new(Evas_Object *obj)
1379 ELM_CTXPOPUP_DATA_GET(obj, sd);
1383 sd->scr = elm_scroller_add(obj);
1384 elm_object_style_set(sd->scr, "ctxpopup");
1385 evas_object_size_hint_align_set(sd->scr, EVAS_HINT_FILL, EVAS_HINT_FILL);
1386 evas_object_event_callback_add(sd->scr, EVAS_CALLBACK_RESIZE,
1387 _scroller_resize, obj);
1388 edje_object_part_swallow(ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.content", sd->scr);
1393 sd->box = elm_box_add(obj);
1394 evas_object_size_hint_weight_set(sd->box, EVAS_HINT_EXPAND,
1396 evas_object_event_callback_add
1397 (sd->box, EVAS_CALLBACK_RESIZE, _on_content_resized, obj);
1398 ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_set
1399 (obj, "elm.swallow.content", sd->box);
1402 elm_object_content_set(sd->scr, sd->box);
1403 elm_ctxpopup_horizontal_set(obj, sd->horizontal);
1407 _elm_ctxpopup_smart_disable(Evas_Object *obj)
1410 Elm_Object_Item *it;
1412 ELM_CTXPOPUP_DATA_GET(obj, sd);
1414 if (!ELM_WIDGET_CLASS(_elm_ctxpopup_parent_sc)->disable(obj))
1417 EINA_LIST_FOREACH(sd->items, l, it)
1418 elm_object_item_disabled_set(it, elm_widget_disabled_get(obj));
1424 _elm_ctxpopup_smart_add(Evas_Object *obj)
1426 EVAS_SMART_DATA_ALLOC(obj, Elm_Ctxpopup_Smart_Data);
1427 ELM_CTXPOPUP_DATA_GET(obj, sd);
1429 ELM_WIDGET_CLASS(_elm_ctxpopup_parent_sc)->base.add(obj);
1431 elm_layout_theme_set(obj, "ctxpopup", "base", elm_widget_style_get(obj));
1432 elm_layout_signal_callback_add
1433 (obj, "elm,action,hide,finished", "", _hide_finished_cb, obj);
1436 priv->bg = edje_object_add(evas_object_evas_get(obj));
1437 elm_widget_theme_object_set(obj, priv->bg, "ctxpopup", "bg", "default");
1438 edje_object_signal_callback_add
1439 (priv->bg, "elm,action,click", "", _bg_clicked_cb, obj);
1441 evas_object_stack_below(priv->bg, obj);
1444 priv->arrow = edje_object_add(evas_object_evas_get(obj));
1445 elm_widget_theme_object_set
1446 (obj, priv->arrow, "ctxpopup", "arrow", "default");
1448 priv->dir_priority[0] = ELM_CTXPOPUP_DIRECTION_UP;
1449 priv->dir_priority[1] = ELM_CTXPOPUP_DIRECTION_LEFT;
1450 priv->dir_priority[2] = ELM_CTXPOPUP_DIRECTION_RIGHT;
1451 priv->dir_priority[3] = ELM_CTXPOPUP_DIRECTION_DOWN;
1452 priv->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1454 evas_object_event_callback_add
1455 (obj, EVAS_CALLBACK_RESTACK, _ctxpopup_restack_cb, obj);
1457 evas_object_smart_callback_add
1458 (obj, "scroll-freeze-on", _freeze_on_cb, obj);
1459 evas_object_smart_callback_add
1460 (obj, "scroll-freeze-off", _freeze_off_cb, obj);
1461 evas_object_smart_callback_add
1462 (obj, "scroll-hold-on", _hold_on_cb, obj);
1463 evas_object_smart_callback_add
1464 (obj, "scroll-hold-off", _hold_off_cb, obj);
1466 priv->box = elm_box_add(obj);
1467 evas_object_size_hint_weight_set
1468 (priv->box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1470 evas_object_event_callback_add
1471 (priv->box, EVAS_CALLBACK_RESIZE, _on_content_resized, obj);
1473 /* box will be our content placeholder, thus the parent's version call */
1474 ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_set
1475 (obj, "elm.swallow.content", priv->box);
1477 priv->layout = edje_object_add(evas_object_evas_get(obj));
1478 elm_widget_theme_object_set(obj, priv->layout, "ctxpopup", "layout", "default");
1480 edje_object_signal_callback_add
1481 (priv->layout, "elm,action,hide,finished", "", _hide_finished_cb, obj);
1482 edje_object_part_swallow(priv->layout, "swallow", ELM_WIDGET_DATA(sd)->resize_obj);
1483 evas_object_size_hint_weight_set
1484 (priv->layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1486 evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _on_show, NULL);
1487 evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _on_hide, NULL);
1488 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _on_move, NULL);
1490 elm_widget_can_focus_set(obj, EINA_TRUE);
1494 _elm_ctxpopup_smart_del(Evas_Object *obj)
1496 ELM_CTXPOPUP_DATA_GET(obj, sd);
1498 evas_object_event_callback_del_full
1499 (sd->box, EVAS_CALLBACK_RESIZE, _on_content_resized, obj);
1500 _parent_detach(obj);
1502 elm_ctxpopup_clear(obj);
1503 evas_object_del(sd->arrow);
1504 sd->arrow = NULL; /* stops _sizing_eval() from going on on deletion */
1506 evas_object_del(sd->bg);
1509 evas_object_del(sd->layout);
1512 ELM_WIDGET_CLASS(_elm_ctxpopup_parent_sc)->base.del(obj);
1516 _elm_ctxpopup_smart_parent_set(Evas_Object *obj,
1517 Evas_Object *parent)
1519 //default parent is to be hover parent
1520 elm_ctxpopup_hover_parent_set(obj, parent);
1524 _elm_ctxpopup_smart_access(Evas_Object *obj, Eina_Bool is_access)
1526 Eina_List *elist = NULL;
1527 Elm_Ctxpopup_Item *it;
1529 ELM_CTXPOPUP_CHECK(obj);
1530 ELM_CTXPOPUP_DATA_GET(obj, sd);
1532 EINA_LIST_FOREACH(sd->items, elist, it)
1533 _access_widget_item_register(it, is_access);
1537 _elm_ctxpopup_smart_set_user(Elm_Ctxpopup_Smart_Class *sc)
1539 ELM_WIDGET_CLASS(sc)->base.add = _elm_ctxpopup_smart_add;
1540 ELM_WIDGET_CLASS(sc)->base.del = _elm_ctxpopup_smart_del;
1542 ELM_WIDGET_CLASS(sc)->parent_set = _elm_ctxpopup_smart_parent_set;
1543 ELM_WIDGET_CLASS(sc)->disable = _elm_ctxpopup_smart_disable;
1544 ELM_WIDGET_CLASS(sc)->event = _elm_ctxpopup_smart_event;
1545 ELM_WIDGET_CLASS(sc)->theme = _elm_ctxpopup_smart_theme;
1546 ELM_WIDGET_CLASS(sc)->sub_object_add = _elm_ctxpopup_smart_sub_object_add;
1547 ELM_WIDGET_CLASS(sc)->focus_next = _elm_ctxpopup_smart_focus_next;
1548 ELM_WIDGET_CLASS(sc)->focus_direction = NULL;
1549 ELM_WIDGET_CLASS(sc)->translate = _elm_ctxpopup_smart_translate;
1551 ELM_CONTAINER_CLASS(sc)->content_get = _elm_ctxpopup_smart_content_get;
1552 ELM_CONTAINER_CLASS(sc)->content_set = _elm_ctxpopup_smart_content_set;
1553 ELM_CONTAINER_CLASS(sc)->content_unset = _elm_ctxpopup_smart_content_unset;
1555 ELM_LAYOUT_CLASS(sc)->sizing_eval = _elm_ctxpopup_smart_sizing_eval;
1557 ELM_WIDGET_CLASS(sc)->access = _elm_ctxpopup_smart_access;
1560 EAPI const Elm_Ctxpopup_Smart_Class *
1561 elm_ctxpopup_smart_class_get(void)
1563 static Elm_Ctxpopup_Smart_Class _sc =
1564 ELM_CTXPOPUP_SMART_CLASS_INIT_NAME_VERSION(ELM_CTXPOPUP_SMART_NAME);
1565 static const Elm_Ctxpopup_Smart_Class *class = NULL;
1566 Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
1571 _elm_ctxpopup_smart_set(&_sc);
1572 esc->callbacks = _smart_callbacks;
1579 elm_ctxpopup_add(Evas_Object *parent)
1583 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1585 obj = elm_widget_add(_elm_ctxpopup_smart_class_new(), parent);
1586 if (!obj) return NULL;
1588 if (!elm_widget_sub_object_add(parent, obj))
1589 ERR("could not add %p as sub object of %p", obj, parent);
1591 /* access: parent could be any object such as elm_list which does
1592 not know elc_ctxpopup as its child object in the focus_next(); */
1593 ELM_WIDGET_DATA_GET(obj, sd);
1594 sd->highlight_root = EINA_TRUE;
1600 elm_ctxpopup_hover_parent_set(Evas_Object *obj,
1601 Evas_Object *parent)
1603 Evas_Coord x, y, w, h;
1605 ELM_CTXPOPUP_CHECK(obj);
1606 ELM_CTXPOPUP_DATA_GET(obj, sd);
1608 if (!parent) return;
1610 _parent_detach(obj);
1612 evas_object_event_callback_add
1613 (parent, EVAS_CALLBACK_DEL, _on_parent_del, obj);
1614 evas_object_event_callback_add
1615 (parent, EVAS_CALLBACK_MOVE, _on_parent_move, obj);
1616 evas_object_event_callback_add
1617 (parent, EVAS_CALLBACK_RESIZE, _on_parent_resize, obj);
1619 sd->parent = parent;
1622 evas_object_geometry_get(parent, &x, &y, &w, &h);
1623 evas_object_move(sd->bg, x, y);
1624 evas_object_resize(sd->bg, w, h);
1626 if (sd->visible) elm_layout_sizing_eval(obj);
1630 elm_ctxpopup_hover_parent_get(const Evas_Object *obj)
1632 ELM_CTXPOPUP_CHECK(obj) NULL;
1633 ELM_CTXPOPUP_DATA_GET(obj, sd);
1639 elm_ctxpopup_clear(Evas_Object *obj)
1641 ELM_CTXPOPUP_CHECK(obj);
1642 ELM_CTXPOPUP_DATA_GET(obj, sd);
1646 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1650 elm_ctxpopup_horizontal_set(Evas_Object *obj,
1651 Eina_Bool horizontal)
1654 Elm_Ctxpopup_Item *item;
1657 ELM_CTXPOPUP_CHECK(obj);
1658 ELM_CTXPOPUP_DATA_GET(obj, sd);
1660 sd->horizontal = !!horizontal;
1667 elm_box_horizontal_set(sd->box, EINA_FALSE);
1668 elm_scroller_bounce_set(sd->scr, EINA_FALSE, EINA_TRUE);
1672 elm_box_horizontal_set(sd->box, EINA_TRUE);
1673 elm_scroller_bounce_set(sd->scr, EINA_TRUE, EINA_FALSE);
1676 EINA_LIST_FOREACH(sd->items, elist, item)
1678 if (item->label && !item->icon && !horizontal)
1679 _elm_theme_object_set(obj, VIEW(item), "ctxpopup", "text_style_item",
1680 elm_widget_style_get(obj));
1681 else if (item->label && !item->icon && horizontal)
1682 _elm_theme_object_set(obj, VIEW(item), "ctxpopup", "text_style_item_horizontal",
1683 elm_widget_style_get(obj));
1686 edje_object_signal_emit(VIEW(item), "elm,state,default", "elm");
1688 edje_object_signal_emit(VIEW(item), "elm,state,separator", "elm");
1690 _item_disable_hook((Elm_Object_Item *)item);
1693 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1695 if (sd->visible) elm_layout_sizing_eval(obj);
1699 elm_ctxpopup_horizontal_get(const Evas_Object *obj)
1701 ELM_CTXPOPUP_CHECK(obj) EINA_FALSE;
1702 ELM_CTXPOPUP_DATA_GET(obj, sd);
1704 return sd->horizontal;
1707 EAPI Elm_Object_Item *
1708 elm_ctxpopup_item_append(Evas_Object *obj,
1714 Elm_Ctxpopup_Item *item;
1715 Evas_Object *content;
1717 ELM_CTXPOPUP_CHECK(obj) NULL;
1718 ELM_CTXPOPUP_DATA_GET(obj, sd);
1720 item = elm_widget_item_new(obj, Elm_Ctxpopup_Item);
1721 if (!item) return NULL;
1723 elm_widget_item_del_pre_hook_set(item, _item_del_pre_hook);
1724 elm_widget_item_disable_hook_set(item, _item_disable_hook);
1725 elm_widget_item_text_set_hook_set(item, _item_text_set_hook);
1726 elm_widget_item_text_get_hook_set(item, _item_text_get_hook);
1727 elm_widget_item_content_set_hook_set(item, _item_content_set_hook);
1728 elm_widget_item_content_get_hook_set(item, _item_content_get_hook);
1729 elm_widget_item_signal_emit_hook_set(item, _item_signal_emit_hook);
1731 //The first item is appended.
1732 content = elm_object_content_unset(obj);
1733 if (content) evas_object_del(content);
1739 item->base.data = data;
1742 _item_new(item, "icon_text_style_item");
1745 if (!sd->horizontal)
1746 _item_new(item, "text_style_item");
1748 _item_new(item, "text_style_item_horizontal");
1751 _item_new(item, "icon_style_item");
1753 _item_icon_set(item, icon);
1754 _item_label_set(item, label);
1755 elm_box_pack_end(sd->box, VIEW(item));
1756 sd->items = eina_list_append(sd->items, item);
1758 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1762 _scroller_size_reset(sd);
1763 _elm_ctxpopup_smart_sizing_eval(obj);
1767 return (Elm_Object_Item *)item;
1771 elm_ctxpopup_direction_priority_set(Evas_Object *obj,
1772 Elm_Ctxpopup_Direction first,
1773 Elm_Ctxpopup_Direction second,
1774 Elm_Ctxpopup_Direction third,
1775 Elm_Ctxpopup_Direction fourth)
1777 ELM_CTXPOPUP_CHECK(obj);
1778 ELM_CTXPOPUP_DATA_GET(obj, sd);
1780 sd->dir_priority[0] = first;
1781 sd->dir_priority[1] = second;
1782 sd->dir_priority[2] = third;
1783 sd->dir_priority[3] = fourth;
1785 if (sd->visible) elm_layout_sizing_eval(obj);
1789 elm_ctxpopup_direction_priority_get(Evas_Object *obj,
1790 Elm_Ctxpopup_Direction *first,
1791 Elm_Ctxpopup_Direction *second,
1792 Elm_Ctxpopup_Direction *third,
1793 Elm_Ctxpopup_Direction *fourth)
1795 ELM_CTXPOPUP_CHECK(obj);
1796 ELM_CTXPOPUP_DATA_GET(obj, sd);
1798 if (first) *first = sd->dir_priority[0];
1799 if (second) *second = sd->dir_priority[1];
1800 if (third) *third = sd->dir_priority[2];
1801 if (fourth) *fourth = sd->dir_priority[3];
1804 EAPI Elm_Ctxpopup_Direction
1805 elm_ctxpopup_direction_get(const Evas_Object *obj)
1807 ELM_CTXPOPUP_CHECK(obj) ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1808 ELM_CTXPOPUP_DATA_GET(obj, sd);
1814 elm_ctxpopup_dismiss(Evas_Object *obj)
1816 ELM_CTXPOPUP_CHECK(obj);
1817 ELM_CTXPOPUP_DATA_GET(obj, sd);
1819 _hide_signals_emit(obj, sd->dir);