test_datetime.c \
test_dayselector.c \
test_diskselector.c \
+test_dnd.c \
test_entry.c \
test_entry_anchor.c \
test_entry_anchor2.c \
void test_web_normal(void *data, Evas_Object *obj, void *event_info);
void test_web_mobile(void *data, Evas_Object *obj, void *event_info);
#endif
+void test_dnd_genlist_default_anim(void *data, Evas_Object *obj, void *event_info);
+void test_dnd_genlist_user_anim(void *data, Evas_Object *obj, void *event_info);
+void test_dnd_genlist_gengrid(void *data, Evas_Object *obj, void *event_info);
Evas_Object *win, *tbx; // TODO: refactoring
void *tt;
ADD_TEST(NULL, "System", "Systray Item", test_systray);
//------------------------------//
+ ADD_TEST(NULL, "Drag & Drop", "Genlist DnD Dflt Anim", test_dnd_genlist_default_anim);
+ ADD_TEST(NULL, "Drag & Drop", "Genlist DnD User Anim", test_dnd_genlist_user_anim);
+ ADD_TEST(NULL, "Drag & Drop", "Genlist-Gengrid DnD", test_dnd_genlist_gengrid);
+
+ //------------------------------//
ADD_TEST(NULL, "Miscellaneous", "Copy And Paste", test_cnp);
ADD_TEST(NULL, "Miscellaneous", "Weather", test_weather);
ADD_TEST(NULL, "Miscellaneous", "Icon Desktops", test_icon_desktops);
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include "elementary_config.h"
+#endif
+#include <Elementary.h>
+
+static const char *img[9] =
+{
+ "panel_01.jpg",
+ "plant_01.jpg",
+ "rock_01.jpg",
+ "rock_02.jpg",
+ "sky_01.jpg",
+ "sky_02.jpg",
+ "sky_03.jpg",
+ "sky_04.jpg",
+ "wood_01.jpg",
+};
+
+struct _anim_icon_st
+{
+ int start_x;
+ int start_y;
+ Evas_Object *o;
+};
+typedef struct _anim_icon_st anim_icon_st;
+
+struct _drag_anim_st
+{
+ Evas_Object *icwin;
+ Evas *e;
+ Evas_Coord mdx; /* Mouse-down x */
+ Evas_Coord mdy; /* Mouse-down y */
+ Eina_List *icons; /* List of icons to animate (anim_icon_st) */
+ Ecore_Timer *tm;
+ Ecore_Animator *ea;
+ Evas_Object *gl;
+};
+typedef struct _drag_anim_st drag_anim_st;
+
+#define DRAG_TIMEOUT 0.3
+#define ANIM_TIME 0.5
+
+static int
+_item_ptr_cmp(const void *d1, const void *d2)
+{
+ return (d1 - d2);
+}
+
+static Elm_Genlist_Item_Class *itc1;
+static Elm_Gengrid_Item_Class *gic;
+static char *
+gl_text_get(void *data, Evas_Object *obj __UNUSED__, const char *part __UNUSED__)
+{
+ return strdup(data);
+}
+
+static Evas_Object *
+gl_content_get(void *data, Evas_Object *obj, const char *part)
+{
+ if (!strcmp(part, "elm.swallow.icon"))
+ {
+ Evas_Object *icon = elm_icon_add(obj);
+ elm_image_file_set(icon, data, NULL);
+ evas_object_size_hint_aspect_set(icon, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
+ evas_object_show(icon);
+ return icon;
+ }
+ return NULL;
+}
+
+static void
+_win_del(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+ printf("<%s> <%d> will del <%p>\n", __func__, __LINE__, data);
+ elm_drop_item_container_del(data);
+ elm_drag_item_container_del(data);
+
+ if (gic) elm_gengrid_item_class_free(gic);
+ gic = NULL;
+ if (itc1) elm_genlist_item_class_free(itc1);
+ itc1 = NULL;
+}
+
+static Elm_Object_Item *
+_gl_item_getcb(Evas_Object *obj, Evas_Coord x, Evas_Coord y, int *xposret __UNUSED__, int *yposret)
+{ /* This function returns pointer to item under (x,y) coords */
+ printf("<%s> <%d> obj=<%p>\n", __func__, __LINE__, obj);
+ Elm_Object_Item *gli;
+ gli = elm_genlist_at_xy_item_get(obj, x, y, yposret);
+ if (gli)
+ printf("over <%s>, gli=<%p> yposret %i\n",
+ elm_object_item_part_text_get(gli, "elm.text"), gli, *yposret);
+ else
+ printf("over none, yposret %i\n", *yposret);
+ return gli;
+}
+
+static Elm_Object_Item *
+_grid_item_getcb(Evas_Object *obj, Evas_Coord x, Evas_Coord y, int *xposret, int *yposret)
+{ /* This function returns pointer to item under (x,y) coords */
+ printf("<%s> <%d> obj=<%p>\n", __func__, __LINE__, obj);
+ Elm_Object_Item *item;
+ item = elm_gengrid_at_xy_item_get(obj, x, y, xposret, yposret);
+ if (item)
+ printf("over <%s>, item=<%p> xposret %i yposret %i\n",
+ elm_object_item_part_text_get(item, "elm.text"), item, *xposret, *yposret);
+ else
+ printf("over none, xposret %i yposret %i\n", *xposret, *yposret);
+ return item;
+}
+
+static Eina_Bool
+_gl_dropcb(void *data __UNUSED__, Evas_Object *obj, Elm_Object_Item *it, Elm_Selection_Data *ev, int xposret __UNUSED__, int yposret)
+{ /* This function is called when data is dropped on the genlist */
+ printf("<%s> <%d> str=<%s>\n", __func__, __LINE__, (char *) ev->data);
+ if (!ev->data)
+ return EINA_FALSE;
+
+ char *p = ev->data;
+ p = strchr(p, '#');
+ while(p)
+ {
+ p++;
+ char *p2 = strchr(p, '#');
+ if (p2)
+ {
+ *p2 = '\0';
+ printf("Item %s\n", p);
+ switch(yposret)
+ {
+ case -1: /* Dropped on top-part of the it item */
+ {
+ elm_genlist_item_insert_before(obj,
+ itc1, strdup(p), NULL, it,
+ ELM_GENLIST_ITEM_NONE,
+ NULL, NULL);
+ break;
+ }
+ case 0: /* Dropped on center of the it item */
+ case 1: /* Dropped on botton-part of the it item */
+ {
+ if (!it) it = elm_genlist_last_item_get(obj);
+ if (it) it = elm_genlist_item_insert_after(obj,
+ itc1, strdup(p), NULL, it,
+ ELM_GENLIST_ITEM_NONE,
+ NULL, NULL);
+ else
+ it = elm_genlist_item_append(obj,
+ itc1, strdup(p), NULL,
+ ELM_GENLIST_ITEM_NONE,
+ NULL, NULL);
+ break;
+ }
+ default:
+ return EINA_FALSE;
+ }
+ p = p2;
+ }
+ else p = NULL;
+ }
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_grid_dropcb(void *data __UNUSED__, Evas_Object *obj, Elm_Object_Item *it, Elm_Selection_Data *ev, int xposret __UNUSED__, int yposret EINA_UNUSED)
+{ /* This function is called when data is dropped on the genlist */
+ printf("<%s> <%d> str=<%s>\n", __func__, __LINE__, (char *) ev->data);
+ if (!ev->data)
+ return EINA_FALSE;
+
+ char *p = ev->data;
+ p = strchr(p, '#');
+ while(p)
+ {
+ p++;
+ char *p2 = strchr(p, '#');
+ if (p2)
+ {
+ *p2 = '\0';
+ printf("Item %s\n", p);
+ if (!it) it = elm_gengrid_last_item_get(obj);
+ if (it) it = elm_gengrid_item_insert_after(obj, gic, strdup(p), it, NULL, NULL);
+ else it = elm_gengrid_item_append(obj, gic, strdup(p), NULL, NULL);
+ p = p2;
+ }
+ else p = NULL;
+ }
+
+ return EINA_TRUE;
+}
+
+static void _gl_obj_mouse_move( void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _gl_obj_mouse_up( void *data, Evas *e, Evas_Object *obj, void *event_info);
+
+static void
+anim_st_free(drag_anim_st *anim_st)
+{ /* Stops and free mem of ongoing animation */
+ printf("<%s> <%d>\n", __func__, __LINE__);
+ if (anim_st)
+ {
+ evas_object_event_callback_del_full
+ (anim_st->gl, EVAS_CALLBACK_MOUSE_MOVE, _gl_obj_mouse_move, anim_st);
+ evas_object_event_callback_del_full
+ (anim_st->gl, EVAS_CALLBACK_MOUSE_UP, _gl_obj_mouse_up, anim_st);
+ if (anim_st->tm)
+ {
+ ecore_timer_del(anim_st->tm);
+ anim_st->tm = NULL;
+ }
+
+ if (anim_st->ea)
+ {
+ ecore_animator_del(anim_st->ea);
+ anim_st->ea = NULL;
+ }
+
+ anim_icon_st *st;
+
+ EINA_LIST_FREE(anim_st->icons, st)
+ {
+ evas_object_hide(st->o);
+ evas_object_del(st->o);
+ free(st);
+ }
+
+ free(anim_st);
+ }
+}
+
+static Eina_Bool
+_drag_anim_play(void *data, double pos)
+{ /* Impl of the animation of icons, called on frame time */
+ drag_anim_st *anim_st = data;
+ printf("<%s> <%d>\n", __func__, __LINE__);
+ Eina_List *l;
+ anim_icon_st *st;
+
+ if (anim_st)
+ {
+ if (pos > 0.99)
+ {
+ anim_st->ea = NULL; /* Avoid deleting on mouse up */
+
+ EINA_LIST_FOREACH(anim_st->icons, l, st)
+ evas_object_hide(st->o); /* Hide animated icons */
+ anim_st_free(anim_st);
+ return ECORE_CALLBACK_CANCEL;
+ }
+
+ EINA_LIST_FOREACH(anim_st->icons, l, st)
+ {
+ int x, y, w, h;
+ Evas_Coord xm, ym;
+ evas_object_geometry_get(st->o, NULL, NULL, &w, &h);
+ evas_pointer_canvas_xy_get(anim_st->e, &xm, &ym);
+ x = st->start_x + (pos * (xm - (st->start_x + (w/2))));
+ y = st->start_y + (pos * (ym - (st->start_y + (h/2))));
+ evas_object_move(st->o, x, y);
+ }
+
+ return ECORE_CALLBACK_RENEW;
+ }
+
+ return ECORE_CALLBACK_CANCEL;
+}
+
+static Eina_Bool
+_gl_anim_start(void *data)
+{ /* Start icons animation before actually drag-starts */
+ drag_anim_st *anim_st = data;
+ printf("<%s> <%d>\n", __func__, __LINE__);
+ int yposret = 0;
+
+ Eina_List *l;
+ Eina_List *items = eina_list_clone(elm_genlist_selected_items_get(anim_st->gl));
+ Elm_Object_Item *gli = elm_genlist_at_xy_item_get(anim_st->gl,
+ anim_st->mdx, anim_st->mdy, &yposret);
+ if (gli)
+ { /* Add the item mouse is over to the list if NOT seleced */
+ void *p = eina_list_search_unsorted(items, _item_ptr_cmp, gli);
+ if (!p)
+ items = eina_list_append(items, gli);
+ }
+
+ EINA_LIST_FOREACH(items, l, gli)
+ { /* Now add icons to animation window */
+ Evas_Object *o = elm_object_item_part_content_get(gli,
+ "elm.swallow.icon");
+
+ if (o)
+ {
+ int w, h;
+ const char *f;
+ const char *g;
+ anim_icon_st *st = calloc(1, sizeof(*st));
+ elm_image_file_get(o, &f, &g);
+ Evas_Object *ic = elm_icon_add(anim_st->gl);
+ elm_image_file_set(ic, f, g);
+ evas_object_geometry_get(o, &st->start_x, &st->start_y, &w, &h);
+ evas_object_size_hint_align_set(ic,
+ EVAS_HINT_FILL, EVAS_HINT_FILL);
+ evas_object_size_hint_weight_set(ic,
+ EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+
+ evas_object_move(ic, st->start_x, st->start_y);
+ evas_object_resize(ic, w, h);
+ evas_object_show(ic);
+
+ st->o = ic;
+ anim_st->icons = eina_list_append(anim_st->icons, st);
+ }
+ }
+
+ eina_list_free(items);
+
+ anim_st->tm = NULL;
+ anim_st->ea = ecore_animator_timeline_add(DRAG_TIMEOUT,
+ _drag_anim_play, anim_st);
+
+ return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_gl_obj_mouse_up(
+ void *data,
+ Evas *e __UNUSED__,
+ Evas_Object *obj __UNUSED__,
+ void *event_info __UNUSED__)
+{ /* Cancel any drag waiting to start on timeout */
+ drag_anim_st *anim_st = data;
+ anim_st_free(anim_st);
+}
+
+static void
+_gl_obj_mouse_move(
+ void *data,
+ Evas *e __UNUSED__,
+ Evas_Object *obj __UNUSED__,
+ void *event_info)
+{ /* Cancel any drag waiting to start on timeout */
+
+ if (((Evas_Event_Mouse_Move *)event_info)->event_flags | EVAS_EVENT_FLAG_ON_HOLD)
+ {
+ drag_anim_st *anim_st = data;
+ anim_st_free(anim_st);
+ }
+}
+
+static void
+_gl_obj_mouse_down(
+ void *data,
+ Evas *e __UNUSED__,
+ Evas_Object *obj __UNUSED__,
+ void *event_info)
+{ /* Launch a timer to start drag animation */
+ Evas_Event_Mouse_Down *ev = event_info;
+ drag_anim_st *anim_st = calloc(1, sizeof(*anim_st));
+ anim_st->e = e;
+ anim_st->mdx = ev->canvas.x;
+ anim_st->mdy = ev->canvas.y;
+ anim_st->gl = data;
+ anim_st->tm = ecore_timer_add(DRAG_TIMEOUT, _gl_anim_start, anim_st);
+ evas_object_event_callback_add(data, EVAS_CALLBACK_MOUSE_UP,
+ _gl_obj_mouse_up, anim_st);
+ evas_object_event_callback_add(data, EVAS_CALLBACK_MOUSE_MOVE,
+ _gl_obj_mouse_move, anim_st);
+}
+/* END - Handling drag start animation */
+
+static void
+_gl_dragdone(void *data, Evas_Object *obj __UNUSED__, Eina_Bool doaccept)
+{
+ printf("<%s> <%d> data=<%p> doaccept=<%d>\n",
+ __func__, __LINE__, data, doaccept);
+
+ Elm_Object_Item *it;
+ Eina_List *l;
+
+ if (doaccept)
+ { /* Remove items dragged out (accepted by target) */
+ EINA_LIST_FOREACH(data, l, it)
+ elm_object_item_del(it);
+ }
+
+ eina_list_free(data);
+ return;
+}
+
+static Evas_Object *
+_gl_createicon(void *data, Evas_Object *win, Evas_Coord *xoff, Evas_Coord *yoff)
+{
+ printf("<%s> <%d>\n", __func__, __LINE__);
+ Evas_Object *icon = NULL;
+ Evas_Object *o = elm_object_item_part_content_get(data, "elm.swallow.icon");
+
+ if (o)
+ {
+ int xm, ym, w = 30, h = 30;
+ const char *f;
+ const char *g;
+ elm_image_file_get(o, &f, &g);
+ evas_pointer_canvas_xy_get(evas_object_evas_get(o), &xm, &ym);
+ if (xoff) *xoff = xm - (w/2);
+ if (yoff) *yoff = ym - (h/2);
+ icon = elm_icon_add(win);
+ elm_image_file_set(icon, f, g);
+ evas_object_size_hint_align_set(icon,
+ EVAS_HINT_FILL, EVAS_HINT_FILL);
+ evas_object_size_hint_weight_set(icon,
+ EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ if (xoff && yoff) evas_object_move(icon, *xoff, *yoff);
+ evas_object_resize(icon, w, h);
+ }
+
+ return icon;
+}
+
+static Eina_List *
+_gl_icons_get(void *data)
+{ /* Start icons animation before actually drag-starts */
+ printf("<%s> <%d>\n", __func__, __LINE__);
+ int yposret = 0;
+
+ Eina_List *l;
+
+ Eina_List *icons = NULL;
+
+ Evas_Coord xm, ym;
+ evas_pointer_canvas_xy_get(evas_object_evas_get(data), &xm, &ym);
+ Eina_List *items = eina_list_clone(elm_genlist_selected_items_get(data));
+ Elm_Object_Item *gli = elm_genlist_at_xy_item_get(data,
+ xm, ym, &yposret);
+ if (gli)
+ { /* Add the item mouse is over to the list if NOT seleced */
+ void *p = eina_list_search_unsorted(items, _item_ptr_cmp, gli);
+ if (!p)
+ items = eina_list_append(items, gli);
+ }
+
+ EINA_LIST_FOREACH(items, l, gli)
+ { /* Now add icons to animation window */
+ Evas_Object *o = elm_object_item_part_content_get(gli,
+ "elm.swallow.icon");
+
+ if (o)
+ {
+ int x, y, w, h;
+ const char *f, *g;
+ elm_image_file_get(o, &f, &g);
+ Evas_Object *ic = elm_icon_add(data);
+ elm_image_file_set(ic, f, g);
+ evas_object_geometry_get(o, &x, &y, &w, &h);
+ evas_object_size_hint_align_set(ic,
+ EVAS_HINT_FILL, EVAS_HINT_FILL);
+ evas_object_size_hint_weight_set(ic,
+ EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+
+ evas_object_move(ic, x, y);
+ evas_object_resize(ic, w, h);
+ evas_object_show(ic);
+
+ icons = eina_list_append(icons, ic);
+ }
+ }
+
+ eina_list_free(items);
+ return icons;
+}
+
+static const char *
+_gl_get_drag_data(Evas_Object *obj, Elm_Object_Item *it, Eina_List **items)
+{ /* Construct a string of dragged info, user frees returned string */
+ const char *drag_data = NULL;
+ printf("<%s> <%d>\n", __func__, __LINE__);
+
+ *items = eina_list_clone(elm_genlist_selected_items_get(obj));
+ if (it)
+ { /* Add the item mouse is over to the list if NOT seleced */
+ void *p = eina_list_search_unsorted(*items, _item_ptr_cmp, it);
+ if (!p)
+ *items = eina_list_append(*items, it);
+ }
+
+ if (*items)
+ { /* Now we can actually compose string to send and start dragging */
+ Eina_List *l;
+ const char *t;
+ unsigned int len = 0;
+
+ EINA_LIST_FOREACH(*items, l, it)
+ {
+ t = elm_object_item_part_text_get(it, "elm.text");
+ if (t)
+ len += strlen(t);
+ }
+
+ drag_data = malloc(len + eina_list_count(*items) * 2 + 8);
+ strcpy((char *) drag_data, "file://");
+
+ EINA_LIST_FOREACH(*items, l, it)
+ {
+ t = elm_object_item_part_text_get(it, "elm.text");
+ if (t)
+ {
+ strcat((char *) drag_data, "#");
+ strcat((char *) drag_data, t);
+ }
+ }
+ strcat((char *) drag_data, "#");
+
+ printf("<%s> <%d> Sending <%s>\n", __func__, __LINE__, drag_data);
+ }
+
+ return drag_data;
+}
+
+static const char *
+_grid_get_drag_data(Evas_Object *obj, Elm_Object_Item *it, Eina_List **items)
+{ /* Construct a string of dragged info, user frees returned string */
+ const char *drag_data = NULL;
+ printf("<%s> <%d>\n", __func__, __LINE__);
+
+ *items = eina_list_clone(elm_gengrid_selected_items_get(obj));
+ if (it)
+ { /* Add the item mouse is over to the list if NOT seleced */
+ void *p = eina_list_search_unsorted(*items, _item_ptr_cmp, it);
+ if (!p)
+ *items = eina_list_append(*items, it);
+ }
+
+ if (*items)
+ { /* Now we can actually compose string to send and start dragging */
+ Eina_List *l;
+ const char *t;
+ unsigned int len = 0;
+
+ EINA_LIST_FOREACH(*items, l, it)
+ {
+ t = elm_object_item_part_text_get(it, "elm.text");
+ if (t)
+ len += strlen(t);
+ }
+
+ drag_data = malloc(len + eina_list_count(*items) * 2 + 8);
+ strcpy((char *) drag_data, "file://");
+
+ EINA_LIST_FOREACH(*items, l, it)
+ {
+ t = elm_object_item_part_text_get(it, "elm.text");
+ if (t)
+ {
+ strcat((char *) drag_data, "#");
+ strcat((char *) drag_data, t);
+ }
+ }
+ strcat((char *) drag_data, "#");
+
+ printf("<%s> <%d> Sending <%s>\n", __func__, __LINE__, drag_data);
+ }
+
+ return drag_data;
+}
+
+static Eina_Bool
+_gl_dnd_default_anim_data_getcb(Evas_Object *obj, /* The genlist object */
+ Elm_Object_Item *it,
+ Elm_Drag_User_Info *info)
+{ /* This called before starting to drag, mouse-down was on it */
+ info->format = ELM_SEL_FORMAT_TARGETS;
+ info->createicon = _gl_createicon;
+ info->createdata = it;
+ info->icons = _gl_icons_get(obj);
+ info->dragdone = _gl_dragdone;
+
+ /* Now, collect data to send for drop from ALL selected items */
+ /* Save list pointer to remove items after drop and free list on done */
+ info->data = _gl_get_drag_data(obj, it, (Eina_List **) &info->donecbdata);
+ printf("%s - data = %s\n", __FUNCTION__, info->data);
+ info->acceptdata = info->donecbdata;
+
+ if (info->data)
+ return EINA_TRUE;
+ else
+ return EINA_FALSE;
+}
+
+static Eina_Bool
+_gl_data_getcb(Evas_Object *obj, /* The genlist object */
+ Elm_Object_Item *it,
+ Elm_Drag_User_Info *info)
+{ /* This called before starting to drag, mouse-down was on it */
+ info->format = ELM_SEL_FORMAT_TARGETS;
+ info->createicon = _gl_createicon;
+ info->createdata = it;
+ info->dragdone = _gl_dragdone;
+
+ /* Now, collect data to send for drop from ALL selected items */
+ /* Save list pointer to remove items after drop and free list on done */
+ info->data = _gl_get_drag_data(obj, it, (Eina_List **) &info->donecbdata);
+ info->acceptdata = info->donecbdata;
+
+ if (info->data)
+ return EINA_TRUE;
+ else
+ return EINA_FALSE;
+}
+
+static Eina_List *
+_grid_icons_get(void *data)
+{ /* Start icons animation before actually drag-starts */
+ printf("<%s> <%d>\n", __func__, __LINE__);
+
+ Eina_List *l;
+
+ Eina_List *icons = NULL;
+
+ Evas_Coord xm, ym;
+ evas_pointer_canvas_xy_get(evas_object_evas_get(data), &xm, &ym);
+ Eina_List *items = eina_list_clone(elm_gengrid_selected_items_get(data));
+ Elm_Object_Item *gli = elm_gengrid_at_xy_item_get(data,
+ xm, ym, NULL, NULL);
+ if (gli)
+ { /* Add the item mouse is over to the list if NOT seleced */
+ void *p = eina_list_search_unsorted(items, _item_ptr_cmp, gli);
+ if (!p)
+ items = eina_list_append(items, gli);
+ }
+
+ EINA_LIST_FOREACH(items, l, gli)
+ { /* Now add icons to animation window */
+ Evas_Object *o = elm_object_item_part_content_get(gli,
+ "elm.swallow.icon");
+
+ if (o)
+ {
+ int x, y, w, h;
+ const char *f, *g;
+ elm_image_file_get(o, &f, &g);
+ Evas_Object *ic = elm_icon_add(data);
+ elm_image_file_set(ic, f, g);
+ evas_object_geometry_get(o, &x, &y, &w, &h);
+ evas_object_size_hint_align_set(ic,
+ EVAS_HINT_FILL, EVAS_HINT_FILL);
+ evas_object_size_hint_weight_set(ic,
+ EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+
+ evas_object_move(ic, x, y);
+ evas_object_resize(ic, w, h);
+ evas_object_show(ic);
+
+ icons = eina_list_append(icons, ic);
+ }
+ }
+
+ eina_list_free(items);
+ return icons;
+}
+
+static Eina_Bool
+_grid_data_getcb(Evas_Object *obj, /* The genlist object */
+ Elm_Object_Item *it,
+ Elm_Drag_User_Info *info)
+{ /* This called before starting to drag, mouse-down was on it */
+ info->format = ELM_SEL_FORMAT_TARGETS;
+ info->createicon = _gl_createicon;
+ info->createdata = it;
+ info->icons = _grid_icons_get(obj);
+ info->dragdone = _gl_dragdone;
+
+ /* Now, collect data to send for drop from ALL selected items */
+ /* Save list pointer to remove items after drop and free list on done */
+ info->data = _grid_get_drag_data(obj, it, (Eina_List **) &info->donecbdata);
+ printf("%s - data = %s\n", __FUNCTION__, info->data);
+ info->acceptdata = info->donecbdata;
+
+ if (info->data)
+ return EINA_TRUE;
+ else
+ return EINA_FALSE;
+}
+
+void
+test_dnd_genlist_default_anim(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+ char buf[PATH_MAX];
+ Evas_Object *win, *gl, *bxx;
+ int i, j;
+
+ win = elm_win_util_standard_add("dnd-genlist-default-anim", "DnD-Genlist-Default-Anim");
+ elm_win_autodel_set(win, EINA_TRUE);
+
+ bxx = elm_box_add(win);
+ elm_box_horizontal_set(bxx, EINA_TRUE);
+ evas_object_size_hint_weight_set(bxx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_win_resize_object_add(win, bxx);
+ evas_object_show(bxx);
+
+ itc1 = elm_genlist_item_class_new();
+ itc1->item_style = "default";
+ itc1->func.text_get = gl_text_get;
+ itc1->func.content_get = gl_content_get;
+ itc1->func.del = NULL;
+
+ for (j = 0; j < 2; j++)
+ {
+ gl = elm_genlist_add(win);
+
+ /* START Drag and Drop handling */
+ evas_object_smart_callback_add(win, "delete,request", _win_del, gl);
+ elm_genlist_multi_select_set(gl, EINA_TRUE); /* We allow multi drag */
+ elm_drop_item_container_add(gl,
+ ELM_SEL_FORMAT_TARGETS,
+ _gl_item_getcb,
+ NULL, NULL,
+ NULL, NULL,
+ NULL, NULL,
+ _gl_dropcb, NULL);
+
+ elm_drag_item_container_add(gl, ANIM_TIME, DRAG_TIMEOUT,
+ _gl_item_getcb, _gl_dnd_default_anim_data_getcb);
+
+ // FIXME: This causes genlist to resize the horiz axis very slowly :(
+ // Reenable this and resize the window horizontally, then try to resize it back
+ //elm_genlist_mode_set(gl, ELM_LIST_LIMIT);
+ evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_box_pack_end(bxx, gl);
+ evas_object_show(gl);
+
+ for (i = 0; i < 20; i++)
+ {
+ snprintf(buf, sizeof(buf), "%s/images/%s", elm_app_data_dir_get(), img[(i % 9)]);
+ const char *path = eina_stringshare_add(buf);
+ elm_genlist_item_append(gl, itc1, path, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
+ }
+ }
+
+ evas_object_resize(win, 680, 800);
+ evas_object_show(win);
+}
+
+void
+test_dnd_genlist_user_anim(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+ char buf[PATH_MAX];
+ Evas_Object *win, *gl, *bxx;
+ int i, j;
+
+ win = elm_win_util_standard_add("dnd-genlist-user-anim", "DnD-Genlist-User-Anim");
+ elm_win_autodel_set(win, EINA_TRUE);
+
+ bxx = elm_box_add(win);
+ elm_box_horizontal_set(bxx, EINA_TRUE);
+ evas_object_size_hint_weight_set(bxx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_win_resize_object_add(win, bxx);
+ evas_object_show(bxx);
+
+ itc1 = elm_genlist_item_class_new();
+ itc1->item_style = "default";
+ itc1->func.text_get = gl_text_get;
+ itc1->func.content_get = gl_content_get;
+ itc1->func.del = NULL;
+
+ for (j = 0; j < 2; j++)
+ {
+ gl = elm_genlist_add(win);
+
+ /* START Drag and Drop handling */
+ evas_object_smart_callback_add(win, "delete,request", _win_del, gl);
+ elm_genlist_multi_select_set(gl, EINA_TRUE); /* We allow multi drag */
+ elm_drop_item_container_add(gl,
+ ELM_SEL_FORMAT_TARGETS,
+ _gl_item_getcb,
+ NULL, NULL,
+ NULL, NULL,
+ NULL, NULL,
+ _gl_dropcb, NULL);
+
+ elm_drag_item_container_add(gl, ANIM_TIME, DRAG_TIMEOUT,
+ _gl_item_getcb, _gl_data_getcb);
+
+ /* We add mouse-down, up callbacks to start/stop drag animation */
+ evas_object_event_callback_add(gl, EVAS_CALLBACK_MOUSE_DOWN,
+ _gl_obj_mouse_down, gl);
+ /* END Drag and Drop handling */
+
+ // FIXME: This causes genlist to resize the horiz axis very slowly :(
+ // Reenable this and resize the window horizontally, then try to resize it back
+ //elm_genlist_mode_set(gl, ELM_LIST_LIMIT);
+ evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_box_pack_end(bxx, gl);
+ evas_object_show(gl);
+
+ for (i = 0; i < 20; i++)
+ {
+ snprintf(buf, sizeof(buf), "%s/images/%s", elm_app_data_dir_get(), img[(i % 9)]);
+ const char *path = eina_stringshare_add(buf);
+ elm_genlist_item_append(gl, itc1, path, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
+ }
+ }
+
+ evas_object_resize(win, 680, 800);
+ evas_object_show(win);
+}
+
+void
+test_dnd_genlist_gengrid(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+ char buf[PATH_MAX];
+ Evas_Object *win, *bxx;
+ int i;
+
+ win = elm_win_util_standard_add("dnd-genlist-gengrid", "DnD-Genlist-Gengrid");
+ elm_win_autodel_set(win, EINA_TRUE);
+
+ bxx = elm_box_add(win);
+ elm_box_horizontal_set(bxx, EINA_TRUE);
+ evas_object_size_hint_weight_set(bxx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_win_resize_object_add(win, bxx);
+ evas_object_show(bxx);
+
+ {
+ itc1 = elm_genlist_item_class_new();
+ itc1->item_style = "default";
+ itc1->func.text_get = gl_text_get;
+ itc1->func.content_get = gl_content_get;
+ itc1->func.del = NULL;
+
+ Evas_Object *gl = elm_genlist_add(win);
+ evas_object_smart_callback_add(win, "delete,request", _win_del, gl);
+
+ /* START Drag and Drop handling */
+ elm_genlist_multi_select_set(gl, EINA_TRUE); /* We allow multi drag */
+ elm_drop_item_container_add(gl, ELM_SEL_FORMAT_TARGETS, _gl_item_getcb, NULL, NULL,
+ NULL, NULL, NULL, NULL, _gl_dropcb, NULL);
+
+ elm_drag_item_container_add(gl, ANIM_TIME, DRAG_TIMEOUT,
+ _gl_item_getcb, _gl_dnd_default_anim_data_getcb);
+ /* END Drag and Drop handling */
+
+ // FIXME: This causes genlist to resize the horiz axis very slowly :(
+ // Reenable this and resize the window horizontally, then try to resize it back
+ //elm_genlist_mode_set(gl, ELM_LIST_LIMIT);
+ evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ elm_box_pack_end(bxx, gl);
+ evas_object_show(gl);
+
+ for (i = 0; i < 20; i++)
+ {
+ snprintf(buf, sizeof(buf), "%s/images/%s", elm_app_data_dir_get(), img[(i % 9)]);
+ const char *path = eina_stringshare_add(buf);
+ elm_genlist_item_append(gl, itc1, path, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
+ }
+ }
+
+ {
+ Evas_Object *grid = elm_gengrid_add(win);
+ evas_object_smart_callback_add(win, "delete,request", _win_del, grid);
+ elm_gengrid_item_size_set(grid,
+ elm_config_scale_get() * 150,
+ elm_config_scale_get() * 150);
+ elm_gengrid_horizontal_set(grid, EINA_FALSE);
+ elm_gengrid_reorder_mode_set(grid, EINA_FALSE);
+ elm_gengrid_multi_select_set(grid, EINA_TRUE); /* We allow multi drag */
+ evas_object_size_hint_weight_set(grid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(grid, EVAS_HINT_FILL, EVAS_HINT_FILL);
+
+ gic = elm_gengrid_item_class_new();
+ gic->item_style = "default";
+ gic->func.text_get = gl_text_get;
+ gic->func.content_get = gl_content_get;
+
+ elm_drop_item_container_add(grid, ELM_SEL_FORMAT_TARGETS, _grid_item_getcb, NULL, NULL,
+ NULL, NULL, NULL, NULL, _grid_dropcb, NULL);
+
+ elm_drag_item_container_add(grid, ANIM_TIME, DRAG_TIMEOUT,
+ _grid_item_getcb, _grid_data_getcb);
+ for (i = 0; i < 20; i++)
+ {
+ snprintf(buf, sizeof(buf), "%s/images/%s", elm_app_data_dir_get(), img[(i % 9)]);
+ const char *path = eina_stringshare_add(buf);
+ elm_gengrid_item_append(grid, gic, path, NULL, NULL);
+ }
+ elm_box_pack_end(bxx, grid);
+ evas_object_show(grid);
+ }
+
+ evas_object_resize(win, 1280, 800);
+ evas_object_show(win);
+}
+
Elm_Object_Item *gli;
gli = elm_genlist_at_xy_item_get(gl, ev->cur.canvas.x, ev->cur.canvas.y, &where);
if (gli)
- INF("over %p, where %i", elm_object_item_data_get(gli), where);
+ INF("<%s> over %p, where %i\n", __func__, elm_object_item_data_get(gli), where);
else
- INF("over none, where %i", where);
+ INF("<%s> over none, where %i\n", __func__,where);
}
static void
typedef struct _Saved_Type Saved_Type;
typedef struct _Cnp_Escape Cnp_Escape;
typedef struct _Dropable Dropable;
+static Eina_Bool doaccept = EINA_FALSE;
struct _Tmp_Info
{
} last;
};
+struct _Item_Container_Drop_Info
+{ /* Info kept for containers to support drop */
+ Evas_Object *obj;
+ Elm_Xy_Item_Get_Cb itemgetcb;
+ Elm_Drop_Item_Container_Cb dropcb;
+ Elm_Drag_Item_Container_Pos poscb;
+};
+typedef struct _Item_Container_Drop_Info Item_Container_Drop_Info;
+
+struct _Anim_Icon
+{
+ int start_x;
+ int start_y;
+ int start_w;
+ int start_h;
+ Evas_Object *o;
+};
+typedef struct _Anim_Icon Anim_Icon;
+
+struct _Item_Container_Drag_Info
+{ /* Info kept for containers to support drag */
+ Evas_Object *obj;
+ Ecore_Timer *tm; /* When this expires, start drag */
+ double anim_tm; /* Time period to set tm */
+ double tm_to_drag; /* Time period to set tm */
+ Elm_Xy_Item_Get_Cb itemgetcb;
+ Elm_Item_Container_Data_Get_Cb data_get;
+
+ Evas_Coord x_down; /* Mouse down x cord when drag starts */
+ Evas_Coord y_down; /* Mouse down y cord when drag starts */
+
+ /* Some extra information needed to impl default anim */
+ Evas *e;
+ Eina_List *icons; /* List of icons to animate (Anim_Icon) */
+ int final_icon_w; /* We need the w and h of the final icon for the animation */
+ int final_icon_h;
+ Ecore_Animator *ea;
+
+ Elm_Drag_User_Info user_info;
+};
+typedef struct _Item_Container_Drag_Info Item_Container_Drag_Info;
+
static int _elm_cnp_init_count = 0;
/* Stringshared, so I can just compare pointers later */
static const char *text_uri;
static Evas_Object *dragwidget = NULL;
static Elm_Xdnd_Action dragaction = ELM_XDND_ACTION_UNKNOWN;
+static Eina_List *cont_drop_tg = NULL; /* List of Item_Container_Drop_Info */
+static Eina_List *cont_drag_tg = NULL; /* List of Item_Container_Drag_Info */
+
+static void _cont_obj_mouse_up( void *data, Evas *e, Evas_Object *obj, void *event_info);
+static void _cont_obj_mouse_move( void *data, Evas *e, Evas_Object *obj, void *event_info);
+
/* Drag & Drop functions */
/* FIXME: Way too many globals */
static Eina_List *drops = NULL;
static Evas_Object *dragwin = NULL;
+static int dragwin_x_start, dragwin_y_start;
+static int dragwin_x_end, dragwin_y_end;
static int _dragx = 0, _dragy = 0;
static Ecore_Event_Handler *handler_pos = NULL;
static Ecore_Event_Handler *handler_drop = NULL;
else
{
X11_Cnp_Selection *sel = _x11_selections + *((int *)data);
- if (data_ret) *data_ret = strdup(sel->selbuf);
- if (size_ret) *size_ret = strlen(sel->selbuf);
+ if (sel->selbuf)
+ {
+ if (data_ret) *data_ret = strdup(sel->selbuf);
+ if (size_ret) *size_ret = strlen(sel->selbuf);
+ }
+ else
+ {
+ if (data_ret) *data_ret = NULL;
+ if (size_ret) *size_ret = 0;
+ }
}
return EINA_TRUE;
}
_x11_dnd_status(void *data __UNUSED__, int etype __UNUSED__, void *ev)
{
Ecore_X_Event_Xdnd_Status *status = ev;
- Eina_Bool doaccept = EINA_FALSE;
-
+ doaccept = EINA_FALSE;
+
/* Only thing we care about: will accept */
if ((status) && (status->will_accept))
{
cnp_debug("Will accept\n");
doaccept = EINA_TRUE;
}
- /* Won't accept */
+ /* Won't accept */
else
{
cnp_debug("Won't accept accept\n");
}
static Eina_Bool
+_drag_cancel_animate(void *data __UNUSED__, double pos)
+{ /* Animation to "move back" drag-window */
+ if (pos >= 0.99)
+ {
+ evas_object_del(data);
+ return ECORE_CALLBACK_CANCEL;
+ }
+ else
+ {
+ int x, y;
+ x = dragwin_x_end - (pos * (dragwin_x_end - dragwin_x_start));
+ y = dragwin_y_end - (pos * (dragwin_y_end - dragwin_y_start));
+ evas_object_move(data, x, y);
+ }
+
+ return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool
_x11_drag_mouse_up(void *data, int etype __UNUSED__, void *event)
{
Ecore_X_Window xwin = (Ecore_X_Window)(long)data;
Eina_Bool have_drops = EINA_FALSE;
Eina_List *l;
Dropable *dropable;
-
+
ecore_x_pointer_ungrab();
- if (handler_up)
+ if (handler_up)
{
ecore_event_handler_del(handler_up);
handler_up = NULL;
handler_status = NULL;
}
ecore_x_dnd_self_drop();
-
+
cnp_debug("mouse up, xwin=%#llx\n", (unsigned long long)xwin);
-
+
EINA_LIST_FOREACH(drops, l, dropable)
{
if (xwin == _x11_elm_widget_xwin_get(dropable->obj))
}
if (!have_drops) ecore_x_dnd_aware_set(xwin, EINA_FALSE);
if (dragdonecb) dragdonecb(dragdonedata, dragwidget);
+ if (dragwin)
+ {
+ if (!doaccept)
+ { /* Commit animation when drag cancelled */
+ /* Record final position of dragwin, then do animation */
+ ecore_animator_timeline_add(0.3,
+ _drag_cancel_animate, dragwin);
+ }
+ else
+ { /* No animation drop was committed */
+ evas_object_del(dragwin);
+ }
+
+ dragwin = NULL; /* if not freed here, free in end of anim */
+ }
+
dragdonecb = NULL;
dragacceptcb = NULL;
dragposcb = NULL;
dragwidget = NULL;
+ doaccept = EINA_FALSE;
+ /* moved to _drag_cancel_animate
if (dragwin)
{
evas_object_del(dragwin);
dragwin = NULL;
}
+ */
}
return EINA_TRUE;
}
static void
_x11_drag_move(void *data __UNUSED__, Ecore_X_Xdnd_Position *pos)
{
- evas_object_move(dragwin,
+ evas_object_move(dragwin,
pos->position.x - _dragx, pos->position.y - _dragy);
- printf("dragevas: %p -> %p\n",
- dragwidget,
+ dragwin_x_end = pos->position.x - _dragx;
+ dragwin_y_end = pos->position.y - _dragy;
+ cnp_debug("dragevas: %p -> %p\n",
+ dragwidget,
evas_object_evas_get(dragwidget));
if (dragposcb)
dragposcb(dragposdata, dragwidget, pos->position.x, pos->position.y,
{
Evas_Object *top;
Ecore_X_Window xwin = 0;
-
+
top = elm_widget_top_get(obj);
if (!top) top = elm_widget_top_get(elm_widget_parent_widget_get(obj));
if (top) xwin = elm_win_xwindow_get(top);
{
int i;
static int _init_count = 0;
-
+
if (_init_count > 0) return EINA_TRUE;
_init_count++;
for (i = 0; i < CNP_N_ATOMS; i++)
}
static Eina_Bool
-_x11_elm_drag_start(Evas_Object *obj, Elm_Sel_Format format, const char *data,
+_x11_elm_drag_start(Evas_Object *obj, Elm_Sel_Format format, const char *data,
Elm_Xdnd_Action action,
Elm_Drag_Icon_Create_Cb createicon, void *createdata,
Elm_Drag_Pos dragpos, void *dragdata,
Ecore_X_Atom actx;
_x11_elm_cnp_init();
-
+
cnp_debug("starting drag... %p\n", obj);
if (dragwin)
if (createicon)
{
Evas_Coord xoff = 0, yoff = 0;
-
+
icon = createicon(createdata, dragwin, &xoff, &yoff);
if (icon)
{
- evas_object_geometry_get(obj, &x2, &y2, NULL, NULL);
+ x2 = xoff;
+ y2 = yoff;
evas_object_geometry_get(icon, NULL, NULL, &w, &h);
- x2 += xoff;
- y2 += yoff;
}
}
- if (!icon)
+ else
{
- evas_object_geometry_get(obj, &x2, &y2, &w, &h);
-
- /* FIXME: Images only */
icon = elm_icon_add(dragwin);
- if (!strncmp(data, "file://", 7))
- elm_image_file_set(icon, data + 7, NULL); /* 7!? "file://" */
- else
- elm_image_file_set(icon, data, NULL);
evas_object_size_hint_weight_set(icon, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(icon, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ // need to resize
}
elm_win_resize_object_add(dragwin, icon);
ecore_evas_geometry_get(ee, &x, &y, NULL, NULL);
x += x2;
y += y2;
+ dragwin_x_start = dragwin_x_end = x;
+ dragwin_y_start = dragwin_y_end = y;
evas_object_move(dragwin, x, y);
- evas_object_resize(icon, w, h);
evas_object_resize(dragwin, w, h);
evas_object_show(icon);
return _local_elm_selection_selection_has_owner(obj);
}
-/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0 :*/
+/* START - Support elm containers for Drag and Drop */
+/* START - Support elm containers for Drop */
+static int
+_drop_item_container_cmp(const void *d1,
+ const void *d2)
+{
+ const Item_Container_Drop_Info *st = d1;
+ return (((uintptr_t) (st->obj)) - ((uintptr_t) d2));
+}
+
+static void
+_elm_item_container_pos_cb(void *data, Evas_Object *obj, Evas_Coord x, Evas_Coord y, Elm_Xdnd_Action action)
+{ /* obj is the container pointer */
+ Elm_Object_Item *it = NULL;
+ int xposret = 0;
+ int yposret = 0;
+ Item_Container_Drop_Info *st =
+ eina_list_search_unsorted(cont_drop_tg, _drop_item_container_cmp, obj);
+
+ if (st && st->poscb)
+ { /* Call container drop func with specific item pointer */
+ int xo = 0;
+ int yo = 0;
+ eo_do(obj, evas_obj_position_get(&xo, &yo));
+ if (st->itemgetcb)
+ it = st->itemgetcb(obj, x+xo, y+yo, &xposret, &yposret);
+
+ st->poscb(data, obj, it, x, y, xposret, yposret, action);
+ }
+}
+
+static Eina_Bool
+_elm_item_container_drop_cb(void *data, Evas_Object *obj , Elm_Selection_Data *ev)
+{ /* obj is the container pointer */
+ Elm_Object_Item *it = NULL;
+ int xposret = 0;
+ int yposret = 0;
+ Item_Container_Drop_Info *st =
+ eina_list_search_unsorted(cont_drop_tg, _drop_item_container_cmp, obj);
+
+ if (st && st->dropcb)
+ { /* Call container drop func with specific item pointer */
+ int xo = 0;
+ int yo = 0;
+ eo_do(obj, evas_obj_position_get(&xo, &yo));
+ if (st->itemgetcb)
+ it = st->itemgetcb(obj, ev->x+xo, ev->y+yo, &xposret, &yposret);
+
+ return st->dropcb(data, obj, it, ev, xposret, yposret);
+ }
+
+ return EINA_FALSE;
+}
+
+static Eina_Bool
+elm_drop_item_container_del_internal(Evas_Object *obj, Eina_Bool full)
+{
+ Item_Container_Drop_Info *st =
+ eina_list_search_unsorted(cont_drop_tg, _drop_item_container_cmp, obj);
+
+ if (st)
+ {
+ elm_drop_target_del(obj);
+ st->itemgetcb= NULL;
+ st->poscb = NULL;
+ st->dropcb = NULL;
+
+ if (full)
+ {
+ cont_drop_tg = eina_list_remove(cont_drop_tg, st);
+ free(st);
+ }
+
+ return EINA_TRUE;
+ }
+
+ return EINA_FALSE;
+}
+
+EAPI Eina_Bool
+elm_drop_item_container_del(Evas_Object *obj)
+{
+ return elm_drop_item_container_del_internal(obj, EINA_TRUE);
+}
+
+EAPI Eina_Bool
+elm_drop_item_container_add(Evas_Object *obj,
+ Elm_Sel_Format format,
+ Elm_Xy_Item_Get_Cb itemgetcb,
+ Elm_Drag_State entercb, void *enterdata,
+ Elm_Drag_State leavecb, void *leavedata,
+ Elm_Drag_Item_Container_Pos poscb, void *posdata,
+ Elm_Drop_Item_Container_Cb dropcb, void *cbdata)
+{
+ Item_Container_Drop_Info *st;
+
+ if (elm_drop_item_container_del_internal(obj, EINA_FALSE))
+ { /* Updating info of existing obj */
+ st = eina_list_search_unsorted(cont_drop_tg, _drop_item_container_cmp, obj);
+ }
+ else
+ {
+ st = calloc(1, sizeof(*st));
+ st->obj = obj;
+ cont_drop_tg = eina_list_append(cont_drop_tg, st);
+ }
+
+ st->itemgetcb = itemgetcb;
+ st->poscb = poscb;
+ st->dropcb = dropcb;
+ elm_drop_target_add(obj, format,
+ entercb, enterdata,
+ leavecb, leavedata,
+ _elm_item_container_pos_cb, posdata,
+ _elm_item_container_drop_cb, cbdata);
+
+ return EINA_TRUE;
+}
+/* END - Support elm containers for Drop */
+
+
+/* START - Support elm containers for Drag */
+static int
+_drag_item_container_cmp(const void *d1,
+ const void *d2)
+{
+ const Item_Container_Drag_Info *st = d1;
+ return (((uintptr_t) (st->obj)) - ((uintptr_t) d2));
+}
+
+static void
+_cont_drag_done_cb(void *data, Evas_Object *obj __UNUSED__)
+{
+ Item_Container_Drag_Info *st = data;
+ elm_widget_scroll_freeze_pop(st->obj);
+ if (st->user_info.dragdone) st->user_info.dragdone(st->user_info.donecbdata, dragwidget, doaccept);
+}
+
+static Eina_Bool
+_cont_obj_drag_start(void *data)
+{ /* Start a drag-action when timer expires */
+ cnp_debug("%s In\n", __FUNCTION__);
+ Item_Container_Drag_Info *st = data;
+ st->tm = NULL;
+ Elm_Drag_User_Info *info = &st->user_info;
+ elm_widget_scroll_freeze_push(st->obj);
+ evas_object_event_callback_del_full
+ (st->obj, EVAS_CALLBACK_MOUSE_MOVE, _cont_obj_mouse_move, st);
+ elm_drag_start( /* Commit the start only if data_get successful */
+ st->obj, info->format,
+ info->data, info->action,
+ info->createicon, info->createdata,
+ info->dragpos, info->dragdata,
+ info->acceptcb, info->acceptdata,
+ _cont_drag_done_cb, st);
+
+ return ECORE_CALLBACK_CANCEL;
+}
+
+void
+_anim_st_free(Item_Container_Drag_Info *st)
+{ /* Stops and free mem of ongoing animation */
+ if (st)
+ {
+ if (st->ea)
+ {
+ ecore_animator_del(st->ea);
+ st->ea = NULL;
+ }
+
+ Anim_Icon *sti;
+
+ EINA_LIST_FREE(st->icons, sti)
+ {
+ evas_object_del(sti->o);
+ free(sti);
+ }
+
+ st->icons = NULL;
+ }
+}
+
+static inline Eina_List *
+_anim_icons_make(Eina_List *icons)
+{ /* Make local copies of all icons, add them to list */
+ Eina_List *list = NULL, *itr;
+ Evas_Object *o;
+
+ EINA_LIST_FOREACH(icons, itr, o)
+ { /* Now add icons to animation window */
+ Anim_Icon *st = calloc(1, sizeof(*st));
+ evas_object_geometry_get(o, &st->start_x, &st->start_y, &st->start_w, &st->start_h);
+ evas_object_show(o);
+ st->o = o;
+ list = eina_list_append(list, st);
+ }
+
+ return list;
+}
+
+static Eina_Bool
+_drag_anim_play(void *data, double pos)
+{ /* Impl of the animation of icons, called on frame time */
+ cnp_debug("%s In\n", __FUNCTION__);
+ Item_Container_Drag_Info *st = data;
+ Eina_List *l;
+ Anim_Icon *sti;
+
+ if (st->ea)
+ {
+ if (pos > 0.99)
+ {
+ st->ea = NULL; /* Avoid deleting on mouse up */
+ EINA_LIST_FOREACH(st->icons, l, sti)
+ evas_object_hide(sti->o);
+
+ _cont_obj_drag_start(st); /* Start dragging */
+ return ECORE_CALLBACK_CANCEL;
+ }
+
+ Evas_Coord xm, ym;
+ evas_pointer_canvas_xy_get(st->e, &xm, &ym);
+ EINA_LIST_FOREACH(st->icons, l, sti)
+ {
+ int x, y, h, w;
+ w = sti->start_w + ((st->final_icon_w - sti->start_w) * pos);
+ h = sti->start_h + ((st->final_icon_h - sti->start_h) * pos);
+ x = sti->start_x - (pos * ((sti->start_x + (w/2) - xm)));
+ y = sti->start_y - (pos * ((sti->start_y + (h/2) - ym)));
+ evas_object_move(sti->o, x, y);
+ evas_object_resize(sti->o, w, h);
+ }
+
+ return ECORE_CALLBACK_RENEW;
+ }
+
+ return ECORE_CALLBACK_CANCEL;
+}
+
+static inline Eina_Bool
+_drag_anim_start(void *data)
+{ /* Start default animation */
+ cnp_debug("%s In\n", __FUNCTION__);
+ Item_Container_Drag_Info *st = data;
+
+ st->tm = NULL;
+ /* Now we need to build an (Anim_Icon *) list */
+ st->icons = _anim_icons_make(st->user_info.icons);
+ if (st->user_info.createicon)
+ {
+ Evas_Object *temp_win = elm_win_add(NULL, "Temp", ELM_WIN_UTILITY);
+ Evas_Object *final_icon = st->user_info.createicon(st->user_info.createdata, temp_win, NULL, NULL);
+ evas_object_geometry_get(final_icon, NULL, NULL, &st->final_icon_w, &st->final_icon_h);
+ evas_object_del(final_icon);
+ evas_object_del(temp_win);
+ }
+ st->ea = ecore_animator_timeline_add(st->anim_tm, _drag_anim_play, st);
+
+ return EINA_FALSE;
+}
+
+static Eina_Bool
+_cont_obj_anim_start(void *data)
+{ /* Start a drag-action when timer expires */
+ cnp_debug("%s In\n", __FUNCTION__);
+ Item_Container_Drag_Info *st = data;
+ int xposret, yposret; /* Unused */
+ Elm_Object_Item *it = (st->itemgetcb) ?
+ (st->itemgetcb(st->obj, st->x_down, st->y_down, &xposret, &yposret))
+ : NULL;
+
+ st->tm = NULL;
+ st->user_info.format = ELM_SEL_FORMAT_TARGETS; /* Default */
+ st->icons = NULL;
+ st->user_info.data = NULL;
+ st->user_info.action = ELM_XDND_ACTION_COPY; /* Default */
+
+ if (!it) /* Failed to get mouse-down item, abort drag */
+ return ECORE_CALLBACK_CANCEL;
+
+ if (st->data_get)
+ { /* collect info then start animation or start dragging */
+ if(st->data_get( /* Collect drag info */
+ st->obj, /* The container object */
+ it, /* Drag started on this item */
+ &st->user_info))
+ {
+ if (st->user_info.icons)
+ _drag_anim_start(st);
+ else
+ {
+ if (st->anim_tm)
+ {
+ // even if we don't manage the icons animation, we have
+ // to wait until it is finished before beginning drag.
+ st->tm = ecore_timer_add(st->anim_tm, _cont_obj_drag_start, st);
+ }
+ else
+ _cont_obj_drag_start(st); /* Start dragging, no anim */
+ }
+ }
+ }
+
+ return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_cont_obj_mouse_down(
+ void *data,
+ Evas *e,
+ Evas_Object *obj __UNUSED__,
+ void *event_info)
+{ /* Launch a timer to start dragging */
+ Evas_Event_Mouse_Down *ev = event_info;
+ cnp_debug("%s In - event %X\n", __FUNCTION__, ev->event_flags);
+ if (ev->button != 1)
+ return; /* We only process left-click at the moment */
+
+ Item_Container_Drag_Info *st = data;
+ evas_object_event_callback_add(st->obj, EVAS_CALLBACK_MOUSE_MOVE,
+ _cont_obj_mouse_move, st);
+
+ evas_object_event_callback_add(st->obj, EVAS_CALLBACK_MOUSE_UP,
+ _cont_obj_mouse_up, st);
+
+ if (st->tm)
+ ecore_timer_del(st->tm);
+
+ st->e = e;
+ st->x_down = ev->canvas.x;
+ st->y_down = ev->canvas.y;
+ st->tm = ecore_timer_add(st->tm_to_drag, _cont_obj_anim_start, st);
+}
+
+static Eina_Bool elm_drag_item_container_del_internal(Evas_Object *obj, Eina_Bool full);
+
+static void
+_cont_obj_mouse_move(
+ void *data,
+ Evas *e __UNUSED__,
+ Evas_Object *obj __UNUSED__,
+ void *event_info)
+{ /* Cancel any drag waiting to start on timeout */
+
+ cnp_debug("%s In\n", __FUNCTION__);
+ if (((Evas_Event_Mouse_Move *)event_info)->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
+ {
+ cnp_debug("%s event on hold - have to cancel DnD\n", __FUNCTION__);
+ Item_Container_Drag_Info *st = data;
+ evas_object_event_callback_del_full
+ (st->obj, EVAS_CALLBACK_MOUSE_MOVE, _cont_obj_mouse_move, st);
+ evas_object_event_callback_del_full
+ (st->obj, EVAS_CALLBACK_MOUSE_UP, _cont_obj_mouse_up, st);
+ elm_drag_item_container_del_internal(obj, EINA_FALSE);
+
+ if (st->tm)
+ {
+ ecore_timer_del(st->tm);
+ st->tm = NULL;
+ }
+
+ _anim_st_free(st);
+ }
+ cnp_debug("%s Out\n", __FUNCTION__);
+}
+
+static void
+_cont_obj_mouse_up(
+ void *data,
+ Evas *e __UNUSED__,
+ Evas_Object *obj __UNUSED__,
+ void *event_info)
+{ /* Cancel any drag waiting to start on timeout */
+ Item_Container_Drag_Info *st = data;
+
+ cnp_debug("%s In\n", __FUNCTION__);
+ if (((Evas_Event_Mouse_Up *)event_info)->button != 1)
+ return; /* We only process left-click at the moment */
+
+ evas_object_event_callback_del_full
+ (st->obj, EVAS_CALLBACK_MOUSE_MOVE, _cont_obj_mouse_move, st);
+ evas_object_event_callback_del_full
+ (st->obj, EVAS_CALLBACK_MOUSE_UP, _cont_obj_mouse_up, st);
+
+ if (st->tm)
+ {
+ ecore_timer_del(st->tm);
+ st->tm = NULL;
+ }
+
+ _anim_st_free(st);
+}
+
+static Eina_Bool
+elm_drag_item_container_del_internal(Evas_Object *obj, Eina_Bool full)
+{
+ Item_Container_Drag_Info *st =
+ eina_list_search_unsorted(cont_drag_tg, _drag_item_container_cmp, obj);
+
+ if (st)
+ {
+ if (st->tm)
+ ecore_timer_del(st->tm); /* Cancel drag-start timer */
+
+ if (st->ea) /* Cancel ongoing default animation */
+ _anim_st_free(st);
+
+ st->tm = NULL;
+
+ if (full)
+ {
+ st->itemgetcb = NULL;;
+ st->data_get = NULL;
+ evas_object_event_callback_del_full
+ (obj, EVAS_CALLBACK_MOUSE_DOWN, _cont_obj_mouse_down, st);
+
+ free(st);
+ cont_drag_tg = eina_list_remove(cont_drag_tg, st);
+ }
+
+ return EINA_TRUE;
+ }
+
+ return EINA_FALSE;
+}
+
+EAPI Eina_Bool
+elm_drag_item_container_del(Evas_Object *obj)
+{
+ return elm_drag_item_container_del_internal(obj, EINA_TRUE);
+}
+
+EAPI Eina_Bool
+elm_drag_item_container_add(
+ Evas_Object *obj,
+ double anim_tm,
+ double tm_to_drag,
+ Elm_Xy_Item_Get_Cb itemgetcb,
+ Elm_Item_Container_Data_Get_Cb data_get)
+{
+ Item_Container_Drag_Info *st;
+
+ if (elm_drag_item_container_del_internal(obj, EINA_FALSE))
+ { /* Updating info of existing obj */
+ st = eina_list_search_unsorted(cont_drag_tg, _drag_item_container_cmp, obj);
+ }
+ else
+ {
+ st = calloc(1, sizeof(*st));
+ st->obj = obj;
+ cont_drag_tg = eina_list_append(cont_drag_tg, st);
+
+ /* Register for mouse callback for container to start/abort drag */
+ evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
+ _cont_obj_mouse_down, st);
+ }
+
+ st->tm = NULL;
+ st->anim_tm = anim_tm;
+ st->tm_to_drag = tm_to_drag;
+ st->itemgetcb = itemgetcb;
+ st->data_get = data_get;
+
+ return EINA_TRUE;
+}
+/* END - Support elm containers for Drag */
+/* END - Support elm containers for Drag and Drop */
typedef Eina_Bool (*Elm_Drop_Cb)(void *data, Evas_Object *obj, Elm_Selection_Data *ev);
/**
+ * Callback invoked to find out what object is under (x,y) coords
+ *
+ * @param obj The container object
+ * @param x cord to check
+ * @param y cord to check
+ * @param xposret Position relative to item (left (-1), middle (0), right (1)
+ * @param yposret Position relative to item (upper (-1), middle (0), bottom (1)
+ * @return object under x,y cords or NULL if not found.
+ */
+typedef Elm_Object_Item *(*Elm_Xy_Item_Get_Cb)(Evas_Object *obj, Evas_Coord x, Evas_Coord y, int *xposret, int *yposret);
+
+/**
* Callback invoked in when the selection ownership for a given selection is lost.
*
* @param data Application specific data
/**
* Callback called to create a drag icon object
- *
+ *
* @param data Application specific data
* @param win The window to create the objects relative to
* @param xoff A return coordinate for the X offset at which to place the drag icon object relative to the source drag object
typedef void (*Elm_Drag_State) (void *data, Evas_Object *obj);
/**
+ * Callback called when a drag is finished.
+ *
+ * @param data Application specific data
+ * @param obj The object where the drag started
+ * @param accepted TRUE if the droppped-data is accepted on drop
+ * @since 1.8
+ */
+typedef void (*Elm_Drag_Done) (void *data, Evas_Object *obj, Eina_Bool accepted);
+
+/**
* Callback called when a drag is responded to with an accept or deny
- *
+ *
* @param data Application specific data
* @param obj The object where the drag started
* @param doaccept A boolean as to if the target accepts the drag or not
* @param dragpos Function called with each position of the drag, x, y being screen coordinates if possible, and action being the current action.
* @param dragdata Application data passed to @p dragpos
* @param acceptcb Function called indicating if drop target accepts (or does not) the drop data while dragging
- *
+ *
* @param acceptdata Application data passed to @p acceptcb
* @param dragdone Function to call when drag is done
* @param donecbdata Application data to pass to @p dragdone
*
* @since 1.8
*/
-EAPI Eina_Bool elm_drag_start(Evas_Object *obj, Elm_Sel_Format format,
- const char *data, Elm_Xdnd_Action action,
- Elm_Drag_Icon_Create_Cb createicon, void *createdata,
+EAPI Eina_Bool elm_drag_start(Evas_Object *obj, Elm_Sel_Format format,
+ const char *data, Elm_Xdnd_Action action,
+ Elm_Drag_Icon_Create_Cb createicon,
+ void *createdata,
Elm_Drag_Pos dragpos, void *dragdata,
Elm_Drag_Accept acceptcb, void *acceptdata,
Elm_Drag_State dragdone, void *donecbdata);
/**
* @brief Changes the current drag action
*
- * @param obj The source of a drag if a drag is underway
+ * @param obj The source of a drag if a drag is underway
* @param action The drag action to be done
* @return Returns EINA_TRUE, if successful, or EINA_FALSE if not.
*
EAPI Eina_Bool elm_drag_action_set(Evas_Object *obj, Elm_Xdnd_Action action);
/**
+ * Callback called when a drag is over an object
+ *
+ * @param data Application specific data
+ * @param cont The container object where the drag started
+ * @param it The object item in container where mouse-over
+ * @param x The X coordinate relative to the top-left of the object
+ * @param y The Y coordinate relative to the top-left of the object
+ * @param xposret Position relative to item (left (-1), middle (0), right (1)
+ * @param yposret Position relative to item (upper (-1), middle (0), bottom (1)
+ * @param action The drag action to be done
+ * @since 1.8
+ */
+typedef void (*Elm_Drag_Item_Container_Pos) (void *data, Evas_Object *cont, Elm_Object_Item *it, Evas_Coord x, Evas_Coord y, int xposret, int yposret, Elm_Xdnd_Action action);
+
+/**
+ * Callback invoked in when the selected data is 'dropped' on container.
+ *
+ * @param data Application specific data
+ * @param obj The evas object where selected data is 'dropped'.
+ * @param it The item in container where drop-cords
+ * @param ev struct holding information about selected data
+ * @param xposret Position relative to item (left (-1), middle (0), right (1)
+ * @param yposret Position relative to item (upper (-1), middle (0), bottom (1)
+ */
+typedef Eina_Bool (*Elm_Drop_Item_Container_Cb)(void *data, Evas_Object *obj, Elm_Object_Item *it, Elm_Selection_Data *ev, int xposret, int yposret);
+
+/**
+ * Structure describing user information for the drag process.
+ *
+ * @param format The drag formats supported by the data (output)
+ * @param data The drag data itself (a string) (output)
+ * @param icons if value not NULL, play default anim (output)
+ * @param action The drag action to be done (output)
+ * @param createicon Function to call to create a drag object, or NULL if not wanted (output)
+ * @param createdata Application data passed to @p createicon (output)
+ * @param dragpos Function called with each position of the drag, x, y being screen coordinates if possible, and action being the current action. (output)
+ * @param dragdata Application data passed to @p dragpos (output)
+ * @param acceptcb Function called indicating if drop target accepts (or does not) the drop data while dragging (output)
+ * @param acceptdata Application data passed to @p acceptcb (output)
+ * @param dragdone Function to call when drag is done (output)
+ * @param donecbdata Application data to pass to @p dragdone (output)
+ */
+typedef struct _Elm_Drag_User_Info Elm_Drag_User_Info;
+
+struct _Elm_Drag_User_Info
+{
+ Elm_Sel_Format format;
+ const char *data;
+ Eina_List *icons;
+ Elm_Xdnd_Action action;
+ Elm_Drag_Icon_Create_Cb createicon;
+ void *createdata;
+ Elm_Drag_Pos dragpos;
+ void *dragdata;
+ Elm_Drag_Accept acceptcb;
+ void *acceptdata;
+ Elm_Drag_Done dragdone;
+ void *donecbdata;
+};
+
+/**
+ * Callback invoked when starting to drag for a container.
+ *
+ * @param obj The container object
+ * @param it The Elm_Object_Item pointer where drag-start
+ * @return Returns EINA_TRUE, if successful, or EINA_FALSE if not.
+ */
+typedef Eina_Bool (*Elm_Item_Container_Data_Get_Cb)(
+ Evas_Object *obj,
+ Elm_Object_Item *it,
+ Elm_Drag_User_Info *info);
+
+/**
+ * @brief Set a item container (list, genlist, grid) as source of drag
+ *
+ * @param obj The container object.
+ * @param tm_to_anim Time period to wait before start animation.
+ * @param tm_to_drag Time period to wait before start draggind.
+ * @param itemgetcb Callback to get Evas_Object pointer for item at (x,y)
+ * @param data_get Callback to get drag info
+ * @return Returns EINA_TRUE, if successful, or EINA_FALSE if not.
+ *
+ * @ingroup CopyPaste
+ *
+ * @since 1.8
+ */
+EAPI Eina_Bool elm_drag_item_container_add(Evas_Object *obj, double tm_to_anim, double tm_to_drag, Elm_Xy_Item_Get_Cb itemgetcb, Elm_Item_Container_Data_Get_Cb data_get);
+
+/**
+ * @brief Deletes a item container from drag-source list
+ *
+ * @param obj The target object
+ * @return Returns EINA_TRUE, if successful, or EINA_FALSE if not.
+ *
+ * @ingroup CopyPaste
+ *
+ * @since 1.8
+ */
+EAPI Eina_Bool elm_drag_item_container_del(Evas_Object *obj);
+
+/**
+ * @brief Set a item container (list, genlist, grid) as target for drop.
+ *
+ * @param obj The container object.
+ * @param format The formats supported for dropping
+ * @param itemgetcb Callback to get Evas_Object pointer for item at (x,y)
+ * @param entercb The function to call when the object is entered with a drag
+ * @param enterdata The application data to pass to enterdata
+ * @param leavecb The function to call when the object is left with a drag
+ * @param leavedata The application data to pass to leavedata
+ * @param poscb The function to call when the object has a drag over it
+ * @param posdata The application data to pass to posdata
+ * @param dropcb The function to call when a drop has occurred
+ * @param cbdata The application data to pass to dropcb
+ * @return Returns EINA_TRUE, if successful, or EINA_FALSE if not.
+ *
+ * @ingroup CopyPaste
+ *
+ * @since 1.8
+ */
+EAPI Eina_Bool elm_drop_item_container_add(Evas_Object *obj,
+ Elm_Sel_Format format,
+ Elm_Xy_Item_Get_Cb itemgetcb,
+ Elm_Drag_State entercb, void *enterdata,
+ Elm_Drag_State leavecb, void *leavedata,
+ Elm_Drag_Item_Container_Pos poscb, void *posdata,
+ Elm_Drop_Item_Container_Cb dropcb, void *cbdata);
+
+/**
+ * @brief Removes a container from list of drop tragets.
+ *
+ * @param obj The container object
+ * @return Returns EINA_TRUE, if successful, or EINA_FALSE if not.
+ *
+ * @ingroup CopyPaste
+ *
+ * @since 1.8
+ */
+EAPI Eina_Bool elm_drop_item_container_del(Evas_Object *obj);
+
+/**
* @}
*/
*ret = (Elm_Object_Item *)it;
}
+
+EAPI Elm_Object_Item *
+elm_gengrid_at_xy_item_get(const Evas_Object *obj,
+ Evas_Coord x,
+ Evas_Coord y,
+ int *xposret,
+ int *yposret)
+{
+ ELM_GENGRID_CHECK(obj) NULL;
+ Elm_Object_Item *ret = NULL;
+ eo_do((Eo *) obj, elm_obj_gengrid_at_xy_item_get(x, y,
+ xposret, yposret, &ret));
+
+ return ret;
+}
+
+static void
+_at_xy_item_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+{
+ Evas_Coord x = va_arg(*list, Evas_Coord);
+ Evas_Coord y = va_arg(*list, Evas_Coord);
+ int *xposret = va_arg(*list, int *);
+ int *yposret = va_arg(*list, int *);
+ Elm_Object_Item **ret = va_arg(*list, Elm_Object_Item **);
+
+ Elm_Gengrid_Smart_Data *sd = _pd;
+ Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(sd->items);
+
+ Evas_Coord l, r, t, b; /* left, right, top, bottom */
+ Eina_Bool init = EINA_TRUE;
+
+ while ((it) && (it->generation < sd->generation))
+ it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
+
+ if (it)
+ do
+ {
+ Evas_Coord itx, ity;
+ Evas_Coord itw, ith;
+ evas_object_geometry_get(VIEW(it), &itx, &ity, &itw, &ith);
+
+ /* Record leftmost, rightmost, top, bottom cords to set posret */
+ if ((itw > 0) && (ith > 0) && (itx >= 0) && (ity >= 0))
+ { /* A scroller, ignore items in negative cords,or not rendered */
+ if (init)
+ {
+ l = itx;
+ r = itx + itw;
+ t = ity;
+ b = ity + ith;
+ init = EINA_FALSE;
+ }
+ else
+ {
+ if (itx < l)
+ l = itx;
+ if ((itx + itw) > r)
+ r = itx + itw;
+ if (ity < t)
+ t = ity;
+ if ((ity + ith) > b)
+ b = ity + ith;
+ }
+ }
+
+ if (ELM_RECTS_INTERSECT
+ (itx, ity, itw, ith, x, y, 1, 1))
+ {
+ if (yposret)
+ {
+ if (y <= (ity + (ith / 4))) *yposret = -1;
+ else if (y >= (ity + ith - (ith / 4)))
+ *yposret = 1;
+ else *yposret = 0;
+ }
+
+ if (xposret)
+ {
+ if (x <= (itx + (itw / 4))) *xposret = -1;
+ else if (x >= (itx + itw - (itw / 4)))
+ *xposret = 1;
+ else *xposret = 0;
+ }
+
+ *ret = (Elm_Object_Item *) it;
+ return;
+ }
+
+ } while ((it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next)));
+
+ /* No item found, tell the user if hit left/right/top/bottom of items */
+ if (xposret)
+ {
+ *xposret = 0;
+ if (x < l)
+ *xposret = (-1);
+ else if (x > r)
+ *xposret = (1);
+ }
+
+ if (yposret)
+ {
+ *yposret = 0;
+ if (y < t)
+ *yposret = (-1);
+ else if (y > b)
+ *yposret = (1);
+ }
+
+ *ret = NULL;
+}
+
EAPI Elm_Object_Item *
elm_gengrid_last_item_get(const Evas_Object *obj)
{
EO_OP_FUNC(ELM_OBJ_GENGRID_ID(ELM_OBJ_GENGRID_SUB_ID_SELECT_MODE_GET), _select_mode_get),
EO_OP_FUNC(ELM_OBJ_GENGRID_ID(ELM_OBJ_GENGRID_SUB_ID_HIGHLIGHT_MODE_SET), _highlight_mode_set),
EO_OP_FUNC(ELM_OBJ_GENGRID_ID(ELM_OBJ_GENGRID_SUB_ID_HIGHLIGHT_MODE_GET), _highlight_mode_get),
+ EO_OP_FUNC(ELM_OBJ_GENGRID_ID(ELM_OBJ_GENGRID_SUB_ID_AT_XY_ITEM_GET), _at_xy_item_get),
EO_OP_FUNC_SENTINEL
};
eo_class_funcs_set(klass, func_desc);
EO_OP_DESCRIPTION(ELM_OBJ_GENGRID_SUB_ID_SELECT_MODE_GET, "Get the gengrid select mode."),
EO_OP_DESCRIPTION(ELM_OBJ_GENGRID_SUB_ID_HIGHLIGHT_MODE_SET, "Set whether the gengrid items should be highlighted when item selected."),
EO_OP_DESCRIPTION(ELM_OBJ_GENGRID_SUB_ID_HIGHLIGHT_MODE_GET, "Get whether the gengrid items should be highlighted when item selected."),
+ EO_OP_DESCRIPTION(ELM_OBJ_GENGRID_SUB_ID_AT_XY_ITEM_GET, "Get the item that is at the x, y canvas coords."),
EO_OP_DESCRIPTION_SENTINEL
};
ELM_OBJ_GENGRID_SUB_ID_SELECT_MODE_GET,
ELM_OBJ_GENGRID_SUB_ID_HIGHLIGHT_MODE_SET,
ELM_OBJ_GENGRID_SUB_ID_HIGHLIGHT_MODE_GET,
+ ELM_OBJ_GENGRID_SUB_ID_AT_XY_ITEM_GET,
ELM_OBJ_GENGRID_SUB_ID_LAST
};
*/
#define elm_obj_gengrid_highlight_mode_get(ret) ELM_OBJ_GENGRID_ID(ELM_OBJ_GENGRID_SUB_ID_HIGHLIGHT_MODE_GET), EO_TYPECHECK(Eina_Bool *, ret)
+/**
+ * @def elm_obj_gengrid_at_xy_item_get
+ * @since 1.8
+ *
+ * Get the item that is at the x, y canvas coords.
+ *
+ * @param[in] x
+ * @param[in] y
+ * @param[out] xposret
+ * @param[out] yposret
+ * @param[out] ret
+ *
+ * @see elm_gengrid_at_xy_item_get
+ */
+#define elm_obj_gengrid_at_xy_item_get(x, y, xposret, yposret, ret) ELM_OBJ_GENGRID_ID(ELM_OBJ_GENGRID_SUB_ID_AT_XY_ITEM_GET), EO_TYPECHECK(Evas_Coord, x), EO_TYPECHECK(Evas_Coord, y), EO_TYPECHECK(int *, xposret), EO_TYPECHECK(int *, yposret), EO_TYPECHECK(Elm_Object_Item **, ret)
+
/**
* @}
* @since 1.8
*/
EAPI Elm_Object_Item *elm_gengrid_nth_item_get(const Evas_Object *obj, unsigned int nth);
+
+/**
+ * Get the item that is at the x, y canvas coords.
+ *
+ * @param obj The gengrid object.
+ * @param x The input x coordinate
+ * @param y The input y coordinate
+ * @param xposret The position relative to the item returned here
+ * @param yposret The position relative to the item returned here
+ * @return The item at the coordinates or NULL if none
+ *
+ * This returns the item at the given coordinates (which are canvas
+ * relative, not object-relative). If an item is at that coordinate,
+ * that item handle is returned, and if @p xposret is not NULL, the
+ * integer pointed to is set to a value of -1, 0 or 1, depending if
+ * the coordinate is on the left portion of that item (-1), on the
+ * middle section (0) or on the right part (1).
+ * if @p yposret is not NULL, the
+ * integer pointed to is set to a value of -1, 0 or 1, depending if
+ * the coordinate is on the upper portion of that item (-1), on the
+ * middle section (0) or on the lower part (1). If NULL is returned as
+ * an item (no item found there), then posret may indicate -1 or 1
+ * based if the coordinate is above or below all items respectively in
+ * the gengrid.
+ *
+ * @ingroup Gengrid
+ */
+EAPI Elm_Object_Item *elm_gengrid_at_xy_item_get(const Evas_Object *obj, Evas_Coord x, Evas_Coord y, int *xposret, int *yposret);
+
else *ret = eina_list_data_get(eina_list_last(sd->items));
}
+EAPI Elm_Object_Item *
+elm_list_at_xy_item_get(const Evas_Object *obj,
+ Evas_Coord x,
+ Evas_Coord y,
+ int *posret)
+{
+ ELM_LIST_CHECK(obj) NULL;
+ Elm_Object_Item *ret = NULL;
+ eo_do((Eo *) obj, elm_obj_list_at_xy_item_get(x, y, posret, &ret));
+ return ret;
+}
+
+static void
+_at_xy_item_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
+{
+ Eina_List *l;
+ Elm_List_Item *it;
+
+ Evas_Coord x = va_arg(*list, Evas_Coord);
+ Evas_Coord y = va_arg(*list, Evas_Coord);
+ int *posret = va_arg(*list, int *);
+ Evas_Coord lasty;
+ Elm_Object_Item **ret = va_arg(*list, Elm_Object_Item **);
+ Elm_List_Smart_Data *sd = _pd;
+ evas_object_geometry_get(sd->hit_rect, &lasty, NULL, NULL, NULL);
+
+ EINA_LIST_FOREACH(sd->items, l, it)
+ {
+ Evas_Coord itx, ity;
+ Evas_Object *vit = VIEW(it);
+ Evas_Coord vx, vy, vw, vh;
+ evas_object_geometry_get(vit, &vx, &vy, &vw, &vh);
+
+ itx = vx;
+ ity = vy;
+ if (ELM_RECTS_INTERSECT
+ (itx, ity, vw, vh, x, y, 1, 1))
+ {
+ if (posret)
+ {
+ if (y <= (ity + (vh / 4))) *posret = -1;
+ else if (y >= (ity + vh - (vh / 4)))
+ *posret = 1;
+ else *posret = 0;
+ }
+
+ *ret = (Elm_Object_Item *) it;
+ return;
+ }
+
+ lasty = ity + vh;
+ }
+
+ if (posret)
+ {
+ if (y > lasty) *posret = 1;
+ else *posret = -1;
+ }
+
+ *ret = NULL;
+}
+
static void
_class_constructor(Eo_Class *klass)
{
EO_OP_FUNC(ELM_OBJ_LIST_ID(ELM_OBJ_LIST_SUB_ID_ITEM_SORTED_INSERT), _item_sorted_insert),
EO_OP_FUNC(ELM_OBJ_LIST_ID(ELM_OBJ_LIST_SUB_ID_FIRST_ITEM_GET), _first_item_get),
EO_OP_FUNC(ELM_OBJ_LIST_ID(ELM_OBJ_LIST_SUB_ID_LAST_ITEM_GET), _last_item_get),
+ EO_OP_FUNC(ELM_OBJ_LIST_ID(ELM_OBJ_LIST_SUB_ID_AT_XY_ITEM_GET), _at_xy_item_get),
EO_OP_FUNC_SENTINEL
};
eo_class_funcs_set(klass, func_desc);
EO_OP_DESCRIPTION(ELM_OBJ_LIST_SUB_ID_ITEM_SORTED_INSERT, "Insert a new item into the sorted list object."),
EO_OP_DESCRIPTION(ELM_OBJ_LIST_SUB_ID_FIRST_ITEM_GET, "Get the first item in the list."),
EO_OP_DESCRIPTION(ELM_OBJ_LIST_SUB_ID_LAST_ITEM_GET, "Get the last item in the list."),
+ EO_OP_DESCRIPTION(ELM_OBJ_LIST_SUB_ID_AT_XY_ITEM_GET, "Get the item that is at the x, y canvas coords."),
EO_OP_DESCRIPTION_SENTINEL
};
ELM_OBJ_LIST_SUB_ID_ITEM_SORTED_INSERT,
ELM_OBJ_LIST_SUB_ID_FIRST_ITEM_GET,
ELM_OBJ_LIST_SUB_ID_LAST_ITEM_GET,
+ ELM_OBJ_LIST_SUB_ID_AT_XY_ITEM_GET,
ELM_OBJ_LIST_SUB_ID_LAST
};
#define elm_obj_list_last_item_get(ret) ELM_OBJ_LIST_ID(ELM_OBJ_LIST_SUB_ID_LAST_ITEM_GET), EO_TYPECHECK(Elm_Object_Item **, ret)
/**
+ * @def elm_obj_list_at_xy_item_get
+ * @since 1.8
+ *
+ * Get the item that is at the x, y canvas coords.
+ *
+ * @param[in] x
+ * @param[in] y
+ * @param[out] posret
+ * @param[out] ret
+ *
+ * @see elm_list_at_xy_item_get
+ */
+#define elm_obj_list_at_xy_item_get(x, y, posret, ret) ELM_OBJ_LIST_ID(ELM_OBJ_LIST_SUB_ID_AT_XY_ITEM_GET), EO_TYPECHECK(Evas_Coord, x), EO_TYPECHECK(Evas_Coord, y), EO_TYPECHECK(int *, posret), EO_TYPECHECK(Elm_Object_Item **, ret)
+
+/**
* @}
*/
* @ingroup List
*/
EAPI Elm_Object_Item *elm_list_last_item_get(const Evas_Object *obj);
+
+/**
+ * Get the item that is at the x, y canvas coords.
+ *
+ * @param obj The list object.
+ * @param x The input x coordinate
+ * @param y The input y coordinate
+ * @param posret The position relative to the item returned here
+ * @return The item at the coordinates or NULL if none
+ *
+ * This returns the item at the given coordinates (which are canvas
+ * relative, not object-relative). If an item is at that coordinate,
+ * that item handle is returned, and if @p posret is not NULL, the
+ * integer pointed to is set to a value of -1, 0 or 1, depending if
+ * the coordinate is on the upper portion of that item (-1), on the
+ * middle section (0) or on the lower part (1). If NULL is returned as
+ * an item (no item found there), then posret may indicate -1 or 1
+ * based if the coordinate is above or below all items respectively in
+ * the list.
+ *
+ *
+ * @ingroup List
+ */
+EAPI Elm_Object_Item *elm_list_at_xy_item_get(const Evas_Object *obj, Evas_Coord x, Evas_Coord y, int *posret);