jaehyun pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=c8c7ac8aae0574ad0c6ad56f284c119dfd2709df

commit c8c7ac8aae0574ad0c6ad56f284c119dfd2709df
Author: JinYong Park <j4939.p...@samsung.com>
Date:   Wed Sep 20 19:36:39 2017 +0900

    efl_ui_popup_anchor: add Efl.Ui.Popup.Anchor class
    
    Summary:
    Add initial code for Efl.Ui.Popup.Anchor class.
    It supports adding anchor object to popup.
    
    Test Plan: 1. run elementary_test -to efluipopupanchor
    
    Reviewers: Jaehyun_Cho, thiepha, herb, jpeg, cedric, woohyun
    
    Reviewed By: Jaehyun_Cho
    
    Differential Revision: https://phab.enlightenment.org/D5126
---
 data/elementary/objects/test.edc                 |  78 +++++
 src/Makefile_Elementary.am                       |   3 +
 src/bin/elementary/test.c                        |   2 +
 src/bin/elementary/test_popup.c                  | 116 ++++++++
 src/lib/elementary/Elementary.h                  |   1 +
 src/lib/elementary/efl_ui_popup_anchor.c         | 357 +++++++++++++++++++++++
 src/lib/elementary/efl_ui_popup_anchor.eo        |  40 +++
 src/lib/elementary/efl_ui_popup_anchor_private.h |  18 ++
 8 files changed, 615 insertions(+)

diff --git a/data/elementary/objects/test.edc b/data/elementary/objects/test.edc
index 834bea4e27..6574ab3adf 100644
--- a/data/elementary/objects/test.edc
+++ b/data/elementary/objects/test.edc
@@ -933,4 +933,82 @@ collections {
          }
       }
    }
+   group { "efl_ui_popup_anchor_layout";
+      parts {
+         spacer { "base";
+            desc { "default";
+            }
+         }
+         swallow { "anchor1";
+            scale;
+            desc { "default";
+               rel.to: "base";
+               rel1.relative: 0.15 0.25;
+               rel2.relative: 0.15 0.25;
+               fixed: 1 1;
+               min: 50 50;
+            }
+         }
+         swallow { "anchor2";
+            scale;
+            desc { "default";
+               rel.to: "base";
+               rel1.relative: 0.75 0.15;
+               rel2.relative: 0.75 0.15;
+               fixed: 1 1;
+               min: 50 50;
+            }
+         }
+         swallow { "anchor3";
+            scale;
+            desc { "default";
+               rel.to: "base";
+               rel1.relative: 0.25 0.85;
+               rel2.relative: 0.25 0.85;
+               fixed: 1 1;
+               min: 50 50;
+            }
+         }
+         swallow { "anchor4";
+            scale;
+            desc { "default";
+               rel.to: "base";
+               rel1.relative: 0.85 0.75;
+               rel2.relative: 0.85 0.75;
+               fixed: 1 1;
+               min: 50 50;
+            }
+         }
+         swallow { "anchor5";
+            scale;
+            desc { "default";
+               rel.to: "base";
+               rel1.relative: 0.45 0.35;
+               rel2.relative: 0.45 0.35;
+               fixed: 1 1;
+               min: 50 50;
+            }
+         }
+         swallow { "anchor6";
+            scale;
+            desc { "default";
+               rel.to: "base";
+               rel2.relative: 0.0 0.0;
+               rel1.offset: 150 300;
+               rel2.offset: 200 350;
+               fixed: 1 1;
+            }
+         }
+         swallow { "anchor_none";
+            scale;
+            desc { "default";
+               rel.to: "base";
+               rel1.relative: 0.60 0.45;
+               rel2.relative: 0.60 0.45;
+               fixed: 1 1;
+               min: 70 50;
+            }
+         }
+      }
+   }
 }
diff --git a/src/Makefile_Elementary.am b/src/Makefile_Elementary.am
index cbee49167e..f62e9f2d9d 100644
--- a/src/Makefile_Elementary.am
+++ b/src/Makefile_Elementary.am
@@ -39,6 +39,7 @@ elm_public_eolian_files = \
        lib/elementary/efl_ui_popup_alert_scroll_part.eo \
        lib/elementary/efl_ui_popup_alert_text.eo \
        lib/elementary/efl_ui_popup_alert_text_part.eo \
