1 #include "e_efx_private.h"
2
3 typedef enum
4 {
5 NONE,
6 TOP_RIGHT,
7 BOTTOM_LEFT,
8 BOTTOM_RIGHT
9 } Anchor;
10
11 typedef struct E_Efx_Resize_Data
12 {
13 E_EFX *e;
14 E_Efx_Effect_Speed speed;
15 Ecore_Animator *anim;
16 int w, h;
17 int start_w, start_h;
18 E_Efx_End_Cb cb;
19 void *data;
20 Anchor anchor_type;
21 Evas_Point anchor;
22 Eina_Bool moving : 1;
23 } E_Efx_Resize_Data;
24
25 static void
_obj_del(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)26 _obj_del(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
27 {
28 E_Efx_Resize_Data *erd = data;
29
30 if (erd->anim) ecore_animator_del(erd->anim);
31 erd->e->resize_data = NULL;
32 if ((!erd->e->owner) && (!erd->e->followers)) e_efx_free(erd->e);
33 free(erd);
34 }
35
36 static void
_resize_anchor(E_Efx_Resize_Data * erd)37 _resize_anchor(E_Efx_Resize_Data *erd)
38 {
39 int x = 0, y = 0;
40 int cx, cy;
41
42 if (!erd->anchor_type) return;
43
44 _e_efx_resize_adjust(erd->e, &x, &y);
45 if ((!x) && (!y)) return;
46
47 if (erd->e->move_data)
48 cx = erd->e->x, cy = erd->e->y;
49 else
50 evas_object_geometry_get(erd->e->obj, &cx, &cy, NULL, NULL);
51 x += cx, y += cy;
52 evas_object_move(erd->e->obj, x, y);
53 }
54
55 static Eina_Bool
_resize_cb(E_Efx_Resize_Data * erd,double pos)56 _resize_cb(E_Efx_Resize_Data *erd, double pos)
57 {
58 double factor;
59
60 if (pos < 1.0)
61 {
62 int w, h;
63
64 factor = ecore_animator_pos_map(pos, (Ecore_Pos_Map)erd->speed, 0, 0);
65 w = lround(factor * (erd->w - erd->start_w)) + erd->start_w;
66 h = lround(factor * (erd->h - erd->start_h)) + erd->start_h;
67 //DBG("%p to (%dx%d)", erd->e->obj, w, h);
68 erd->e->w = w, erd->e->h = h;
69 evas_object_resize(erd->e->obj, w, h);
70 _resize_anchor(erd);
71 return EINA_TRUE;
72 }
73 /* lround will usually be off by 1 at the end, so we manually set this here */
74 erd->e->w = erd->w, erd->e->h = erd->h;
75 evas_object_resize(erd->e->obj, erd->w, erd->h);
76 _resize_anchor(erd);
77
78 erd->anim = NULL;
79 E_EFX_QUEUE_CHECK(erd);
80 return EINA_TRUE;
81 }
82
83 static void
_resize_stop(Evas_Object * obj,Eina_Bool reset)84 _resize_stop(Evas_Object *obj, Eina_Bool reset)
85 {
86 E_EFX *e;
87 E_Efx_Resize_Data *erd;
88
89 e = evas_object_data_get(obj, "e_efx-data");
90 if ((!e) || (!e->resize_data)) return;
91 erd = e->resize_data;
92 if (reset)
93 {
94 erd->e->w = erd->start_w, erd->e->h = erd->start_h;
95 evas_object_resize(obj, erd->start_w, erd->start_h);
96 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)_obj_del, erd);
97 if (erd->moving)
98 {
99 erd->moving = 0;
100 e_efx_move_reset(obj);
101 }
102 else if (e_efx_queue_complete(erd->e, erd))
103 e_efx_queue_process(erd->e);
104 _obj_del(erd, NULL, NULL, NULL);
105 INF("reset resized object %p", obj);
106 }
107 else
108 {
109 INF("stopped resized object %p", obj);
110 if (erd->anim) ecore_animator_del(erd->anim);
111 erd->anim = NULL;
112 if (erd->moving)
113 {
114 erd->moving = 0;
115 e_efx_move_stop(obj);
116 }
117 if (e_efx_queue_complete(erd->e, erd))
118 e_efx_queue_process(erd->e);
119 }
120 }
121
122 void
_e_efx_resize_adjust(E_EFX * e,int * ax,int * ay)123 _e_efx_resize_adjust(E_EFX *e, int *ax, int *ay)
124 {
125 E_Efx_Resize_Data *erd = e->resize_data;
126 int x, y, w, h;
127
128 if ((!erd) || (!erd->anim)) return;
129 if (e->move_data)
130 x = e->x, y = e->y;
131 else
132 evas_object_geometry_get(e->obj, &x, &y, NULL, NULL);
133 w = e->w, h = e->h;
134 switch (erd->anchor_type)
135 {
136 case TOP_RIGHT:
137 *ax = erd->anchor.x - (x + w);
138 *ay = erd->anchor.y - y;
139 break;
140 case BOTTOM_LEFT:
141 *ax = erd->anchor.x - x;
142 *ay = erd->anchor.y - (y + h);
143 break;
144 case BOTTOM_RIGHT:
145 *ax = erd->anchor.x - (x + w);
146 *ay = erd->anchor.y - (y + h);
147 break;
148 default: break;
149 }
150 }
151
152 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)153 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)
154 {
155 E_EFX *e;
156 E_Efx_Resize_Data *erd;
157 int x, y;
158
159 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
160 EINA_SAFETY_ON_TRUE_RETURN_VAL(w < 0, EINA_FALSE);
161 EINA_SAFETY_ON_TRUE_RETURN_VAL(h < 0, EINA_FALSE);
162 e = evas_object_data_get(obj, "e_efx-data");
163 if (!e) e = e_efx_new(obj);
164 EINA_SAFETY_ON_NULL_RETURN_VAL(e, EINA_FALSE);
165 erd = e->resize_data;
166 if (!erd)
167 {
168 e->resize_data = erd = calloc(1, sizeof(E_Efx_Resize_Data));
169 EINA_SAFETY_ON_NULL_RETURN_VAL(erd, EINA_FALSE);
170 evas_object_event_callback_add(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)_obj_del, e->resize_data);
171 }
172
173 erd->e = e;
174 erd->anchor_type = NONE;
175 erd->w = w;
176 erd->h = h;
177 erd->cb = cb;
178 erd->data = (void*)data;
179 evas_object_geometry_get(obj, &x, &y, &erd->start_w, &erd->start_h);
180 e->w = erd->start_w;
181 e->h = erd->start_h;
182 if (e->move_data)
183 x = e->x, y = e->y;
184 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);
185 if (position)
186 {
187 if ((position->x != x) || (position->y != y))
188 {
189 Evas_Point tr, bl, br;
190 Evas_Point atr, abl, abr;
191
192 tr = (Evas_Point){x + erd->start_w, y};
193 bl = (Evas_Point){x, y + erd->start_h};
194 br = (Evas_Point){x + erd->start_w, y + erd->start_h};
195 atr = (Evas_Point){position->x + w, position->y};
196 abl = (Evas_Point){position->x, position->y + h};
197 abr = (Evas_Point){position->x + w, position->y + h};
198 if (!memcmp(&tr, &atr, sizeof(Evas_Point)))
199 {
200 erd->anchor_type = TOP_RIGHT;
201 erd->anchor = tr;
202 }
203 else if (!memcmp(&bl, &abl, sizeof(Evas_Point)))
204 {
205 erd->anchor_type = BOTTOM_LEFT;
206 erd->anchor = bl;
207 }
208 else if (!memcmp(&br, &abr, sizeof(Evas_Point)))
209 {
210 erd->anchor_type = BOTTOM_RIGHT;
211 erd->anchor = br;
212 }
213
214 if (!e_efx_move(obj, speed, position, total_time, NULL, NULL))
215 {
216 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_FREE, (Evas_Object_Event_Cb)_obj_del, e->resize_data);
217 free(erd);
218 e->resize_data = NULL;
219 e_efx_free(e);
220 return EINA_FALSE;
221 }
222 else
223 erd->moving = 1;
224 }
225 else
226 evas_object_move(obj, position->x, position->y);
227 }
228 if (!eina_dbl_exact(total_time, 0))
229 erd->anim = ecore_animator_timeline_add(total_time, (Ecore_Timeline_Cb)_resize_cb, erd);
230 else
231 _resize_cb(erd, 1.0);
232
233 return EINA_TRUE;
234 }
235
236 EAPI void
e_efx_resize_reset(Evas_Object * obj)237 e_efx_resize_reset(Evas_Object *obj)
238 {
239 _resize_stop(obj, EINA_TRUE);
240 }
241
242 EAPI void
e_efx_resize_stop(Evas_Object * obj)243 e_efx_resize_stop(Evas_Object *obj)
244 {
245 _resize_stop(obj, EINA_FALSE);
246 }
247