efm2/src/efm/efm_dnd.c

280 lines
8.0 KiB
C

// utils for draga and drop handling
static Eina_Bool
_cb_dnd_scroll_timer(void *data)
{
Smart_Data *sd = data;
Evas_Coord fmx, fmy, sx, sy, sw, sh, x, y;
Evas_Coord scr_edge_x, scr_edge_y, scr_mul;
evas_object_geometry_get(sd->o_smart, &fmx, &fmy, NULL, NULL);
evas_object_geometry_get(sd->o_scroller, &sx, &sy, &sw, &sh);
scr_mul = 4;
scr_edge_x = sd->icon_min_w / 2;
scr_edge_y = sd->icon_min_h / 2;
if (sd->dnd_scroll_x < scr_edge_x)
x = sx - fmx + sd->dnd_scroll_x - scr_edge_x - ((scr_edge_x - sd->dnd_scroll_x) * scr_mul);
else if (sd->dnd_scroll_x > (sw - scr_edge_x))
x = sx - fmx + sd->dnd_scroll_x + scr_edge_x + ((sd->dnd_scroll_x - (sw - scr_edge_x)) * scr_mul);
else
x = sx - fmx + sd->dnd_scroll_x;
if (sd->dnd_scroll_y < scr_edge_y)
y = sy - fmy + sd->dnd_scroll_y - scr_edge_y - ((scr_edge_y - sd->dnd_scroll_y) * scr_mul);
else if (sd->dnd_scroll_y > (sh - scr_edge_y))
y = sy - fmy + sd->dnd_scroll_y + scr_edge_y + ((sd->dnd_scroll_y - (sh - scr_edge_y)) * scr_mul);
else
y = sy - fmy + sd->dnd_scroll_y;
printf("SSS %i %i | %i %i %ix%i | %i %i\n", x, y, sx, sy, sw, sh, sd->dnd_scroll_x, sd->dnd_scroll_y);
elm_scroller_region_bring_in(sd->o_scroller, x, y, 1, 1);
return EINA_TRUE;
}
static void
_dnd_scroll_handle(Smart_Data *sd, Evas_Coord x, Evas_Coord y)
{
sd->dnd_scroll_x = x;
sd->dnd_scroll_y = y;
if (!sd->dnd_scroll_timer)
sd->dnd_scroll_timer = ecore_timer_add
(SCROLL_DND_TIMER, _cb_dnd_scroll_timer, sd);
}
static void
_dnd_scroll_end_handle(Smart_Data *sd)
{
if (sd->dnd_scroll_timer)
{
ecore_timer_del(sd->dnd_scroll_timer);
sd->dnd_scroll_timer = NULL;
}
}
static void
_dnd_over(Icon *icon)
{
_icon_over_on(icon);
}
static void
_dnd_over_none_handle(Smart_Data *sd)
{
if (sd->over_icon) _icon_over_off(sd->over_icon);
}
static void
_dnd_over_handle(Smart_Data *sd, Evas_Coord x, Evas_Coord y)
{
Icon *icon;
Eina_List *bl, *il;
Block *block;
EINA_LIST_FOREACH(sd->blocks, bl, block)
{
if (!eina_rectangle_coords_inside(&(block->bounds), x, y)) continue;
EINA_LIST_FOREACH(block->icons, il, icon)
{
if (!eina_rectangle_coords_inside(&(icon->geom), x, y)) continue;
_dnd_over(icon);
return;
}
}
_dnd_over_none_handle(sd);
}
// drop handling
static void
_cb_drop_in(void *data EINA_UNUSED, Evas_Object *o EINA_UNUSED)
{
// Smart_Data *sd = data;
printf("XXX: drop in.....\n");
// XXX: call drop in smart callback}
}
static void
_cb_drop_out(void *data, Evas_Object *o EINA_UNUSED)
{
Smart_Data *sd = data;
_dnd_scroll_end_handle(sd);
_dnd_over_none_handle(sd);
printf("XXX: drop out.....\n");
// XXX: call drop out smart callback}
}
void
_cb_drop_pos(void *data, Evas_Object *o EINA_UNUSED, Evas_Coord x, Evas_Coord y, Elm_Xdnd_Action action EINA_UNUSED)
{
Smart_Data *sd = data;
Evas_Coord fmx, fmy, fmw, fmh;
Evas_Coord sx, sy, sw, sh;
sd->dnd_action = action;
evas_object_geometry_get(sd->o_smart, &fmx, &fmy, &fmw, &fmh);
evas_object_geometry_get(sd->o_scroller, &sx, &sy, &sw, &sh);
_dnd_scroll_handle(sd, x - sx, y - sy);
if (((x - sx) > 0) && ((y - sy) > 0) &&
((x - sx) < sw) && ((y - sy) < sh))
_dnd_over_handle(sd, x - fmx, y - fmy);
else
_dnd_over_none_handle(sd);
if (sd->over_icon) sd->drop_over = sd->over_icon;
else sd->drop_over = NULL;
}
static Eina_Bool
_cb_drop(void *data, Evas_Object *o EINA_UNUSED, Elm_Selection_Data *ev)
{
Smart_Data *sd = data;
char **plist, **p, *esc, *tmp;
if (sd->drop_over) printf("XXX: DND DROP OVER [%s]\n", sd->drop_over->info.file);
else printf("XXX: DND DROP ...\n");
tmp = malloc(ev->len + 1);
if (!tmp) goto err;
memcpy(tmp, ev->data, ev->len);
tmp[ev->len] = 0;
plist = eina_str_split(tmp, "\n", -1);
for (p = plist; *p != NULL; ++p)
{
if (**p)
{
esc = _escape_parse(*p);
if (!esc) continue;
printf("XXX: DROP FILE: [%s]\n", esc);
}
}
free(*plist);
free(plist);
free(tmp);
err:
sd->drop_over = NULL;
return EINA_TRUE;
}
static void
_drop_init(Smart_Data *sd)
{ // called once we have our elm scroller around our file view
elm_drop_target_add(sd->o_scroller,
ELM_SEL_FORMAT_URILIST,
_cb_drop_in, sd,
_cb_drop_out, sd,
_cb_drop_pos, sd,
_cb_drop, sd);
}
// drag handling
static Evas_Object *
_cb_drag_icon_add(void *data, Evas_Object *parent, Evas_Coord *xoff, Evas_Coord *yoff)
{
Icon *icon = data;
Icon *icon2;
Block *block;
Evas_Object *obj = icon->sd->o_smart;
Evas_Object *o;
const char *theme_edj_file;
Evas *e;
ENTRY NULL;
Eina_List *bl, *il;
int num = 0;
if (sd->config.view_mode >= EFM_VIEW_MODE_LIST)
{
EINA_LIST_FOREACH(sd->blocks, bl, block)
{
if (block->realized_num <= 0)
{
num += eina_list_count(block->icons);
continue;
}
EINA_LIST_FOREACH(block->icons, il, icon2)
{
if (icon == icon2) goto found;
num++;
}
num += eina_list_count(block->icons);
}
}
found:
e = evas_object_evas_get(parent);
theme_edj_file = elm_theme_group_path_find(NULL,
"e/fileman/default/icon/fixed");
_icon_object_add(icon, icon->sd, e, theme_edj_file, EINA_FALSE, num);
o = icon->o_base;
evas_object_resize(o, icon->geom.w, icon->geom.h);
if (xoff) *xoff = (icon->geom.x + icon->sd->geom.x);
if (yoff) *yoff = (icon->geom.y + icon->sd->geom.y);
if (xoff && yoff)
printf("DND: drag begin %p %p off: %i %i\n", obj, o, *xoff, *yoff);
else
printf("DND: drag begin %p %p\n", obj, o);
return o;
}
static void
_cb_drag_pos(void *data EINA_UNUSED, Evas_Object *obj_drag EINA_UNUSED, Evas_Coord x, Evas_Coord y, Elm_Xdnd_Action action)
{
printf("DND: %i %i act=%i\n", x, y, action);
}
static void
_cb_drag_accept(void *data EINA_UNUSED, Evas_Object *obj_drag EINA_UNUSED, Eina_Bool accept)
{
printf("DND: accept %i\n", accept);
}
static void
_cb_drag_done(void *data, Evas_Object *obj_drag EINA_UNUSED)
{
Icon *icon = data;
Evas_Object *obj;
if (icon->sd)
{
obj = icon->sd->o_smart;
ENTRY;
printf("DND: drag done %p %p\n", obj, obj_drag);
sd->drag = EINA_FALSE;
icon->o_base = NULL; // try and not del this as dnd will do it
icon->sd->drag_icon = NULL;
}
_icon_free(icon);
}
static void
_drag_start(Icon *icon)
{
Eina_Strbuf *strbuf;
Icon *icon_dup;
strbuf = eina_strbuf_new();
if (!strbuf) return;
icon_dup = _icon_dup(icon);
if (!icon_dup) goto err;
if (icon->sd->rename_icon) _icon_rename_end(icon->sd->rename_icon);
printf("XXX: begin dnd\n");
icon->sd->drag = EINA_TRUE;
icon->sd->just_dragged = EINA_TRUE;
icon->sd->drag_icon = icon_dup;
if (_selected_icons_uri_strbuf_append(icon->sd, strbuf))
{ // begin the drag with that list of files
// XXX: if you use no modifier - do default (move)
// XXX: if you hold ctrl then do copy
// XXX: on win ... to/from removable drive it copies always
// XXX: if you hold shift then do move
// XXX; on mac option key forces a copy normally except from
// removable device then it forces a move
// XXX: this "except to/from removable drive" is bad/inconsistent imho
elm_drag_start(icon_dup->sd->o_scroller,
ELM_SEL_FORMAT_URILIST,
eina_strbuf_string_get(strbuf),
ELM_XDND_ACTION_MOVE,
_cb_drag_icon_add, icon_dup,
_cb_drag_pos, icon_dup,
_cb_drag_accept, icon_dup,
_cb_drag_done, icon_dup);
}
err:
eina_strbuf_free(strbuf);
}