+       lib/elementary/efl_ui_popup_anchor.eo \
        lib/elementary/efl_ui_text_editable.eo \
        lib/elementary/efl_ui_text_async.eo \
        lib/elementary/efl_ui_textpath.eo \
@@ -295,6 +296,7 @@ includesunstable_HEADERS = \
        lib/elementary/efl_ui_popup_alert_private.h \
        lib/elementary/efl_ui_popup_alert_scroll_private.h \
        lib/elementary/efl_ui_popup_alert_text_private.h \
+       lib/elementary/efl_ui_popup_anchor_private.h \
        lib/elementary/elm_widget_index.h \
        lib/elementary/elm_widget_inwin.h \
        lib/elementary/elm_widget_label.h \
@@ -708,6 +710,7 @@ lib_elementary_libelementary_la_SOURCES = \
        lib/elementary/efl_ui_popup_alert.c \
        lib/elementary/efl_ui_popup_alert_scroll.c \
        lib/elementary/efl_ui_popup_alert_text.c \
+       lib/elementary/efl_ui_popup_anchor.c \
        lib/elementary/efl_ui_grid.c \
        lib/elementary/efl_ui_grid_static.c \
        lib/elementary/efl_ui_grid_private.h \
diff --git a/src/bin/elementary/test.c b/src/bin/elementary/test.c
index f5666e52ff..ae576feec8 100644
--- a/src/bin/elementary/test.c
+++ b/src/bin/elementary/test.c
@@ -278,6 +278,7 @@ void test_efl_ui_popup(void *data, Evas_Object *obj, void 
*event_info);
 void test_efl_ui_popup_alert(void *data, Evas_Object *obj, void *event_info);
 void test_efl_ui_popup_alert_scroll(void *data, Evas_Object *obj, void 
*event_info);
 void test_efl_ui_popup_alert_text(void *data, Evas_Object *obj, void 
*event_info);
+void test_efl_ui_popup_anchor(void *data, Evas_Object *obj, void *event_info);
 void test_dayselector(void *data, Evas_Object *obj, void *event_info);
 void test_image(void *data, Evas_Object *obj, void *event_info);
 void test_image_scale_type(void *data, Evas_Object *obj, void *event_info);
@@ -1050,6 +1051,7 @@ add_tests:
    ADD_TEST(NULL, "Popups", "Efl UI Popup Alert", test_efl_ui_popup_alert);
    ADD_TEST(NULL, "Popups", "Efl UI Popup Alert Scroll", 
test_efl_ui_popup_alert_scroll);
    ADD_TEST(NULL, "Popups", "Efl UI Popup Alert Text", 
test_efl_ui_popup_alert_text);
+   ADD_TEST(NULL, "Popups", "Efl UI Popup Anchor", test_efl_ui_popup_anchor);
 
    //------------------------------//
    ADD_TEST(NULL, "Times & Dates", "Calendar", test_calendar);
diff --git a/src/bin/elementary/test_popup.c b/src/bin/elementary/test_popup.c
index 2bb6edea45..701cd178b5 100644
--- a/src/bin/elementary/test_popup.c
+++ b/src/bin/elementary/test_popup.c
@@ -1,6 +1,8 @@
 #ifdef HAVE_CONFIG_H
 # include "elementary_config.h"
 #endif
+
+#define EFL_UI_POPUP_ANCHOR_BETA
 #include <Elementary.h>
 
 #define POPUP_POINT_MAX 8
@@ -1205,3 +1207,117 @@ test_efl_ui_popup_alert_text(void *data EINA_UNUSED, 
Evas_Object *obj EINA_UNUSE
 
    efl_event_callback_add(efl_ui_popup, EFL_UI_POPUP_ALERT_EVENT_CLICKED, 
efl_ui_popup_alert_clicked_cb, NULL);
 }
