From 093935f2359b3806b10d6978dfe04d5920cdcaeb Mon Sep 17 00:00:00 2001 From: ChunEon Park Date: Mon, 5 Jul 2010 18:05:56 +0900 Subject: [PATCH] [elm_ctxpopup.c] --- src/lib/elm_ctxpopup.c | 328 ++++++++++++++++++++++++------------------------- 1 file changed, 163 insertions(+), 165 deletions(-) diff --git a/src/lib/elm_ctxpopup.c b/src/lib/elm_ctxpopup.c index 5e72362..02d415a 100644 --- a/src/lib/elm_ctxpopup.c +++ b/src/lib/elm_ctxpopup.c @@ -33,11 +33,11 @@ struct _Widget_Data Evas_Object *box; Evas_Object *arrow; Evas_Object *scroller; + Evas_Object *bg; Eina_List *items; - Evas_Coord x, y; - Arrow_Direction last_arrow_dir; Eina_Bool scroller_disabled:1; Eina_Bool horizontal:1; + Eina_Bool arrow_disabled:1; }; static const char *widtype = NULL; @@ -45,8 +45,9 @@ 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 _hover_clicked_cb(void *data, Evas_Object *obj, void *event_info); +static void _bg_clicked_cb(void *data, Evas_Object *obj, void *event_info); static void _parent_resize(void *data, Evas *e, Evas_Object *obj, void *event_info); +static void _parent_move(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); @@ -57,12 +58,10 @@ static void _ctxpopup_item_select(void *data, Evas_Object *obj, const char *emis static void _separator_obj_add(Evas_Object *obj); static void _separator_obj_del(Widget_Data *wd, Elm_Ctxpopup_Item *remove_item); static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info); -static Arrow_Direction _calc_best_geometry(Widget_Data *wd, Evas_Coord_Rectangle *rect); -static void _arrow_obj_add(Evas_Object *obj, const char *group_name); +static Arrow_Direction _calc_base_geometry(Evas_Object *obj, Evas_Coord_Rectangle *rect); +//static void _arrow_obj_add(Evas_Object *obj, const char *group_name); static void _update_arrow_obj(Evas_Object *obj, Arrow_Direction arrow_dir); -static Evas_Coord _adjust_arrow_pos_x(Widget_Data *wd); -static Evas_Coord _adjust_arrow_pos_y(Widget_Data *wd); -static void _shift_geometry_by_arrow(Evas_Object *arrow, Arrow_Direction arrow_dir, Evas_Coord_Rectangle *rect); +static void _shift_base_by_arrow(Evas_Object *arrow, Arrow_Direction arrow_dir, Evas_Coord_Rectangle *rect); static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info) @@ -117,7 +116,7 @@ _separator_obj_add(Evas_Object *obj) return; } - _elm_theme_object_set(obj, item->obj, "ctxpopup", "seperator", + _elm_theme_object_set(obj, item->obj, "ctxpopup", "separator", elm_widget_style_get(obj)); if (wd->horizontal) @@ -125,7 +124,7 @@ _separator_obj_add(Evas_Object *obj) else edje_object_signal_emit(item->obj, "elm,state,vertical", "elm"); - evas_object_show(item->obj); + evas_object_show(item->obj); item->separator = EINA_TRUE; elm_box_pack_end(wd->box, item->obj); wd->items = eina_list_append(wd->items, item); @@ -157,8 +156,8 @@ _item_sizing_eval(Elm_Ctxpopup_Item *item) #define BOX_HALF_W (box_w/2) #define BOX_HALF_H (box_h/2) -#define ADJUST_POS_X() do { \ - x = wd->x - (box_w/2); \ +#define ADJUST_POS_X(x) do { \ + x = x - (box_w/2); \ if(x < x1) { \ x = x1; \ }else if(x + box_w > WORLD_PARENT_W) { \ @@ -166,8 +165,8 @@ _item_sizing_eval(Elm_Ctxpopup_Item *item) } \ }while(0) -#define ADJUST_POS_Y() do { \ - y = wd->y - (box_h/2); \ +#define ADJUST_POS_Y(y) do { \ + y = y - (box_h/2); \ if(y < y1) { \ y = y1; \ }else if(y + box_h > WORLD_PARENT_H) \ @@ -177,24 +176,28 @@ _item_sizing_eval(Elm_Ctxpopup_Item *item) }while(0) static Arrow_Direction -_calc_best_geometry(Widget_Data *wd, Evas_Coord_Rectangle *rect) +_calc_base_geometry(Evas_Object *obj, Evas_Coord_Rectangle *rect) { - Evas_Coord x, y; + Widget_Data *wd; + Evas_Coord x, y; Evas_Coord parent_x, parent_y, parent_w, parent_h; Evas_Coord box_w, box_h; Arrow_Direction arrow_dir; Evas_Coord x1, x2, y1, y2; - int available_direction[4] = { 1, 1, 1, 1 }; - int idx = 0; + int idx; Evas_Coord finger_size; - Evas_Coord arrow_size_w, arrow_size_h; Evas_Coord max_width_size, max_height_size; + Evas_Coord arrow_w=0, arrow_h=0; + int available_direction[4] = { 1, 1, 1, 1 }; + + wd = elm_widget_data_get(obj); if ((!wd) || (!rect)) - return arrow_dir; - x = wd->x; - y = wd->y; - evas_object_geometry_get(wd->parent, &parent_x, &parent_y, &parent_w, + return NONE_ARROW; + + evas_object_geometry_get(obj, &x, &y, NULL, NULL); + + evas_object_geometry_get(wd->parent, &parent_x, &parent_y, &parent_w, &parent_h); evas_object_geometry_get(wd->box, NULL, NULL, &box_w, &box_h); @@ -209,12 +212,14 @@ _calc_best_geometry(Widget_Data *wd, Evas_Coord_Rectangle *rect) box_w = max_width_size; finger_size = elm_finger_size_get(); - edje_object_size_min_calc(wd->arrow, &arrow_size_w, &arrow_size_h); + if (!wd->arrow_disabled) + edje_object_size_min_calc(wd->arrow, &arrow_w, &arrow_h); + //Phase 1: Define x, y Segments and find invalidated direction. //Left x1 = x - box_w; - if ((x1 - arrow_size_w - finger_size) < parent_x) + if ((x1 - arrow_w - finger_size) < parent_x) { x1 = parent_x; available_direction[RIGHT_ARROW] = 0; @@ -222,7 +227,7 @@ _calc_best_geometry(Widget_Data *wd, Evas_Coord_Rectangle *rect) //Right x2 = x + box_w; - if (x2 + arrow_size_w + finger_size > WORLD_PARENT_W) + if (x2 + arrow_w + finger_size > WORLD_PARENT_W) { x2 = WORLD_PARENT_W - box_w; available_direction[LEFT_ARROW] = 0; @@ -230,14 +235,14 @@ _calc_best_geometry(Widget_Data *wd, Evas_Coord_Rectangle *rect) //Top y1 = y - box_h; - if (y1 - arrow_size_h - finger_size < parent_y) + if (y1 - arrow_h - finger_size < parent_y) { y1 = parent_y; available_direction[BOTTOM_ARROW] = 0; } //Bottom y2 = y + box_h; - if (y2 + arrow_size_h + finger_size > WORLD_PARENT_H) + if (y2 + arrow_h + finger_size > WORLD_PARENT_H) { y2 = WORLD_PARENT_H - box_h; available_direction[TOP_ARROW] = 0; @@ -245,7 +250,7 @@ _calc_best_geometry(Widget_Data *wd, Evas_Coord_Rectangle *rect) //ADDITIONAL OPTION: Phase 2: Determine Direction Priority ? -//Phase 3: adjust geometry information. +//Phase 3: adjust base geometry. for (idx = 0; idx < 4; ++idx) { if (available_direction[idx] == 0) @@ -255,23 +260,23 @@ _calc_best_geometry(Widget_Data *wd, Evas_Coord_Rectangle *rect) switch (idx) { case BOTTOM_ARROW: - ADJUST_POS_X(); - y = wd->y - box_h - finger_size; + ADJUST_POS_X(x); + y -= (box_h + finger_size); arrow_dir = BOTTOM_ARROW; break; case RIGHT_ARROW: - ADJUST_POS_Y(); - x = wd->x - box_w - finger_size; + ADJUST_POS_Y(y); + x -= (box_w + finger_size); arrow_dir = RIGHT_ARROW; break; case LEFT_ARROW: - ADJUST_POS_Y(); - x = wd->x + finger_size; + ADJUST_POS_Y(y); + x += finger_size; arrow_dir = LEFT_ARROW; break; case TOP_ARROW: - ADJUST_POS_X(); - y = wd->y + finger_size; + ADJUST_POS_X(x); + y += finger_size; arrow_dir = TOP_ARROW; break; default: @@ -286,128 +291,57 @@ _calc_best_geometry(Widget_Data *wd, Evas_Coord_Rectangle *rect) return arrow_dir; } -static Evas_Coord -_adjust_arrow_pos_x(Widget_Data * wd) -{ - Evas_Coord parent_x, parent_w; - Evas_Coord arrow_x; - Evas_Coord arrow_size; - Evas_Coord half_arrow_size; - - if (!wd ) return 0; - - edje_object_size_max_get(wd->arrow, &arrow_size, NULL); - half_arrow_size = (arrow_size * 0.5); - evas_object_geometry_get(wd->parent, &parent_x, NULL, &parent_w, NULL); - arrow_x = wd->x; - - if (arrow_x - half_arrow_size < parent_x) - arrow_x = parent_x + half_arrow_size; - else if (wd->x + arrow_size > WORLD_PARENT_W) - arrow_x = WORLD_PARENT_W - half_arrow_size; - - return arrow_x; -} - -static Evas_Coord -_adjust_arrow_pos_y(Widget_Data *wd) -{ - Evas_Coord parent_y, parent_h; - Evas_Coord arrow_y; - Evas_Coord arrow_size; - Evas_Coord half_arrow_size; - - if (!wd) return 0; - - edje_object_size_max_get(wd->arrow, &arrow_size, NULL); - half_arrow_size = (arrow_size * 0.5); - - evas_object_geometry_get(wd->parent, NULL, &parent_y, NULL, &parent_h); - - arrow_y = wd->y; - - if (arrow_y - half_arrow_size < parent_y) - arrow_y = (parent_y + half_arrow_size); - else if (wd->y + half_arrow_size > WORLD_PARENT_H) - arrow_y = (WORLD_PARENT_H - half_arrow_size); - - return arrow_y; -} static void _update_arrow_obj(Evas_Object *obj, Arrow_Direction arrow_dir) { - Evas_Coord arrow_x, arrow_y; - - Widget_Data *wd = elm_widget_data_get(obj); + Evas_Coord x, y; + Evas_Coord arrow_x, arrow_y, arrow_w, arrow_h; + Widget_Data *wd = elm_widget_data_get(obj); if (!wd) return; - arrow_x = wd->x; - arrow_y = wd->y; + evas_object_geometry_get(obj, &x, &y, NULL, NULL); + + edje_object_size_min_calc(wd->arrow, &arrow_w, &arrow_h); + evas_object_resize( wd->arrow, arrow_w, arrow_h ); switch (arrow_dir) { case LEFT_ARROW: { - if (wd->last_arrow_dir != LEFT_ARROW) - { - _arrow_obj_add(obj, "left_arrow"); - _elm_theme_object_set(obj, wd->arrow, "ctxpopup", "left_arrow", - elm_widget_style_get(obj)); - wd->last_arrow_dir = LEFT_ARROW; - } - arrow_y = _adjust_arrow_pos_y(wd); - arrow_x += elm_finger_size_get(); + edje_object_signal_emit(wd->arrow, "elm,state,left", "elm"); + arrow_y = (y - (arrow_h*0.5)); + arrow_x = (x + elm_finger_size_get()); break; } case RIGHT_ARROW: { - if (wd->last_arrow_dir != RIGHT_ARROW) - { - _arrow_obj_add(obj, "right_arrow"); - _elm_theme_object_set(obj, wd->arrow, "ctxpopup", "right_arrow", - elm_widget_style_get(obj)); - wd->last_arrow_dir = RIGHT_ARROW; - } - arrow_y = _adjust_arrow_pos_y(wd); - arrow_y = _adjust_arrow_pos_y(wd); - arrow_x -= elm_finger_size_get(); + edje_object_signal_emit(wd->arrow, "elm,state,right", "elm"); + arrow_y = (y - (arrow_h*0.5)); + arrow_x = (x - elm_finger_size_get() - arrow_w); break; } case TOP_ARROW: { - if (wd->last_arrow_dir != TOP_ARROW) - { - _arrow_obj_add(obj, "top_arrow"); - _elm_theme_object_set(obj, wd->arrow, "ctxpopup", "top_arrow", - elm_widget_style_get(obj)); - wd->last_arrow_dir = TOP_ARROW; - } - arrow_x = _adjust_arrow_pos_x(wd); - arrow_y += elm_finger_size_get(); + edje_object_signal_emit(wd->arrow, "elm,state,top", "elm"); + arrow_x = (x - (arrow_w*0.5)); + arrow_y = (y + elm_finger_size_get()); break; } case BOTTOM_ARROW: { - if (wd->last_arrow_dir != BOTTOM_ARROW) - { - _arrow_obj_add(obj, "bottom_arrow"); - _elm_theme_object_set(obj, wd->arrow, "ctxpopup", - "bottom_arrow", - elm_widget_style_get(obj)); - wd->last_arrow_dir = BOTTOM_ARROW; - } - arrow_x = _adjust_arrow_pos_x(wd); - arrow_y -= elm_finger_size_get(); + edje_object_signal_emit(wd->arrow, "elm,state,bottom", "elm"); + arrow_x = (x - (arrow_w*0.5)); + arrow_y = (y - elm_finger_size_get() - arrow_h); break; } default: break; } - - evas_object_move(wd->arrow, arrow_x, arrow_y); + + evas_object_move(wd->arrow, arrow_x, arrow_y); } static void @@ -416,7 +350,7 @@ _sizing_eval(Evas_Object *obj) Widget_Data *wd; Eina_List *elist; Elm_Ctxpopup_Item *item; - Evas_Coord_Rectangle rect; + Evas_Coord_Rectangle rect = {0,0,1,1}; wd = (Widget_Data *) elm_widget_data_get(obj); if ((!wd) || (!wd->parent)) @@ -427,11 +361,14 @@ _sizing_eval(Evas_Object *obj) _item_sizing_eval(item); } - Arrow_Direction arrow_dir = _calc_best_geometry(wd, &rect); - _update_arrow_obj(obj, arrow_dir); - _shift_geometry_by_arrow(wd->arrow, arrow_dir, &rect); + Arrow_Direction arrow_dir = _calc_base_geometry(obj, &rect); + fprintf( stderr, "%d %d %d %d %d\n", arrow_dir, rect.x, rect.y, rect.w, rect.h ); - fprintf( stderr, "%d %d %d %d\n", rect.x, rect.y, rect.w, rect.h ); + if(!wd->arrow_disabled) + { + _update_arrow_obj(obj, arrow_dir); + _shift_base_by_arrow(wd->arrow, arrow_dir, &rect); + } evas_object_move(wd->scroller, rect.x, rect.y); evas_object_resize(wd->scroller, rect.w, rect.h); @@ -440,29 +377,28 @@ _sizing_eval(Evas_Object *obj) } static void -_shift_geometry_by_arrow(Evas_Object * arrow, Arrow_Direction arrow_dir, - Evas_Coord_Rectangle * rect) +_shift_base_by_arrow(Evas_Object *arrow, Arrow_Direction arrow_dir, + Evas_Coord_Rectangle *rect) { - Evas_Coord arrow_size_w, arrow_size_h; - - edje_object_size_min_calc(arrow, &arrow_size_w, &arrow_size_h); + Evas_Coord arrow_w, arrow_h; + edje_object_size_min_calc(arrow, &arrow_w, &arrow_h); + fprintf( stderr, "arrow size - %d %d\n", arrow_w, arrow_h ); switch (arrow_dir) { case LEFT_ARROW: - rect->x += arrow_size_w; + rect->x += arrow_w; break; case RIGHT_ARROW: - rect->x -= arrow_size_w; + rect->x -= arrow_w; break; case TOP_ARROW: - rect->y += arrow_size_h; + rect->y += arrow_h; break; case BOTTOM_ARROW: - rect->y -= arrow_size_h; + rect->y -= arrow_h; break; case NONE_ARROW: - fprintf(stderr, "NONE ARROW?\n"); break; } } @@ -475,6 +411,7 @@ _del_pre_hook(Evas_Object *obj) if (!wd) return; evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_RESIZE, _parent_resize, obj); + evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_MOVE, _parent_move, obj); } static void @@ -484,6 +421,7 @@ _del_hook(Evas_Object *obj) if (!wd) return; elm_ctxpopup_clear(obj); + free(wd); } @@ -559,17 +497,35 @@ _theme_hook(Evas_Object *obj) static void -_hover_clicked_cb(void *data, Evas_Object *obj, void *event_info) +_bg_clicked_cb(void *data, Evas_Object *obj, void *event_info) { evas_object_hide(data); - evas_object_smart_callback_call(data, "ctxpopup,hide", NULL); } +static void +_parent_move(void *data, Evas *e, Evas_Object *obj, void *event_info) +{ + Widget_Data *wd = (Widget_Data *) data; + if (!wd) return; + + Evas_Coord x, y; + evas_object_geometry_get(obj, &x, &y, NULL, NULL); + evas_object_move(wd->bg, x, y); + + _sizing_eval(data); +} static void _parent_resize(void *data, Evas *e, Evas_Object *obj, void *event_info) { - _sizing_eval(data); + Widget_Data *wd = (Widget_Data *) data; + if (!wd) return; + + Evas_Coord w, h; + evas_object_geometry_get(obj, NULL, NULL, &w, &h); + evas_object_move(wd->bg, w, h); + + _sizing_eval(data); } static void @@ -579,9 +535,11 @@ _ctxpopup_show(void *data, Evas *e, Evas_Object *obj, void *event_info) if (!wd) return; if (eina_list_count(wd->items) < 1) return; - evas_object_show(wd->arrow); - evas_object_show(wd->base); - fprintf( stderr, "show!\n" ); + + if(!wd->arrow_disabled) evas_object_show(wd->arrow); + evas_object_show(wd->bg); + evas_object_show(wd->base); + } static void @@ -591,7 +549,8 @@ _ctxpopup_hide(void *data, Evas *e, Evas_Object *obj, void *event_info) if (!wd) return; evas_object_hide(wd->arrow); - evas_object_hide(wd->base); + evas_object_hide(wd->bg); + evas_object_hide(wd->base); } static void @@ -604,16 +563,12 @@ _ctxpopup_scroller_resize(void *data, Evas *e, Evas_Object *obj, static void _ctxpopup_move(void *data, Evas *e, Evas_Object *obj, void *event_info) { - Evas_Coord x, y, w, h; - Widget_Data *wd = (Widget_Data *) data; if (!wd) return; - evas_object_geometry_get(obj, &x, &y, &w, &h); - wd->x = x; - wd->y = y; - _sizing_eval(obj); + + _sizing_eval(obj); } static void @@ -740,6 +695,7 @@ 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); @@ -753,35 +709,53 @@ elm_ctxpopup_add(Evas_Object *parent) elm_widget_theme_hook_set(obj, _theme_hook); wd->parent = parent; - wd->last_arrow_dir = NONE_ARROW; - + wd->scroller_disabled = EINA_FALSE; + wd->arrow_disabled = EINA_FALSE; + + //Background + wd->bg = edje_object_add(e); + elm_widget_sub_object_add(obj, wd->bg); + _elm_theme_object_set(obj, wd->bg, "ctxpopup", "bg", + elm_widget_style_get(obj)); + 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_theme_object_set(obj, wd->base, "ctxpopup", "base", + elm_widget_sub_object_add(obj, wd->base); + _elm_theme_object_set(obj, wd->base, "ctxpopup", "base", elm_widget_style_get(obj)); //Scroller wd->scroller = elm_scroller_add(obj); - wd->scroller_disabled = EINA_FALSE; - elm_object_style_set(wd->scroller, "ctxpopup_vbar"); + elm_object_style_set(wd->scroller, "ctxpopup_vbar"); elm_scroller_content_min_limit(wd->scroller, EINA_TRUE, EINA_TRUE); elm_scroller_policy_set(wd->scroller, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_ON); elm_scroller_bounce_set(wd->scroller, EINA_FALSE, EINA_TRUE); - edje_object_part_swallow(wd->base, "elm.swallow.content", wd->scroller); + evas_object_event_callback_add(wd->scroller, EVAS_CALLBACK_RESIZE, + _ctxpopup_scroller_resize, obj); //Box wd->box = elm_box_add(obj); elm_scroller_content_set(wd->scroller, wd->box); + //Arrow + wd->arrow = edje_object_add(e); + elm_widget_sub_object_add(obj, wd->arrow); + _elm_theme_object_set(obj, wd->arrow, "ctxpopup", "arrow", + elm_widget_style_get(obj)); + + evas_object_event_callback_add(parent, EVAS_CALLBACK_MOVE, _parent_move, obj); evas_object_event_callback_add(parent, EVAS_CALLBACK_RESIZE, _parent_resize, obj); evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _ctxpopup_show, wd); evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _ctxpopup_hide, wd); evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _ctxpopup_move, wd); - evas_object_event_callback_add(wd->scroller, EVAS_CALLBACK_RESIZE, - _ctxpopup_scroller_resize, obj); _sizing_eval(obj); return obj; @@ -1092,3 +1066,27 @@ elm_ctxpopup_item_disabled_set(Elm_Ctxpopup_Item *item, Eina_Bool disabled) edje_object_message_signal_process(item->obj); item->disabled = disabled; } + +/** + * Disable or Enable arrow. + * @param obj Ctxpopup object + * @param disabled EINA_TRUE - disable, EINA_FALSE - enable + * + * @ingroup Ctxpopup + */ +EAPI void +elm_ctxpopup_arrow_disabled_set(Evas_Object* obj, Eina_Bool disabled) +{ + ELM_CHECK_WIDTYPE(obj, widtype) NULL; + + Widget_Data *wd = (Widget_Data *) elm_widget_data_get(obj); + if(!wd) return; + + if(wd->arrow_disabled == disabled) return; + + wd->arrow_disabled = disabled; + + if(disabled) evas_object_hide(wd->arrow); + else evas_object_show(wd->arrow); + +} -- 2.7.4