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 Evas_Smart_Cb_Description _smart_callbacks[] = {
13 EVAS_SMART_SUBCLASS_NEW
14 (ELM_CTXPOPUP_SMART_NAME, _elm_ctxpopup, Elm_Ctxpopup_Smart_Class,
15 Elm_Layout_Smart_Class, elm_layout_smart_class_get, _smart_callbacks);
18 _elm_ctxpopup_smart_focus_next(const Evas_Object *obj,
19 Elm_Focus_Direction dir,
22 Eina_List *items = NULL;
23 Eina_List *elist = NULL;
24 Elm_Ctxpopup_Item *it;
26 ELM_CTXPOPUP_DATA_GET(obj, sd);
31 if (!elm_widget_focus_next_get(sd->box, dir, next))
33 elm_widget_focused_object_clear(sd->box);
34 elm_widget_focus_next_get(sd->box, dir, next);
37 EINA_LIST_FOREACH(sd->items, elist, it)
38 items = eina_list_append(items, it->base.access_obj);
40 return elm_widget_focus_list_next_get
41 (obj, items, eina_list_data_get, dir, next);
45 _elm_ctxpopup_smart_event(Evas_Object *obj,
46 Evas_Object *src __UNUSED__,
47 Evas_Callback_Type type,
50 Evas_Event_Key_Down *ev = event_info;
52 ELM_CTXPOPUP_DATA_GET(obj, sd);
54 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
55 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
56 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
58 if (!strcmp(ev->keyname, "Tab"))
60 if (evas_key_modifier_is_set(ev->modifiers, "Shift"))
61 elm_widget_focus_cycle(sd->box, ELM_FOCUS_PREVIOUS);
63 elm_widget_focus_cycle(sd->box, ELM_FOCUS_NEXT);
67 if (strcmp(ev->keyname, "Escape")) return EINA_FALSE;
69 evas_object_hide(obj);
70 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
75 _freeze_on_cb(void *data __UNUSED__,
77 void *event_info __UNUSED__)
79 ELM_CTXPOPUP_DATA_GET(obj, sd);
81 if ((!sd) || (!sd->scr)) return;
82 elm_object_scroll_freeze_push(sd->scr);
86 _freeze_off_cb(void *data __UNUSED__,
88 void *event_info __UNUSED__)
90 ELM_CTXPOPUP_DATA_GET(obj, sd);
92 if ((!sd) || (!sd->scr)) return;
93 elm_object_scroll_freeze_pop(sd->scr);
97 _hold_on_cb(void *data __UNUSED__,
99 void *event_info __UNUSED__)
101 ELM_CTXPOPUP_DATA_GET(obj, sd);
103 if ((!sd) || (!sd->scr)) return;
104 elm_object_scroll_hold_push(sd->scr);
108 _hold_off_cb(void *data __UNUSED__,
110 void *event_info __UNUSED__)
112 ELM_CTXPOPUP_DATA_GET(obj, sd);
114 if ((!sd) || (!sd->scr)) return;
115 elm_object_scroll_hold_pop(sd->scr);
119 _x_pos_adjust(Evas_Coord_Point *pos,
120 Evas_Coord_Point *base_size,
121 Evas_Coord_Rectangle *hover_area)
123 pos->x -= (base_size->x / 2);
125 if (pos->x < hover_area->x)
126 pos->x = hover_area->x;
127 else if ((pos->x + base_size->x) > (hover_area->x + hover_area->w))
128 pos->x = (hover_area->x + hover_area->w) - base_size->x;
130 if (base_size->x > hover_area->w)
131 base_size->x -= (base_size->x - hover_area->w);
133 if (pos->x < hover_area->x)
134 pos->x = hover_area->x;
138 _y_pos_adjust(Evas_Coord_Point *pos,
139 Evas_Coord_Point *base_size,
140 Evas_Coord_Rectangle *hover_area)
142 pos->y -= (base_size->y / 2);
144 if (pos->y < hover_area->y)
145 pos->y = hover_area->y;
146 else if ((pos->y + base_size->y) > (hover_area->y + hover_area->h))
147 pos->y = hover_area->y + hover_area->h - base_size->y;
149 if (base_size->y > hover_area->h)
150 base_size->y -= (base_size->y - hover_area->h);
152 if (pos->y < hover_area->y)
153 pos->y = hover_area->y;
157 _item_select_cb(void *data, Evas_Object *obj __UNUSED__,
158 const char *emission __UNUSED__,
159 const char *source __UNUSED__)
161 Elm_Ctxpopup_Item *item = data;
164 if (elm_widget_item_disabled_get(item)) return;
167 item->func((void*)item->base.data, WIDGET(item), data);
171 _access_info_cb(void *data, Evas_Object *obj __UNUSED__)
173 Elm_Ctxpopup_Item *it = (Elm_Ctxpopup_Item *)data;
174 const char *txt = NULL;
175 Evas_Object *icon = NULL;
176 Eina_Strbuf *buf = NULL;
179 if (!it) return NULL;
181 if ((!txt) && (!icon))
186 else if (!txt) txt = it->label;
187 else if (!icon) icon = it->icon;
191 buf = eina_strbuf_new();
192 eina_strbuf_append(buf, E_("icon "));
193 eina_strbuf_append(buf, txt);
194 str = eina_strbuf_string_steal(buf);
195 eina_strbuf_free(buf);
198 else if ((!txt) && icon) return strdup(E_("icon"));
199 else if (txt && (!icon)) return strdup(txt);
205 _access_state_cb(void *data, Evas_Object *obj __UNUSED__)
207 Elm_Ctxpopup_Item *it = (Elm_Ctxpopup_Item *)data;
208 if (!it) return NULL;
210 if (it->base.disabled)
211 return strdup(E_("State: Disabled"));
217 _access_activate_cb(void *data __UNUSED__,
218 Evas_Object *part_obj __UNUSED__,
219 Elm_Object_Item *item)
221 _item_select_cb(item, NULL, NULL, NULL);
225 _access_widget_item_register(Elm_Ctxpopup_Item *it, Eina_Bool is_access)
229 if (!is_access) _elm_access_widget_item_unregister((Elm_Widget_Item *)it);
232 _elm_access_widget_item_register((Elm_Widget_Item *)it);
234 ai = _elm_access_object_get(it->base.access_obj);
236 _elm_access_callback_set(ai, ELM_ACCESS_INFO, _access_info_cb, it);
237 _elm_access_callback_set(ai, ELM_ACCESS_STATE, _access_state_cb, it);
238 _elm_access_text_set(ai, ELM_ACCESS_TYPE, E_("Contextual Popup"));
239 _elm_access_activate_callback_set(ai, _access_activate_cb, it);
244 _item_new(Elm_Ctxpopup_Item *item,
247 ELM_CTXPOPUP_DATA_GET(WIDGET(item), sd);
250 VIEW(item) = edje_object_add(evas_object_evas_get(sd->box));
251 edje_object_mirrored_set(VIEW(item), elm_widget_mirrored_get(WIDGET(item)));
252 _elm_theme_object_set(WIDGET(item), VIEW(item), "ctxpopup", group_name,
253 elm_widget_style_get(WIDGET(item)));
254 edje_object_signal_callback_add(VIEW(item), "elm,action,click", "",
255 _item_select_cb, item);
256 evas_object_size_hint_align_set(VIEW(item), EVAS_HINT_FILL, EVAS_HINT_FILL);
257 evas_object_show(VIEW(item));
260 if (_elm_config->access_mode) _access_widget_item_register(item, EINA_TRUE);
264 _item_icon_set(Elm_Ctxpopup_Item *item,
268 evas_object_del(item->icon);
273 edje_object_part_swallow(VIEW(item), "elm.swallow.icon", item->icon);
274 edje_object_message_signal_process(VIEW(item));
278 _item_label_set(Elm_Ctxpopup_Item *item,
281 if (!eina_stringshare_replace(&item->label, label))
284 edje_object_part_text_set(VIEW(item), "elm.text", label);
285 edje_object_message_signal_process(VIEW(item));
289 _item_del_pre_hook(Elm_Object_Item *it)
291 Elm_Ctxpopup_Item *ctxpopup_it = (Elm_Ctxpopup_Item *)it;
293 ELM_CTXPOPUP_DATA_GET(WIDGET(ctxpopup_it), sd);
294 if (!sd) return EINA_FALSE;
296 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
298 if (ctxpopup_it->icon)
299 evas_object_del(ctxpopup_it->icon);
300 if (VIEW(ctxpopup_it))
301 evas_object_del(VIEW(ctxpopup_it));
303 eina_stringshare_del(ctxpopup_it->label);
304 sd->items = eina_list_remove(sd->items, ctxpopup_it);
306 if (eina_list_count(sd->items) < 1)
308 evas_object_hide(WIDGET(ctxpopup_it));
311 if (sd->visible) elm_layout_sizing_eval(WIDGET(ctxpopup_it));
317 _items_remove(Elm_Ctxpopup_Smart_Data *sd)
320 Elm_Ctxpopup_Item *item;
322 if (!sd->items) return;
324 EINA_LIST_FOREACH(sd->items, elist, item)
326 _item_del_pre_hook((Elm_Object_Item *)item);
333 _scroller_size_reset(Elm_Ctxpopup_Smart_Data *sd)
335 sd->finished = EINA_FALSE;
341 _item_sizing_eval(Elm_Ctxpopup_Item *item)
343 Evas_Coord min_w = -1, min_h = -1, max_w = -1, max_h = -1;
347 edje_object_size_min_restricted_calc(VIEW(item), &min_w, &min_h, min_w,
349 evas_object_size_hint_min_set(VIEW(item), min_w, min_h);
350 evas_object_size_hint_max_set(VIEW(item), max_w, max_h);
353 static Elm_Ctxpopup_Direction
354 _base_geometry_calc(Evas_Object *obj,
355 Evas_Coord_Rectangle *rect)
357 Elm_Ctxpopup_Direction dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
358 Evas_Coord_Rectangle hover_area;
359 Evas_Coord_Point pos = {0, 0};
360 Evas_Coord_Point arrow_size;
361 Evas_Coord_Point base_size;
362 Evas_Coord_Point max_size;
363 Evas_Coord_Point min_size;
364 Evas_Coord_Point temp;
367 ELM_CTXPOPUP_DATA_GET(obj, sd);
369 if (!rect) return ELM_CTXPOPUP_DIRECTION_DOWN;
371 edje_object_part_geometry_get
372 (sd->arrow, "ctxpopup_arrow", NULL, NULL, &arrow_size.x, &arrow_size.y);
373 evas_object_resize(sd->arrow, arrow_size.x, arrow_size.y);
375 //Initialize Area Rectangle.
376 evas_object_geometry_get
377 (sd->parent, &hover_area.x, &hover_area.y, &hover_area.w,
380 evas_object_geometry_get(obj, &pos.x, &pos.y, NULL, NULL);
383 edje_object_size_min_calc
384 (ELM_WIDGET_DATA(sd)->resize_obj, &base_size.x, &base_size.y);
385 evas_object_smart_calculate(ELM_WIDGET_DATA(sd)->resize_obj);
388 evas_object_size_hint_max_get(obj, &max_size.x, &max_size.y);
389 if ((max_size.x == -1) || (max_size.y == -1))
390 edje_object_size_max_get(sd->layout, &max_size.x, &max_size.y);
392 if ((max_size.y > 0) && (base_size.y > max_size.y))
393 base_size.y = max_size.y;
395 if ((max_size.x > 0) && (base_size.x > max_size.x))
396 base_size.x = max_size.x;
399 evas_object_size_hint_min_get(obj, &min_size.x, &min_size.y);
400 if ((min_size.x == 0) || (min_size.y == 0))
401 edje_object_size_min_get(sd->layout, &min_size.x, &min_size.y);
403 if ((min_size.y > 0) && (base_size.y < min_size.y))
404 base_size.y = min_size.y;
406 if ((min_size.x > 0) && (base_size.x < min_size.x))
407 base_size.x = min_size.x;
409 //Check the Which direction is available.
410 //If find a avaialble direction, it adjusts position and size.
411 for (idx = 0; idx < 4; idx++)
413 switch (sd->dir_priority[idx])
415 case ELM_CTXPOPUP_DIRECTION_UNKNOWN:
417 case ELM_CTXPOPUP_DIRECTION_UP:
418 temp.y = (pos.y - base_size.y);
419 if ((temp.y - arrow_size.y) < hover_area.y)
422 _x_pos_adjust(&pos, &base_size, &hover_area);
423 pos.y -= base_size.y;
424 dir = ELM_CTXPOPUP_DIRECTION_UP;
427 case ELM_CTXPOPUP_DIRECTION_LEFT:
428 temp.x = (pos.x - base_size.x);
429 if ((temp.x - arrow_size.x) < hover_area.x)
432 _y_pos_adjust(&pos, &base_size, &hover_area);
433 pos.x -= base_size.x;
434 dir = ELM_CTXPOPUP_DIRECTION_LEFT;
437 case ELM_CTXPOPUP_DIRECTION_RIGHT:
438 temp.x = (pos.x + base_size.x);
439 if ((temp.x + arrow_size.x) >
440 (hover_area.x + hover_area.w))
443 _y_pos_adjust(&pos, &base_size, &hover_area);
444 dir = ELM_CTXPOPUP_DIRECTION_RIGHT;
447 case ELM_CTXPOPUP_DIRECTION_DOWN:
448 temp.y = (pos.y + base_size.y);
449 if ((temp.y + arrow_size.y) >
450 (hover_area.y + hover_area.h))
453 _x_pos_adjust(&pos, &base_size, &hover_area);
454 dir = ELM_CTXPOPUP_DIRECTION_DOWN;
463 //In this case, all directions are invalid because of lack of space.
466 Evas_Coord length[2];
470 length[0] = pos.y - hover_area.y;
471 length[1] = (hover_area.y + hover_area.h) - pos.y;
473 // ELM_CTXPOPUP_DIRECTION_UP
474 if (length[0] > length[1])
476 _x_pos_adjust(&pos, &base_size, &hover_area);
477 pos.y -= base_size.y;
478 dir = ELM_CTXPOPUP_DIRECTION_UP;
479 if (pos.y < (hover_area.y + arrow_size.y))
481 base_size.y -= ((hover_area.y + arrow_size.y) - pos.y);
482 pos.y = hover_area.y + arrow_size.y;
485 //ELM_CTXPOPUP_DIRECTION_DOWN
488 _x_pos_adjust(&pos, &base_size, &hover_area);
489 dir = ELM_CTXPOPUP_DIRECTION_DOWN;
490 if ((pos.y + arrow_size.y + base_size.y) >
491 (hover_area.y + hover_area.h))
493 ((pos.y + arrow_size.y + base_size.y) -
494 (hover_area.y + hover_area.h));
499 length[0] = pos.x - hover_area.x;
500 length[1] = (hover_area.x + hover_area.w) - pos.x;
502 //ELM_CTXPOPUP_DIRECTION_LEFT
503 if (length[0] > length[1])
505 _y_pos_adjust(&pos, &base_size, &hover_area);
506 pos.x -= base_size.x;
507 dir = ELM_CTXPOPUP_DIRECTION_LEFT;
508 if (pos.x < (hover_area.x + arrow_size.x))
510 base_size.x -= ((hover_area.x + arrow_size.x) - pos.x);
511 pos.x = hover_area.x + arrow_size.x;
514 //ELM_CTXPOPUP_DIRECTION_RIGHT
517 _y_pos_adjust(&pos, &base_size, &hover_area);
518 dir = ELM_CTXPOPUP_DIRECTION_RIGHT;
519 if (pos.x + (arrow_size.x + base_size.x) >
520 hover_area.x + hover_area.w)
522 ((pos.x + arrow_size.x + base_size.x) -
523 (hover_area.x + hover_area.w));
528 //Final position and size.
531 rect->w = base_size.x;
532 rect->h = base_size.y;
538 _arrow_update(Evas_Object *obj,
539 Elm_Ctxpopup_Direction dir,
540 Evas_Coord_Rectangle base_size)
542 Evas_Coord_Rectangle arrow_size;
545 Evas_Coord_Rectangle shadow_left_top, shadow_right_bottom, arrow_padding;
547 ELM_CTXPOPUP_DATA_GET(obj, sd);
549 evas_object_geometry_get(obj, &x, &y, NULL, NULL);
550 evas_object_geometry_get
551 (sd->arrow, NULL, NULL, &arrow_size.w, &arrow_size.h);
553 /* tizen only : since ctxpopup of tizen has shadow, start and end padding of arrow, it should be put together when updating arrow
554 * so there are some differences between open source and tizen */
555 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);
556 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);
557 edje_object_part_geometry_get(ELM_WIDGET_DATA(sd)->resize_obj, "ctxpopup_frame_left_top", NULL, NULL, &arrow_padding.w, &arrow_padding.h);
559 /* arrow is not being kept as sub-object on purpose, here. the
560 * design of the widget does not help with the contrary */
564 case ELM_CTXPOPUP_DIRECTION_RIGHT:
565 edje_object_signal_emit(sd->arrow, "elm,state,left", "elm");
566 edje_object_part_swallow
567 (ELM_WIDGET_DATA(sd)->resize_obj,
568 (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_right" :
569 "elm.swallow.arrow_left"), sd->arrow);
573 if (y <= ((arrow_size.h * 0.5) + base_size.y + shadow_left_top.h + arrow_padding.h))
575 else if (y >= (base_size.y + base_size.h - ((arrow_size.h * 0.5) + shadow_right_bottom.h + arrow_padding.h)))
576 y = base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2));
578 y = y - base_size.y - ((arrow_size.h * 0.5) + shadow_left_top.h + arrow_padding.h);
579 drag = (double)(y) / (double)(base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2)));
580 edje_object_part_drag_value_set
581 (ELM_WIDGET_DATA(sd)->resize_obj,
582 (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_right" :
583 "elm.swallow.arrow_left"), 1, drag);
587 case ELM_CTXPOPUP_DIRECTION_LEFT:
588 edje_object_signal_emit(sd->arrow, "elm,state,right", "elm");
589 edje_object_part_swallow
590 (ELM_WIDGET_DATA(sd)->resize_obj,
591 (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_left" :
592 "elm.swallow.arrow_right"), sd->arrow);
596 if (y <= ((arrow_size.h * 0.5) + base_size.y + shadow_left_top.h + arrow_padding.h))
598 else if (y >= (base_size.y + base_size.h - ((arrow_size.h * 0.5) + shadow_right_bottom.h + arrow_padding.h)))
599 y = base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2));
601 y = y - base_size.y - ((arrow_size.h * 0.5) + shadow_left_top.h + arrow_padding.h);
602 drag = (double)(y) / (double)(base_size.h - (arrow_size.h + shadow_right_bottom.h + shadow_left_top.h + (arrow_padding.h * 2)));
603 edje_object_part_drag_value_set
604 (ELM_WIDGET_DATA(sd)->resize_obj,
605 (elm_widget_mirrored_get(obj) ? "elm.swallow.arrow_left" :
606 "elm.swallow.arrow_right"), 0, drag);
610 case ELM_CTXPOPUP_DIRECTION_DOWN:
611 edje_object_signal_emit(sd->arrow, "elm,state,top", "elm");
612 edje_object_part_swallow
613 (ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.arrow_up",
618 if (x <= ((arrow_size.w * 0.5) + base_size.x + shadow_left_top.w + arrow_padding.w))
620 else if (x >= (base_size.x + base_size.w - ((arrow_size.w * 0.5) + shadow_right_bottom.w + arrow_padding.w)))
621 x = base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2));
623 x = x - base_size.x - ((arrow_size.w * 0.5) + shadow_left_top.w + arrow_padding.w);
624 drag = (double)(x) / (double)(base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2)));
625 edje_object_part_drag_value_set
626 (ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.arrow_up",
631 case ELM_CTXPOPUP_DIRECTION_UP:
632 edje_object_signal_emit(sd->arrow, "elm,state,bottom", "elm");
633 edje_object_part_swallow
634 (ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.arrow_down",
639 if (x <= ((arrow_size.w * 0.5) + base_size.x + shadow_left_top.w + arrow_padding.w))
641 else if (x >= (base_size.x + base_size.w - ((arrow_size.w * 0.5) + shadow_right_bottom.w + arrow_padding.w)))
642 x = base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2));
644 x = x - base_size.x - ((arrow_size.w * 0.5) + shadow_left_top.w + arrow_padding.w);
645 drag = (double)(x) / (double)(base_size.w - (arrow_size.w + shadow_right_bottom.w + shadow_left_top.w + (arrow_padding.w * 2)));
646 edje_object_part_drag_value_set
647 (ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.arrow_down",
656 //should be here for getting accurate geometry value
657 evas_object_smart_calculate(ELM_WIDGET_DATA(sd)->resize_obj);
661 _show_signals_emit(Evas_Object *obj,
662 Elm_Ctxpopup_Direction dir)
664 ELM_CTXPOPUP_DATA_GET(obj, sd);
666 if (!sd->visible) return;
670 case ELM_CTXPOPUP_DIRECTION_UP:
671 edje_object_signal_emit(sd->layout, "elm,state,show,up", "elm");
674 case ELM_CTXPOPUP_DIRECTION_LEFT:
675 edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,show,right" :
676 "elm,state,show,left"), "elm");
679 case ELM_CTXPOPUP_DIRECTION_RIGHT:
680 edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,show,left" :
681 "elm,state,show,right"), "elm");
684 case ELM_CTXPOPUP_DIRECTION_DOWN:
685 edje_object_signal_emit(sd->layout, "elm,state,show,down", "elm");
692 edje_object_signal_emit(sd->bg, "elm,state,show", "elm");
693 // elm_layout_signal_emit(obj, "elm,state,show", "elm");
697 _hide_signals_emit(Evas_Object *obj,
698 Elm_Ctxpopup_Direction dir)
700 ELM_CTXPOPUP_DATA_GET(obj, sd);
702 if (!sd->visible) return;
706 case ELM_CTXPOPUP_DIRECTION_UP:
707 edje_object_signal_emit(sd->layout, "elm,state,hide,up", "elm");
710 case ELM_CTXPOPUP_DIRECTION_LEFT:
711 edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,hide,right" :
712 "elm,state,hide,left"), "elm");
715 case ELM_CTXPOPUP_DIRECTION_RIGHT:
716 edje_object_signal_emit(sd->layout, (elm_widget_mirrored_get(obj) ? "elm,state,hide,left" :
717 "elm,state,hide,right"), "elm");
720 case ELM_CTXPOPUP_DIRECTION_DOWN:
721 edje_object_signal_emit(sd->layout, "elm,state,hide,down", "elm");
728 edje_object_signal_emit(sd->bg, "elm,state,hide", "elm");
732 _base_shift_by_arrow(Evas_Object *arrow,
733 Elm_Ctxpopup_Direction dir,
734 Evas_Coord_Rectangle *rect)
736 Evas_Coord arrow_w, arrow_h;
738 evas_object_geometry_get(arrow, NULL, NULL, &arrow_w, &arrow_h);
742 case ELM_CTXPOPUP_DIRECTION_RIGHT:
746 case ELM_CTXPOPUP_DIRECTION_LEFT:
750 case ELM_CTXPOPUP_DIRECTION_DOWN:
754 case ELM_CTXPOPUP_DIRECTION_UP:
763 //TODO: compress item - different from opensource
765 _compress_item(Evas_Object *obj)
768 Elm_Ctxpopup_Item *item;
770 ELM_CTXPOPUP_DATA_GET(obj, sd);
773 EINA_LIST_FOREACH(sd->items, elist, item)
775 edje_object_signal_emit(item->base.view, "elm,state,compress", "elm");
780 _elm_ctxpopup_smart_sub_object_add(Evas_Object *obj,
783 Elm_Widget_Smart_Class *parent_parent;
785 parent_parent = (Elm_Widget_Smart_Class *)((Evas_Smart_Class *)
786 _elm_ctxpopup_parent_sc)->parent;
788 /* skipping layout's code, which registers size hint changing
789 * callback on sub objects. a hack to make ctxpopup live, as it is,
790 * on the new classing schema. this widget needs a total
792 if (!parent_parent->sub_object_add(obj, sobj))
799 _elm_ctxpopup_smart_sizing_eval(Evas_Object *obj)
802 Elm_Ctxpopup_Item *item;
803 Evas_Coord_Rectangle rect = { 0, 0, 1, 1 };
804 Evas_Coord_Point box_size = { 0, 0 };
805 Evas_Coord_Point _box_size = { 0, 0 };
807 ELM_CTXPOPUP_DATA_GET(obj, sd);
810 EINA_LIST_FOREACH(sd->items, elist, item)
812 _item_sizing_eval(item);
813 evas_object_size_hint_min_get(VIEW(item), &_box_size.x, &_box_size.y);
816 if (_box_size.x > box_size.x)
817 box_size.x = _box_size.x;
818 if (_box_size.y != -1)
819 box_size.y += _box_size.y;
823 if (_box_size.x != -1)
824 box_size.x += _box_size.x;
825 if (_box_size.y > box_size.y)
826 box_size.y = _box_size.y;
830 if (!sd->arrow) return; /* simple way to flag "under deletion" */
832 if ((!sd->content) && (sd->scr))
834 evas_object_size_hint_min_set(sd->box, box_size.x, box_size.y);
835 elm_scroller_content_min_limit(sd->scr, EINA_TRUE, EINA_TRUE);
836 evas_object_size_hint_min_set(sd->scr, box_size.x, box_size.y);
840 sd->dir = _base_geometry_calc(obj, &rect);
842 //TODO: compress item - different from opensource
843 if (!sd->horizontal && !sd->content)
846 _arrow_update(obj, sd->dir, rect);
847 _base_shift_by_arrow(sd->arrow, sd->dir, &rect);
849 //resize scroller according to final size
850 if ((!sd->content) && (sd->scr))
852 elm_scroller_content_min_limit(sd->scr, EINA_FALSE, EINA_FALSE);
853 evas_object_smart_calculate(sd->scr);
856 evas_object_size_hint_min_set(ELM_WIDGET_DATA(sd)->resize_obj, rect.w, rect.h);
857 evas_object_resize(ELM_WIDGET_DATA(sd)->resize_obj, rect.w, rect.h);
859 evas_object_move(sd->layout, rect.x, rect.y);
860 evas_object_resize(sd->layout, rect.w, rect.h);
862 _show_signals_emit(obj, sd->dir);
866 _on_parent_del(void *data,
868 Evas_Object *obj __UNUSED__,
869 void *event_info __UNUSED__)
871 evas_object_del(data);
875 _on_parent_move(void *data,
877 Evas_Object *obj __UNUSED__,
878 void *event_info __UNUSED__)
880 ELM_CTXPOPUP_DATA_GET(data, sd);
883 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
887 _scroller_size_reset(sd);
888 elm_layout_sizing_eval(data);
893 _on_parent_resize(void *data,
895 Evas_Object *obj __UNUSED__,
896 void *event_info __UNUSED__)
898 ELM_CTXPOPUP_DATA_GET(data, sd);
900 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
902 evas_object_hide(data);
903 evas_object_smart_callback_call(data, SIG_DISMISSED, NULL);
907 _parent_detach(Evas_Object *obj)
909 ELM_CTXPOPUP_DATA_GET(obj, sd);
911 if (!sd->parent) return;
913 evas_object_event_callback_del_full
914 (sd->parent, EVAS_CALLBACK_DEL, _on_parent_del, obj);
915 evas_object_event_callback_del_full
916 (sd->parent, EVAS_CALLBACK_MOVE, _on_parent_move, obj);
917 evas_object_event_callback_del_full
918 (sd->parent, EVAS_CALLBACK_RESIZE, _on_parent_resize, obj);
922 _on_content_resized(void *data,
924 Evas_Object *obj __UNUSED__,
925 void *event_info __UNUSED__)
927 ELM_CTXPOPUP_DATA_GET(data, sd);
929 elm_box_recalculate(sd->box);
930 elm_layout_sizing_eval(data);
933 //FIXME: lost the content size when theme hook is called.
935 _elm_ctxpopup_smart_theme(Evas_Object *obj)
938 Elm_Ctxpopup_Item *item;
942 ELM_CTXPOPUP_DATA_GET(obj, sd);
944 if (!ELM_WIDGET_CLASS(_elm_ctxpopup_parent_sc)->theme(obj))
947 rtl = elm_widget_mirrored_get(obj);
949 elm_widget_theme_object_set
950 (obj, sd->bg, "ctxpopup", "bg", elm_widget_style_get(obj));
951 elm_widget_theme_object_set
952 (obj, sd->arrow, "ctxpopup", "arrow", elm_widget_style_get(obj));
953 elm_widget_theme_object_set
954 (obj, sd->layout, "ctxpopup", "layout", elm_widget_style_get(obj));
957 EINA_LIST_FOREACH(sd->items, elist, item)
959 edje_object_mirrored_set(VIEW(item), rtl);
961 if (item->label && item->icon)
962 _elm_theme_object_set
963 (obj, VIEW(item), "ctxpopup", "icon_text_style_item", elm_widget_style_get(obj));
964 else if (item->label)
967 _elm_theme_object_set(obj, VIEW(item), "ctxpopup", "text_style_item",
968 elm_widget_style_get(obj));
970 _elm_theme_object_set(obj, VIEW(item), "ctxpopup", "text_style_item_horizontal",
971 elm_widget_style_get(obj));
974 _elm_theme_object_set
975 (obj, VIEW(item), "ctxpopup", "icon_style_item", elm_widget_style_get(obj));
977 edje_object_part_text_set(VIEW(item), "elm.text", item->label);
979 if (elm_widget_item_disabled_get(item))
980 edje_object_signal_emit(VIEW(item), "elm,state,disabled", "elm");
983 * For separator, if the first item has visible separator,
984 * then it should be aligned with edge of the base part.
985 * In some cases, it gives improper display. Ex) rounded corner
986 * So the first item separator should be invisible.
989 edje_object_signal_emit(VIEW(item), "elm,state,default", "elm");
991 edje_object_signal_emit(VIEW(item), "elm,state,separator", "elm");
993 edje_object_message_signal_process(VIEW(item));
996 if (evas_object_visible_get(sd->bg))
997 edje_object_signal_emit(sd->bg, "elm,state,show", "elm");
1001 if (!strncmp(elm_object_style_get(obj), "default", strlen("default")))
1002 elm_object_style_set(sd->scr, "ctxpopup");
1004 elm_object_style_set(sd->scr, elm_object_style_get(obj));
1007 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1011 _scroller_size_reset(sd);
1012 _elm_ctxpopup_smart_sizing_eval(obj);
1018 /* kind of a big and tricky override here: an internal box will hold
1019 * the actual content. content aliases won't be of much help here */
1021 _elm_ctxpopup_smart_content_set(Evas_Object *obj,
1023 Evas_Object *content)
1025 Evas_Coord min_w = -1, min_h = -1;
1027 ELM_CTXPOPUP_DATA_GET(obj, sd);
1029 if ((part) && (strcmp(part, "default")))
1030 return ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_set
1031 (obj, part, content);
1033 if (!content) return EINA_FALSE;
1035 if (content == sd->content) return EINA_TRUE;
1037 if (sd->items) elm_ctxpopup_clear(obj);
1038 if (sd->content) evas_object_del(sd->content);
1043 sd->box = elm_box_add(obj);
1044 evas_object_size_hint_weight_set(sd->box, EVAS_HINT_EXPAND,
1046 evas_object_event_callback_add
1047 (sd->box, EVAS_CALLBACK_RESIZE, _on_content_resized, obj);
1048 ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_set
1049 (obj, "elm.swallow.content", sd->box);
1052 evas_object_size_hint_weight_set
1053 (content, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1054 evas_object_size_hint_fill_set
1055 (content, EVAS_HINT_FILL, EVAS_HINT_FILL);
1057 /* since it's going to be a box content, not a layout's... */
1058 evas_object_show(content);
1060 evas_object_size_hint_min_get(content, &min_w, &min_h);
1061 evas_object_size_hint_min_set(sd->box, min_w, min_h);
1062 elm_box_pack_end(sd->box, content);
1064 sd->content = content;
1065 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1067 if (sd->visible) elm_layout_sizing_eval(obj);
1072 static Evas_Object *
1073 _elm_ctxpopup_smart_content_get(const Evas_Object *obj,
1076 ELM_CTXPOPUP_DATA_GET(obj, sd);
1078 if ((part) && (strcmp(part, "default")))
1079 return ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_get
1085 static Evas_Object *
1086 _elm_ctxpopup_smart_content_unset(Evas_Object *obj,
1089 Evas_Object *content;
1091 ELM_CTXPOPUP_DATA_GET(obj, sd);
1093 if ((part) && (strcmp(part, "default")))
1094 return ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_unset
1097 content = sd->content;
1098 if (!content) return NULL;
1100 evas_object_del(sd->box);
1103 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1105 if (sd->visible) elm_layout_sizing_eval(obj);
1111 _item_text_set_hook(Elm_Object_Item *it,
1115 Elm_Ctxpopup_Item *ctxpopup_it;
1117 if ((part) && (strcmp(part, "default"))) return;
1119 ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1121 _item_label_set(ctxpopup_it, label);
1125 _item_text_get_hook(const Elm_Object_Item *it,
1128 Elm_Ctxpopup_Item *ctxpopup_it;
1130 if (part && strcmp(part, "default")) return NULL;
1132 ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1133 return ctxpopup_it->label;
1137 _item_content_set_hook(Elm_Object_Item *it,
1139 Evas_Object *content)
1141 Elm_Ctxpopup_Item *ctxpopup_it;
1143 if ((part) && (strcmp(part, "icon"))) return;
1145 ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1147 ELM_CTXPOPUP_DATA_GET(WIDGET(ctxpopup_it), sd);
1149 _item_icon_set(ctxpopup_it, content);
1150 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1154 _scroller_size_reset(sd);
1155 _elm_ctxpopup_smart_sizing_eval(WIDGET(ctxpopup_it));
1159 static Evas_Object *
1160 _item_content_get_hook(const Elm_Object_Item *it,
1163 Elm_Ctxpopup_Item *ctxpopup_it;
1165 if (part && strcmp(part, "icon")) return NULL;
1167 ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1168 return ctxpopup_it->icon;
1172 _item_disable_hook(Elm_Object_Item *it)
1174 Elm_Ctxpopup_Item *ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1176 ELM_CTXPOPUP_DATA_GET(WIDGET(it), sd);
1179 if (elm_widget_item_disabled_get(it))
1180 edje_object_signal_emit(VIEW(ctxpopup_it), "elm,state,disabled", "elm");
1182 edje_object_signal_emit(VIEW(ctxpopup_it), "elm,state,enabled", "elm");
1186 _item_signal_emit_hook(Elm_Object_Item *it,
1187 const char *emission,
1190 Elm_Ctxpopup_Item *ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1192 edje_object_signal_emit(VIEW(ctxpopup_it), emission, source);
1196 _bg_clicked_cb(void *data,
1197 Evas_Object *obj __UNUSED__,
1198 const char *emission __UNUSED__,
1199 const char *source __UNUSED__)
1201 ELM_CTXPOPUP_DATA_GET(data, sd);
1203 _hide_signals_emit(data, sd->dir);
1207 _on_show(void *data __UNUSED__,
1210 void *event_info __UNUSED__)
1213 Elm_Ctxpopup_Item *item;
1216 ELM_CTXPOPUP_DATA_GET(obj, sd);
1218 if ((!sd->items) && (!sd->content)) return;
1220 sd->visible = EINA_TRUE;
1222 evas_object_show(sd->bg);
1223 evas_object_show(sd->arrow);
1224 evas_object_show(sd->layout);
1226 edje_object_signal_emit(sd->bg, "elm,state,show", "elm");
1227 elm_layout_signal_emit(obj, "elm,state,show", "elm");
1229 EINA_LIST_FOREACH(sd->items, elist, item)
1231 if (item->label && !item->icon)
1234 _elm_theme_object_set(obj, VIEW(item), "ctxpopup", "text_style_item",
1235 elm_widget_style_get(obj));
1237 _elm_theme_object_set(obj, VIEW(item), "ctxpopup", "text_style_item_horizontal",
1238 elm_widget_style_get(obj));
1242 edje_object_signal_emit(VIEW(item), "elm,state,default", "elm");
1244 edje_object_signal_emit(VIEW(item), "elm,state,separator", "elm");
1247 elm_layout_sizing_eval(obj);
1249 elm_object_focus_set(obj, EINA_TRUE);
1253 _on_hide(void *data __UNUSED__,
1256 void *event_info __UNUSED__)
1258 ELM_CTXPOPUP_DATA_GET(obj, sd);
1260 if (!sd->visible) return;
1262 evas_object_hide(sd->bg);
1263 evas_object_hide(sd->arrow);
1264 evas_object_hide(sd->layout);
1266 _scroller_size_reset(sd);
1268 sd->visible = EINA_FALSE;
1272 _on_move(void *data __UNUSED__,
1275 void *event_info __UNUSED__)
1277 ELM_CTXPOPUP_DATA_GET(obj, sd);
1279 if (sd->visible) evas_object_show(sd->arrow);
1281 _scroller_size_reset(sd);
1282 _elm_ctxpopup_smart_sizing_eval(obj);
1286 _hide_finished_cb(void *data,
1287 Evas_Object *obj __UNUSED__,
1288 const char *emission __UNUSED__,
1289 const char *source __UNUSED__)
1291 evas_object_hide(data);
1292 evas_object_smart_callback_call(data, SIG_DISMISSED, NULL);
1296 _scroller_resize(void *data, Evas *e __UNUSED__,
1298 void *event_info __UNUSED__)
1302 ELM_CTXPOPUP_DATA_GET(data, sd);
1304 if (!sd->visible) return;
1305 if (sd->finished) return;
1307 evas_object_geometry_get(obj, 0, 0, &w, &h);
1309 if (w != 0 && h != 0)
1311 if ((w <= sd->max_sc_w) && (h <= sd->max_sc_h))
1313 _elm_ctxpopup_smart_sizing_eval(data);
1314 sd->finished = EINA_TRUE;
1319 if (sd->max_sc_w < w)
1321 if (sd->max_sc_h < h)
1324 _elm_ctxpopup_smart_sizing_eval(data);
1328 _ctxpopup_restack_cb(void *data __UNUSED__,
1331 void *event_info __UNUSED__)
1333 ELM_CTXPOPUP_DATA_GET(obj, sd);
1334 evas_object_stack_below(sd->bg, obj);
1335 evas_object_stack_below(sd->layout, obj);
1339 _list_del(Elm_Ctxpopup_Smart_Data *sd)
1341 if (!sd->scr) return;
1343 edje_object_part_unswallow(ELM_WIDGET_DATA(sd)->resize_obj, sd->scr);
1344 evas_object_del(sd->scr);
1346 evas_object_del(sd->box);
1351 _list_new(Evas_Object *obj)
1353 ELM_CTXPOPUP_DATA_GET(obj, sd);
1357 sd->scr = elm_scroller_add(obj);
1358 elm_object_style_set(sd->scr, "ctxpopup");
1359 evas_object_size_hint_align_set(sd->scr, EVAS_HINT_FILL, EVAS_HINT_FILL);
1360 evas_object_event_callback_add(sd->scr, EVAS_CALLBACK_RESIZE,
1361 _scroller_resize, obj);
1362 edje_object_part_swallow(ELM_WIDGET_DATA(sd)->resize_obj, "elm.swallow.content", sd->scr);
1367 sd->box = elm_box_add(obj);
1368 evas_object_size_hint_weight_set(sd->box, EVAS_HINT_EXPAND,
1370 evas_object_event_callback_add
1371 (sd->box, EVAS_CALLBACK_RESIZE, _on_content_resized, obj);
1372 ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_set
1373 (obj, "elm.swallow.content", sd->box);
1376 elm_object_content_set(sd->scr, sd->box);
1377 elm_ctxpopup_horizontal_set(obj, sd->horizontal);
1381 _elm_ctxpopup_smart_disable(Evas_Object *obj)
1384 Elm_Object_Item *it;
1386 ELM_CTXPOPUP_DATA_GET(obj, sd);
1388 if (!ELM_WIDGET_CLASS(_elm_ctxpopup_parent_sc)->disable(obj))
1391 EINA_LIST_FOREACH(sd->items, l, it)
1392 elm_object_item_disabled_set(it, elm_widget_disabled_get(obj));
1398 _elm_ctxpopup_smart_add(Evas_Object *obj)
1400 EVAS_SMART_DATA_ALLOC(obj, Elm_Ctxpopup_Smart_Data);
1401 ELM_CTXPOPUP_DATA_GET(obj, sd);
1403 ELM_WIDGET_CLASS(_elm_ctxpopup_parent_sc)->base.add(obj);
1405 elm_layout_theme_set(obj, "ctxpopup", "base", elm_widget_style_get(obj));
1406 elm_layout_signal_callback_add
1407 (obj, "elm,action,hide,finished", "", _hide_finished_cb, obj);
1410 priv->bg = edje_object_add(evas_object_evas_get(obj));
1411 elm_widget_theme_object_set(obj, priv->bg, "ctxpopup", "bg", "default");
1412 edje_object_signal_callback_add
1413 (priv->bg, "elm,action,click", "", _bg_clicked_cb, obj);
1415 evas_object_stack_below(priv->bg, obj);
1418 priv->arrow = edje_object_add(evas_object_evas_get(obj));
1419 elm_widget_theme_object_set
1420 (obj, priv->arrow, "ctxpopup", "arrow", "default");
1422 priv->dir_priority[0] = ELM_CTXPOPUP_DIRECTION_UP;
1423 priv->dir_priority[1] = ELM_CTXPOPUP_DIRECTION_LEFT;
1424 priv->dir_priority[2] = ELM_CTXPOPUP_DIRECTION_RIGHT;
1425 priv->dir_priority[3] = ELM_CTXPOPUP_DIRECTION_DOWN;
1426 priv->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1428 evas_object_event_callback_add
1429 (obj, EVAS_CALLBACK_RESTACK, _ctxpopup_restack_cb, obj);
1431 evas_object_smart_callback_add
1432 (obj, "scroll-freeze-on", _freeze_on_cb, obj);
1433 evas_object_smart_callback_add
1434 (obj, "scroll-freeze-off", _freeze_off_cb, obj);
1435 evas_object_smart_callback_add
1436 (obj, "scroll-hold-on", _hold_on_cb, obj);
1437 evas_object_smart_callback_add
1438 (obj, "scroll-hold-off", _hold_off_cb, obj);
1440 priv->box = elm_box_add(obj);
1441 evas_object_size_hint_weight_set
1442 (priv->box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1444 evas_object_event_callback_add
1445 (priv->box, EVAS_CALLBACK_RESIZE, _on_content_resized, obj);
1447 /* box will be our content placeholder, thus the parent's version call */
1448 ELM_CONTAINER_CLASS(_elm_ctxpopup_parent_sc)->content_set
1449 (obj, "elm.swallow.content", priv->box);
1451 priv->layout = edje_object_add(evas_object_evas_get(obj));
1452 elm_widget_theme_object_set(obj, priv->layout, "ctxpopup", "layout", "default");
1454 edje_object_signal_callback_add
1455 (priv->layout, "elm,action,hide,finished", "", _hide_finished_cb, obj);
1456 edje_object_part_swallow(priv->layout, "swallow", ELM_WIDGET_DATA(sd)->resize_obj);
1457 evas_object_size_hint_weight_set
1458 (priv->layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1460 evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _on_show, NULL);
1461 evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _on_hide, NULL);
1462 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _on_move, NULL);
1464 elm_widget_can_focus_set(obj, EINA_TRUE);
1468 _elm_ctxpopup_smart_del(Evas_Object *obj)
1470 ELM_CTXPOPUP_DATA_GET(obj, sd);
1472 evas_object_event_callback_del_full
1473 (sd->box, EVAS_CALLBACK_RESIZE, _on_content_resized, obj);
1474 _parent_detach(obj);
1476 elm_ctxpopup_clear(obj);
1477 evas_object_del(sd->arrow);
1478 sd->arrow = NULL; /* stops _sizing_eval() from going on on deletion */
1480 evas_object_del(sd->bg);
1483 evas_object_del(sd->layout);
1486 ELM_WIDGET_CLASS(_elm_ctxpopup_parent_sc)->base.del(obj);
1490 _elm_ctxpopup_smart_parent_set(Evas_Object *obj,
1491 Evas_Object *parent)
1493 //default parent is to be hover parent
1494 elm_ctxpopup_hover_parent_set(obj, parent);
1498 _elm_ctxpopup_smart_access(Evas_Object *obj, Eina_Bool is_access)
1500 Eina_List *elist = NULL;
1501 Elm_Ctxpopup_Item *it;
1503 ELM_CTXPOPUP_CHECK(obj);
1504 ELM_CTXPOPUP_DATA_GET(obj, sd);
1506 EINA_LIST_FOREACH(sd->items, elist, it)
1507 _access_widget_item_register(it, is_access);
1511 _elm_ctxpopup_smart_set_user(Elm_Ctxpopup_Smart_Class *sc)
1513 ELM_WIDGET_CLASS(sc)->base.add = _elm_ctxpopup_smart_add;
1514 ELM_WIDGET_CLASS(sc)->base.del = _elm_ctxpopup_smart_del;
1516 ELM_WIDGET_CLASS(sc)->parent_set = _elm_ctxpopup_smart_parent_set;
1517 ELM_WIDGET_CLASS(sc)->disable = _elm_ctxpopup_smart_disable;
1518 ELM_WIDGET_CLASS(sc)->event = _elm_ctxpopup_smart_event;
1519 ELM_WIDGET_CLASS(sc)->theme = _elm_ctxpopup_smart_theme;
1520 ELM_WIDGET_CLASS(sc)->sub_object_add = _elm_ctxpopup_smart_sub_object_add;
1521 ELM_WIDGET_CLASS(sc)->focus_next = _elm_ctxpopup_smart_focus_next;
1522 ELM_WIDGET_CLASS(sc)->focus_direction = NULL;
1524 ELM_CONTAINER_CLASS(sc)->content_get = _elm_ctxpopup_smart_content_get;
1525 ELM_CONTAINER_CLASS(sc)->content_set = _elm_ctxpopup_smart_content_set;
1526 ELM_CONTAINER_CLASS(sc)->content_unset = _elm_ctxpopup_smart_content_unset;
1528 ELM_LAYOUT_CLASS(sc)->sizing_eval = _elm_ctxpopup_smart_sizing_eval;
1530 ELM_WIDGET_CLASS(sc)->access = _elm_ctxpopup_smart_access;
1533 EAPI const Elm_Ctxpopup_Smart_Class *
1534 elm_ctxpopup_smart_class_get(void)
1536 static Elm_Ctxpopup_Smart_Class _sc =
1537 ELM_CTXPOPUP_SMART_CLASS_INIT_NAME_VERSION(ELM_CTXPOPUP_SMART_NAME);
1538 static const Elm_Ctxpopup_Smart_Class *class = NULL;
1539 Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
1544 _elm_ctxpopup_smart_set(&_sc);
1545 esc->callbacks = _smart_callbacks;
1552 elm_ctxpopup_add(Evas_Object *parent)
1556 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1558 obj = elm_widget_add(_elm_ctxpopup_smart_class_new(), parent);
1559 if (!obj) return NULL;
1561 if (!elm_widget_sub_object_add(parent, obj))
1562 ERR("could not add %p as sub object of %p", obj, parent);
1564 /* access: parent could be any object such as elm_list which does
1565 not know elc_ctxpopup as its child object in the focus_next(); */
1566 ELM_WIDGET_DATA_GET(obj, sd);
1567 sd->highlight_root = EINA_TRUE;
1573 elm_ctxpopup_hover_parent_set(Evas_Object *obj,
1574 Evas_Object *parent)
1576 Evas_Coord x, y, w, h;
1578 ELM_CTXPOPUP_CHECK(obj);
1579 ELM_CTXPOPUP_DATA_GET(obj, sd);
1581 if (!parent) return;
1583 _parent_detach(obj);
1585 evas_object_event_callback_add
1586 (parent, EVAS_CALLBACK_DEL, _on_parent_del, obj);
1587 evas_object_event_callback_add
1588 (parent, EVAS_CALLBACK_MOVE, _on_parent_move, obj);
1589 evas_object_event_callback_add
1590 (parent, EVAS_CALLBACK_RESIZE, _on_parent_resize, obj);
1592 sd->parent = parent;
1595 evas_object_geometry_get(parent, &x, &y, &w, &h);
1596 evas_object_move(sd->bg, x, y);
1597 evas_object_resize(sd->bg, w, h);
1599 if (sd->visible) elm_layout_sizing_eval(obj);
1603 elm_ctxpopup_hover_parent_get(const Evas_Object *obj)
1605 ELM_CTXPOPUP_CHECK(obj) NULL;
1606 ELM_CTXPOPUP_DATA_GET(obj, sd);
1612 elm_ctxpopup_clear(Evas_Object *obj)
1614 ELM_CTXPOPUP_CHECK(obj);
1615 ELM_CTXPOPUP_DATA_GET(obj, sd);
1619 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1623 elm_ctxpopup_horizontal_set(Evas_Object *obj,
1624 Eina_Bool horizontal)
1627 Elm_Ctxpopup_Item *item;
1630 ELM_CTXPOPUP_CHECK(obj);
1631 ELM_CTXPOPUP_DATA_GET(obj, sd);
1633 sd->horizontal = !!horizontal;
1640 elm_box_horizontal_set(sd->box, EINA_FALSE);
1641 elm_scroller_bounce_set(sd->scr, EINA_FALSE, EINA_TRUE);
1645 elm_box_horizontal_set(sd->box, EINA_TRUE);
1646 elm_scroller_bounce_set(sd->scr, EINA_TRUE, EINA_FALSE);
1649 EINA_LIST_FOREACH(sd->items, elist, item)
1651 if (item->label && !item->icon && !horizontal)
1652 _elm_theme_object_set(obj, VIEW(item), "ctxpopup", "text_style_item",
1653 elm_widget_style_get(obj));
1654 else if (item->label && !item->icon && horizontal)
1655 _elm_theme_object_set(obj, VIEW(item), "ctxpopup", "text_style_item_horizontal",
1656 elm_widget_style_get(obj));
1659 edje_object_signal_emit(VIEW(item), "elm,state,default", "elm");
1661 edje_object_signal_emit(VIEW(item), "elm,state,separator", "elm");
1663 _item_disable_hook((Elm_Object_Item *)item);
1666 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1668 if (sd->visible) elm_layout_sizing_eval(obj);
1672 elm_ctxpopup_horizontal_get(const Evas_Object *obj)
1674 ELM_CTXPOPUP_CHECK(obj) EINA_FALSE;
1675 ELM_CTXPOPUP_DATA_GET(obj, sd);
1677 return sd->horizontal;
1680 EAPI Elm_Object_Item *
1681 elm_ctxpopup_item_append(Evas_Object *obj,
1687 Elm_Ctxpopup_Item *item;
1688 Evas_Object *content;
1690 ELM_CTXPOPUP_CHECK(obj) NULL;
1691 ELM_CTXPOPUP_DATA_GET(obj, sd);
1693 item = elm_widget_item_new(obj, Elm_Ctxpopup_Item);
1694 if (!item) return NULL;
1696 elm_widget_item_del_pre_hook_set(item, _item_del_pre_hook);
1697 elm_widget_item_disable_hook_set(item, _item_disable_hook);
1698 elm_widget_item_text_set_hook_set(item, _item_text_set_hook);
1699 elm_widget_item_text_get_hook_set(item, _item_text_get_hook);
1700 elm_widget_item_content_set_hook_set(item, _item_content_set_hook);
1701 elm_widget_item_content_get_hook_set(item, _item_content_get_hook);
1702 elm_widget_item_signal_emit_hook_set(item, _item_signal_emit_hook);
1704 //The first item is appended.
1705 content = elm_object_content_unset(obj);
1706 if (content) evas_object_del(content);
1712 item->base.data = data;
1715 _item_new(item, "icon_text_style_item");
1718 if (!sd->horizontal)
1719 _item_new(item, "text_style_item");
1721 _item_new(item, "text_style_item_horizontal");
1724 _item_new(item, "icon_style_item");
1726 _item_icon_set(item, icon);
1727 _item_label_set(item, label);
1728 elm_box_pack_end(sd->box, VIEW(item));
1729 sd->items = eina_list_append(sd->items, item);
1731 sd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1735 _scroller_size_reset(sd);
1736 _elm_ctxpopup_smart_sizing_eval(obj);
1740 return (Elm_Object_Item *)item;
1744 elm_ctxpopup_direction_priority_set(Evas_Object *obj,
1745 Elm_Ctxpopup_Direction first,
1746 Elm_Ctxpopup_Direction second,
1747 Elm_Ctxpopup_Direction third,
1748 Elm_Ctxpopup_Direction fourth)
1750 ELM_CTXPOPUP_CHECK(obj);
1751 ELM_CTXPOPUP_DATA_GET(obj, sd);
1753 sd->dir_priority[0] = first;
1754 sd->dir_priority[1] = second;
1755 sd->dir_priority[2] = third;
1756 sd->dir_priority[3] = fourth;
1758 if (sd->visible) elm_layout_sizing_eval(obj);
1762 elm_ctxpopup_direction_priority_get(Evas_Object *obj,
1763 Elm_Ctxpopup_Direction *first,
1764 Elm_Ctxpopup_Direction *second,
1765 Elm_Ctxpopup_Direction *third,
1766 Elm_Ctxpopup_Direction *fourth)
1768 ELM_CTXPOPUP_CHECK(obj);
1769 ELM_CTXPOPUP_DATA_GET(obj, sd);
1771 if (first) *first = sd->dir_priority[0];
1772 if (second) *second = sd->dir_priority[1];
1773 if (third) *third = sd->dir_priority[2];
1774 if (fourth) *fourth = sd->dir_priority[3];
1777 EAPI Elm_Ctxpopup_Direction
1778 elm_ctxpopup_direction_get(const Evas_Object *obj)
1780 ELM_CTXPOPUP_CHECK(obj) ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1781 ELM_CTXPOPUP_DATA_GET(obj, sd);
1787 elm_ctxpopup_dismiss(Evas_Object *obj)
1789 ELM_CTXPOPUP_CHECK(obj);
1790 ELM_CTXPOPUP_DATA_GET(obj, sd);
1792 _hide_signals_emit(obj, sd->dir);