247 lines
6.7 KiB
C
247 lines
6.7 KiB
C
#include "e_efx_private.h"
|
|
|
|
typedef enum
|
|
{
|
|
NONE,
|
|
TOP_RIGHT,
|
|
BOTTOM_LEFT,
|
|
BOTTOM_RIGHT
|
|
} Anchor;
|
|
|
|
typedef struct E_Efx_Resize_Data
|
|
{
|
|
E_EFX *e;
|
|
E_Efx_Effect_Speed speed;
|
|
Ecore_Animator *anim;
|
|
int w, h;
|
|
int start_w, start_h;
|
|
E_Efx_End_Cb cb;
|
|
void *data;
|
|
Anchor anchor_type;
|
|
Evas_Point anchor;
|
|
Eina_Bool moving : 1;
|
|
} E_Efx_Resize_Data;
|
|
|
|
static void
|
|
_obj_del(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
|
|
{
|
|
E_Efx_Resize_Data *erd = data;
|
|
|
|
if (erd->anim) ecore_animator_del(erd->anim);
|
|
erd->e->resize_data = NULL;
|
|
if ((!erd->e->owner) && (!erd->e->followers)) e_efx_free(erd->e);
|
|
free(erd);
|
|
}
|
|
|
|
static void
|
|
_resize_anchor(E_Efx_Resize_Data *erd)
|
|
{
|
|
int x = 0, y = 0;
|
|
int cx, cy;
|
|
|
|
if (!erd->anchor_type) return;
|
|
|
|
_e_efx_resize_adjust(erd->e, &x, &y);
|
|
if ((!x) && (!y)) return;
|
|
|
|
if (erd->e->move_data)
|
|
cx = erd->e->x, cy = erd->e->y;
|
|
else
|
|
evas_object_geometry_get(erd->e->obj, &cx, &cy, NULL, NULL);
|
|
x += cx, y += cy;
|
|
evas_object_move(erd->e->obj, x, y);
|
|
}
|
|
|
|
static Eina_Bool
|
|
_resize_cb(E_Efx_Resize_Data *erd, double pos)
|
|
{
|
|
double factor;
|
|
|
|
if (pos < 1.0)
|
|
{
|
|
int w, h;
|
|
|
|
factor = ecore_animator_pos_map(pos, erd->speed, 0, 0);
|
|
w = lround(factor * (erd->w - erd->start_w)) + erd->start_w;
|
|
h = lround(factor * (erd->h - erd->start_h)) + erd->start_h;
|
|
//DBG("%p to (%dx%d)", erd->e->obj, w, h);
|
|
erd->e->w = w, erd->e->h = h;
|
|
evas_object_resize(erd->e->obj, w, h);
|
|
_resize_anchor(erd);
|
|
return EINA_TRUE;
|
|
}
|
|
/* lround will usually be off by 1 at the end, so we manually set this here */
|
|
erd->e->w = erd->w, erd->e->h = erd->h;
|
|
evas_object_resize(erd->e->obj, erd->w, erd->h);
|
|
_resize_anchor(erd);
|
|
|
|
erd->anim = NULL;
|
|
E_EFX_QUEUE_CHECK(erd);
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
static void
|
|
_resize_stop(Evas_Object *obj, Eina_Bool reset)
|
|
{
|
|
E_EFX *e;
|
|
E_Efx_Resize_Data *erd;
|
|
|
|
e = evas_object_data_get(obj, "e_efx-data");
|
|
if ((!e) || (!e->resize_data)) return;
|
|
erd = e->resize_data;
|
|
if (reset)
|
|
{
|
|
erd->e->w = erd->start_w, erd->e->h = erd->start_h;
|
|
evas_object_resize(obj, erd->start_w, erd->start_h);
|
|
evas_object_event_callback_del_full(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)_obj_del, erd);
|
|
if (erd->moving)
|
|
{
|
|
erd->moving = 0;
|
|
e_efx_move_reset(obj);
|
|
}
|
|
else if (e_efx_queue_complete(erd->e, erd))
|
|
e_efx_queue_process(erd->e);
|
|
_obj_del(erd, NULL, NULL, NULL);
|
|
INF("reset resized object %p", obj);
|
|
}
|
|
else
|
|
{
|
|
INF("stopped resized object %p", obj);
|
|
if (erd->anim) ecore_animator_del(erd->anim);
|
|
erd->anim = NULL;
|
|
if (erd->moving)
|
|
{
|
|
erd->moving = 0;
|
|
e_efx_move_stop(obj);
|
|
}
|
|
if (e_efx_queue_complete(erd->e, erd))
|
|
e_efx_queue_process(erd->e);
|
|
}
|
|
}
|
|
|
|
void
|
|
_e_efx_resize_adjust(E_EFX *e, int *ax, int *ay)
|
|
{
|
|
E_Efx_Resize_Data *erd = e->resize_data;
|
|
int x, y, w, h;
|
|
|
|
if ((!erd) || (!erd->anim)) return;
|
|
if (e->move_data)
|
|
x = e->x, y = e->y;
|
|
else
|
|
evas_object_geometry_get(e->obj, &x, &y, NULL, NULL);
|
|
w = e->w, h = e->h;
|
|
switch (erd->anchor_type)
|
|
{
|
|
case TOP_RIGHT:
|
|
*ax = erd->anchor.x - (x + w);
|
|
*ay = erd->anchor.y - y;
|
|
break;
|
|
case BOTTOM_LEFT:
|
|
*ax = erd->anchor.x - x;
|
|
*ay = erd->anchor.y - (y + h);
|
|
break;
|
|
case BOTTOM_RIGHT:
|
|
*ax = erd->anchor.x - (x + w);
|
|
*ay = erd->anchor.y - (y + h);
|
|
break;
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
EAPI Eina_Bool
|
|
e_efx_resize(Evas_Object *obj, E_Efx_Effect_Speed speed, const Evas_Point *position, int w, int h, double total_time, E_Efx_End_Cb cb, const void *data)
|
|
{
|
|
E_EFX *e;
|
|
E_Efx_Resize_Data *erd;
|
|
int x, y;
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
|
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(w < 0, EINA_FALSE);
|
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(h < 0, EINA_FALSE);
|
|
e = evas_object_data_get(obj, "e_efx-data");
|
|
if (!e) e = e_efx_new(obj);
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(e, EINA_FALSE);
|
|
erd = e->resize_data;
|
|
if (!erd)
|
|
{
|
|
e->resize_data = erd = calloc(1, sizeof(E_Efx_Resize_Data));
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(erd, EINA_FALSE);
|
|
evas_object_event_callback_add(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)_obj_del, e->resize_data);
|
|
}
|
|
|
|
erd->e = e;
|
|
erd->anchor_type = NONE;
|
|
erd->w = w;
|
|
erd->h = h;
|
|
erd->cb = cb;
|
|
erd->data = (void*)data;
|
|
evas_object_geometry_get(obj, &x, &y, &erd->start_w, &erd->start_h);
|
|
e->w = erd->start_w;
|
|
e->h = erd->start_h;
|
|
if (e->move_data)
|
|
x = e->x, y = e->y;
|
|
INF("resize: %p || %dx%d => %dx%d %s over %gs", obj, erd->start_w, erd->start_h, w, h, e_efx_speed_str[speed], total_time);
|
|
if (position)
|
|
{
|
|
if ((position->x != x) || (position->y != y))
|
|
{
|
|
Evas_Point tr, bl, br;
|
|
Evas_Point atr, abl, abr;
|
|
|
|
tr = (Evas_Point){x + erd->start_w, y};
|
|
bl = (Evas_Point){x, y + erd->start_h};
|
|
br = (Evas_Point){x + erd->start_w, y + erd->start_h};
|
|
atr = (Evas_Point){position->x + w, position->y};
|
|
abl = (Evas_Point){position->x, position->y + h};
|
|
abr = (Evas_Point){position->x + w, position->y + h};
|
|
if (!memcmp(&tr, &atr, sizeof(Evas_Point)))
|
|
{
|
|
erd->anchor_type = TOP_RIGHT;
|
|
erd->anchor = tr;
|
|
}
|
|
else if (!memcmp(&bl, &abl, sizeof(Evas_Point)))
|
|
{
|
|
erd->anchor_type = BOTTOM_LEFT;
|
|
erd->anchor = bl;
|
|
}
|
|
else if (!memcmp(&br, &abr, sizeof(Evas_Point)))
|
|
{
|
|
erd->anchor_type = BOTTOM_RIGHT;
|
|
erd->anchor = br;
|
|
}
|
|
|
|
if (!e_efx_move(obj, speed, position, total_time, NULL, NULL))
|
|
{
|
|
evas_object_event_callback_del_full(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)_obj_del, e->resize_data);
|
|
free(erd);
|
|
e->resize_data = NULL;
|
|
e_efx_free(e);
|
|
return EINA_FALSE;
|
|
}
|
|
else
|
|
erd->moving = 1;
|
|
}
|
|
else
|
|
evas_object_move(obj, position->x, position->y);
|
|
}
|
|
if (!eina_dbl_exact(total_time, 0))
|
|
erd->anim = ecore_animator_timeline_add(total_time, (Ecore_Timeline_Cb)_resize_cb, erd);
|
|
else
|
|
_resize_cb(erd, 1.0);
|
|
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
EAPI void
|
|
e_efx_resize_reset(Evas_Object *obj)
|
|
{
|
|
_resize_stop(obj, EINA_TRUE);
|
|
}
|
|
|
|
EAPI void
|
|
e_efx_resize_stop(Evas_Object *obj)
|
|
{
|
|
_resize_stop(obj, EINA_FALSE);
|
|
}
|