+
+static void
+_anchor_set_cb(void *data, Evas_Object *obj EINA_UNUSED,
+                void *event_info EINA_UNUSED)
+{
+   efl_ui_popup_anchor_set(data, obj);
+}
+
+static void
+_anchor_unset_cb(void *data, Evas_Object *obj EINA_UNUSED,
+                void *event_info EINA_UNUSED)
+{
+   efl_ui_popup_anchor_set(data, NULL);
+}
+
+void
+test_efl_ui_popup_anchor(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, 
void *event_info EINA_UNUSED)
+{
+   Evas_Object *win, *layout, *tbl, *btn;
+   char buf[PATH_MAX];
+
+   win = elm_win_util_standard_add("Efl UI AnchorPopup", "Efl UI AnchorPopup");
+   elm_win_autodel_set(win, EINA_TRUE);
+
+   evas_object_resize(win, 500, 500);
+   evas_object_show(win);
+
+   layout = elm_layout_add(win);
+   snprintf(buf, sizeof(buf), "%s/objects/test.edj", elm_app_data_dir_get());
+   elm_layout_file_set(layout, buf, "efl_ui_popup_anchor_layout");
+   evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, 
EVAS_HINT_EXPAND);
+   elm_win_resize_object_add(win, layout);
+   evas_object_show(layout);
+
+   Evas_Object *efl_ui_popup= efl_add(EFL_UI_POPUP_ANCHOR_CLASS, win);
+
+   efl_ui_popup_bg_repeat_events_set(efl_ui_popup, EINA_TRUE);
+
+   //Default align priority order is top, left, right, bottom, center.
+   efl_ui_popup_anchor_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,
+                                          EFL_UI_POPUP_ALIGN_CENTER);
+
+   evas_object_move(efl_ui_popup, 80, 80);
+   evas_object_resize(efl_ui_popup, 160, 120);
+   evas_object_show(efl_ui_popup);
+
+   for (int i = 0; i < 6; i++)
+     {
+        btn = elm_button_add(win);
+        elm_object_text_set(btn, "anchor");
+        evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND, 
EVAS_HINT_EXPAND);
+        evas_object_smart_callback_add(btn, "clicked", _anchor_set_cb, 
efl_ui_popup);
+
+        snprintf(buf, sizeof(buf), "anchor%d", i+1);
+        elm_object_part_content_set(layout, buf, btn);
+     }
+
+   btn = elm_button_add(win);
+   elm_object_text_set(btn, "anchor none");
+   evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_smart_callback_add(btn, "clicked", _anchor_unset_cb, 
efl_ui_popup);
+   elm_object_part_content_set(layout, "anchor_none", btn);
+
+   tbl = elm_table_add(efl_ui_popup);
+   evas_object_size_hint_weight_set(tbl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(tbl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+   btn = elm_button_add(efl_ui_popup);
+   elm_object_text_set(btn, "Center Align");
+   evas_object_size_hint_min_set(btn, 70, 35);
+   evas_object_smart_callback_add(btn, "clicked", _center_align_cb, 
efl_ui_popup);
+   elm_table_pack(tbl, btn, 0, 0, 1, 1);
+   evas_object_show(btn);
+
+   btn = elm_button_add(efl_ui_popup);
+   elm_object_text_set(btn, "Left Align");
+   evas_object_size_hint_min_set(btn, 70, 35);
+   evas_object_smart_callback_add(btn, "clicked", _left_align_cb, 
efl_ui_popup);
+   elm_table_pack(tbl, btn, 1, 0, 1, 1);
+   evas_object_show(btn);
+
+   btn = elm_button_add(efl_ui_popup);
+   elm_object_text_set(btn, "Right Align");
+   evas_object_size_hint_min_set(btn, 70, 35);
+   evas_object_smart_callback_add(btn, "clicked", _right_align_cb, 
efl_ui_popup);
+   elm_table_pack(tbl, btn, 2, 0, 1, 1);
+   evas_object_show(btn);
+
+   btn = elm_button_add(efl_ui_popup);
+   elm_object_text_set(btn, "Top Align");
+   evas_object_size_hint_min_set(btn, 70, 35);
+   evas_object_smart_callback_add(btn, "clicked", _top_align_cb, efl_ui_popup);
+   elm_table_pack(tbl, btn, 0, 1, 1, 1);
+   evas_object_show(btn);
+
+   btn = elm_button_add(efl_ui_popup);
+   elm_object_text_set(btn, "Bottom Align");
+   evas_object_size_hint_min_set(btn, 70, 35);
+   evas_object_smart_callback_add(btn, "clicked", _bottom_align_cb, 
efl_ui_popup);
+   elm_table_pack(tbl, btn, 1, 1, 1, 1);
+   evas_object_show(btn);
+
+   btn = elm_button_add(efl_ui_popup);
+   elm_object_text_set(btn, "Position Set");
+   evas_object_size_hint_min_set(btn, 70, 35);
+   evas_object_smart_callback_add(btn, "clicked", _position_set_cb, 
efl_ui_popup);
+   elm_table_pack(tbl, btn, 2, 1, 1, 1);
+   evas_object_show(btn);
+
+   efl_content_set(efl_ui_popup, tbl);
+}
diff --git a/src/lib/elementary/Elementary.h b/src/lib/elementary/Elementary.h
index 6ea73c2de1..66b3c8fd14 100644
--- a/src/lib/elementary/Elementary.h
+++ b/src/lib/elementary/Elementary.h
@@ -305,6 +305,7 @@ EAPI extern Elm_Version *elm_version;
 # include <efl_ui_popup_alert.eo.h>
 # include <efl_ui_popup_alert_scroll.eo.h>
 # include <efl_ui_popup_alert_text.eo.h>
+# include <efl_ui_popup_anchor.eo.h>
 # include <efl_ui_text_editable.eo.h>
 # include <efl_ui_text_async.eo.h>
 # include <efl_ui_clock.eo.h>
diff --git a/src/lib/elementary/efl_ui_popup_anchor.c 
b/src/lib/elementary/efl_ui_popup_anchor.c
new file mode 100644
index 0000000000..8ec41bc991
--- /dev/null
+++ b/src/lib/elementary/efl_ui_popup_anchor.c
@@ -0,0 +1,357 @@
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+
+#define EFL_UI_POPUP_PROTECTED
+#define EFL_UI_POPUP_ANCHOR_BETA
+
+#include <Elementary.h>
+
+#include "elm_priv.h"
+#include "efl_ui_popup_anchor_private.h"
+
+#define MY_CLASS EFL_UI_POPUP_ANCHOR_CLASS
+#define MY_CLASS_NAME "Efl.Ui.Popup.Anchor"
+
+static void
+_anchor_calc(Evas_Object *obj)
+{
+   ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
+   EFL_UI_POPUP_ANCHOR_DATA_GET(obj, sd);
+
+   Evas_Coord_Rectangle anchor_geom = {0, 0, 0, 0};
+   Evas_Coord_Size popup_size = {0, 0};
+   Evas_Coord_Size parent_size = {0, 0};
+   Eina_Position2D pos = {0, 0};
+
+   Evas_Object *parent = efl_ui_popup_parent_window_get(obj);
+
+   evas_object_geometry_get(sd->anchor, &anchor_geom.x, &anchor_geom.y, 
&anchor_geom.w, &anchor_geom.h);
+   evas_object_geometry_get(obj, NULL, NULL, &popup_size.w, &popup_size.h);
+   evas_object_geometry_get(parent, NULL, NULL, &parent_size.w, 
&parent_size.h);
+
+   sd->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 = sd->align;
+        else
+          cur_align = sd->priority[idx - 1];
+
+        if (cur_align == EFL_UI_POPUP_ALIGN_NONE)
+          continue;
+
+        switch(cur_align)
+          {
+             case EFL_UI_POPUP_ALIGN_TOP:
+               pos.x = anchor_geom.x + ((anchor_geom.w - popup_size.w) / 2);
+               pos.y = (anchor_geom.y - popup_size.h);
+
+               if ((pos.y < 0) ||
+                   ((pos.y + popup_size.h) > parent_size.h) ||
+                   (popup_size.w > parent_size.w))
+                 continue;
+               break;
+
+             case EFL_UI_POPUP_ALIGN_LEFT:
+               pos.x = (anchor_geom.x - popup_size.w);
+               pos.y = anchor_geom.y + ((anchor_geom.h - popup_size.h) / 2);
+
+               if ((pos.x < 0) ||
+                   ((pos.x + popup_size.w) > parent_size.w) ||
+                   (popup_size.h > parent_size.h))
+                 continue;
+               break;
+
+             case EFL_UI_POPUP_ALIGN_RIGHT:
+               pos.x = (anchor_geom.x + anchor_geom.w);
+               pos.y = anchor_geom.y + ((anchor_geom.h - popup_size.h) / 2);
+
+               if ((pos.x < 0) ||
+                   ((pos.x + popup_size.w) > parent_size.w) ||
+                   (popup_size.h > parent_size.h))
+                 continue;
+               break;
+
+             case EFL_UI_POPUP_ALIGN_BOTTOM:
+               pos.x = anchor_geom.x + ((anchor_geom.w - popup_size.w) / 2);
+               pos.y = (anchor_geom.y + anchor_geom.h);
+
+               if ((pos.y < 0) ||
+                   ((pos.y + popup_size.h) > parent_size.h) ||
+                   (popup_size.w > parent_size.w))
+                 continue;
+               break;
+
+             case EFL_UI_POPUP_ALIGN_CENTER:
+               pos.x = anchor_geom.x + ((anchor_geom.w - popup_size.w) / 2);
+               pos.y = anchor_geom.y + ((anchor_geom.h - popup_size.h) / 2);
+
+               if (popup_size.w > parent_size.w || popup_size.h > 
parent_size.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 + popup_size.w) > parent_size.w)
+               pos.x = parent_size.w - popup_size.w;
+
+             if ((pos.x > (anchor_geom.x + anchor_geom.w)) ||
+                 ((pos.x + popup_size.w) < anchor_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 + popup_size.h) > parent_size.h)
+               pos.y = parent_size.h - popup_size.h;
+
+             if ((pos.y > (anchor_geom.y + anchor_geom.h)) ||
+                 ((pos.y + popup_size.h) < anchor_geom.y))
+               continue;
+          }
+
+        sd->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 = sd->align;
+         else
+           cur_align = sd->priority[idx - 1];
+
+         if (cur_align == EFL_UI_POPUP_ALIGN_NONE)
+           continue;
+
+         switch(cur_align)
+           {
+             case EFL_UI_POPUP_ALIGN_TOP:
+               pos.x = anchor_geom.x + ((anchor_geom.w - popup_size.w) / 2);
+               pos.y = (anchor_geom.y - popup_size.h);
+               sd->used_align = cur_align;
+               goto end;
+               break;
+
+             case EFL_UI_POPUP_ALIGN_LEFT:
+               pos.x = (anchor_geom.x - popup_size.w);
+               pos.y = anchor_geom.y + ((anchor_geom.h - popup_size.h) / 2);
+               sd->used_align = cur_align;
+               goto end;
+               break;
+
+             case EFL_UI_POPUP_ALIGN_RIGHT:
+               pos.x = (anchor_geom.x + anchor_geom.w);
+               pos.y = anchor_geom.y + ((anchor_geom.h - popup_size.h) / 2);
+               sd->used_align = cur_align;
+               goto end;
+               break;
+
+             case EFL_UI_POPUP_ALIGN_BOTTOM:
+               pos.x = anchor_geom.x + ((anchor_geom.w - popup_size.w) / 2);
+               pos.y = (anchor_geom.y + anchor_geom.h);
+               sd->used_align = cur_align;
+               goto end;
+               break;
+
+             case EFL_UI_POPUP_ALIGN_CENTER:
+               pos.x = anchor_geom.x + ((anchor_geom.w - popup_size.w) / 2);
+               pos.y = anchor_geom.y + ((anchor_geom.h - popup_size.h) / 2);
+               sd->used_align = cur_align;
+               goto end;
+               break;
+
+             default:
+               break;
+           }
+     }
+
+end:
+   if (sd->used_align != EFL_UI_POPUP_ALIGN_NONE)
+     efl_gfx_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_ANCHOR_DATA_GET(data, sd);
+
+   efl_event_callback_del(efl_ui_popup_parent_window_get(data), 
EFL_GFX_EVENT_RESIZE, _anchor_geom_cb, data);
+
+   sd->anchor = NULL;
+   efl_ui_popup_align_set(efl_super(data, MY_CLASS), sd->align);
+}
+
+static void
+_anchor_detach(Evas_Object *obj)
+{
+   EFL_UI_POPUP_ANCHOR_DATA_GET(obj, sd);
+
+   if (sd->anchor == NULL) return;
+
+   efl_event_callback_del(efl_ui_popup_parent_window_get(obj), 
EFL_GFX_EVENT_RESIZE, _anchor_geom_cb, obj);
+   efl_event_callback_del(sd->anchor, EFL_GFX_EVENT_RESIZE, _anchor_geom_cb, 
obj);
+   efl_event_callback_del(sd->anchor, EFL_GFX_EVENT_MOVE, _anchor_geom_cb, 
obj);
+   efl_event_callback_del(sd->anchor, EFL_EVENT_DEL, _anchor_del_cb, obj);
+}
+
+EOLIAN static void
+_efl_ui_popup_anchor_anchor_set(Eo *obj, Efl_Ui_Popup_Anchor_Data *pd, 
Evas_Object *anchor)
+{
+   _anchor_detach(obj);
+   pd->anchor = anchor;
+
+   if (anchor == NULL)
+      efl_ui_popup_align_set(efl_super(obj, MY_CLASS), pd->align);
+   else
+     {
+        efl_ui_popup_align_set(efl_super(obj, MY_CLASS), 
EFL_UI_POPUP_ALIGN_NONE);
+
+        _anchor_calc(obj);
+
+        efl_event_callback_add(efl_ui_popup_parent_window_get(obj), 
EFL_GFX_EVENT_RESIZE, _anchor_geom_cb, obj);
+        efl_event_callback_add(anchor, EFL_GFX_EVENT_RESIZE, _anchor_geom_cb, 
obj);
+        efl_event_callback_add(anchor, EFL_GFX_EVENT_MOVE, _anchor_geom_cb, 
obj);
+        efl_event_callback_add(anchor, EFL_EVENT_DEL, _anchor_del_cb, obj);
+     }
+}
+
+EOLIAN static Efl_Object *
+_efl_ui_popup_anchor_anchor_get(Eo *obj EINA_UNUSED, Efl_Ui_Popup_Anchor_Data 
*pd)
+{
+   return pd->anchor;
+}
+
+EOLIAN static void
+_efl_ui_popup_anchor_align_priority_set(Eo *obj EINA_UNUSED,
+                                        Efl_Ui_Popup_Anchor_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_anchor_align_priority_get(Eo *obj EINA_UNUSED,
+                                        Efl_Ui_Popup_Anchor_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_popup_anchor_efl_gfx_position_set(Eo *obj, Efl_Ui_Popup_Anchor_Data 
*pd EINA_UNUSED, Eina_Position2D pos)
+{
+   _anchor_detach(obj);
+
+   pd->anchor = NULL;
+   pd->align = EFL_UI_POPUP_ALIGN_NONE;
+
+   efl_gfx_position_set(efl_super(obj, MY_CLASS), pos);
+}
+
+EOLIAN static void
+_efl_ui_popup_anchor_elm_layout_sizing_eval(Eo *obj, Efl_Ui_Popup_Anchor_Data 
*pd EINA_UNUSED)
+{
+   elm_layout_sizing_eval(efl_super(obj, MY_CLASS));
+
+   if (pd->anchor != NULL)
+     _anchor_calc(obj);
+}
+
+EOLIAN static void
+_efl_ui_popup_anchor_efl_ui_popup_align_set(Eo *obj, Efl_Ui_Popup_Anchor_Data 
*pd, Efl_Ui_Popup_Align type)
+{
+   pd->align = type;
+   if (pd->anchor == NULL)
+      efl_ui_popup_align_set(efl_super(obj, MY_CLASS), type);
+   else
+      _anchor_calc(obj);
+}
+
+EOLIAN static Efl_Ui_Popup_Align
+_efl_ui_popup_anchor_efl_ui_popup_align_get(Eo *obj EINA_UNUSED, 
Efl_Ui_Popup_Anchor_Data *pd)
+{
+   return pd->align;
+}
+
+EOLIAN static void
+_efl_ui_popup_anchor_efl_canvas_group_group_add(Eo *obj, 
Efl_Ui_Popup_Anchor_Data *pd EINA_UNUSED)
+{
+   ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
+
+   efl_canvas_group_add(efl_super(obj, MY_CLASS));
+   elm_widget_sub_object_parent_add(obj);
+
+   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;
+}
+
+EOLIAN static void
+_efl_ui_popup_anchor_efl_canvas_group_group_del(Eo *obj, 
Efl_Ui_Popup_Anchor_Data *pd EINA_UNUSED)
+{
+   efl_canvas_group_del(efl_super(obj, MY_CLASS));
+}
+
+EOLIAN static void
+_efl_ui_popup_anchor_class_constructor(Efl_Class *klass)
+{
+   evas_smart_legacy_type_register(MY_CLASS_NAME, klass);
+}
+
+#define EFL_UI_POPUP_ANCHOR_EXTRA_OPS \
+   EFL_CANVAS_GROUP_ADD_DEL_OPS(efl_ui_popup_anchor), \
+   ELM_LAYOUT_SIZING_EVAL_OPS(efl_ui_popup_anchor)
+
+#include "efl_ui_popup_anchor.eo.c"
diff --git a/src/lib/elementary/efl_ui_popup_anchor.eo 
b/src/lib/elementary/efl_ui_popup_anchor.eo
new file mode 100644
index 0000000000..1dc422dba0
--- /dev/null
+++ b/src/lib/elementary/efl_ui_popup_anchor.eo
@@ -0,0 +1,40 @@
+class Efl.Ui.Popup.Anchor(Efl.Ui.Popup)
+{
+   methods {
+      @property anchor {
+         set {
+            [[Set anchor popup follows the 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 NULL, the anchor popup stop to following 
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;
+            second: Efl.Ui.Popup.Align;
+            third: Efl.Ui.Popup.Align;
+            fourth: Efl.Ui.Popup.Align;
+            fifth: Efl.Ui.Popup.Align;
+         }
+      }
+   }
+   implements {
+      class.constructor;
+      Efl.Gfx.position { set; }
+      Efl.Ui.Popup.align { set; get; }
+   }
+}
diff --git a/src/lib/elementary/efl_ui_popup_anchor_private.h 
b/src/lib/elementary/efl_ui_popup_anchor_private.h
new file mode 100644
index 0000000000..e99094c591
--- /dev/null
+++ b/src/lib/elementary/efl_ui_popup_anchor_private.h
@@ -0,0 +1,18 @@
+#ifndef EFL_UI_POPUP_ANCHOR_H
+#define EFL_UI_POPUP_ANCHOR_H
+
+#include "Elementary.h"
+
+typedef struct _Efl_Ui_Popup_Anchor_Data Efl_Ui_Popup_Anchor_Data;
+struct _Efl_Ui_Popup_Anchor_Data
+{
+   Evas_Object        *anchor;
+   Efl_Ui_Popup_Align  align;
+   Efl_Ui_Popup_Align  priority[5];
+   Efl_Ui_Popup_Align  used_align;
+};
+
+#define EFL_UI_POPUP_ANCHOR_DATA_GET(o, sd) \
+  Efl_Ui_Popup_Anchor_Data * sd = efl_data_scope_get(o, 
EFL_UI_POPUP_ANCHOR_CLASS)
+
+#endif

-- 


Reply via email to