From bedb6df9739b5d74cbbeef652fcf2ba4ac3b7709 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Wed, 21 Aug 2019 10:41:57 -0400 Subject: [PATCH] efl_ui/popup: remove anchor_popup class Summary: all functionality is now merged into the base popup class. this greatly simplifies the codebase and deduplicates a lot of code ref T7902 Depends on D9651 Reviewers: cedric Reviewed By: cedric Subscribers: herb, cedric, #reviewers, #committers Tags: #efl_widgets Maniphest Tasks: T7902 Differential Revision: https://phab.enlightenment.org/D9652 --- data/elementary/themes/edc/efl/popup.edc | 5 - src/bin/elementary/test_ui_popup.c | 10 +- src/lib/elementary/Efl_Ui.h | 1 - src/lib/elementary/Elementary.h | 1 - src/lib/elementary/efl_ui_anchor_popup.c | 337 ------------------ src/lib/elementary/efl_ui_anchor_popup.eo | 42 --- .../elementary/efl_ui_anchor_popup_private.h | 17 - src/lib/elementary/efl_ui_popup.c | 317 +++++++++++++++- src/lib/elementary/efl_ui_popup.eo | 30 ++ src/lib/elementary/efl_ui_popup_private.h | 3 + src/lib/elementary/meson.build | 3 - src/tests/elementary/efl_ui_test_popup.c | 10 +- 12 files changed, 341 insertions(+), 435 deletions(-) delete mode 100644 src/lib/elementary/efl_ui_anchor_popup.c delete mode 100644 src/lib/elementary/efl_ui_anchor_popup.eo delete mode 100644 src/lib/elementary/efl_ui_anchor_popup_private.h diff --git a/data/elementary/themes/edc/efl/popup.edc b/data/elementary/themes/edc/efl/popup.edc index 68714ade58..b81d878ae6 100644 --- a/data/elementary/themes/edc/efl/popup.edc +++ b/data/elementary/themes/edc/efl/popup.edc @@ -121,15 +121,10 @@ group { "efl/alert_popup"; } } -group { "efl/anchor_popup"; - inherit: "efl/popup"; -} - group { "efl/popup/backwall"; alias: "efl/alert_popup/backwall"; alias: "efl/scroll_alert_popup/backwall"; alias: "efl/text_alert_popup/backwall"; - alias: "efl/anchor_popup/backwall"; parts { rect { "base"; desc { "default"; diff --git a/src/bin/elementary/test_ui_popup.c b/src/bin/elementary/test_ui_popup.c index 16b0b9ccb1..208b7bd260 100644 --- a/src/bin/elementary/test_ui_popup.c +++ b/src/bin/elementary/test_ui_popup.c @@ -2,7 +2,7 @@ # include "elementary_config.h" #endif -#define EFL_UI_ANCHOR_POPUP_BETA +#define EFL_UI_POPUP_BETA #define EFL_UI_SCROLL_ALERT_POPUP_BETA #include #include @@ -992,13 +992,13 @@ test_ui_text_alert_popup(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, v static void _anchor_set_cb(void *data, const Efl_Event *ev) { - efl_ui_anchor_popup_anchor_set(data, ev->object); + efl_ui_popup_anchor_set(data, ev->object); } static void _anchor_unset_cb(void *data, const Efl_Event *ev EINA_UNUSED) { - efl_ui_anchor_popup_anchor_set(data, NULL); + efl_ui_popup_anchor_set(data, NULL); } void @@ -1021,12 +1021,12 @@ test_ui_anchor_popup(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void efl_gfx_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); efl_content_set(win, layout); - Eo *efl_ui_popup = efl_add(EFL_UI_ANCHOR_POPUP_CLASS, win); + Eo *efl_ui_popup = efl_add(EFL_UI_POPUP_CLASS, win); efl_ui_popup_part_backwall_repeat_events_set(efl_part(efl_ui_popup, "backwall"), EINA_TRUE); //Default align priority order is top, left, right, bottom, center. - efl_ui_anchor_popup_align_priority_set(efl_ui_popup, EFL_UI_POPUP_ALIGN_TOP, + efl_ui_popup_align_priority_set(efl_ui_popup, EFL_UI_POPUP_ALIGN_TOP, EFL_UI_POPUP_ALIGN_BOTTOM, EFL_UI_POPUP_ALIGN_LEFT, EFL_UI_POPUP_ALIGN_RIGHT, diff --git a/src/lib/elementary/Efl_Ui.h b/src/lib/elementary/Efl_Ui.h index b79ed12ea6..0f377b7aec 100644 --- a/src/lib/elementary/Efl_Ui.h +++ b/src/lib/elementary/Efl_Ui.h @@ -269,7 +269,6 @@ typedef Eo Efl_Ui_Spotlight_Indicator; # include # include # include -# include # include # include # include diff --git a/src/lib/elementary/Elementary.h b/src/lib/elementary/Elementary.h index 929825692d..0a4b321fa4 100644 --- a/src/lib/elementary/Elementary.h +++ b/src/lib/elementary/Elementary.h @@ -313,7 +313,6 @@ typedef Eo Efl_Ui_Focus_Manager; # include # include # include -# include # include # include # include diff --git a/src/lib/elementary/efl_ui_anchor_popup.c b/src/lib/elementary/efl_ui_anchor_popup.c deleted file mode 100644 index 47bf9a5b19..0000000000 --- a/src/lib/elementary/efl_ui_anchor_popup.c +++ /dev/null @@ -1,337 +0,0 @@ -#ifdef HAVE_CONFIG_H -# include "elementary_config.h" -#endif - -#define EFL_UI_POPUP_PROTECTED - -#include - -#include "elm_priv.h" -#include "efl_ui_popup_private.h" -#include "efl_ui_anchor_popup_private.h" - -#define MY_CLASS EFL_UI_ANCHOR_POPUP_CLASS -#define MY_CLASS_NAME "Efl.Ui.Anchor_Popup" - -static void -_anchor_calc(Eo *obj) -{ - ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); - EFL_UI_POPUP_DATA_GET_OR_RETURN(obj, ppd); - EFL_UI_ANCHOR_POPUP_DATA_GET(obj, pd); - - if (!pd->anchor) return; - - Eina_Position2D pos = {0, 0}; - - Eina_Rect a_geom = efl_gfx_entity_geometry_get(pd->anchor); - Eina_Rect o_geom = efl_gfx_entity_geometry_get(obj); - Eina_Rect p_geom = efl_gfx_entity_geometry_get(ppd->win_parent); - - pd->used_align = EFL_UI_POPUP_ALIGN_NONE; - - /* 1. Find align which display popup. - It enables to shifting popup from exact position. - LEFT, RIGHT - shift only y position within anchor object's height - TOP, BOTTOM - shift only x position within anchor object's width - CENTER - shift both x, y position within anchor object's area - */ - - for (int idx = 0; idx < 6; idx++) - { - Efl_Ui_Popup_Align cur_align; - - if (idx == 0) - cur_align = ppd->align; - else - cur_align = pd->priority[idx - 1]; - - if (cur_align == EFL_UI_POPUP_ALIGN_NONE) - continue; - - switch(cur_align) - { - case EFL_UI_POPUP_ALIGN_TOP: - pos.x = a_geom.x + ((a_geom.w - o_geom.w) / 2); - pos.y = (a_geom.y - o_geom.h); - - if ((pos.y < 0) || - ((pos.y + o_geom.h) > p_geom.h) || - (o_geom.w > p_geom.w)) - continue; - break; - - case EFL_UI_POPUP_ALIGN_LEFT: - pos.x = (a_geom.x - o_geom.w); - pos.y = a_geom.y + ((a_geom.h - o_geom.h) / 2); - - if ((pos.x < 0) || - ((pos.x + o_geom.w) > p_geom.w) || - (o_geom.h > p_geom.h)) - continue; - break; - - case EFL_UI_POPUP_ALIGN_RIGHT: - pos.x = (a_geom.x + a_geom.w); - pos.y = a_geom.y + ((a_geom.h - o_geom.h) / 2); - - if ((pos.x < 0) || - ((pos.x + o_geom.w) > p_geom.w) || - (o_geom.h > p_geom.h)) - continue; - break; - - case EFL_UI_POPUP_ALIGN_BOTTOM: - pos.x = a_geom.x + ((a_geom.w - o_geom.w) / 2); - pos.y = (a_geom.y + a_geom.h); - - if ((pos.y < 0) || - ((pos.y + o_geom.h) > p_geom.h) || - (o_geom.w > p_geom.w)) - continue; - break; - - case EFL_UI_POPUP_ALIGN_CENTER: - pos.x = a_geom.x + ((a_geom.w - o_geom.w) / 2); - pos.y = a_geom.y + ((a_geom.h - o_geom.h) / 2); - - if ((o_geom.w > p_geom.w) || (o_geom.h > p_geom.h)) - continue; - break; - - default: - continue; - } - - if ((cur_align == EFL_UI_POPUP_ALIGN_TOP) || - (cur_align == EFL_UI_POPUP_ALIGN_BOTTOM) || - (cur_align == EFL_UI_POPUP_ALIGN_CENTER)) - { - if (pos.x < 0) - pos.x = 0; - if ((pos.x + o_geom.w) > p_geom.w) - pos.x = p_geom.w - o_geom.w; - - if ((pos.x > (a_geom.x + a_geom.w)) || - ((pos.x + o_geom.w) < a_geom.x)) - continue; - } - - if ((cur_align == EFL_UI_POPUP_ALIGN_LEFT) || - (cur_align == EFL_UI_POPUP_ALIGN_RIGHT) || - (cur_align == EFL_UI_POPUP_ALIGN_CENTER)) - { - if (pos.y < 0) - pos.y = 0; - if ((pos.y + o_geom.h) > p_geom.h) - pos.y = p_geom.h - o_geom.h; - - if ((pos.y > (a_geom.y + a_geom.h)) || - ((pos.y + o_geom.h) < a_geom.y)) - continue; - } - - pd->used_align = cur_align; - goto end; - } - - /* 2. Move popup to fit first valid align although entire popup can't display */ - - for (int idx = 0; idx < 6; idx++) - { - Efl_Ui_Popup_Align cur_align; - - if (idx == 0) - cur_align = ppd->align; - else - cur_align = pd->priority[idx - 1]; - - if (cur_align == EFL_UI_POPUP_ALIGN_NONE) - continue; - - switch(cur_align) - { - case EFL_UI_POPUP_ALIGN_TOP: - pos.x = a_geom.x + ((a_geom.w - o_geom.w) / 2); - pos.y = (a_geom.y - o_geom.h); - pd->used_align = cur_align; - goto end; - break; - - case EFL_UI_POPUP_ALIGN_LEFT: - pos.x = (a_geom.x - o_geom.w); - pos.y = a_geom.y + ((a_geom.h - o_geom.h) / 2); - pd->used_align = cur_align; - goto end; - break; - - case EFL_UI_POPUP_ALIGN_RIGHT: - pos.x = (a_geom.x + a_geom.w); - pos.y = a_geom.y + ((a_geom.h - o_geom.h) / 2); - pd->used_align = cur_align; - goto end; - break; - - case EFL_UI_POPUP_ALIGN_BOTTOM: - pos.x = a_geom.x + ((a_geom.w - o_geom.w) / 2); - pos.y = (a_geom.y + a_geom.h); - pd->used_align = cur_align; - goto end; - break; - - case EFL_UI_POPUP_ALIGN_CENTER: - pos.x = a_geom.x + ((a_geom.w - o_geom.w) / 2); - pos.y = a_geom.y + ((a_geom.h - o_geom.h) / 2); - pd->used_align = cur_align; - goto end; - break; - - default: - break; - } - } - -end: - if (pd->used_align != EFL_UI_POPUP_ALIGN_NONE) - efl_gfx_entity_position_set(efl_super(obj, EFL_UI_POPUP_CLASS), pos); -} - -static void -_anchor_geom_cb(void *data, const Efl_Event *ev EINA_UNUSED) -{ - _anchor_calc(data); -} - -static void -_anchor_del_cb(void *data, const Efl_Event *ev EINA_UNUSED) -{ - EFL_UI_POPUP_DATA_GET_OR_RETURN(data, ppd); - EFL_UI_ANCHOR_POPUP_DATA_GET(data, pd); - - efl_event_callback_del(ppd->win_parent, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _anchor_geom_cb, data); - - pd->anchor = NULL; - _anchor_calc(data); -} - -static void -_anchor_detach(Eo *obj) -{ - EFL_UI_POPUP_DATA_GET_OR_RETURN(obj, ppd); - EFL_UI_ANCHOR_POPUP_DATA_GET(obj, pd); - - if (!pd->anchor) return; - - efl_event_callback_del(ppd->win_parent, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _anchor_geom_cb, obj); - efl_event_callback_del(pd->anchor, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _anchor_geom_cb, obj); - efl_event_callback_del(pd->anchor, EFL_GFX_ENTITY_EVENT_POSITION_CHANGED, _anchor_geom_cb, obj); - efl_event_callback_del(pd->anchor, EFL_EVENT_DEL, _anchor_del_cb, obj); -} - -EOLIAN static void -_efl_ui_anchor_popup_anchor_set(Eo *obj, Efl_Ui_Anchor_Popup_Data *pd, Eo *anchor) -{ - EFL_UI_POPUP_DATA_GET_OR_RETURN(obj, ppd); - - _anchor_detach(obj); - pd->anchor = anchor; - - if (anchor) - { - efl_event_callback_add(ppd->win_parent, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _anchor_geom_cb, obj); - efl_event_callback_add(anchor, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _anchor_geom_cb, obj); - efl_event_callback_add(anchor, EFL_GFX_ENTITY_EVENT_POSITION_CHANGED, _anchor_geom_cb, obj); - efl_event_callback_add(anchor, EFL_EVENT_DEL, _anchor_del_cb, obj); - } - - _anchor_calc(obj); -} - -EOLIAN static Efl_Object * -_efl_ui_anchor_popup_anchor_get(const Eo *obj EINA_UNUSED, Efl_Ui_Anchor_Popup_Data *pd) -{ - return pd->anchor; -} - -EOLIAN static void -_efl_ui_anchor_popup_align_priority_set(Eo *obj EINA_UNUSED, - Efl_Ui_Anchor_Popup_Data *pd, - Efl_Ui_Popup_Align first, - Efl_Ui_Popup_Align second, - Efl_Ui_Popup_Align third, - Efl_Ui_Popup_Align fourth, - Efl_Ui_Popup_Align fifth) -{ - pd->priority[0] = first; - pd->priority[1] = second; - pd->priority[2] = third; - pd->priority[3] = fourth; - pd->priority[4] = fifth; -} - -EOLIAN static void -_efl_ui_anchor_popup_align_priority_get(const Eo *obj EINA_UNUSED, - Efl_Ui_Anchor_Popup_Data *pd, - Efl_Ui_Popup_Align *first, - Efl_Ui_Popup_Align *second, - Efl_Ui_Popup_Align *third, - Efl_Ui_Popup_Align *fourth, - Efl_Ui_Popup_Align *fifth) -{ - if (first) *first = pd->priority[0]; - if (second) *second = pd->priority[1]; - if (third) *third = pd->priority[2]; - if (fourth) *fourth = pd->priority[3]; - if (fifth) *fifth = pd->priority[4]; -} - -EOLIAN static void -_efl_ui_anchor_popup_efl_gfx_entity_position_set(Eo *obj, Efl_Ui_Anchor_Popup_Data *pd, Eina_Position2D pos) -{ - _anchor_detach(obj); - - pd->anchor = NULL; - - efl_gfx_entity_position_set(efl_super(obj, MY_CLASS), pos); -} - -EOLIAN static void -_efl_ui_anchor_popup_efl_canvas_group_group_calculate(Eo *obj, Efl_Ui_Anchor_Popup_Data *pd EINA_UNUSED) -{ - efl_canvas_group_need_recalculate_set(obj, EINA_FALSE); - - efl_canvas_group_calculate(efl_super(obj, MY_CLASS)); - - _anchor_calc(obj); -} - -EOLIAN static Eo * -_efl_ui_anchor_popup_efl_object_constructor(Eo *obj, - Efl_Ui_Anchor_Popup_Data *pd) -{ - ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL); - - if (!elm_widget_theme_klass_get(obj)) - elm_widget_theme_klass_set(obj, "anchor_popup"); - obj = efl_constructor(efl_super(obj, MY_CLASS)); - efl_canvas_object_type_set(obj, MY_CLASS_NAME); - - pd->priority[0] = EFL_UI_POPUP_ALIGN_TOP; - pd->priority[1] = EFL_UI_POPUP_ALIGN_LEFT; - pd->priority[2] = EFL_UI_POPUP_ALIGN_RIGHT; - pd->priority[3] = EFL_UI_POPUP_ALIGN_BOTTOM; - pd->priority[4] = EFL_UI_POPUP_ALIGN_CENTER; - - return obj; -} - -EOLIAN static void -_efl_ui_anchor_popup_efl_object_destructor(Eo *obj, - Efl_Ui_Anchor_Popup_Data *pd EINA_UNUSED) -{ - _anchor_detach(obj); - - efl_destructor(efl_super(obj, MY_CLASS)); -} - -#include "efl_ui_anchor_popup.eo.c" diff --git a/src/lib/elementary/efl_ui_anchor_popup.eo b/src/lib/elementary/efl_ui_anchor_popup.eo deleted file mode 100644 index 85b81c80e3..0000000000 --- a/src/lib/elementary/efl_ui_anchor_popup.eo +++ /dev/null @@ -1,42 +0,0 @@ -class @beta Efl.Ui.Anchor_Popup extends Efl.Ui.Popup -{ - [[EFL UI Anchor Popup class]] - methods { - @property anchor { - set { - [[Set anchor popup to follow an anchor object. - If anchor object is moved or parent window is resized, the anchor popup moves to the new position. - If anchor object is set to NULL, the anchor popup stops following the anchor object. - When the popup is moved by using gfx_position_set, anchor is set NULL. - ]] - } - get { - [[Returns the anchor object which the popup is following.]] - } - values { - anchor: Efl.Canvas.Object; [[The object which popup is following.]] - } - } - @property align_priority @beta { - set { - [[Set the align priority of a popup.]] - } - get { - [[Get the align priority of a popup.]] - } - values { - first: Efl.Ui.Popup_Align; [[First align priority]] - second: Efl.Ui.Popup_Align; [[Second align priority]] - third: Efl.Ui.Popup_Align; [[Third align priority]] - fourth: Efl.Ui.Popup_Align; [[Fourth align priority]] - fifth: Efl.Ui.Popup_Align; [[Fifth align priority]] - } - } - } - implements { - Efl.Object.constructor; - Efl.Object.destructor; - Efl.Canvas.Group.group_calculate; - Efl.Gfx.Entity.position { set; } - } -} diff --git a/src/lib/elementary/efl_ui_anchor_popup_private.h b/src/lib/elementary/efl_ui_anchor_popup_private.h deleted file mode 100644 index db383d3fd9..0000000000 --- a/src/lib/elementary/efl_ui_anchor_popup_private.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef EFL_UI_ANCHOR_POPUP_H -#define EFL_UI_ANCHOR_POPUP_H - -#include "Elementary.h" - -typedef struct _Efl_Ui_Anchor_Popup_Data Efl_Ui_Anchor_Popup_Data; -struct _Efl_Ui_Anchor_Popup_Data -{ - Eo *anchor; - Efl_Ui_Popup_Align priority[5]; - Efl_Ui_Popup_Align used_align; -}; - -#define EFL_UI_ANCHOR_POPUP_DATA_GET(o, sd) \ - Efl_Ui_Anchor_Popup_Data * sd = efl_data_scope_get(o, EFL_UI_ANCHOR_POPUP_CLASS) - -#endif diff --git a/src/lib/elementary/efl_ui_popup.c b/src/lib/elementary/efl_ui_popup.c index 643b578a3e..c29b3f2fc8 100644 --- a/src/lib/elementary/efl_ui_popup.c +++ b/src/lib/elementary/efl_ui_popup.c @@ -18,23 +18,6 @@ static const char PART_NAME_BACKWALL[] = "backwall"; -static void -_backwall_clicked_cb(void *data, - Eo *o EINA_UNUSED, - const char *emission EINA_UNUSED, - const char *source EINA_UNUSED) -{ - Eo *obj = data; - efl_event_callback_call(obj, EFL_UI_POPUP_EVENT_BACKWALL_CLICKED, NULL); -} - -EOLIAN static void -_efl_ui_popup_efl_gfx_entity_position_set(Eo *obj, Efl_Ui_Popup_Data *pd EINA_UNUSED, Eina_Position2D pos) -{ - pd->align = EFL_UI_POPUP_ALIGN_NONE; - efl_gfx_entity_position_set(efl_super(obj, MY_CLASS), pos); -} - static void _calc_align(Eo *obj) { @@ -74,6 +57,293 @@ _calc_align(Eo *obj) } } +static void +_anchor_calc(Eo *obj) +{ + ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); + EFL_UI_POPUP_DATA_GET_OR_RETURN(obj, pd); + + if (!pd->anchor) return; + + Eina_Position2D pos = {0, 0}; + + Eina_Rect a_geom = efl_gfx_entity_geometry_get(pd->anchor); + Eina_Rect o_geom = efl_gfx_entity_geometry_get(obj); + Eina_Rect p_geom = efl_gfx_entity_geometry_get(pd->win_parent); + + pd->used_align = EFL_UI_POPUP_ALIGN_NONE; + + /* 1. Find align which display popup. + It enables to shifting popup from exact position. + LEFT, RIGHT - shift only y position within anchor object's height + TOP, BOTTOM - shift only x position within anchor object's width + CENTER - shift both x, y position within anchor object's area + */ + + for (int idx = 0; idx < 6; idx++) + { + Efl_Ui_Popup_Align cur_align; + + if (idx == 0) + cur_align = pd->align; + else + cur_align = pd->priority[idx - 1]; + + if (cur_align == EFL_UI_POPUP_ALIGN_NONE) + continue; + + switch(cur_align) + { + case EFL_UI_POPUP_ALIGN_TOP: + pos.x = a_geom.x + ((a_geom.w - o_geom.w) / 2); + pos.y = (a_geom.y - o_geom.h); + + if ((pos.y < 0) || + ((pos.y + o_geom.h) > p_geom.h) || + (o_geom.w > p_geom.w)) + continue; + break; + + case EFL_UI_POPUP_ALIGN_LEFT: + pos.x = (a_geom.x - o_geom.w); + pos.y = a_geom.y + ((a_geom.h - o_geom.h) / 2); + + if ((pos.x < 0) || + ((pos.x + o_geom.w) > p_geom.w) || + (o_geom.h > p_geom.h)) + continue; + break; + + case EFL_UI_POPUP_ALIGN_RIGHT: + pos.x = (a_geom.x + a_geom.w); + pos.y = a_geom.y + ((a_geom.h - o_geom.h) / 2); + + if ((pos.x < 0) || + ((pos.x + o_geom.w) > p_geom.w) || + (o_geom.h > p_geom.h)) + continue; + break; + + case EFL_UI_POPUP_ALIGN_BOTTOM: + pos.x = a_geom.x + ((a_geom.w - o_geom.w) / 2); + pos.y = (a_geom.y + a_geom.h); + + if ((pos.y < 0) || + ((pos.y + o_geom.h) > p_geom.h) || + (o_geom.w > p_geom.w)) + continue; + break; + + case EFL_UI_POPUP_ALIGN_CENTER: + pos.x = a_geom.x + ((a_geom.w - o_geom.w) / 2); + pos.y = a_geom.y + ((a_geom.h - o_geom.h) / 2); + + if ((o_geom.w > p_geom.w) || (o_geom.h > p_geom.h)) + continue; + break; + + default: + continue; + } + + if ((cur_align == EFL_UI_POPUP_ALIGN_TOP) || + (cur_align == EFL_UI_POPUP_ALIGN_BOTTOM) || + (cur_align == EFL_UI_POPUP_ALIGN_CENTER)) + { + if (pos.x < 0) + pos.x = 0; + if ((pos.x + o_geom.w) > p_geom.w) + pos.x = p_geom.w - o_geom.w; + + if ((pos.x > (a_geom.x + a_geom.w)) || + ((pos.x + o_geom.w) < a_geom.x)) + continue; + } + + if ((cur_align == EFL_UI_POPUP_ALIGN_LEFT) || + (cur_align == EFL_UI_POPUP_ALIGN_RIGHT) || + (cur_align == EFL_UI_POPUP_ALIGN_CENTER)) + { + if (pos.y < 0) + pos.y = 0; + if ((pos.y + o_geom.h) > p_geom.h) + pos.y = p_geom.h - o_geom.h; + + if ((pos.y > (a_geom.y + a_geom.h)) || + ((pos.y + o_geom.h) < a_geom.y)) + continue; + } + + pd->used_align = cur_align; + goto end; + } + + /* 2. Move popup to fit first valid align although entire popup can't display */ + + for (int idx = 0; idx < 6; idx++) + { + Efl_Ui_Popup_Align cur_align; + + if (idx == 0) + cur_align = pd->align; + else + cur_align = pd->priority[idx - 1]; + + if (cur_align == EFL_UI_POPUP_ALIGN_NONE) + continue; + + switch(cur_align) + { + case EFL_UI_POPUP_ALIGN_TOP: + pos.x = a_geom.x + ((a_geom.w - o_geom.w) / 2); + pos.y = (a_geom.y - o_geom.h); + pd->used_align = cur_align; + goto end; + break; + + case EFL_UI_POPUP_ALIGN_LEFT: + pos.x = (a_geom.x - o_geom.w); + pos.y = a_geom.y + ((a_geom.h - o_geom.h) / 2); + pd->used_align = cur_align; + goto end; + break; + + case EFL_UI_POPUP_ALIGN_RIGHT: + pos.x = (a_geom.x + a_geom.w); + pos.y = a_geom.y + ((a_geom.h - o_geom.h) / 2); + pd->used_align = cur_align; + goto end; + break; + + case EFL_UI_POPUP_ALIGN_BOTTOM: + pos.x = a_geom.x + ((a_geom.w - o_geom.w) / 2); + pos.y = (a_geom.y + a_geom.h); + pd->used_align = cur_align; + goto end; + break; + + case EFL_UI_POPUP_ALIGN_CENTER: + pos.x = a_geom.x + ((a_geom.w - o_geom.w) / 2); + pos.y = a_geom.y + ((a_geom.h - o_geom.h) / 2); + pd->used_align = cur_align; + goto end; + break; + + default: + break; + } + } + +end: + if (pd->used_align != EFL_UI_POPUP_ALIGN_NONE) + efl_gfx_entity_position_set(efl_super(obj, MY_CLASS), pos); +} + +static void +_anchor_geom_cb(void *data, const Efl_Event *ev EINA_UNUSED) +{ + _anchor_calc(data); +} + +static void +_anchor_del_cb(void *data, const Efl_Event *ev EINA_UNUSED) +{ + EFL_UI_POPUP_DATA_GET_OR_RETURN(data, pd); + + efl_event_callback_del(pd->win_parent, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _anchor_geom_cb, data); + + pd->anchor = NULL; + _anchor_calc(data); +} + +static void +_anchor_detach(Eo *obj, Efl_Ui_Popup_Data *pd) +{ + if (!pd->anchor) return; + + efl_event_callback_del(pd->win_parent, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _anchor_geom_cb, obj); + efl_event_callback_del(pd->anchor, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _anchor_geom_cb, obj); + efl_event_callback_del(pd->anchor, EFL_GFX_ENTITY_EVENT_POSITION_CHANGED, _anchor_geom_cb, obj); + efl_event_callback_del(pd->anchor, EFL_EVENT_DEL, _anchor_del_cb, obj); +} + +EOLIAN static void +_efl_ui_popup_anchor_set(Eo *obj, Efl_Ui_Popup_Data *pd, Eo *anchor) +{ + _anchor_detach(obj, pd); + pd->anchor = anchor; + + if (anchor) + { + efl_event_callback_add(pd->win_parent, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _anchor_geom_cb, obj); + efl_event_callback_add(anchor, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _anchor_geom_cb, obj); + efl_event_callback_add(anchor, EFL_GFX_ENTITY_EVENT_POSITION_CHANGED, _anchor_geom_cb, obj); + efl_event_callback_add(anchor, EFL_EVENT_DEL, _anchor_del_cb, obj); + _anchor_calc(obj); + } + else + _calc_align(obj); +} + +EOLIAN static Efl_Object * +_efl_ui_popup_anchor_get(const Eo *obj EINA_UNUSED, Efl_Ui_Popup_Data *pd) +{ + return pd->anchor; +} + +EOLIAN static void +_efl_ui_popup_align_priority_set(Eo *obj EINA_UNUSED, + Efl_Ui_Popup_Data *pd, + Efl_Ui_Popup_Align first, + Efl_Ui_Popup_Align second, + Efl_Ui_Popup_Align third, + Efl_Ui_Popup_Align fourth, + Efl_Ui_Popup_Align fifth) +{ + pd->priority[0] = first; + pd->priority[1] = second; + pd->priority[2] = third; + pd->priority[3] = fourth; + pd->priority[4] = fifth; +} + +EOLIAN static void +_efl_ui_popup_align_priority_get(const Eo *obj EINA_UNUSED, + Efl_Ui_Popup_Data *pd, + Efl_Ui_Popup_Align *first, + Efl_Ui_Popup_Align *second, + Efl_Ui_Popup_Align *third, + Efl_Ui_Popup_Align *fourth, + Efl_Ui_Popup_Align *fifth) +{ + if (first) *first = pd->priority[0]; + if (second) *second = pd->priority[1]; + if (third) *third = pd->priority[2]; + if (fourth) *fourth = pd->priority[3]; + if (fifth) *fifth = pd->priority[4]; +} + + +static void +_backwall_clicked_cb(void *data, + Eo *o EINA_UNUSED, + const char *emission EINA_UNUSED, + const char *source EINA_UNUSED) +{ + Eo *obj = data; + efl_event_callback_call(obj, EFL_UI_POPUP_EVENT_BACKWALL_CLICKED, NULL); +} + +EOLIAN static void +_efl_ui_popup_efl_gfx_entity_position_set(Eo *obj, Efl_Ui_Popup_Data *pd, Eina_Position2D pos) +{ + pd->align = EFL_UI_POPUP_ALIGN_NONE; + _anchor_detach(obj, pd); + + pd->anchor = NULL; + efl_gfx_entity_position_set(efl_super(obj, MY_CLASS), pos); +} + EOLIAN static void _efl_ui_popup_efl_gfx_entity_size_set(Eo *obj, Efl_Ui_Popup_Data *pd, Eina_Size2D size) { @@ -103,7 +373,7 @@ _hints_changed_cb(void *data, const Efl_Event *ev EINA_UNUSED) } EOLIAN static void -_efl_ui_popup_efl_ui_widget_widget_parent_set(Eo *obj, Efl_Ui_Popup_Data *pd EINA_UNUSED, Eo *parent) +_efl_ui_popup_efl_ui_widget_widget_parent_set(Eo *obj, Efl_Ui_Popup_Data *pd, Eo *parent) { if (!parent) { @@ -237,6 +507,11 @@ _efl_ui_popup_efl_object_constructor(Eo *obj, Efl_Ui_Popup_Data *pd) pd->align = EFL_UI_POPUP_ALIGN_CENTER; + pd->priority[0] = EFL_UI_POPUP_ALIGN_TOP; + pd->priority[1] = EFL_UI_POPUP_ALIGN_LEFT; + pd->priority[2] = EFL_UI_POPUP_ALIGN_RIGHT; + pd->priority[3] = EFL_UI_POPUP_ALIGN_BOTTOM; + pd->priority[4] = EFL_UI_POPUP_ALIGN_CENTER; return obj; } @@ -244,6 +519,7 @@ EOLIAN static void _efl_ui_popup_efl_object_destructor(Eo *obj, Efl_Ui_Popup_Data *pd) { ELM_SAFE_DEL(pd->backwall); + _anchor_detach(obj, pd); efl_event_callback_del(pd->win_parent, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _parent_geom_cb, obj); @@ -284,7 +560,10 @@ _efl_ui_popup_efl_canvas_group_group_calculate(Eo *obj, Efl_Ui_Popup_Data *pd) _sizing_eval(obj); pd->in_calc = EINA_FALSE; } - _calc_align(obj); + if (pd->anchor) + _anchor_calc(obj); + else + _calc_align(obj); Eina_Rect p_geom = efl_gfx_entity_geometry_get(pd->win_parent); diff --git a/src/lib/elementary/efl_ui_popup.eo b/src/lib/elementary/efl_ui_popup.eo index 37a0104741..15dde23413 100644 --- a/src/lib/elementary/efl_ui_popup.eo +++ b/src/lib/elementary/efl_ui_popup.eo @@ -36,6 +36,36 @@ class @beta Efl.Ui.Popup extends Efl.Ui.Layout_Base implements Efl.Content, Efl. time: double; [[Timeout in seconds]] } } + @property anchor { + set { + [[Set anchor popup to follow an anchor object. + If anchor object is moved or parent window is resized, the anchor popup moves to the new position. + If anchor object is set to NULL, the anchor popup stops following the anchor object. + When the popup is moved by using gfx_position_set, anchor is set NULL. + ]] + } + get { + [[Returns the anchor object which the popup is following.]] + } + values { + anchor: Efl.Canvas.Object; [[The object which popup is following.]] + } + } + @property align_priority { + set { + [[Set the align priority of a popup.]] + } + get { + [[Get the align priority of a popup.]] + } + values { + first: Efl.Ui.Popup_Align; [[First align priority]] + second: Efl.Ui.Popup_Align; [[Second align priority]] + third: Efl.Ui.Popup_Align; [[Third align priority]] + fourth: Efl.Ui.Popup_Align; [[Fourth align priority]] + fifth: Efl.Ui.Popup_Align; [[Fifth align priority]] + } + } } parts { backwall: Efl.Ui.Popup_Part_Backwall; [[A backwall behind the popup.]] diff --git a/src/lib/elementary/efl_ui_popup_private.h b/src/lib/elementary/efl_ui_popup_private.h index 9472d63b87..d29c4b24c1 100644 --- a/src/lib/elementary/efl_ui_popup_private.h +++ b/src/lib/elementary/efl_ui_popup_private.h @@ -7,6 +7,9 @@ struct _Efl_Ui_Popup_Data Eo *win_parent; Eo *backwall; Efl_Ui_Popup_Align align; + Eo *anchor; + Efl_Ui_Popup_Align priority[5]; + Efl_Ui_Popup_Align used_align; Ecore_Timer *timer; double timeout; Eina_Bool in_calc : 1; diff --git a/src/lib/elementary/meson.build b/src/lib/elementary/meson.build index 35fb166827..6e82c93f84 100644 --- a/src/lib/elementary/meson.build +++ b/src/lib/elementary/meson.build @@ -87,7 +87,6 @@ pub_eo_files = [ 'efl_ui_scroll_alert_popup_part.eo', 'efl_ui_text_alert_popup.eo', 'efl_ui_text_alert_popup_part.eo', - 'efl_ui_anchor_popup.eo', 'efl_ui_text_editable.eo', 'efl_ui_text_async.eo', 'efl_ui_text_factory_images.eo', @@ -312,7 +311,6 @@ elementary_headers_unstable = [ 'efl_ui_alert_popup_private.h', 'efl_ui_scroll_alert_popup_private.h', 'efl_ui_text_alert_popup_private.h', - 'efl_ui_anchor_popup_private.h', 'elm_widget_index.h', 'elm_widget_inwin.h', 'elm_widget_label.h', @@ -873,7 +871,6 @@ elementary_src = [ 'efl_ui_alert_popup.c', 'efl_ui_scroll_alert_popup.c', 'efl_ui_text_alert_popup.c', - 'efl_ui_anchor_popup.c', 'efl_ui_table.c', 'efl_ui_table_static.c', 'efl_ui_table_layout.c', diff --git a/src/tests/elementary/efl_ui_test_popup.c b/src/tests/elementary/efl_ui_test_popup.c index 7bd0ad1909..a71e04c3c5 100644 --- a/src/tests/elementary/efl_ui_test_popup.c +++ b/src/tests/elementary/efl_ui_test_popup.c @@ -630,7 +630,7 @@ can_move_y(Align align) static void verify_anchor(Eo *popup, Eo **align_buttons, Align align, Eina_Size2D *popup_sz) { - Eo *anchor = efl_ui_anchor_popup_anchor_get(popup); + Eo *anchor = efl_ui_popup_anchor_get(popup); Eo *win = efl_provider_find(popup, EFL_UI_WIN_CLASS); Eina_Rect anchor_geom; Efl_Ui_Popup_Align cur_prio; @@ -766,10 +766,10 @@ EFL_START_TEST(efl_ui_test_popup_text_anchor) ck_assert(efl_file_simple_load(layout, buf, "efl_ui_popup_anchor_layout")); efl_content_set(win, layout); - popup = efl_add(EFL_UI_ANCHOR_POPUP_CLASS, win); + popup = efl_add(EFL_UI_POPUP_CLASS, win); efl_ui_popup_part_backwall_repeat_events_set(efl_part(popup, "backwall"), EINA_TRUE); //Default align priority order is top, left, right, bottom, center. - efl_ui_anchor_popup_align_priority_set(popup, EFL_UI_POPUP_ALIGN_TOP, + efl_ui_popup_align_priority_set(popup, EFL_UI_POPUP_ALIGN_TOP, EFL_UI_POPUP_ALIGN_BOTTOM, EFL_UI_POPUP_ALIGN_LEFT, EFL_UI_POPUP_ALIGN_RIGHT, @@ -871,9 +871,9 @@ EFL_START_TEST(efl_ui_test_popup_text_anchor) } for (i = -1; i < num_anchors; i++) { - if (i >= 0) efl_ui_anchor_popup_anchor_set(popup, bganchors[i]); + if (i >= 0) efl_ui_popup_anchor_set(popup, bganchors[i]); /* -1 is anchored to win object */ - else efl_ui_anchor_popup_anchor_set(popup, NULL); + else efl_ui_popup_anchor_set(popup, NULL); for (unsigned int j = 0; j < ALIGN_RESIZE; j++) { verify_anchor(popup, aligns, j, &popup_sz);