From: ChunEon Park Date: Wed, 26 Jan 2011 02:39:05 +0000 (+0900) Subject: [Elementary.h.in] X-Git-Tag: REL_I9200_20110603-1~427 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=86dc26cd8a27db0621a153450dca5bedef7b9200;p=framework%2Fuifw%2Felementary.git [Elementary.h.in] [elc_ctxpopup.c] [test.c] [test_ctxpopup.c] [Makefile.am] mereged ctxpopup [changelog] repackaging --- diff --git a/debian/changelog b/debian/changelog index 3d78596..5a53650 100644 --- a/debian/changelog +++ b/debian/changelog @@ -5,7 +5,7 @@ elementary (1.0.0+svn.51480slp2+build102) unstable; urgency=low * Git: 165.213.180.234:slp/pkgs/e/elementary * Tag: elementary_1.0.0+svn.51480slp2+build102 - -- Juyung Seo Wed, 26 Jan 2011 11:10:04 +0900 + -- ChunEon Park Wed, 26 Jan 2011 11:10:04 +0900 elementary (1.0.0+svn.51480slp2+build101) unstable; urgency=low diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am index 2672432..dcdcb0f 100644 --- a/src/bin/Makefile.am +++ b/src/bin/Makefile.am @@ -79,7 +79,8 @@ test_floating.c \ test_launcher.c \ test_anim.c \ test_calendar.c \ -test_diskselector.c +test_diskselector.c \ +test_ctxpopup.c elementary_test_LDADD = $(top_builddir)/src/lib/libelementary.la @ELEMENTARY_EWEATHER_LIBS@ elementary_test_LDFLAGS = diff --git a/src/bin/test.c b/src/bin/test.c index dcc6f32..6878f5d 100644 --- a/src/bin/test.c +++ b/src/bin/test.c @@ -82,6 +82,7 @@ void test_launcher2(void *data, Evas_Object *obj, void *event_info); void test_launcher3(void *data, Evas_Object *obj, void *event_info); void test_anim(void *data, Evas_Object *obj, void *event_info); void test_diskselector(void *data, Evas_Object *obj, void *event_info); +void test_ctxpopup(void *data, Evas_Object *obj, void *event_info); struct elm_test { @@ -283,6 +284,7 @@ my_win_main(void) ADD_TEST("Calendar", test_calendar); ADD_TEST("Calendar 2", test_calendar2); ADD_TEST("Disk Selector", test_diskselector); + ADD_TEST("Ctxpopup", test_ctxpopup); #undef ADD_TEST if (tests) diff --git a/src/bin/test_ctxpopup.c b/src/bin/test_ctxpopup.c new file mode 100644 index 0000000..1c4e0b8 --- /dev/null +++ b/src/bin/test_ctxpopup.c @@ -0,0 +1,178 @@ +#include +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif +#ifndef ELM_LIB_QUICKLAUNCH + +static void +_ctxpopup_item_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) +{ + printf("ctxpopup item selected: %s\n", + elm_ctxpopup_item_label_get(event_info)); +} + +#define ITEM_NEW(_hov, _label, _icon) \ + if(_icon) \ + { \ + ic = elm_icon_add(obj); \ + elm_icon_standard_set(ic, _icon); \ + elm_icon_scale_set(ic, EINA_FALSE, EINA_FALSE); \ + } \ + else \ + ic = NULL; \ + it = elm_ctxpopup_item_append(_hov, _label, ic, _ctxpopup_item_cb, NULL); \ + +static void +_list_item_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Evas_Object *ctxpopup, *ic; + Elm_Ctxpopup_Item *it; + Evas_Coord x,y; + + ctxpopup = elm_ctxpopup_add(obj); + + ITEM_NEW(ctxpopup, "Go to home folder", "home"); + ITEM_NEW(ctxpopup, "Save file", "file"); + ITEM_NEW(ctxpopup, "Delete file", "delete"); + ITEM_NEW(ctxpopup, "Navigate to folder", "folder"); + elm_ctxpopup_item_disabled_set(it, EINA_TRUE); + ITEM_NEW(ctxpopup, "Edit entry", "edit"); + ITEM_NEW(ctxpopup, "Set date and time", "clock"); + elm_ctxpopup_item_disabled_set(it, EINA_TRUE); + + evas_pointer_output_xy_get(evas_object_evas_get(obj), &x, &y); + evas_object_size_hint_max_set(ctxpopup, 240, 240); + evas_object_move(ctxpopup, x, y); + evas_object_show(ctxpopup); +} + +static void +_list_item_cb2(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Evas_Object *ctxpopup, *ic; + Elm_Ctxpopup_Item *it; + Evas_Coord x,y; + + ctxpopup = elm_ctxpopup_add(obj); + + ITEM_NEW(ctxpopup, NULL, "home"); + ITEM_NEW(ctxpopup, NULL, "file"); + ITEM_NEW(ctxpopup, NULL, "delete"); + ITEM_NEW(ctxpopup, NULL, "folder"); + ITEM_NEW(ctxpopup, NULL, "edit"); + elm_ctxpopup_item_disabled_set(it, EINA_TRUE); + ITEM_NEW(ctxpopup, NULL, "clock"); + + evas_pointer_output_xy_get(evas_object_evas_get(obj), &x, &y); + evas_object_size_hint_max_set(ctxpopup, 240, 240); + evas_object_move(ctxpopup, x, y); + evas_object_show(ctxpopup); +} + +static void +_list_item_cb3(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Evas_Object *ctxpopup, *ic; + Elm_Ctxpopup_Item *it; + Evas_Coord x,y; + + ctxpopup = elm_ctxpopup_add(obj); + + ITEM_NEW(ctxpopup, "Eina", NULL); + ITEM_NEW(ctxpopup, "Eet", NULL); + ITEM_NEW(ctxpopup, "Evas", NULL); + ITEM_NEW(ctxpopup, "Ecore", NULL); + elm_ctxpopup_item_disabled_set(it, EINA_TRUE); + ITEM_NEW(ctxpopup, "Embryo", NULL); + ITEM_NEW(ctxpopup, "Edje", NULL); + + evas_pointer_output_xy_get(evas_object_evas_get(obj), &x, &y); + evas_object_move(ctxpopup, x, y); + evas_object_show(ctxpopup); +} + +static void +_list_item_cb4(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Evas_Object *ctxpopup, *ic; + Elm_Ctxpopup_Item *it; + Evas_Coord x,y; + + ctxpopup = elm_ctxpopup_add(obj); + elm_ctxpopup_horizontal_set(ctxpopup, EINA_TRUE); + + ITEM_NEW(ctxpopup, NULL, "home"); + ITEM_NEW(ctxpopup, NULL, "file"); + ITEM_NEW(ctxpopup, NULL, "delete"); + ITEM_NEW(ctxpopup, NULL, "folder"); + ITEM_NEW(ctxpopup, NULL, "edit"); + ITEM_NEW(ctxpopup, NULL, "clock"); + + evas_pointer_output_xy_get(evas_object_evas_get(obj), &x, &y); + evas_object_size_hint_max_set(ctxpopup, 240, 240); + evas_object_move(ctxpopup, x, y); + evas_object_show(ctxpopup); +} + + +static void +_list_item_cb5(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Evas_Object *ctxpopup, *btn; + Evas_Coord x,y; + + btn = elm_button_add(obj); + elm_button_label_set(btn, "Enlightenment"); + evas_object_size_hint_min_set(btn, 150, 150); + + ctxpopup = elm_ctxpopup_add(obj); + elm_ctxpopup_content_set(ctxpopup, btn); + + evas_pointer_output_xy_get(evas_object_evas_get(obj), &x, &y); + evas_object_move(ctxpopup, x, y); + evas_object_show(ctxpopup); +} + + +static void _list_clicked(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) +{ + elm_list_item_selected_set(event_info, EINA_FALSE); +} + +void +test_ctxpopup(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Evas_Object *win, *bg, *list; + + win = elm_win_add(NULL, "Contexual Popup", ELM_WIN_BASIC); + elm_win_title_set(win, "Contextual Popup"); + elm_win_autodel_set(win, EINA_TRUE); + + bg = elm_bg_add(win); + evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_win_resize_object_add(win, bg); + evas_object_show(bg); + + list = elm_list_add(win); + elm_win_resize_object_add(win, list); + elm_list_mode_set(list, ELM_LIST_COMPRESS); + evas_object_smart_callback_add(list, "selected", _list_clicked, NULL); + +#undef ITEM_NEW + elm_list_item_append(list, "Ctxpopup with icons and labels", NULL, NULL, + _list_item_cb, NULL); + elm_list_item_append(list, "Ctxpopup with icons only", NULL, NULL, + _list_item_cb2, NULL); + elm_list_item_append(list, "Ctxpopup with labels only", NULL, NULL, + _list_item_cb3, NULL); + elm_list_item_append(list, "Ctxpopup at horizontal mode", NULL, NULL, + _list_item_cb4, NULL); + elm_list_item_append(list, "Ctxpopup with user content", NULL, NULL, + _list_item_cb5, NULL); + evas_object_show(list); + elm_list_go(list); + + evas_object_resize(win, 400, 400); + evas_object_show(win); +} +#endif diff --git a/src/lib/Elementary.h.in b/src/lib/Elementary.h.in index b2dda77..bdf6110 100644 --- a/src/lib/Elementary.h.in +++ b/src/lib/Elementary.h.in @@ -2617,40 +2617,6 @@ extern "C" { EAPI void elm_popup_orient_set(Evas_Object *obj, Elm_Popup_Orient orient); EAPI int elm_popup_run(Evas_Object *obj); - /* Contextual Popup */ - typedef struct _Ctxpopup_Item Elm_Ctxpopup_Item; - - typedef enum _Ctxpopup_Arrow_Direction - { - ELM_CTXPOPUP_ARROW_DOWN, - ELM_CTXPOPUP_ARROW_RIGHT, - ELM_CTXPOPUP_ARROW_LEFT, - ELM_CTXPOPUP_ARROW_UP, - } Elm_Ctxpopup_Arrow; - - EAPI Evas_Object *elm_ctxpopup_add(Evas_Object *parent); - EAPI void elm_ctxpopup_horizontal_set(Evas_Object *obj, Eina_Bool horizontal); - EAPI Eina_Bool elm_ctxpopup_horizontal_get(Evas_Object *obj); - EAPI void elm_ctxpopup_item_icon_set(Elm_Ctxpopup_Item *item, Evas_Object *icon); - EAPI void elm_ctxpopup_item_label_set(Elm_Ctxpopup_Item *item, const char *label); - EAPI Elm_Ctxpopup_Item *elm_ctxpopup_label_add(Evas_Object *obj, const char *label, Evas_Smart_Cb func, void *data); - EAPI Elm_Ctxpopup_Item *elm_ctxpopup_icon_add(Evas_Object *obj, Evas_Object *icon, Evas_Smart_Cb func, void *data); - EAPI Elm_Ctxpopup_Item *elm_ctxpopup_item_add(Evas_Object *obj, Evas_Object *icon, const char* label, Evas_Smart_Cb func, void *data); - EAPI void elm_ctxpopup_item_del(Elm_Ctxpopup_Item *item); - EAPI void elm_ctxpopup_item_disabled_set(Elm_Ctxpopup_Item *item, Eina_Bool disabled); - EAPI void elm_ctxpopup_clear(Evas_Object *obj); - EAPI const char *elm_ctxpopup_item_label_get(Elm_Ctxpopup_Item *item); - EAPI Evas_Object *elm_ctxpopup_item_icon_get(Elm_Ctxpopup_Item *item); - EAPI void elm_ctxpopup_scroller_disabled_set(Evas_Object *obj, Eina_Bool disabled); - EAPI void elm_ctxpopup_screen_dimmed_disabled_set(Evas_Object *obj, Eina_Bool disabled); - EAPI void elm_ctxpopup_button_append(Evas_Object *obj, const char *label, Evas_Smart_Cb func, const void *data); - EAPI void elm_ctxpopup_arrow_priority_set(Evas_Object *obj, Elm_Ctxpopup_Arrow first, Elm_Ctxpopup_Arrow second, Elm_Ctxpopup_Arrow third, Elm_Ctxpopup_Arrow fourth); - EAPI void elm_ctxpopup_content_set(Evas_Object *obj, Evas_Object *content); - EAPI Evas_Object *elm_ctxpopup_content_unset(Evas_Object *obj); - EAPI void elm_ctxpopup_position_forced_set(Evas_Object *obj, Eina_Bool forced); - EAPI Eina_Bool elm_ctxpopup_position_forced_get(Evas_Object *obj); - EAPI void elm_ctxpopup_area_set(Evas_Object *obj, Evas_Object *rect); - /* tansit */ typedef enum { @@ -2881,6 +2847,59 @@ extern "C" { * "changed" - when the color value changes */ + /* Contextual Popup */ + typedef struct _Elm_Ctxpopup_Item Elm_Ctxpopup_Item; + + typedef enum _Elm_Ctxpopup_Direction + { + ELM_CTXPOPUP_DIRECTION_DOWN, + ELM_CTXPOPUP_DIRECTION_RIGHT, + ELM_CTXPOPUP_DIRECTION_LEFT, + ELM_CTXPOPUP_DIRECTION_UP, + } Elm_Ctxpopup_Direction; + + EAPI Evas_Object *elm_ctxpopup_add(Evas_Object *parent) EINA_ARG_NONNULL(1); + EAPI Evas_Object *elm_ctxpopup_item_icon_get(const Elm_Ctxpopup_Item *item) EINA_ARG_NONNULL(1); + EAPI void elm_ctxpopup_item_icon_set(Elm_Ctxpopup_Item *item, Evas_Object *icon) EINA_ARG_NONNULL(1); + EAPI const char *elm_ctxpopup_item_label_get(const Elm_Ctxpopup_Item *item) EINA_ARG_NONNULL(1); + EAPI void elm_ctxpopup_item_label_set(Elm_Ctxpopup_Item *item, const char *label) EINA_ARG_NONNULL(1); + EAPI void elm_ctxpopup_hover_parent_set(Evas_Object *obj, Evas_Object *parent) EINA_ARG_NONNULL(1, 2); + EAPI Evas_Object *elm_ctxpopup_hover_parent_get(const Evas_Object *obj) EINA_ARG_NONNULL(1); + EAPI void elm_ctxpopup_clear(Evas_Object *obj) EINA_ARG_NONNULL(1); + EAPI void elm_ctxpopup_horizontal_set(Evas_Object *obj, Eina_Bool horizontal) EINA_ARG_NONNULL(1); + EAPI Eina_Bool elm_ctxpopup_horizontal_get(const Evas_Object *obj) EINA_ARG_NONNULL(1); + Elm_Ctxpopup_Item *elm_ctxpopup_item_append(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Smart_Cb func, const void *data) EINA_ARG_NONNULL(1); + EAPI void elm_ctxpopup_item_del(Elm_Ctxpopup_Item *item) EINA_ARG_NONNULL(1); + EAPI void elm_ctxpopup_item_disabled_set(Elm_Ctxpopup_Item *item, Eina_Bool disabled) EINA_ARG_NONNULL(1); + EAPI Eina_Bool elm_ctxpopup_item_disabled_get(const Elm_Ctxpopup_Item *item) EINA_ARG_NONNULL(1); + EAPI void elm_ctxpopup_content_set(Evas_Object *obj, Evas_Object *content) EINA_ARG_NONNULL(1, 2); + EAPI Evas_Object *elm_ctxpopup_content_unset(Evas_Object *obj) EINA_ARG_NONNULL(1); + EAPI void elm_ctxpopup_direction_priority_set(Evas_Object *obj, Elm_Ctxpopup_Direction first, Elm_Ctxpopup_Direction second, Elm_Ctxpopup_Direction third, Elm_Ctxpopup_Direction fourth) EINA_ARG_NONNULL(1); + EAPI void elm_ctxpopup_direction_priority_get(Evas_Object *obj, Elm_Ctxpopup_Direction *first, Elm_Ctxpopup_Direction *second, Elm_Ctxpopup_Direction *third, Elm_Ctxpopup_Direction *fourth) EINA_ARG_NONNULL(1); + /* smart callbacks called: + * "dismissed" - the ctxpopup was dismissed + */ + + //DEPRECATED CTXPOPUP APIS... + typedef enum _Ctxpopup_Arrow_Direction + { + ELM_CTXPOPUP_ARROW_DOWN, + ELM_CTXPOPUP_ARROW_RIGHT, + ELM_CTXPOPUP_ARROW_LEFT, + ELM_CTXPOPUP_ARROW_UP, + } Elm_Ctxpopup_Arrow; + + EINA_DEPRECATED EAPI void elm_ctxpopup_area_set(Evas_Object *obj, Evas_Object *rect); + EINA_DEPRECATED EAPI Elm_Ctxpopup_Item *elm_ctxpopup_label_add(Evas_Object *obj, const char *label, Evas_Smart_Cb func, void *data); + EINA_DEPRECATED EAPI Elm_Ctxpopup_Item *elm_ctxpopup_icon_add(Evas_Object *obj, Evas_Object *icon, Evas_Smart_Cb func, void *data); + EINA_DEPRECATED EAPI Elm_Ctxpopup_Item *elm_ctxpopup_item_add(Evas_Object *obj, Evas_Object *icon, const char* label, Evas_Smart_Cb func, void *data); + EINA_DEPRECATED EAPI void elm_ctxpopup_scroller_disabled_set(Evas_Object *obj, Eina_Bool disabled); + EINA_DEPRECATED EAPI void elm_ctxpopup_screen_dimmed_disabled_set(Evas_Object *obj, Eina_Bool disabled); + EINA_DEPRECATED EAPI void elm_ctxpopup_button_append(Evas_Object *obj, const char *label, Evas_Smart_Cb func, const void *data); + EINA_DEPRECATED EAPI void elm_ctxpopup_arrow_priority_set(Evas_Object *obj, Elm_Ctxpopup_Arrow first, Elm_Ctxpopup_Arrow second, Elm_Ctxpopup_Arrow third, Elm_Ctxpopup_Arrow fourth); + EINA_DEPRECATED EAPI void elm_ctxpopup_position_forced_set(Evas_Object *obj, Eina_Bool forced); + EINA_DEPRECATED EAPI Eina_Bool elm_ctxpopup_position_forced_get(const Evas_Object *obj); + /* colorpalette */ typedef struct _Colorpalette_Color Elm_Colorpalette_Color; diff --git a/src/lib/elc_ctxpopup.c b/src/lib/elc_ctxpopup.c index a23ef7c..7d11afb 100644 --- a/src/lib/elc_ctxpopup.c +++ b/src/lib/elc_ctxpopup.c @@ -2,1630 +2,1647 @@ #include "elm_priv.h" /** - * @defgroup Ctxpopup Ctxpopup - * @ingroup Elementary + * @defgroup Ctxpopup * - * Contextual popup. + * A ctxpopup is a widget that, when shown, pops up a list of items. + * It automatically chooses an area inside its parent object's view + * (set via elm_ctxpopup_add() and elm_ctxpopup_hover_parent_set()) to + * optimally fit into it. In the default theme, it will also point an + * arrow to the cursor position at the time one shows it. Ctxpopup + * items have a label and/or an icon. It is intended for a small + * number of items (hence the use of list, not genlist). * * Signals that you can add callbacks for are: * - * hide - This is emitted when the ctxpopup is hided. - * + * dismissed - the ctxpopup was dismissed */ typedef struct _Widget_Data Widget_Data; -struct _Ctxpopup_Item { - Elm_Widget_Item base; - const char *label; - Evas_Object *icon; - Evas_Smart_Cb func; - Eina_Bool disabled :1; - Eina_Bool separator :1; +struct _Elm_Ctxpopup_Item +{ + Elm_Widget_Item base; + const char *label; + Evas_Object *icon; + Evas_Smart_Cb func; + Eina_Bool disabled:1; }; -struct _Widget_Data { - Evas_Object *parent; - Evas_Object *base; - Evas_Object *content; - Evas_Object *box; - Evas_Object *arrow; - Evas_Object *scroller; - Evas_Object *bg; - Evas_Object *btn_layout; - Evas_Object *area_rect; - Eina_List *items; - Elm_Ctxpopup_Arrow arrow_dir; - Elm_Ctxpopup_Arrow arrow_priority[4]; - int btn_cnt; - Elm_Transit *transit; - Evas_Coord max_sc_w, max_sc_h; - char *title; - Eina_Bool scroller_disabled :1; - Eina_Bool horizontal :1; - Eina_Bool visible :1; - Eina_Bool screen_dimmed_disabled :1; - Eina_Bool position_forced :1; - Eina_Bool finished :1; +struct _Widget_Data +{ + Evas_Object *parent; + Evas_Object *base; + Evas_Object *content; + Evas_Object *box; + Evas_Object *arrow; + Evas_Object *scr; + Evas_Object *bg; + Evas_Object *hover_parent; + Eina_List *items; + Elm_Ctxpopup_Direction dir; + Elm_Ctxpopup_Direction dir_priority[4]; + Evas_Coord max_sc_w, max_sc_h; + Eina_Bool horizontal:1; + Eina_Bool visible:1; + Eina_Bool finished:1; }; static const char *widtype = NULL; + static void _del_hook(Evas_Object *obj); static void _del_pre_hook(Evas_Object *obj); static void _theme_hook(Evas_Object *obj); static void _sizing_eval(Evas_Object *obj); -static void _area_rect_resize(void *data, Evas *e, Evas_Object *obj, - void *event_info); -static void _area_rect_move(void *data, Evas *e, Evas_Object *obj, - void *event_info); -static void _area_rect_del(void *data, Evas *e, Evas_Object *obj, - void *event_info); -static void _bg_clicked_cb(void *data, Evas_Object *obj, const char *emission, - const char *source); +static void _hover_parent_resize(void *data, Evas *e __UNUSED__, + Evas_Object *obj __UNUSED__, + void *event_info __UNUSED__); +static void _hover_parent_move(void *data, Evas *e __UNUSED__, + Evas_Object *obj __UNUSED__, + void *event_info __UNUSED__); +static void _hover_parent_del(void *data, Evas *e __UNUSED__, + Evas_Object *obj __UNUSED__, + void *event_info __UNUSED__); +static void _hover_parent_callbacks_del(Evas_Object *obj); +static void _bg_clicked_cb(void *data, Evas_Object *obj __UNUSED__, + const char *emission __UNUSED__, + const char *source __UNUSED__); static void _parent_resize(void *data, Evas *e, Evas_Object *obj, - void *event_info); -static void _ctxpopup_show(void *data, Evas *e, Evas_Object *obj, - void *event_info); -static void _ctxpopup_hide(void *data, Evas *e, Evas_Object *obj, - void *event_info); -static void _ctxpopup_move(void *data, Evas *e, Evas_Object *obj, - void *event_info); -static void _ctxpopup_changed_size_hints(void *data, Evas *e, Evas_Object *obj, - void *event_info); -static void _ctxpopup_scroller_resize(void *data, Evas *e, Evas_Object *obj, - void *event_info); -static void _item_obj_create(Elm_Ctxpopup_Item *item, char *group_name); + void *event_info __UNUSED__); +static void _ctxpopup_show(void *data __UNUSED__, Evas *e __UNUSED__, + Evas_Object *obj, void *event_info __UNUSED__); +static void _ctxpopup_hide(void *data __UNUSED__, Evas *e __UNUSED__, + Evas_Object *obj, void *event_info __UNUSED__); +static void _ctxpopup_move(void *data __UNUSED__, Evas *e __UNUSED__, + Evas_Object *obj, void *event_info __UNUSED__); +static void _scroller_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj, + void *event_info __UNUSED__); +static void _ctxpopup_changed_size_hints(void *data __UNUSED__, + Evas *e __UNUSED__, Evas_Object *obj, + void *event_info __UNUSED__); +static void _item_new(Elm_Ctxpopup_Item *item, char *group_name); +static void _list_new(Evas_Object *obj); static void _item_sizing_eval(Elm_Ctxpopup_Item *item); -static void _ctxpopup_item_select(void *data, Evas_Object *obj, - const char *emission, const char *source); -static void _separator_obj_add(Evas_Object *obj); -static void _separator_obj_del(Widget_Data *wd, Elm_Ctxpopup_Item *remove_item); -static Elm_Ctxpopup_Arrow _calc_base_geometry(Evas_Object *obj, - Evas_Coord_Rectangle *rect); -static void _update_arrow_obj(Evas_Object *obj, Elm_Ctxpopup_Arrow arrow_dir); +static void _item_select_cb(void *data, Evas_Object *obj __UNUSED__, + const char *emission __UNUSED__, + const char *source __UNUSED__); +static Elm_Ctxpopup_Direction _calc_base_geometry(Evas_Object *obj, + Evas_Coord_Rectangle *rect); +static void _update_arrow(Evas_Object *obj, Elm_Ctxpopup_Direction dir); static void _shift_base_by_arrow(Evas_Object *arrow, - Elm_Ctxpopup_Arrow arrow_dir, Evas_Coord_Rectangle *rect); -static void _btn_layout_create(Evas_Object *obj); -static int _get_indicator_h(Evas_Object *parent); -static void _delete_area_rect_callbacks(Widget_Data *wd); + Elm_Ctxpopup_Direction dir, + Evas_Coord_Rectangle *rect); static void _adjust_pos_x(Evas_Coord_Point *pos, Evas_Coord_Point *base_size, - Evas_Coord_Rectangle *area_rect); -static void _adjust_pos_y(int indicator_h, Evas_Coord_Point *pos, - Evas_Coord_Point *base_size, Evas_Coord_Rectangle *area_rect); -static void _reset_scroller_size(Widget_Data *wd); -static void _hide_ctxpopup(Evas_Object *obj); -static void _content_del(void *data, Evas *e, Evas_Object *obj, void *event_info); -static void _content_resize(void *data, Evas *e, Evas_Object *obj, void *event_info); - -static void _reset_scroller_size(Widget_Data *wd) -{ - wd->finished = EINA_FALSE; - wd->max_sc_h = -1; - wd->max_sc_w = -1; -} + Evas_Coord_Rectangle *hover_area); +static void _adjust_pos_y(Evas_Coord_Point *pos, Evas_Coord_Point *base_size, + Evas_Coord_Rectangle *hover_area); +static void _scroller_size_reset(Widget_Data *wd); +static void _hide(Evas_Object *obj); +static void _content_del(void *data, Evas *e, Evas_Object *obj __UNUSED__, + void *event_info __UNUSED__); +static void _freeze_on(void *data __UNUSED__, Evas_Object *obj, + void *event_info __UNUSED__); +static void _freeze_off(void *data __UNUSED__, Evas_Object *obj, + void *event_info __UNUSED__); +static void _hold_on(void *data __UNUSED__, Evas_Object *obj, + void *event_info __UNUSED__); +static void _hold_off(void *data __UNUSED__, Evas_Object *obj, + void *event_info __UNUSED__); +static void _item_icon_set(Elm_Ctxpopup_Item *item, Evas_Object *icon); +static void _item_label_set(Elm_Ctxpopup_Item *item, const char *label); +static void _remove_items(Widget_Data * wd); + +static const char SIG_DISMISSED[] = "dismissed"; +static const char SIG_HIDE[] = "hide"; + +static const Evas_Smart_Cb_Description _signals[] = { + {SIG_DISMISSED, ""}, + {SIG_HIDE, ""}, //TOOD: Remove!! + {NULL, NULL} +}; -static void _delete_area_rect_callbacks(Widget_Data *wd) +#define ELM_CTXPOPUP_ITEM_CHECK_RETURN(it, ...) \ + ELM_WIDGET_ITEM_CHECK_OR_RETURN((Elm_Widget_Item *)it, __VA_ARGS__); \ +ELM_CHECK_WIDTYPE(item->base.widget, widtype) __VA_ARGS__; + +static void +_freeze_on(void *data __UNUSED__, Evas_Object *obj, + void *event_info __UNUSED__) { - if (!wd->area_rect) return; + Widget_Data *wd = elm_widget_data_get(obj); - evas_object_event_callback_del(wd->area_rect, EVAS_CALLBACK_DEL, - _area_rect_del); - evas_object_event_callback_del(wd->area_rect, EVAS_CALLBACK_MOVE, - _area_rect_move); - evas_object_event_callback_del(wd->area_rect, EVAS_CALLBACK_RESIZE, - _area_rect_resize); + if (!wd) + return; + elm_object_scroll_freeze_push(wd->scr); } -static void _area_rect_resize(void *data, Evas *e, Evas_Object *obj, void *event_info) +static void +_freeze_off(void *data __UNUSED__, Evas_Object *obj, + void *event_info __UNUSED__) { - Widget_Data *wd = elm_widget_data_get(data); - if(wd->visible) { - _reset_scroller_size(wd); - _sizing_eval(obj); - } -} + Widget_Data *wd = elm_widget_data_get(obj); -static void _area_rect_move(void *data, Evas *e, Evas_Object *obj, void *event_info) -{ - Widget_Data *wd = elm_widget_data_get(data); - if(wd->visible) { - _reset_scroller_size(wd); - _sizing_eval(obj); - } + if (!wd) + return; + elm_object_scroll_freeze_pop(wd->scr); } -static void _area_rect_del(void *data, Evas *e, Evas_Object *obj, void *event_info) +static void +_hold_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) { - Widget_Data *wd = elm_widget_data_get(data); - wd->area_rect = NULL; -} -/* -static void _show_effect_done(void *data, Elm_Transit *transit) -{ - //TODO: Consider implementing effect in edc. - Widget_Data *wd = data; - elm_transit_fx_clear(transit); - - if (wd->box) - elm_transit_fx_insert(transit, elm_fx_color_add(wd->box, 0, 0, 0, 0, - 255, 255, 255, 255)); - if (wd->content) - elm_transit_fx_insert(transit, elm_fx_color_add(wd->content, 0, 0, 0, - 0, 255, 255, 255, 255)); - if (wd->btn_layout) - elm_transit_fx_insert(transit, elm_fx_color_add(wd->btn_layout, 0, 0, - 0, 0, 255, 255, 255, 255)); - elm_transit_run(transit, 0.2); - elm_transit_completion_callback_set(transit, NULL, NULL); - elm_transit_del(transit); - wd->transit = NULL; - edje_object_signal_emit(wd->base, "elm,state,show", "elm"); -} + Widget_Data *wd = elm_widget_data_get(obj); -static void _show_effect(Widget_Data* wd) -{ - //TODO: Consider implementing effect in edc. - if (wd->transit) { - elm_transit_stop(wd->transit); - elm_transit_fx_clear(wd->transit); - } else { - wd->transit = elm_transit_add(wd->base); - elm_transit_curve_style_set(wd->transit, ELM_ANIMATOR_CURVE_OUT); - elm_transit_completion_callback_set(wd->transit, _show_effect_done, wd); - } - - elm_transit_fx_insert(wd->transit, elm_fx_color_add(wd->base, 0, 0, 0, 0, - 255, 255, 255, 255)); - elm_transit_fx_insert(wd->transit, elm_fx_wipe_add(wd->base, - ELM_FX_WIPE_TYPE_SHOW, wd->arrow_dir)); - - if(!wd->position_forced) - elm_transit_fx_insert(wd->transit, elm_fx_color_add(wd->arrow, 0, 0, 0, 0, 255, 255, 255, 255)); - - if (wd->box) - evas_object_color_set(wd->box, 0, 0, 0, 0); - if (wd->content) - evas_object_color_set(wd->content, 0, 0, 0, 0); - if (wd->btn_layout) - evas_object_color_set(wd->btn_layout, 0, 0, 0, 0); - - elm_transit_run(wd->transit, 0.3); + if (!wd) + return; + elm_object_scroll_hold_push(wd->scr); } -static void _hide_effect_done(void *data, Elm_Transit *transit) +static void +_hold_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) { - //TODO: Consider implementing effect in edc. - Widget_Data *wd = elm_widget_data_get(data); - if(!wd) return ; - elm_transit_del(transit); - wd->transit = NULL; - _hide_ctxpopup(data); -} + Widget_Data *wd = elm_widget_data_get(obj); -static void _hide_effect(Evas_Object *obj) -{ - //TODO: Consider implementing effect in edc. - Widget_Data *wd = elm_widget_data_get(obj); - if(!wd) return; - - if (wd->transit) { - elm_transit_stop(wd->transit); - elm_transit_fx_clear(wd->transit); - } else { - wd->transit = elm_transit_add(wd->base); - elm_transit_curve_style_set(wd->transit, ELM_ANIMATOR_CURVE_OUT); - elm_transit_completion_callback_set(wd->transit, _hide_effect_done, obj); - } - - switch(wd->arrow_dir) { - case ELM_CTXPOPUP_ARROW_DOWN: - elm_transit_fx_insert(wd->transit, elm_fx_wipe_add(wd->base, ELM_FX_WIPE_TYPE_HIDE, ELM_FX_WIPE_DIR_DOWN)); - break; - case ELM_CTXPOPUP_ARROW_RIGHT: - elm_transit_fx_insert(wd->transit, elm_fx_wipe_add(wd->base, ELM_FX_WIPE_TYPE_HIDE, ELM_FX_WIPE_DIR_RIGHT)); - break; - case ELM_CTXPOPUP_ARROW_LEFT: - elm_transit_fx_insert(wd->transit, elm_fx_wipe_add(wd->base, ELM_FX_WIPE_TYPE_HIDE, ELM_FX_WIPE_DIR_LEFT)); - break; - case ELM_CTXPOPUP_ARROW_UP: - elm_transit_fx_insert(wd->transit, elm_fx_wipe_add(wd->base, ELM_FX_WIPE_TYPE_HIDE, ELM_FX_WIPE_DIR_UP)); - break; - default: - break; - } - - elm_transit_run(wd->transit, 0.3); + if (!wd) + return; + elm_object_scroll_hold_pop(wd->scr); } -*/ -static void _separator_obj_del(Widget_Data *wd, Elm_Ctxpopup_Item *remove_item) +static void +_scroller_size_reset(Widget_Data *wd) { - Eina_List *elist, *cur_list, *prev_list; - Elm_Ctxpopup_Item *separator; - - if ((!remove_item) || (!wd)) return; - - elist = wd->items; - cur_list = eina_list_data_find_list(elist, remove_item); + wd->finished = EINA_FALSE; + wd->max_sc_h = -1; + wd->max_sc_w = -1; +} - if (!cur_list) return; +static void +_hover_parent_callbacks_del(Evas_Object *obj) +{ + Widget_Data *wd = elm_widget_data_get(obj); - prev_list = eina_list_prev(cur_list); - - if (!prev_list) return; + if ((!wd) || (!wd->hover_parent)) + return; - separator = (Elm_Ctxpopup_Item *) eina_list_data_get(prev_list); - - if (!separator)return; - - wd->items = eina_list_remove(wd->items, separator); - evas_object_del(separator->base.view); - free(separator); + evas_object_event_callback_del_full(wd->hover_parent, EVAS_CALLBACK_DEL, + _hover_parent_del, obj); + evas_object_event_callback_del_full(wd->hover_parent, EVAS_CALLBACK_MOVE, + _hover_parent_move, obj); + evas_object_event_callback_del_full(wd->hover_parent, EVAS_CALLBACK_RESIZE, + _hover_parent_resize, obj); } -static void _btn_layout_create(Evas_Object *obj) +static void +_hover_parent_resize(void *data, Evas *e __UNUSED__, + Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) { - Widget_Data *wd = elm_widget_data_get(obj); + Widget_Data *wd = elm_widget_data_get(data); - wd->btn_layout = edje_object_add(evas_object_evas_get(obj)); - elm_widget_sub_object_add(obj, wd->btn_layout); - edje_object_signal_emit(wd->base, "elm,state,buttons,enable", "elm"); - edje_object_part_swallow(wd->base, "elm.swallow.btns", wd->btn_layout); + if (!wd) + return; + + if (wd->visible) + { + _scroller_size_reset(wd); + _sizing_eval(data); + } } -static void _separator_obj_add(Evas_Object *obj) +static void +_hover_parent_move(void *data, Evas *e __UNUSED__, + Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) { - Elm_Ctxpopup_Item *item; - - Widget_Data *wd = (Widget_Data *) elm_widget_data_get(obj); - - if (!wd) return; - if (eina_list_count(wd->items) == 0) return; + Widget_Data *wd = elm_widget_data_get(data); - item = ELM_NEW(Elm_Ctxpopup_Item); - if (!item) return; + if (!wd) + return; - item->base.view = edje_object_add(evas_object_evas_get(wd->base)); - if (!item->base.view) { - free(item); - return; - } + if (wd->visible) + { + _scroller_size_reset(wd); + _sizing_eval(obj); + } +} - _elm_theme_object_set(obj, item->base.view, "ctxpopup", "separator", - elm_widget_style_get(obj)); +static void +_hover_parent_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, + void *event_info __UNUSED__) +{ + Widget_Data *wd = elm_widget_data_get(data); - if (wd->horizontal) - edje_object_signal_emit(item->base.view, "elm,state,horizontal", "elm"); - else - edje_object_signal_emit(item->base.view, "elm,state,vertical", "elm"); + if (!wd) + return; - evas_object_size_hint_align_set(item->base.view, EVAS_HINT_FILL, EVAS_HINT_FILL); - evas_object_show(item->base.view); - item->separator = EINA_TRUE; - elm_box_pack_end(wd->box, item->base.view); - wd->items = eina_list_append(wd->items, item); + wd->hover_parent = NULL; } -static void _item_sizing_eval(Elm_Ctxpopup_Item *item) +static void +_item_sizing_eval(Elm_Ctxpopup_Item *item) { - Evas_Coord min_w = -1, min_h = -1, max_w = -1, max_h = -1; - Evas_Coord x, y, w, h; + Evas_Coord min_w = -1, min_h = -1, max_w = -1, max_h = -1; - if (!item) return; + Evas_Coord x, y, w, h; - if (!item->separator) elm_coords_finger_size_adjust(1, &min_w, 1, &min_h); + if (!item) + return; - evas_object_geometry_get(item->base.view, &x, &y, &w, &h); - edje_object_size_min_restricted_calc(item->base.view, &min_w, &min_h, min_w, min_h); - evas_object_size_hint_min_set(item->base.view, min_w, min_h); - evas_object_size_hint_max_set(item->base.view, max_w, max_h); + evas_object_geometry_get(item->base.view, &x, &y, &w, &h); + edje_object_size_min_restricted_calc(item->base.view, &min_w, &min_h, min_w, + min_h); + evas_object_size_hint_min_set(item->base.view, min_w, min_h); + evas_object_size_hint_max_set(item->base.view, max_w, max_h); } -static void _adjust_pos_x(Evas_Coord_Point *pos, Evas_Coord_Point *base_size, - Evas_Coord_Rectangle *area_rect) +static void +_adjust_pos_x(Evas_Coord_Point *pos, Evas_Coord_Point *base_size, + Evas_Coord_Rectangle *hover_area) { - pos->x -= (base_size->x / 2); + pos->x -= (base_size->x / 2); + + if (pos->x < hover_area->x) + pos->x = hover_area->x; + else if ((pos->x + base_size->x) > (hover_area->x + hover_area->w)) + pos->x = (hover_area->x + hover_area->w) - base_size->x; - if (pos->x < area_rect->x) pos->x = area_rect->x; - else if ((pos->x + base_size->x) > (area_rect->x + area_rect->w)) - pos->x = (area_rect->x + area_rect->w) - base_size->x; + if (base_size->x > hover_area->w) + base_size->x -= (base_size->x - hover_area->w); - if (base_size->x > area_rect->w) - base_size->x -= (base_size->x - area_rect->w); - if (pos->x < area_rect->x) - pos->x = area_rect->x; + if (pos->x < hover_area->x) + pos->x = hover_area->x; } -static void _adjust_pos_y(int indicator_h, Evas_Coord_Point *pos, - Evas_Coord_Point *base_size, Evas_Coord_Rectangle *area_rect) +static void +_adjust_pos_y(Evas_Coord_Point *pos, Evas_Coord_Point *base_size, + Evas_Coord_Rectangle *hover_area) { - pos->y -= (base_size->y / 2); + pos->y -= (base_size->y / 2); + + if (pos->y < hover_area->y) + pos->y = hover_area->y; + else if ((pos->y + base_size->y) > (hover_area->y + hover_area->h)) + pos->y = hover_area->y + hover_area->h - base_size->y; - if (pos->y < area_rect->y) pos->y = area_rect->y; - else if ((pos->y + base_size->y) > (area_rect->y + area_rect->h)) - pos->y = area_rect->y + area_rect->h - base_size->y; + if (base_size->y > hover_area->h) + base_size->y -= (base_size->y - hover_area->h); - if (base_size->y > area_rect->h) - base_size->y -= (base_size->y - area_rect->h); - - if (pos->y < area_rect->y) pos->y = area_rect->y; + if (pos->y < hover_area->y) + pos->y = hover_area->y; } -static int _get_indicator_h(Evas_Object *parent) +static void +_ctxpopup_changed_size_hints(void *data __UNUSED__, Evas *e __UNUSED__, + Evas_Object *obj, void *event_info __UNUSED__) { - Ecore_X_Window zone, xwin; - int h = 0; + Widget_Data *wd; - if (elm_win_indicator_state_get(parent) != 1) - return 0; + wd = elm_widget_data_get(obj); + if (!wd) + return; - xwin = elm_win_xwindow_get(parent); - zone = ecore_x_e_illume_zone_get(xwin); - ecore_x_e_illume_indicator_geometry_get(zone, NULL, NULL, NULL, &h); - - return h; + if (wd->visible) + _sizing_eval(obj); } -static void _ctxpopup_changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info) +static Elm_Ctxpopup_Direction +_calc_base_geometry(Evas_Object *obj, Evas_Coord_Rectangle *rect) { - Widget_Data *wd = (Widget_Data *) elm_widget_data_get(obj); - if (!wd) return; - if(wd->visible)_sizing_eval(obj); -} - -static Elm_Ctxpopup_Arrow _calc_base_geometry(Evas_Object *obj, Evas_Coord_Rectangle *rect) -{ - Widget_Data *wd; - Evas_Coord_Point pos; - Evas_Coord_Point base_size; - Evas_Coord_Point max_size; - Evas_Coord_Point min_size; - Evas_Coord_Rectangle area_rect; - Evas_Coord_Point parent_size; - Evas_Coord_Point arrow_size; - Elm_Ctxpopup_Arrow arrow; - Evas_Coord finger_size; - Evas_Coord indicator_h; - Evas_Coord_Point temp; - int idx; - - wd = elm_widget_data_get(obj); - - if ((!wd) || (!rect)) return ELM_CTXPOPUP_ARROW_DOWN; - - indicator_h = _get_indicator_h(wd->parent); - finger_size = elm_finger_size_get(); - - edje_object_part_geometry_get(wd->arrow, "ctxpopup_arrow", NULL, NULL, - &arrow_size.x, &arrow_size.y); - evas_object_resize(wd->arrow, arrow_size.x, arrow_size.y); - - //Initialize Area Rectangle. - if (wd->area_rect) - evas_object_geometry_get(wd->area_rect, &area_rect.x, &area_rect.y, - &area_rect.w, &area_rect.h); - else { - evas_object_geometry_get(wd->parent, NULL, NULL, &parent_size.x, &parent_size.y); - area_rect.x = 0; - area_rect.y = 0; - area_rect.w = parent_size.x; - area_rect.h = parent_size.y; - } - - if (area_rect.y < indicator_h) { - temp.y = indicator_h - area_rect.y; - area_rect.y = indicator_h; - area_rect.h -= temp.y; - } - evas_object_geometry_get(obj, &pos.x, &pos.y, NULL, NULL); - - //recalc the edje - edje_object_size_min_calc(wd->base, &base_size.x, &base_size.y); - evas_object_smart_calculate(wd->base); - - //Limit to Max Size - evas_object_size_hint_max_get(obj, &max_size.x, &max_size.y); - - if((max_size.y > 0 ) && (base_size.y > max_size.y)) - base_size.y = max_size.y; - - if((max_size.x > 0 ) && (base_size.x > max_size.x)) - base_size.x = max_size.x; - - //Limit to Min Size - evas_object_size_hint_min_get(obj, &min_size.x, &min_size.y); - - if( min_size.y > 0 ) - if(base_size.y < min_size.y) base_size.y = min_size.y; - - if( min_size.x > 0 ) - if(base_size.x < min_size.x) base_size.x = min_size.x; - - //In case of position forced. It shows up just like popup. - if (wd->position_forced) { - //TODO: calculate the size of ctxpopup - rect->x = pos.x; - rect->y = pos.y; - rect->w = base_size.x; - rect->h = base_size.y; - return ELM_CTXPOPUP_ARROW_UP; - } - - //Check the Which direction is available. - //If find a avaialble direction, it adjusts position and size. - for (idx = 0; idx < 4; ++idx) { - switch (wd->arrow_priority[idx]) { - case ELM_CTXPOPUP_ARROW_DOWN: - temp.y = pos.y - base_size.y; - if ((temp.y - arrow_size.y - finger_size) < area_rect.y) continue; - _adjust_pos_x(&pos, &base_size, &area_rect); - pos.y -= (base_size.y + finger_size); - arrow = ELM_CTXPOPUP_ARROW_DOWN; - break; - case ELM_CTXPOPUP_ARROW_RIGHT: - temp.x = (pos.x - base_size.x); - if ((temp.x - arrow_size.x - finger_size) < area_rect.x) continue; - _adjust_pos_y(indicator_h, &pos, &base_size, &area_rect); - pos.x -= (base_size.x + finger_size); - arrow = ELM_CTXPOPUP_ARROW_RIGHT; - break; - case ELM_CTXPOPUP_ARROW_LEFT: - temp.x = (pos.x + base_size.x); - if ((temp.x + arrow_size.x + finger_size) > (area_rect.x + area_rect.w)) continue; - _adjust_pos_y(indicator_h, &pos, &base_size, &area_rect); - pos.x += finger_size; - arrow = ELM_CTXPOPUP_ARROW_LEFT; - break; - case ELM_CTXPOPUP_ARROW_UP: - temp.y = (pos.y + base_size.y); - if ((temp.y + arrow_size.y + finger_size) > (area_rect.y + area_rect.h)) continue; - _adjust_pos_x(&pos, &base_size, &area_rect); - pos.y += finger_size; - arrow = ELM_CTXPOPUP_ARROW_UP; - break; - default: - break; - } - break; - } - - //In this case, all directions are invalid because of lack of space. - if (idx == 4) { - //TODO 1: Find the largest space direction. - /* - Evas_Coord length[4]; - - length[ ELM_CTXPOPUP_ARROW_DOWN ] = pos.y - area_rect.y; - length[ ELM_CTXPOPUP_ARROW_UP ] = ( area_rect.y + area_rect.h ) - pos.y; - length[ ELM_CTXPOPUP_ARROW_RIGHT ] = pos.x - area_rect.x; - length[ ELM_CTXPOPUP_ARROW_LEFT ] = ( area_rect.x + area_rect.w ) - pos.x; - - int i, j, idx; - for( i = 0; i < 4; ++i ) { - for( j = 1; j < 4; ++j ) { - if( length[ idx ] < length[ j ] ) { - idx = j; - } - } - } - */ - //TODO 1: Find the largest space direction. - Evas_Coord length[2]; - length[0] = pos.y - area_rect.y; - length[1] = (area_rect.y + area_rect.h) - pos.y; - - if (length[0] > length[1]) idx = ELM_CTXPOPUP_ARROW_DOWN; - else idx = ELM_CTXPOPUP_ARROW_UP; - - //TODO 2: determine x , y - switch (idx) { - case ELM_CTXPOPUP_ARROW_DOWN: - _adjust_pos_x(&pos, &base_size, &area_rect); - pos.y -= (base_size.y + finger_size); - arrow = ELM_CTXPOPUP_ARROW_DOWN; - if (pos.y < area_rect.y + arrow_size.y) { - base_size.y -= ((area_rect.y + arrow_size.y) - pos.y); - pos.y = area_rect.y + arrow_size.y; - } - break; - case ELM_CTXPOPUP_ARROW_RIGHT: - _adjust_pos_y(indicator_h, &pos, &base_size, &area_rect); - pos.x -= (base_size.x + finger_size); - arrow = ELM_CTXPOPUP_ARROW_RIGHT; - if (pos.x < area_rect.x + arrow_size.x) { - base_size.x -= ((area_rect.x + arrow_size.x) - pos.x); - pos.x = area_rect.x + arrow_size.x; - } - break; - case ELM_CTXPOPUP_ARROW_LEFT: - _adjust_pos_y(indicator_h, &pos, &base_size, &area_rect); - pos.x += finger_size; - arrow = ELM_CTXPOPUP_ARROW_LEFT; - if (pos.x + arrow_size.x + base_size.x > area_rect.x + area_rect.w) { - base_size.x -= ((pos.x + arrow_size.x + base_size.x) - - (area_rect.x + area_rect.w)); - } - break; - case ELM_CTXPOPUP_ARROW_UP: - _adjust_pos_x(&pos, &base_size, &area_rect); - pos.y += finger_size; - arrow = ELM_CTXPOPUP_ARROW_UP; - if (pos.y + arrow_size.y + base_size.y > area_rect.y + area_rect.h) { - base_size.y -= ((pos.y + arrow_size.y + base_size.y) - (area_rect.y + area_rect.h)); - } - break; - default: - break; - } - } - - //Final position and size. - rect->x = pos.x; - rect->y = pos.y; - rect->w = base_size.x; - rect->h = base_size.y; - - return arrow; + Widget_Data *wd; + Evas_Coord_Point pos = {0, 0}; + Evas_Coord_Point base_size; + Evas_Coord_Point max_size; + Evas_Coord_Point min_size; + Evas_Coord_Rectangle hover_area; + Evas_Coord_Rectangle parent_size; + Evas_Coord_Point arrow_size; + Elm_Ctxpopup_Direction arrow = ELM_CTXPOPUP_DIRECTION_DOWN; + Evas_Coord finger_size; + Evas_Coord_Point temp; + int idx; + + wd = elm_widget_data_get(obj); + + if ((!wd) || (!rect)) + return ELM_CTXPOPUP_DIRECTION_DOWN; + + finger_size = elm_finger_size_get(); + + edje_object_part_geometry_get(wd->arrow, "ctxpopup_arrow", NULL, NULL, + &arrow_size.x, &arrow_size.y); + evas_object_resize(wd->arrow, arrow_size.x, arrow_size.y); + + //Initialize Area Rectangle. + if (wd->hover_parent) + evas_object_geometry_get(wd->hover_parent, &hover_area.x, &hover_area.y, + &hover_area.w, &hover_area.h); + else + { + evas_object_geometry_get(wd->parent, &parent_size.x, &parent_size.y, + &parent_size.w, &parent_size.h); + hover_area.x = parent_size.x; + hover_area.y = parent_size.y; + hover_area.w = parent_size.w; + hover_area.h = parent_size.h; + } + + evas_object_geometry_get(obj, &pos.x, &pos.y, NULL, NULL); + + //recalc the edje + edje_object_size_min_calc(wd->base, &base_size.x, &base_size.y); + evas_object_smart_calculate(wd->base); + + //Limit to Max Size + evas_object_size_hint_max_get(obj, &max_size.x, &max_size.y); + + if ((max_size.y > 0) && (base_size.y > max_size.y)) + base_size.y = max_size.y; + + if ((max_size.x > 0) && (base_size.x > max_size.x)) + base_size.x = max_size.x; + + //Limit to Min Size + evas_object_size_hint_min_get(obj, &min_size.x, &min_size.y); + + if ((min_size.y > 0) && (base_size.y < min_size.y)) + base_size.y = min_size.y; + + if ((min_size.x > 0) && (base_size.x < min_size.x)) + base_size.x = min_size.x; + + //Check the Which direction is available. + //If find a avaialble direction, it adjusts position and size. + for (idx = 0; idx < 4; idx++) + { + switch (wd->dir_priority[idx]) + { + case ELM_CTXPOPUP_DIRECTION_UP: + temp.y = pos.y - base_size.y; + if ((temp.y - arrow_size.y - finger_size) < hover_area.y) + continue; + _adjust_pos_x(&pos, &base_size, &hover_area); + pos.y -= (base_size.y + finger_size); + arrow = ELM_CTXPOPUP_DIRECTION_DOWN; + break; + case ELM_CTXPOPUP_DIRECTION_LEFT: + temp.x = (pos.x - base_size.x); + if ((temp.x - arrow_size.x - finger_size) < hover_area.x) + continue; + _adjust_pos_y(&pos, &base_size, &hover_area); + pos.x -= (base_size.x + finger_size); + arrow = ELM_CTXPOPUP_DIRECTION_RIGHT; + break; + case ELM_CTXPOPUP_DIRECTION_RIGHT: + temp.x = (pos.x + base_size.x); + if ((temp.x + arrow_size.x + finger_size) > + (hover_area.x + hover_area.w)) + continue; + _adjust_pos_y(&pos, &base_size, &hover_area); + pos.x += finger_size; + arrow = ELM_CTXPOPUP_DIRECTION_LEFT; + break; + case ELM_CTXPOPUP_DIRECTION_DOWN: + temp.y = (pos.y + base_size.y); + if ((temp.y + arrow_size.y + finger_size) > + (hover_area.y + hover_area.h)) + continue; + _adjust_pos_x(&pos, &base_size, &hover_area); + pos.y += finger_size; + arrow = ELM_CTXPOPUP_DIRECTION_UP; + break; + default: + break; + } + break; + } + + //In this case, all directions are invalid because of lack of space. + if (idx == 4) + { + //TODO 1: Find the largest space direction. + Evas_Coord length[2]; + + length[0] = pos.y - hover_area.y; + length[1] = (hover_area.y + hover_area.h) - pos.y; + + if (length[0] > length[1]) + idx = ELM_CTXPOPUP_DIRECTION_DOWN; + else + idx = ELM_CTXPOPUP_DIRECTION_UP; + + //TODO 2: determine x , y + switch (idx) + { + case ELM_CTXPOPUP_DIRECTION_UP: + _adjust_pos_x(&pos, &base_size, &hover_area); + pos.y -= (base_size.y + finger_size); + arrow = ELM_CTXPOPUP_DIRECTION_DOWN; + if (pos.y < hover_area.y + arrow_size.y) + { + base_size.y -= ((hover_area.y + arrow_size.y) - pos.y); + pos.y = hover_area.y + arrow_size.y; + } + break; + case ELM_CTXPOPUP_DIRECTION_LEFT: + _adjust_pos_y(&pos, &base_size, &hover_area); + pos.x -= (base_size.x + finger_size); + arrow = ELM_CTXPOPUP_DIRECTION_RIGHT; + if (pos.x < hover_area.x + arrow_size.x) + { + base_size.x -= ((hover_area.x + arrow_size.x) - pos.x); + pos.x = hover_area.x + arrow_size.x; + } + break; + case ELM_CTXPOPUP_DIRECTION_RIGHT: + _adjust_pos_y(&pos, &base_size, &hover_area); + pos.x += finger_size; + arrow = ELM_CTXPOPUP_DIRECTION_LEFT; + if (pos.x + arrow_size.x + base_size.x > + hover_area.x + hover_area.w) + base_size.x -= + ((pos.x + arrow_size.x + base_size.x) - + (hover_area.x + hover_area.w)); + break; + case ELM_CTXPOPUP_DIRECTION_DOWN: + _adjust_pos_x(&pos, &base_size, &hover_area); + pos.y += finger_size; + arrow = ELM_CTXPOPUP_DIRECTION_UP; + if (pos.y + arrow_size.y + base_size.y > + hover_area.y + hover_area.h) + base_size.y -= + ((pos.y + arrow_size.y + base_size.y) - + (hover_area.y + hover_area.h)); + break; + default: + break; + } + } + + //Final position and size. + rect->x = pos.x; + rect->y = pos.y; + rect->w = base_size.x; + rect->h = base_size.y; + + return arrow; } -static void _update_arrow_obj(Evas_Object *obj, Elm_Ctxpopup_Arrow arrow_dir) -{ - Evas_Coord x, y; - Evas_Coord_Rectangle arrow_size; - Evas_Coord_Rectangle area_rect; - Evas_Coord parent_w, parent_h; - Widget_Data *wd = elm_widget_data_get(obj); - - if (!wd) return; - - evas_object_geometry_get(obj, &x, &y, NULL, NULL); - evas_object_geometry_get(wd->arrow, NULL, NULL, &arrow_size.w, - &arrow_size.h); - - switch (arrow_dir) { - case ELM_CTXPOPUP_ARROW_LEFT: { - edje_object_signal_emit(wd->arrow, "elm,state,left", "elm"); - arrow_size.y = (y - (arrow_size.h * 0.5)); - arrow_size.x = (x + elm_finger_size_get()); - break; - } - case ELM_CTXPOPUP_ARROW_RIGHT: { - edje_object_signal_emit(wd->arrow, "elm,state,right", "elm"); - arrow_size.y = (y - (arrow_size.h * 0.5)); - arrow_size.x = (x - elm_finger_size_get() - arrow_size.w); - break; - } - case ELM_CTXPOPUP_ARROW_UP: { - edje_object_signal_emit(wd->arrow, "elm,state,top", "elm"); - arrow_size.x = (x - (arrow_size.w * 0.5)); - arrow_size.y = (y + elm_finger_size_get()); - break; - } - case ELM_CTXPOPUP_ARROW_DOWN: { - edje_object_signal_emit(wd->arrow, "elm,state,bottom", "elm"); - arrow_size.x = (x - (arrow_size.w * 0.5)); - arrow_size.y = (y - elm_finger_size_get() - arrow_size.h); - break; - } - default: - break; - } - - //Adjust arrow position to prevent out of area - if (wd->area_rect) - evas_object_geometry_get(wd->area_rect, &area_rect.x, &area_rect.y, - &area_rect.w, &area_rect.h); - else { - evas_object_geometry_get(wd->parent, NULL, NULL, &parent_w, &parent_h); - area_rect.x = 0; - area_rect.y = 0; - area_rect.w = parent_w; - area_rect.h = parent_h; - } - - //TODO: Temporary Code. make it more flexible - if ((arrow_size.x - (arrow_size.w / 2)) < area_rect.x) - arrow_size.x = area_rect.x + (arrow_size.w / 2); - else if ((arrow_size.x + arrow_size.w) > (area_rect.x + area_rect.w)) - arrow_size.x = (area_rect.x + area_rect.w) - arrow_size.w - - (arrow_size.w / 2); -/* - //TODO: Temporary Code. make it more flexible - if ((arrow_size.y - (arrow_size.h / 2)) < area_rect.y) { - arrow_size.y = arrow_size.y + (arrow_size.h / 2); - } else if ((arrow_size.y + arrow_size.h) > (area_rect.y + area_rect.h)) { - arrow_size.y = (area_rect.y + area_rect.h) - arrow_size.h - - (arrow_size.h / 2); - } -*/ - evas_object_move(wd->arrow, arrow_size.x, arrow_size.y); +static void +_update_arrow(Evas_Object *obj, Elm_Ctxpopup_Direction dir) +{ + Evas_Coord x, y; + Evas_Coord_Rectangle arrow_size; + Widget_Data *wd; + + wd = elm_widget_data_get(obj); + if (!wd) + return; + + evas_object_geometry_get(obj, &x, &y, NULL, NULL); + evas_object_geometry_get(wd->arrow, NULL, NULL, &arrow_size.w, + &arrow_size.h); + + switch (dir) + { + case ELM_CTXPOPUP_DIRECTION_LEFT: + edje_object_signal_emit(wd->arrow, "elm,state,left", "elm"); + arrow_size.y = (y - (arrow_size.h * 0.5)); + arrow_size.x = (x + elm_finger_size_get()); + break; + case ELM_CTXPOPUP_DIRECTION_RIGHT: + edje_object_signal_emit(wd->arrow, "elm,state,right", "elm"); + arrow_size.y = (y - (arrow_size.h * 0.5)); + arrow_size.x = (x - elm_finger_size_get() - arrow_size.w); + break; + case ELM_CTXPOPUP_DIRECTION_UP: + edje_object_signal_emit(wd->arrow, "elm,state,top", "elm"); + arrow_size.x = (x - (arrow_size.w * 0.5)); + arrow_size.y = (y + elm_finger_size_get()); + break; + case ELM_CTXPOPUP_DIRECTION_DOWN: + edje_object_signal_emit(wd->arrow, "elm,state,bottom", "elm"); + arrow_size.x = (x - (arrow_size.w * 0.5)); + arrow_size.y = (y - elm_finger_size_get() - arrow_size.h); + break; + default: + break; + } + + evas_object_move(wd->arrow, arrow_size.x, arrow_size.y); } -static void _sizing_eval(Evas_Object *obj) -{ - Widget_Data *wd; - Eina_List *elist; - Elm_Ctxpopup_Item *item; - Evas_Coord_Rectangle rect = { 0, 0, 1, 1 }; - Evas_Coord_Point box_size = { 0, 0 }; - Evas_Coord_Point _box_size = { 0, 0 }; - - wd = (Widget_Data *) elm_widget_data_get(obj); - if ((!wd) || (!wd->parent)) return; - int idx = 0; - - //Box, scroller - EINA_LIST_FOREACH(wd->items, elist, item) - { - _item_sizing_eval(item); - evas_object_size_hint_min_get(item->base.view, &_box_size.x, &_box_size.y); - if(!wd->horizontal) { - if(_box_size.x > box_size.x) box_size.x = _box_size.x; - if(_box_size.y != -1 ) box_size.y += _box_size.y; - } else { - if(_box_size.x != -1 ) box_size.x += _box_size.x; - if(_box_size.y > box_size.y) box_size.y = _box_size.y; - } - ++idx; - } - - if(!wd->content) { - evas_object_size_hint_min_set(wd->box, box_size.x, box_size.y); - evas_object_size_hint_min_set(wd->scroller, box_size.x, box_size.y); - } - - //Base - wd->arrow_dir = _calc_base_geometry(obj, &rect); - if ((!wd->position_forced) && (wd->arrow_dir != -1)) { - _update_arrow_obj(obj, wd->arrow_dir); - _shift_base_by_arrow(wd->arrow, wd->arrow_dir, &rect); - } - - //resize scroller according to final size. - if (!wd->content) { - evas_object_smart_calculate(wd->scroller); - } - - evas_object_move(wd->base, rect.x, rect.y); - evas_object_resize(wd->base, rect.w, rect.h); - - if(wd->visible) - edje_object_signal_emit(wd->base, "elm,state,show", "elm"); +static void +_sizing_eval(Evas_Object *obj) +{ + Widget_Data *wd; + Eina_List *elist; + Elm_Ctxpopup_Item *item; + Evas_Coord_Rectangle rect = { 0, 0, 1, 1 }; + Evas_Coord_Point box_size = { 0, 0 }; + Evas_Coord_Point _box_size = { 0, 0 }; + + wd = elm_widget_data_get(obj); + if ((!wd) || (!wd->parent)) + return; + + //Box, Scroller + EINA_LIST_FOREACH(wd->items, elist, item) + { + _item_sizing_eval(item); + evas_object_size_hint_min_get(item->base.view, &_box_size.x, &_box_size.y); + if (!wd->horizontal) + { + if (_box_size.x > box_size.x) + box_size.x = _box_size.x; + if (_box_size.y != -1) + box_size.y += _box_size.y; + } + else + { + if (_box_size.x != -1) + box_size.x += _box_size.x; + if (_box_size.y > box_size.y) + box_size.y = _box_size.y; + } + } + + if (!wd->content) + { + evas_object_size_hint_min_set(wd->box, box_size.x, box_size.y); + evas_object_size_hint_min_set(wd->scr, box_size.x, box_size.y); + } + + //Base + wd->dir = _calc_base_geometry(obj, &rect); + _update_arrow(obj, wd->dir); + _shift_base_by_arrow(wd->arrow, wd->dir, &rect); + + //resize scroller according to final size. + if (!wd->content) + evas_object_smart_calculate(wd->scr); + + evas_object_move(wd->base, rect.x, rect.y); + evas_object_resize(wd->base, rect.w, rect.h); } -static void _shift_base_by_arrow(Evas_Object *arrow, - Elm_Ctxpopup_Arrow arrow_dir, Evas_Coord_Rectangle *rect) -{ - Evas_Coord arrow_w, arrow_h; - evas_object_geometry_get(arrow, NULL, NULL, &arrow_w, &arrow_h); - - switch (arrow_dir) { - case ELM_CTXPOPUP_ARROW_LEFT: - rect->x += arrow_w; - break; - case ELM_CTXPOPUP_ARROW_RIGHT: - rect->x -= arrow_w; - break; - case ELM_CTXPOPUP_ARROW_UP: - rect->y += arrow_h; - break; - case ELM_CTXPOPUP_ARROW_DOWN: - rect->y -= arrow_h; - break; - default: - break; - } +static void +_shift_base_by_arrow(Evas_Object *arrow, Elm_Ctxpopup_Direction dir, + Evas_Coord_Rectangle *rect) +{ + Evas_Coord arrow_w, arrow_h; + + evas_object_geometry_get(arrow, NULL, NULL, &arrow_w, &arrow_h); + + switch (dir) + { + case ELM_CTXPOPUP_DIRECTION_LEFT: + rect->x += arrow_w; + break; + case ELM_CTXPOPUP_DIRECTION_RIGHT: + rect->x -= arrow_w; + break; + case ELM_CTXPOPUP_DIRECTION_UP: + rect->y += arrow_h; + break; + case ELM_CTXPOPUP_DIRECTION_DOWN: + rect->y -= arrow_h; + break; + default: + break; + } } -static void _del_pre_hook(Evas_Object *obj) { - - Widget_Data *wd = (Widget_Data *) elm_widget_data_get(obj); - if (!wd) return; - - evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_RESIZE, - _parent_resize, obj); +static void +_del_pre_hook(Evas_Object *obj) +{ + Widget_Data *wd; - if(wd->transit) { - elm_transit_stop(wd->transit); - elm_transit_del(wd->transit); - wd->transit = NULL; - } + wd = elm_widget_data_get(obj); + if (!wd) + return; - _delete_area_rect_callbacks(wd); + evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_RESIZE, + _parent_resize, obj); + _hover_parent_callbacks_del(obj); } -static void _del_hook(Evas_Object *obj) +static void +_del_hook(Evas_Object *obj) { - Widget_Data *wd = (Widget_Data *) elm_widget_data_get(obj); + Widget_Data *wd; - if (!wd) return; + wd = elm_widget_data_get(obj); + if (!wd) + return; - elm_ctxpopup_clear(obj); - evas_object_del(wd->arrow); - evas_object_del(wd->base); - - free(wd); + elm_ctxpopup_clear(obj); + evas_object_del(wd->arrow); + evas_object_del(wd->base); + free(wd); } -static void _theme_hook(Evas_Object *obj) -{ - Eina_List *elist; - Elm_Ctxpopup_Item *item; - char buf[256]; - - Widget_Data *wd = (Widget_Data *) elm_widget_data_get(obj); - - if (!wd) return; - - //Items - EINA_LIST_FOREACH(wd->items, elist, item) - { - if (item->separator) - { - _elm_theme_object_set(obj, item->base.view, "ctxpopup", "separator", - elm_widget_style_get(obj)); - if (wd->horizontal) - edje_object_signal_emit(item->base.view, "elm,state,horizontal", "elm"); - } - else - { - if (item->label && item->icon) - { - _elm_theme_object_set(obj, item->base.view, "ctxpopup", - "icon_text_style_item", - elm_widget_style_get(obj)); - } - else if (item->label) - { - _elm_theme_object_set(obj, item->base.view, "ctxpopup", - "text_style_item", - elm_widget_style_get(obj)); - } - else if (item->icon) - { - _elm_theme_object_set(obj, item->base.view, "ctxpopup", - "icon_style_item", - elm_widget_style_get(obj)); - } - if (item->label) - edje_object_part_text_set(item->base.view, "elm.text", item->label); - - if (item->disabled) - edje_object_signal_emit(item->base.view, "elm,state,disabled", "elm"); - } - edje_object_message_signal_process(item->base.view); - } - - //button layout - if (wd->btn_layout) { - sprintf(buf, "buttons%d", wd->btn_cnt); - _elm_theme_object_set(obj, wd->btn_layout, "ctxpopup", buf, - elm_widget_style_get(obj)); - } - - _elm_theme_object_set(obj, wd->bg, "ctxpopup", "bg", elm_widget_style_get(obj)); - _elm_theme_object_set(obj, wd->base, "ctxpopup", "base", elm_widget_style_get(obj)); - _elm_theme_object_set(obj, wd->arrow, "ctxpopup", "arrow", - elm_widget_style_get(obj)); - - if (!strncmp(elm_object_style_get(obj), "default", strlen("default") - * sizeof(char))) - elm_object_style_set(wd->scroller, "ctxpopup"); - else - elm_object_style_set(wd->scroller, elm_object_style_get(obj)); - - if(wd->visible) { - _reset_scroller_size(wd); - _sizing_eval(obj); - } +static void +_theme_hook(Evas_Object *obj) +{ + Widget_Data *wd; + Eina_List *elist; + Elm_Ctxpopup_Item *item; + + wd = elm_widget_data_get(obj); + if (!wd) + return; + + //Items + EINA_LIST_FOREACH(wd->items, elist, item) + { + if (item->label && item->icon) + _elm_theme_object_set(obj, item->base.view, "ctxpopup", + "icon_text_style_item", + elm_widget_style_get(obj)); + else if (item->label) + _elm_theme_object_set(obj, item->base.view, "ctxpopup", "text_style_item", + elm_widget_style_get(obj)); + else if (item->icon) + _elm_theme_object_set(obj, item->base.view, "ctxpopup", "icon_style_item", + elm_widget_style_get(obj)); + if (item->label) + edje_object_part_text_set(item->base.view, "elm.text", item->label); + + if (item->disabled) + edje_object_signal_emit(item->base.view, "elm,state,disabled", "elm"); + + edje_object_message_signal_process(item->base.view); + } + + _elm_theme_object_set(obj, wd->bg, "ctxpopup", "bg", + elm_widget_style_get(obj)); + _elm_theme_object_set(obj, wd->base, "ctxpopup", "base", + elm_widget_style_get(obj)); + _elm_theme_object_set(obj, wd->arrow, "ctxpopup", "arrow", + elm_widget_style_get(obj)); + + if(wd->scr) + { + if (!strncmp(elm_object_style_get(obj), "default", + strlen("default"))) + elm_object_style_set(wd->scr, "ctxpopup"); + else + elm_object_style_set(wd->scr, elm_object_style_get(obj)); + } + + if (wd->visible) + { + _scroller_size_reset(wd); + _sizing_eval(obj); + } } -static void _bg_clicked_cb(void *data, Evas_Object *obj, const char *emission, - const char *source) +static void +_bg_clicked_cb(void *data, Evas_Object *obj __UNUSED__, + const char *emission __UNUSED__, const char *source __UNUSED__) { - evas_object_hide(data); + evas_object_hide(data); } -static void _parent_resize(void *data, Evas *e, Evas_Object *obj, - void *event_info) +static void +_parent_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj, + void *event_info __UNUSED__) { - Evas_Coord w, h; + Evas_Coord w, h; + Widget_Data *wd; - Widget_Data *wd = (Widget_Data *) elm_widget_data_get(data); - if (!wd) return; + wd = elm_widget_data_get(data); + if (!wd) + return; - evas_object_geometry_get(obj, NULL, NULL, &w, &h); - evas_object_resize(wd->bg, w, h); + evas_object_geometry_get(obj, NULL, NULL, &w, &h); + evas_object_resize(wd->bg, w, h); - if(wd->visible == EINA_FALSE) return; - wd->visible = EINA_FALSE; - _hide_ctxpopup(data); + if (!wd->visible) + return; + _hide(data); } -static void _ctxpopup_show(void *data, Evas *e, Evas_Object *obj, - void *event_info) +static void +_ctxpopup_show(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, + void *event_info __UNUSED__) { - Widget_Data *wd = (Widget_Data *) elm_widget_data_get(obj); - if(wd == NULL) return; - - if ((eina_list_count(wd->items) < 1) && (!wd->content) && (wd->btn_cnt < 1)) - return; + Widget_Data *wd; - wd->visible = EINA_TRUE; + wd = elm_widget_data_get(obj); + if (!wd) + return; - if (!wd->screen_dimmed_disabled) { - evas_object_show(wd->bg); - edje_object_signal_emit(wd->bg, "elm,state,show", "elm"); - } + if ((!wd->items) && (!wd->content)) + return; - evas_object_show(wd->base); + wd->visible = EINA_TRUE; - if (!wd->position_forced) { - evas_object_show(wd->arrow); - } + evas_object_show(wd->bg); + evas_object_show(wd->base); + evas_object_show(wd->arrow); - _sizing_eval(obj); + edje_object_signal_emit(wd->bg, "elm,state,show", "elm"); + _sizing_eval(obj); } -static void _hide_ctxpopup(Evas_Object *obj) +static void +_hide(Evas_Object *obj) { - //TODO: Consider implementing effect in edc. - Widget_Data *wd = elm_widget_data_get(obj); - - if (!wd->screen_dimmed_disabled) - evas_object_hide(wd->bg); + Widget_Data *wd = elm_widget_data_get(obj); - if(!wd->position_forced) - evas_object_hide(wd->arrow); + if (!wd) + return; - evas_object_hide(wd->base); + evas_object_hide(wd->bg); + evas_object_hide(wd->arrow); + evas_object_hide(wd->base); - _reset_scroller_size(wd); + _scroller_size_reset(wd); - evas_object_smart_callback_call(obj, "hide", NULL); + evas_object_smart_callback_call(obj, SIG_DISMISSED, NULL); + evas_object_smart_callback_call(obj, SIG_HIDE, NULL); //TODO: Remove! + wd->visible = EINA_FALSE; } -static void _ctxpopup_hide(void *data, Evas *e, Evas_Object *obj, void *event_info) +static void +_ctxpopup_hide(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, + void *event_info __UNUSED__) { - Widget_Data *wd = (Widget_Data*) elm_widget_data_get(obj); - if(wd == NULL) return; + Widget_Data *wd; - if(wd->visible == EINA_FALSE) return; + wd = elm_widget_data_get(obj); + if (!wd) + return; - wd->visible = EINA_FALSE; -/* - if (!wd->screen_dimmed_disabled) - edje_object_signal_emit(wd->bg, "elm,state,hide", "elm"); + if (!wd->visible) + return; - _hide_effect(obj); -*/ - _hide_ctxpopup(obj); + _hide(obj); } -static void _ctxpopup_scroller_resize(void *data, Evas *e, Evas_Object * obj, - void *event_info) +static void +_scroller_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj, + void *event_info __UNUSED__) { - Widget_Data *wd; - Evas_Coord w, h; - - wd = elm_widget_data_get(data); - if(wd == NULL) return; + Widget_Data *wd; + Evas_Coord w, h; + + wd = elm_widget_data_get(data); + if (!wd) + return; + + if (!wd->visible) + return; + if (wd->finished) + return; + + evas_object_geometry_get(obj, 0, 0, &w, &h); + + if (w != 0 && h != 0) + { + if ((w <= wd->max_sc_w) && (h <= wd->max_sc_h)) + { + _sizing_eval(data); + wd->finished = EINA_TRUE; + return; + } + } + + if (wd->max_sc_w < w) + wd->max_sc_w = w; + if (wd->max_sc_h < h) + wd->max_sc_h = h; + + _sizing_eval(data); +} - if(!wd->visible) return; - if(wd->finished) return; +static void +_ctxpopup_move(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, + void *event_info __UNUSED__) +{ + Widget_Data *wd; - evas_object_geometry_get(wd->scroller, 0, 0, &w, &h); + wd = elm_widget_data_get(obj); - if( w != 0 && h !=0 ) { - if((w <= wd->max_sc_w) && (h <= wd->max_sc_h) ) { - _sizing_eval(data); - wd->finished = EINA_TRUE; - return ; - } - } + if (!wd) + return; - if(wd->max_sc_w < w ) wd->max_sc_w = w; - if(wd->max_sc_h < h ) wd->max_sc_h = h; + if (wd->visible) + evas_object_show(wd->arrow); - _sizing_eval(data); + _scroller_size_reset(wd); + _sizing_eval(obj); } -static void _ctxpopup_move(void *data, Evas *e, Evas_Object *obj, - void *event_info) +static void +_item_select_cb(void *data, Evas_Object *obj __UNUSED__, + const char *emission __UNUSED__, const char *source __UNUSED__) { - Widget_Data *wd = (Widget_Data *) elm_widget_data_get(obj); - if(wd == NULL) return; + Elm_Ctxpopup_Item *item = data; - if (wd->visible && !wd->position_forced) - evas_object_show(wd->arrow); + if (!item) + return; + if (item->disabled) + return; - _reset_scroller_size(wd); - _sizing_eval(obj); + if (item->func) + item->func((void*) item->base.data, item->base.widget, data); } -static void _ctxpopup_item_select(void *data, Evas_Object *obj, - const char *emission, const char *source) +static void +_item_icon_set(Elm_Ctxpopup_Item *item, Evas_Object *icon) { - Elm_Ctxpopup_Item *item = (Elm_Ctxpopup_Item *) data; + if (item->icon) + { + elm_widget_sub_object_del(item->base.view, item->icon); + evas_object_del(item->icon); + } + + item->icon = icon; + edje_object_part_swallow(item->base.view, "elm.swallow.icon", item->icon); + edje_object_message_signal_process(item->base.view); +} - if (!item) return; - if (item->disabled) return; +static void +_item_label_set(Elm_Ctxpopup_Item *item, const char *label) +{ + if (!eina_stringshare_replace(&item->label, label)) + return; - if (item->func) { - evas_object_hide(item->base.widget); - item->func( (void *) item->base.data, item->base.widget, item); - } + edje_object_part_text_set(item->base.view, "elm.text", label); + edje_object_message_signal_process(item->base.view); } -static void _item_obj_create(Elm_Ctxpopup_Item *item, char *group_name) +static void +_item_new(Elm_Ctxpopup_Item *item, char *group_name) { - Widget_Data *wd = (Widget_Data *) elm_widget_data_get(item->base.widget); + Widget_Data *wd; + + wd = elm_widget_data_get(item->base.widget); + if (!wd) + return; + + item->base.view = edje_object_add(evas_object_evas_get(wd->base)); + _elm_theme_object_set(item->base.widget, item->base.view, "ctxpopup", group_name, + elm_widget_style_get(item->base.widget)); + edje_object_signal_callback_add(item->base.view, "elm,action,click", "", + _item_select_cb, item); + evas_object_size_hint_align_set(item->base.view, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_show(item->base.view); +} - if (!wd) return; - item->base.view = edje_object_add(evas_object_evas_get(wd->base)); - _elm_theme_object_set(item->base.widget, item->base.view, "ctxpopup", group_name, - elm_widget_style_get(item->base.widget)); - edje_object_signal_callback_add(item->base.view, "elm,action,click", "", - _ctxpopup_item_select, item); - evas_object_size_hint_align_set(item->base.view, EVAS_HINT_FILL, EVAS_HINT_FILL); - evas_object_size_hint_weight_set(item->base.view, EVAS_HINT_EXPAND, - EVAS_HINT_EXPAND); - evas_object_show(item->base.view); +static void +_content_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, + void *event_info __UNUSED__) +{ + elm_ctxpopup_content_unset(data); } -static void _content_resize(void *data, Evas *e, Evas_Object *obj, void *event_info) +static void +_list_del(Widget_Data *wd) { - Widget_Data *wd = (Widget_Data *) elm_widget_data_get(data); - Evas_Coord w, h; + if (!wd->scr) + return; - if(!wd) return; + edje_object_part_unswallow(wd->base, wd->scr); + evas_object_del(wd->scr); + wd->scr = NULL; + wd->box = NULL; +} - evas_object_geometry_get(obj, NULL, NULL, &w, &h); - evas_object_size_hint_min_set(obj, w, h); - - if(wd->visible) _sizing_eval(data); +static void +_list_new(Evas_Object *obj) +{ + Widget_Data *wd; + wd = elm_widget_data_get(obj); + if (!wd) + return; + + //scroller + wd->scr = elm_scroller_add(obj); + elm_object_style_set(wd->scr, "ctxpopup"); + evas_object_size_hint_align_set(wd->scr, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_RESIZE, + _scroller_resize, obj); + edje_object_part_swallow(wd->base, "elm.swallow.content", wd->scr); + + //box + wd->box = elm_box_add(obj); + evas_object_size_hint_weight_set(wd->box, EVAS_HINT_EXPAND, + EVAS_HINT_EXPAND); + + elm_scroller_content_set(wd->scr, wd->box); + elm_ctxpopup_horizontal_set(obj, wd->horizontal); } -static void _content_del(void *data, Evas *e, Evas_Object *obj, void *event_info) +/** + * Add a new Ctxpopup object to the parent. + * + * @param parent Parent object + * @return New object or @c NULL, if it cannot be created + * + * @ingroup Ctxpopup + */ +EAPI Evas_Object * +elm_ctxpopup_add(Evas_Object *parent) { - elm_ctxpopup_content_unset(data); + Evas_Object *obj; + Evas *e; + Widget_Data *wd; + Evas_Coord x, y, w, h; + + EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL); + + wd = ELM_NEW(Widget_Data); + e = evas_object_evas_get(parent); + if (!e) + return NULL; + obj = elm_widget_add(e); + ELM_SET_WIDTYPE(widtype, "ctxpopup"); + elm_widget_type_set(obj, "ctxpopup"); + elm_widget_sub_object_add(parent, obj); + elm_widget_data_set(obj, wd); + elm_widget_del_pre_hook_set(obj, _del_pre_hook); + elm_widget_del_hook_set(obj, _del_hook); + elm_widget_theme_hook_set(obj, _theme_hook); + + wd->parent = parent; + + //Background + wd->bg = edje_object_add(e); + elm_widget_sub_object_add(obj, wd->bg); + _elm_theme_object_set(obj, wd->bg, "ctxpopup", "bg", "default"); + evas_object_geometry_get(parent, &x, &y, &w, &h); + evas_object_move(wd->bg, x, y); + evas_object_resize(wd->bg, w, h); + edje_object_signal_callback_add(wd->bg, "elm,action,click", "", + _bg_clicked_cb, obj); + + //Base + wd->base = edje_object_add(e); + elm_widget_sub_object_add(obj, wd->base); + _elm_theme_object_set(obj, wd->base, "ctxpopup", "base", "default"); + + //Arrow + wd->arrow = edje_object_add(e); + elm_widget_sub_object_add(obj, wd->arrow); + _elm_theme_object_set(obj, wd->arrow, "ctxpopup", "arrow", "default"); + + wd->dir_priority[0] = ELM_CTXPOPUP_DIRECTION_UP; + wd->dir_priority[1] = ELM_CTXPOPUP_DIRECTION_LEFT; + wd->dir_priority[2] = ELM_CTXPOPUP_DIRECTION_RIGHT; + wd->dir_priority[3] = ELM_CTXPOPUP_DIRECTION_DOWN; + + evas_object_event_callback_add(parent, EVAS_CALLBACK_RESIZE, _parent_resize, + obj); + evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _ctxpopup_show, + NULL); + evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _ctxpopup_hide, + NULL); + evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _ctxpopup_move, + NULL); + evas_object_event_callback_add(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, + _ctxpopup_changed_size_hints, NULL); + evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj); + evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj); + evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj); + evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj); + + evas_object_smart_callbacks_descriptions_set(obj, _signals); + + return obj; } /** - * Get the icon object for the given item. + * Get the icon object for the given ctxpopup item. * - * @param[in] item Ctxpopup item - * @return Icon object or NULL if the item does not have icon + * @param item Ctxpopup item + * @return icon object or @c NULL, if the item does not have icon or an error occurred * * @ingroup Ctxpopup */ EAPI Evas_Object * -elm_ctxpopup_item_icon_get(Elm_Ctxpopup_Item *item) +elm_ctxpopup_item_icon_get(const Elm_Ctxpopup_Item *item) { - if (!item) return NULL; - return item->icon; + ELM_CTXPOPUP_ITEM_CHECK_RETURN(item, NULL); + return item->icon; } /** - * Disable or Enable the scroller for contextual popup. + * Sets the side icon associated with the ctxpopup item * - * @param[in] obj Ctxpopup object - * @param[in] disabled disable or enable + * Once the icon object is set, a previously set one will be deleted. + * You probably don't want, then, to have the same icon object + * set for more than one item of the list (when replacing one of its + * instances). + * + * @param item Ctxpopup item + * @param icon Icon object to be set * * @ingroup Ctxpopup */ -EAPI void elm_ctxpopup_scroller_disabled_set(Evas_Object *obj, - Eina_Bool disabled) +EAPI void +elm_ctxpopup_item_icon_set(Elm_Ctxpopup_Item *item, Evas_Object *icon) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = (Widget_Data *) elm_widget_data_get(obj); + ELM_CTXPOPUP_ITEM_CHECK_RETURN(item); + + Widget_Data *wd; - if (!wd) return; - if (wd->scroller_disabled == disabled) return; + wd = elm_widget_data_get(item->base.widget); + if (!wd) + return; - if (disabled) - elm_object_scroll_freeze_push(wd->scroller); - else - elm_object_scroll_freeze_pop(wd->scroller); + _item_icon_set(item, icon); - wd->scroller_disabled = disabled; + if (wd->visible) + { + _scroller_size_reset(wd); + _sizing_eval(item->base.widget); + } } /** - * Get the label for the given item. + * Get the label object for the given ctxpopup item. * - * @param[in] item Ctxpopup item - * @return Label or NULL if the item does not have label + * @param item Ctxpopup item + * @return label object or @c NULL, if the item does not have label or an error occured * * @ingroup Ctxpopup * */ EAPI const char * -elm_ctxpopup_item_label_get(Elm_Ctxpopup_Item *item) +elm_ctxpopup_item_label_get(const Elm_Ctxpopup_Item *item) { - if (!item) return NULL; - return item->label; + ELM_CTXPOPUP_ITEM_CHECK_RETURN(item, NULL); + return item->label; } /** - * Add a new ctxpopup object to the parent. - * - * @param[in] parent window object - * @return New object or NULL if it cannot be created + * (Re)set the label on the given ctxpopup item. * + * @param item Ctxpopup item + * @param label String to set as label + * * @ingroup Ctxpopup */ -EAPI Evas_Object * -elm_ctxpopup_add(Evas_Object *parent) -{ - Evas_Object *obj; - Evas *e; - Widget_Data *wd; - Evas_Coord x, y, w, h; - - wd = ELM_NEW(Widget_Data); - e = evas_object_evas_get(parent); - - if (!e) - return NULL; - - obj = elm_widget_add(e); - ELM_SET_WIDTYPE(widtype, "ctxpopup"); - elm_widget_type_set(obj, "ctxpopup"); - elm_widget_sub_object_add(parent, obj); - elm_widget_data_set(obj, wd); - elm_widget_del_pre_hook_set(obj, _del_pre_hook); - elm_widget_del_hook_set(obj, _del_hook); - elm_widget_theme_hook_set(obj, _theme_hook); - - wd->parent = parent; - - //Background - wd->bg = edje_object_add(e); - elm_widget_sub_object_add(obj, wd->bg); - _elm_theme_object_set(obj, wd->bg, "ctxpopup", "bg", "default"); - evas_object_geometry_get(parent, &x, &y, &w, &h); - evas_object_move(wd->bg, x, y); - evas_object_resize(wd->bg, w, h); - edje_object_signal_callback_add(wd->bg, "elm,action,click", "", - _bg_clicked_cb, obj); - - //Base - wd->base = edje_object_add(e); - elm_widget_sub_object_add(obj, wd->base); - _elm_theme_object_set(obj, wd->base, "ctxpopup", "base", "default"); - - //Scroller - wd->scroller = elm_scroller_add(obj); - elm_object_style_set(wd->scroller, "ctxpopup"); - evas_object_size_hint_align_set(wd->scroller, EVAS_HINT_FILL, - EVAS_HINT_FILL); - elm_scroller_bounce_set(wd->scroller, EINA_FALSE, EINA_TRUE); - evas_object_event_callback_add(wd->scroller, EVAS_CALLBACK_RESIZE, - _ctxpopup_scroller_resize, obj); - - //Box - wd->box = elm_box_add(obj); - evas_object_size_hint_weight_set(wd->box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); - elm_scroller_content_set(wd->scroller, wd->box); - edje_object_part_swallow(wd->base, "elm.swallow.scroller", wd->scroller); - - //Arrow - wd->arrow = edje_object_add(e); - elm_widget_sub_object_add(obj, wd->arrow); - _elm_theme_object_set(obj, wd->arrow, "ctxpopup", "arrow", "default"); - - wd->arrow_priority[0] = ELM_CTXPOPUP_ARROW_DOWN; - wd->arrow_priority[1] = ELM_CTXPOPUP_ARROW_RIGHT; - wd->arrow_priority[2] = ELM_CTXPOPUP_ARROW_LEFT; - wd->arrow_priority[3] = ELM_CTXPOPUP_ARROW_UP; - - evas_object_event_callback_add(parent, EVAS_CALLBACK_RESIZE, _parent_resize, obj); - evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _ctxpopup_show, NULL); - evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _ctxpopup_hide, NULL); - evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _ctxpopup_move, NULL); - evas_object_event_callback_add(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _ctxpopup_changed_size_hints, NULL); - - return obj; +EAPI void +elm_ctxpopup_item_label_set(Elm_Ctxpopup_Item *item, const char *label) +{ + ELM_CTXPOPUP_ITEM_CHECK_RETURN(item); + + Widget_Data *wd; + + wd = elm_widget_data_get(item->base.widget); + if (!wd) + return; + + _item_label_set(item, label); + + if (wd->visible) + { + _scroller_size_reset(wd); + _sizing_eval(item->base.widget); + } } /** - * Clear all items in given ctxpopup object. + * Set the Ctxpopup's parent + * Set the parent object (it would much probably be the + * window that the ctxpopup is in). * - * @param[in] obj Ctxpopup object + * @param obj The ctxpopup object + * @param area The parent to use + * + * @note elm_ctxpopup_add() will automatically call this function + * with its @c parent argument. * * @ingroup Ctxpopup */ -EAPI void elm_ctxpopup_clear(Evas_Object *obj) +EAPI void +elm_ctxpopup_hover_parent_set(Evas_Object *obj, Evas_Object *hover_parent) { - ELM_CHECK_WIDTYPE(obj, widtype); - Eina_List *elist; - Elm_Ctxpopup_Item *item; + ELM_CHECK_WIDTYPE(obj, widtype); + + Widget_Data *wd; - Widget_Data *wd = (Widget_Data *) elm_widget_data_get(obj); + wd = elm_widget_data_get(obj); + if (!wd) + return; - if (!wd) return; + _hover_parent_callbacks_del(obj); - EINA_LIST_FOREACH(wd->items, elist, item) - { - if (item->label) - eina_stringshare_del(item->label); - if (item->icon) - evas_object_del(item->icon); - wd->items = eina_list_remove(wd->items, item); - free(item); - } + if (hover_parent) + { + evas_object_event_callback_add(hover_parent, EVAS_CALLBACK_DEL, + _hover_parent_del, obj); + evas_object_event_callback_add(hover_parent, EVAS_CALLBACK_MOVE, + _hover_parent_move, obj); + evas_object_event_callback_add(hover_parent, EVAS_CALLBACK_RESIZE, + _hover_parent_resize, obj); + } - evas_object_hide(wd->arrow); - evas_object_hide(wd->base); + wd->hover_parent = hover_parent; } /** - * Change the mode to horizontal or vertical. + * Get the Ctxpopup's parent * - * @param[in] obj Ctxpopup object - * @param horizontal EINA_TRUE - horizontal mode, EINA_FALSE - vertical mode + * @param obj The ctxpopup object + * + * @see elm_ctxpopup_hover_parent_set() for more information * * @ingroup Ctxpopup */ -EAPI void elm_ctxpopup_horizontal_set(Evas_Object *obj, Eina_Bool horizontal) -{ - ELM_CHECK_WIDTYPE(obj, widtype); - Eina_List *elist; - Elm_Ctxpopup_Item *item; - Widget_Data *wd = (Widget_Data *) elm_widget_data_get(obj); - - if (!wd) return; - - if (wd->horizontal == horizontal) return; - wd->horizontal = horizontal; - if (!horizontal) { - elm_box_horizontal_set(wd->box, EINA_FALSE); - elm_scroller_bounce_set(wd->scroller, EINA_FALSE, EINA_TRUE); - EINA_LIST_FOREACH (wd->items, elist, item) - edje_object_signal_emit(item->base.view, "elm,state,vertical", "elm"); - } - else - { - elm_box_horizontal_set(wd->box, EINA_TRUE); - elm_scroller_bounce_set(wd->scroller, EINA_TRUE, EINA_FALSE); - EINA_LIST_FOREACH(wd->items, elist, item) - edje_object_signal_emit(item->base.view, "elm,state,horizontal", "elm"); - } +EAPI Evas_Object * +elm_ctxpopup_hover_parent_get(const Evas_Object *obj) +{ + ELM_CHECK_WIDTYPE(obj, widtype) NULL; + + Widget_Data *wd; + + wd = elm_widget_data_get(obj); + if (!wd) + return NULL; + + return wd->hover_parent; +} + +static void +_remove_items(Widget_Data *wd) +{ + Eina_List *elist; + Elm_Ctxpopup_Item *item; + + if (!wd->items) + return; + + EINA_LIST_FOREACH(wd->items, elist, item) + { + if (item->label) + eina_stringshare_del(item->label); + if (item->icon) + evas_object_del(item->icon); + wd->items = eina_list_remove(wd->items, item); + free(item); + } + + wd->items = NULL; } /** - * Get the value of current horizontal mode. + * Clear all items in the given ctxpopup object. * - * @param[in] obj Ctxpopup object - * @return EINA_TRUE - horizontal mode, EINA_FALSE - vertical mode. + * @param obj Ctxpopup object * * @ingroup Ctxpopup */ -EAPI Eina_Bool elm_ctxpopup_horizontal_get(Evas_Object *obj) +EAPI void +elm_ctxpopup_clear(Evas_Object * obj) { - ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; - Widget_Data *wd = (Widget_Data *) elm_widget_data_get(obj); - if (!wd) return EINA_FALSE; - return wd->horizontal; + ELM_CHECK_WIDTYPE(obj, widtype); + + Widget_Data *wd = elm_widget_data_get(obj); + + if (!wd) + return; + + _remove_items(wd); + _list_del(wd); } /** - * reset the icon on the given item. + * Change the ctxpopup's orientation to horizontal or vertical. * - * @param[in] item Ctxpopup item - * @param[in] icon Icon object to be set + * @param obj Ctxpopup object + * @param horizontal @c EINA_TRUE for horizontal mode, @c EINA_FALSE for vertical * * @ingroup Ctxpopup */ -EAPI void elm_ctxpopup_item_icon_set(Elm_Ctxpopup_Item *item, Evas_Object *icon) -{ - Widget_Data *wd; - - if (!item) return; - wd = (Widget_Data *) elm_widget_data_get(item->base.widget); - if (!wd) return; - if (item->icon == icon) return; - if (item->icon) { - elm_widget_sub_object_del(item->base.view, item->icon); - evas_object_del(item->icon); - } - item->icon = icon; - edje_object_part_swallow(item->base.view, "elm.swallow.icon", item->icon); - edje_object_message_signal_process(item->base.view); - - if (wd->visible) { - _reset_scroller_size(wd); - _sizing_eval(item->base.widget); - } +EAPI void +elm_ctxpopup_horizontal_set(Evas_Object *obj, Eina_Bool horizontal) +{ + ELM_CHECK_WIDTYPE(obj, widtype); + + Widget_Data *wd; + + wd = elm_widget_data_get(obj); + if (!wd) + return; + + wd->horizontal = !!horizontal; + + if ((!wd->scr) && (!wd->box)) + return; + + if (!horizontal) + { + elm_box_horizontal_set(wd->box, EINA_FALSE); + elm_scroller_bounce_set(wd->scr, EINA_FALSE, EINA_TRUE); + } + else + { + elm_box_horizontal_set(wd->box, EINA_TRUE); + elm_scroller_bounce_set(wd->scr, EINA_TRUE, EINA_FALSE); + } + + if (wd->visible) + _sizing_eval(obj); } /** - * reset the label on the given item. + * Get the value of current ctxpopup object's orientation. + * + * @param obj Ctxpopup object + * @return @c EINA_TRUE for horizontal mode, @c EINA_FALSE for vertical mode (or errors) * - * @param[in] item Ctxpopup item - * @param[in] label Label to be set - * * @ingroup Ctxpopup */ -EAPI void elm_ctxpopup_item_label_set(Elm_Ctxpopup_Item *item, - const char *label) +EAPI Eina_Bool +elm_ctxpopup_horizontal_get(const Evas_Object *obj) { - Widget_Data *wd; - - if (!item) - return; - - if (item->label) { - eina_stringshare_del(item->label); - item->label = NULL; - } + ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; - item->label = eina_stringshare_add(label); - edje_object_message_signal_process(item->base.view); - edje_object_part_text_set(item->base.view, "elm.text", label); + Widget_Data *wd; - wd = elm_widget_data_get(item->base.widget); - if (!wd) - return; + wd = elm_widget_data_get(obj); + if (!wd) + return EINA_FALSE; - if (wd->visible) { - _reset_scroller_size(wd); - _sizing_eval(item->base.widget); - } + return wd->horizontal; } /** - * Add a new item in given ctxpopup object. + * Add a new item to a ctxpopup object. * - * @param[in] obj Ctxpopup object - * @param[in] icon Icon to be set - * @param[in] label Label to be set - * @param[in] func Callback function to call when this item click is clicked - * @param[in] data User data for callback function - * @return Added ctxpopup item + * Both a item list and a content could not be set at the same time! + * once you set add a item, the previous content will be removed. + * + * @param obj Ctxpopup object + * @param icon Icon to be set on new item + * @param label The Label of the new item + * @param func Convenience function called when item selected + * @param data Data passed to @p func above + * @return A handle to the item added or @c NULL, on errors * * @ingroup Ctxpopup */ EAPI Elm_Ctxpopup_Item * -elm_ctxpopup_item_add(Evas_Object *obj, Evas_Object *icon, const char *label, - Evas_Smart_Cb func, void *data) +elm_ctxpopup_item_append(Evas_Object *obj, const char *label, + Evas_Object *icon, Evas_Smart_Cb func, + const void *data) { - ELM_CHECK_WIDTYPE(obj, widtype)NULL; - Elm_Ctxpopup_Item *item; - Widget_Data *wd = (Widget_Data *) elm_widget_data_get(obj); + ELM_CHECK_WIDTYPE(obj, widtype) NULL; - if (!wd) - return NULL; + Widget_Data *wd; + Elm_Ctxpopup_Item *item; - _separator_obj_add(obj); + wd = elm_widget_data_get(obj); + if (!wd) + return NULL; - item = ELM_NEW(Elm_Ctxpopup_Item); - if (!item) - return NULL; + item = elm_widget_item_new(obj, Elm_Ctxpopup_Item); + if (!item) + return NULL; - item->func = func; - item->base.data = data; - item->base.widget = obj; - item->separator = EINA_FALSE; + //The first item is appended. + if (wd->content) + evas_object_del(elm_ctxpopup_content_unset(obj)); - if (icon && label) - _item_obj_create(item, "icon_text_style_item"); - else if (icon) - _item_obj_create(item, "icon_style_item"); - else - _item_obj_create(item, "text_style_item"); + if (!wd->items) + _list_new(obj); - wd->items = eina_list_append(wd->items, item); - elm_box_pack_end(wd->box, item->base.view); - elm_ctxpopup_item_icon_set(item, icon); - elm_ctxpopup_item_label_set(item, label); + item->func = func; + item->base.data = data; - return item; -} + if (icon && label) + _item_new(item, "icon_text_style_item"); + else if (label) + _item_new(item, "text_style_item"); + else + _item_new(item, "icon_style_item"); -/** - * Delete the given item in ctxpopup object. - * - * @param item[in] Ctxpopup item to be deleted - * - * @ingroup Ctxpopup - */ -EAPI void elm_ctxpopup_item_del(Elm_Ctxpopup_Item *item) -{ - Widget_Data *wd; - Evas_Object *obj; - - if (!item) - return; - - obj = item->base.widget; - - if (item->label) - eina_stringshare_del(item->label); - if (item->icon) - evas_object_del(item->icon); - if (item->base.view) - evas_object_del(item->base.view); - - wd = (Widget_Data *) elm_widget_data_get(item->base.widget); - if (wd) { - _separator_obj_del(wd, item); - wd->items = eina_list_remove(wd->items, item); - } - free(item); - if (eina_list_count(wd->items) == 0) { - evas_object_hide(obj); - } + _item_icon_set(item, icon); + _item_label_set(item, label); + elm_box_pack_end(wd->box, item->base.view); + wd->items = eina_list_append(wd->items, item); + + if (wd->visible) + { + _scroller_size_reset(wd); + _sizing_eval(obj); + } + + return item; } /** - * Disable or Enable the given item. Once an item is disabled, the click event will be never happend for the item. + * Delete the given item in a ctxpopup object. * - * @param[in] item Ctxpopup item to be disabled - * @param[in] disabled EINA_TRUE - disable, EINA_FALSE - enable + * @param item Ctxpopup item to be deleted * * @ingroup Ctxpopup */ -EAPI void elm_ctxpopup_item_disabled_set(Elm_Ctxpopup_Item *item, - Eina_Bool disabled) +EAPI void +elm_ctxpopup_item_del(Elm_Ctxpopup_Item *item) { - Widget_Data *wd; + ELM_CTXPOPUP_ITEM_CHECK_RETURN(item); + + Widget_Data *wd; + + wd = elm_widget_data_get(item->base.widget); + if (!wd) + return; - if (!item) return; - if (disabled == item->disabled) return; + if (item->icon) + evas_object_del(item->icon); + if (item->base.view) + evas_object_del(item->base.view); - wd = (Widget_Data *) elm_widget_data_get(item->base.widget); - - if (disabled) - edje_object_signal_emit(item->base.view, "elm,state,disabled", "elm"); - else - edje_object_signal_emit(item->base.view, "elm,state,enabled", "elm"); + eina_stringshare_del(item->label); - edje_object_message_signal_process(item->base.view); - item->disabled = disabled; + wd->items = eina_list_remove(wd->items, item); + + if (eina_list_count(wd->items) < 1) + wd->items = NULL; + + if (wd->visible) + _sizing_eval(item->base.widget); + + free(item); } /** - * Disable or Enable background dimmed function - * @param[in] obj Ctxpopup object - * @param[in] dimmed EINA_TRUE - disable, EINA_FALSE - enable + * Set the ctxpopup item's state as disabled or enabled. + * + * @param item Ctxpopup item to be enabled/disabled + * @param disabled @c EINA_TRUE to disable it, @c EINA_FALSE to enable it * * @ingroup Ctxpopup */ -EAPI void elm_ctxpopup_screen_dimmed_disabled_set(Evas_Object *obj, - Eina_Bool disabled) +EAPI void +elm_ctxpopup_item_disabled_set(Elm_Ctxpopup_Item *item, Eina_Bool disabled) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = (Widget_Data *) elm_widget_data_get(obj); + ELM_CTXPOPUP_ITEM_CHECK_RETURN(item); - if (!wd) - return; + Widget_Data *wd; - wd->screen_dimmed_disabled = disabled; + wd = elm_widget_data_get(item->base.widget); + if (!wd) + return; - if (wd->visible) { - if (!disabled) { - evas_object_show(wd->bg); - } - } -} + if (disabled == item->disabled) + return; -/** - * Append additional button in ctxpoppup bottom layout. - * @param[in] obj Ctxpopup object - * @param[in] label Button label - * @param[in] func Button clicked event callback function - * @param[in] data Button clicked event callback function data - * - * @ingroup Ctxpopup - */ -EAPI void elm_ctxpopup_button_append(Evas_Object *obj, const char *label, - Evas_Smart_Cb func, const void *data) -{ - ELM_CHECK_WIDTYPE(obj, widtype); - char buf[256]; - Evas_Object *btn; - Evas_Coord w, h; - Widget_Data *wd = (Widget_Data *) elm_widget_data_get(obj); - - if (!wd) return; - if (!wd->btn_layout) _btn_layout_create(obj); - - ++wd->btn_cnt; - sprintf(buf, "buttons%d", wd->btn_cnt); - _elm_theme_object_set(obj, wd->btn_layout, "ctxpopup", buf, - elm_widget_style_get(obj)); - - btn = elm_button_add(obj); - elm_object_style_set(btn, "text_only/style1"); - elm_button_label_set(btn, label); - evas_object_smart_callback_add(btn, "clicked", func, data); - sprintf(buf, "actionbtn%d", wd->btn_cnt); - edje_object_part_swallow(wd->btn_layout, buf, btn); - - edje_object_part_geometry_get(wd->btn_layout, buf, NULL, NULL, &w, &h); - evas_object_size_hint_max_set(wd->btn_layout, -1, h); - - if (wd->visible) { - _reset_scroller_size(wd); - _sizing_eval(obj); - } + if (disabled) + edje_object_signal_emit(item->base.view, "elm,state,disabled", "elm"); + else + edje_object_signal_emit(item->base.view, "elm,state,enabled", "elm"); + + item->disabled = !!disabled; } /** - * Set the priority of arrow direction + * Get the ctxpopup item's disabled/enabled state. * - * This functions gives user to set the priority of ctxpopup box showing position. - * - * @param[in] obj Ctxpopup object - * @param[in] first 1st priority of arrow direction - * @param[in] second 2nd priority of arrow direction - * @param[in] third 3th priority of arrow direction - * @param[in] fourth 4th priority of arrow direction + * @param item Ctxpopup item to be enabled/disabled + * @return disabled @c EINA_TRUE, if disabled, @c EINA_FALSE otherwise * * @ingroup Ctxpopup */ -EAPI void elm_ctxpopup_arrow_priority_set(Evas_Object *obj, - Elm_Ctxpopup_Arrow first, Elm_Ctxpopup_Arrow second, - Elm_Ctxpopup_Arrow third, Elm_Ctxpopup_Arrow fourth) -{ - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = (Widget_Data *) elm_widget_data_get(obj); - - if (!wd) - return; - wd->arrow_priority[0] = first; - wd->arrow_priority[1] = second; - wd->arrow_priority[2] = third; - wd->arrow_priority[3] = fourth; +EAPI Eina_Bool +elm_ctxpopup_item_disabled_get(const Elm_Ctxpopup_Item *item) +{ + ELM_CTXPOPUP_ITEM_CHECK_RETURN(item, EINA_FALSE); + + return item->disabled; } /** - * Swallow the user content + * Once the content object is set, a previously set one will be deleted. + * If you want to keep that old content object, use the + * elm_ctxpopup_content_unset() function + * + * Both a item list and a content could not be set at the same time! + * once you set a content, the previous list items will be removed. * - * @param[in] obj Ctxpopup object - * @param[in] content Content to be swallowed + * @param obj Ctxpopup object + * @param content Content to be swallowed * * @ingroup Ctxpopup */ -EAPI void elm_ctxpopup_content_set(Evas_Object *obj, Evas_Object *content) -{ - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = (Widget_Data *) elm_widget_data_get(obj); - Evas_Coord w, h; - if(!wd || !content) return; - - evas_object_event_callback_add(content, EVAS_CALLBACK_DEL, _content_del, obj); - evas_object_event_callback_add(content, EVAS_CALLBACK_RESIZE, _content_resize, obj); - - evas_object_geometry_get(content, NULL, NULL, &w, &h); - - if((w > 0) || (h > 0)) evas_object_size_hint_min_set(content, w, h); - - edje_object_part_swallow(wd->base, "elm.swallow.content", content); - elm_widget_sub_object_add(obj, content); - edje_object_signal_emit(wd->base, "elm,state,content,enable", "elm"); - elm_ctxpopup_scroller_disabled_set(obj, EINA_TRUE); - wd->content = content; - - if(wd->visible) _sizing_eval(obj); +EAPI void +elm_ctxpopup_content_set(Evas_Object *obj, Evas_Object *content) +{ + ELM_CHECK_WIDTYPE(obj, widtype); + + Widget_Data *wd; + + wd = elm_widget_data_get(obj); + if ((!wd) || (!content)) + return; + + if (wd->items) + elm_ctxpopup_clear(obj); + + if (wd->content) + evas_object_del(wd->content); + + evas_object_event_callback_add(content, EVAS_CALLBACK_DEL, _content_del, + obj); + + elm_widget_sub_object_add(obj, content); + edje_object_part_swallow(wd->base, "elm.swallow.content", content); + edje_object_message_signal_process(wd->base); + + wd->content = content; + + if (wd->visible) + _sizing_eval(obj); } /** - * Unswallow the user content + * Unset the ctxpopup content * - * @param[in] obj Ctxpopup object - * @return The unswallowed content + * Unparent and return the content object which was set for this widget + * + * @param obj Ctxpopup object + * @return The content that was being used * * @ingroup Ctxpopup */ EAPI Evas_Object * -elm_ctxpopup_content_unset(Evas_Object *obj) +elm_ctxpopup_content_unset(Evas_Object *obj) { - ELM_CHECK_WIDTYPE(obj, widtype)NULL; - Widget_Data *wd = (Widget_Data *) elm_widget_data_get(obj); - Evas_Object *content; + ELM_CHECK_WIDTYPE(obj, widtype) NULL; + + Widget_Data *wd; + Evas_Object *content; - content = wd->content; - - if(!content) return NULL; + wd = elm_widget_data_get(obj); + if (!wd) + return NULL; - edje_object_part_unswallow(wd->base, content); - elm_widget_sub_object_del(obj, content); - evas_object_event_callback_del(content, EVAS_CALLBACK_DEL, _content_del); - evas_object_event_callback_del(content, EVAS_CALLBACK_RESIZE, _content_resize); - edje_object_signal_emit(wd->base, "elm,state,content,disable", "elm"); + content = wd->content; + if (!content) + return NULL; - elm_ctxpopup_scroller_disabled_set(obj, EINA_FALSE); + edje_object_part_unswallow(wd->base, content); + elm_widget_sub_object_del(obj, content); + evas_object_event_callback_del(content, EVAS_CALLBACK_DEL, _content_del); + edje_object_signal_emit(wd->base, "elm,state,content,disable", "elm"); - if (wd->visible) - _sizing_eval(obj); + wd->content = NULL; - return content; + return content; } /** - * Change the origin of the ctxpopup position. + * Set the direction priority of a ctxpopup. + * This functions gives a chance to user to set the priority of ctxpopup showing direction. * - * Basically, ctxpopup position is computed internally. When user call evas_object_move, - * Ctxpopup will be showed up with that position which is indicates the arrow point. - * - * @param[in] obj Ctxpopup object - * @param[in] forced EINA_TRUE is left-top. EINA_FALSE is indicates arrow point. + * @param obj Ctxpopup object + * @param first 1st priority of direction + * @param second 2nd priority of direction + * @param third 3th priority of direction + * @param fourth 4th priority of direction * * @ingroup Ctxpopup */ -EAPI void elm_ctxpopup_position_forced_set(Evas_Object *obj, Eina_Bool forced) +EAPI void +elm_ctxpopup_direction_priority_set(Evas_Object *obj, + Elm_Ctxpopup_Direction first, + Elm_Ctxpopup_Direction second, + Elm_Ctxpopup_Direction third, + Elm_Ctxpopup_Direction fourth) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = (Widget_Data *) elm_widget_data_get(obj); + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd; - wd->position_forced = forced; + wd = elm_widget_data_get(obj); + if (!wd) + return; - if (forced) evas_object_hide(wd->arrow); + wd->dir_priority[0] = first; + wd->dir_priority[1] = second; + wd->dir_priority[2] = third; + wd->dir_priority[3] = fourth; - if (wd->visible) { - _reset_scroller_size(wd); - _sizing_eval(obj); - } + if (wd->visible) + _sizing_eval(obj); } /** - * Get the status of the position forced + * Get the direction priority of a ctxpopup. * - * @param[in] obj Ctxpopup objet - * @return value of position forced + * @param obj Ctxpopup object + * @param first 1st priority of direction to be returned + * @param second 2nd priority of direction to be returned + * @param third 3th priority of direction to be returned + * @param fourth 4th priority of direction to be returned * + * @see elm_ctxpopup_direction_priority_set for more information. + * * @ingroup Ctxpopup */ -EAPI Eina_Bool elm_ctxpopup_position_forced_get(Evas_Object *obj) +EAPI void +elm_ctxpopup_direction_priority_get(Evas_Object *obj, + Elm_Ctxpopup_Direction *first, + Elm_Ctxpopup_Direction *second, + Elm_Ctxpopup_Direction *third, + Elm_Ctxpopup_Direction *fourth) +{ + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd; + + wd = elm_widget_data_get(obj); + if (!wd) + return; + + if (first) + *first = wd->dir_priority[0]; + if (second) + *second = wd->dir_priority[1]; + if (third) + *third = wd->dir_priority[2]; + if (fourth) + *fourth = wd->dir_priority[3]; +} + +EAPI void +elm_ctxpopup_screen_dimmed_disabled_set(Evas_Object *obj, + Eina_Bool disabled) { - ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; - Widget_Data *wd = (Widget_Data *) elm_widget_data_get(obj); - return wd->position_forced; + return ; +} + +EAPI void +elm_ctxpopup_button_append(Evas_Object *obj, const char *label, + Evas_Smart_Cb func, const void *data) +{ + return ; +} + +EAPI void +elm_ctxpopup_position_forced_set(Evas_Object *obj, Eina_Bool forced) +{ + return; +} + +EAPI Eina_Bool +elm_ctxpopup_position_forced_get(const Evas_Object *obj) +{ + return EINA_FALSE; } EAPI Elm_Ctxpopup_Item * elm_ctxpopup_icon_add(Evas_Object *obj, Evas_Object *icon, Evas_Smart_Cb func, - void *data) + void *data) { - return elm_ctxpopup_item_add(obj, icon, NULL, func, data); + return elm_ctxpopup_item_append(obj, NULL, icon, func, data); } EAPI Elm_Ctxpopup_Item * elm_ctxpopup_label_add(Evas_Object *obj, const char *label, Evas_Smart_Cb func, - void *data) + void *data) { - return elm_ctxpopup_item_add(obj, NULL, label, func, data); + return elm_ctxpopup_item_add(obj, label, NULL, func, data); } -/** - * Set the area of ctxpopup will show up. Ctxpopup will not be out of this area. - * The responsibility of the area object is to user. - * - * @param[in] obj Ctxpopup objet - * @param[in] area area object - * - * @ingroup Ctxpopup - */ -EAPI void elm_ctxpopup_area_set(Evas_Object *obj, Evas_Object *area) -{ - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = (Widget_Data *) elm_widget_data_get(obj); - - _delete_area_rect_callbacks(wd); - - if (area) { - evas_object_event_callback_add(area, EVAS_CALLBACK_DEL, _area_rect_del, - obj); - evas_object_event_callback_add(area, EVAS_CALLBACK_MOVE, - _area_rect_move, obj); - evas_object_event_callback_add(area, EVAS_CALLBACK_RESIZE, - _area_rect_resize, obj); - wd->area_rect = area; - } +EAPI void +elm_ctxpopup_area_set(Evas_Object *obj, Evas_Object *area) +{ + elm_ctxpopup_hover_parent_set(obj, area); +} + +EAPI void +elm_ctxpopup_scroller_disabled_set(Evas_Object *obj, Eina_Bool disabled) +{ + ELM_CHECK_WIDTYPE(obj, widtype); + + Widget_Data *wd; + + wd = elm_widget_data_get(obj); + if (!wd) + return; + + if (disabled) + elm_object_scroll_freeze_push(wd->scr); + else + elm_object_scroll_freeze_pop(wd->scr); +} + +EAPI Elm_Ctxpopup_Item * +elm_ctxpopup_item_add(Evas_Object *obj, Evas_Object *icon, const char *label, + Evas_Smart_Cb func, void *data) +{ + return elm_ctxpopup_item_append(obj, label, icon, func, data); } + +EAPI void +elm_ctxpopup_arrow_priority_set(Evas_Object *obj, + Elm_Ctxpopup_Arrow first, Elm_Ctxpopup_Arrow second, + Elm_Ctxpopup_Arrow third, Elm_Ctxpopup_Arrow fourth) +{ + elm_ctxpopup_direction_priority_set(obj, first, second, third, fourth); +} + diff --git a/src/lib/elm_popup.c b/src/lib/elm_popup.c index 407a9f7..5d08c75 100644 --- a/src/lib/elm_popup.c +++ b/src/lib/elm_popup.c @@ -306,8 +306,12 @@ _elm_popup_buttons_add_valist(Evas_Object *obj, const char *first_button_text, v static void _elm_popup_timeout(void *data, Evas_Object *obj, void *event_info) { - evas_object_hide((Evas_Object*)data); - evas_object_smart_callback_call((Evas_Object *)data, "response", (void *)ELM_POPUP_RESPONSE_TIMEOUT); + printf("%s begin\n"); + evas_object_hide((Evas_Object*)data); + printf("!!!!!!!!!!!!!!!!!!\n"); + evas_object_smart_callback_call((Evas_Object *)data, "response", (void *)ELM_POPUP_RESPONSE_TIMEOUT); + printf("@@@@@@@@@@@@@@@@@\n"); + printf("%s end\n"); } static Eina_Bool