Revise the comment and remove unsed functions
[framework/uifw/elementary.git] / src / lib / elm_imageslider.c
1 /* 
2
3 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 
4 */
5 #include <stdio.h>
6 #include <math.h>
7 #include <Elementary.h>
8 #include "elm_priv.h"
9
10 /**
11 * @defgroup Imageslider Imageslider
12 * @ingroup Elementary
13 */
14
15 typedef struct _Widget_Data Widget_Data;
16
17 #define ANI_STEP                                (14 * elm_scale_get())
18 #define ANI_TIME                                (0.005)
19 #define ANI_TIME_MSEC           (12)
20 #define FLICK_TIME_MAX          (200)
21 #define FLICK_WIDTH_MIN (elm_finger_size_get() >> 2)
22 #define MOVE_STEP                       (3)
23 #define STEP_WEIGHT_DEF (1)
24 #define STEP_WEIGHT_MAX (2)
25 #define STEP_WEIGHT_MIN (0)
26 #define MOVING_IMAGE_SIZE       (128)
27 #define MAX_ZOOM_SIZE           (6)
28 #define INTERVAL_WIDTH          (15)
29 #define MULTITOUCHDEVICE        (11)
30
31 enum {
32         BLOCK_LEFT = 0,
33         BLOCK_CENTER,
34         BLOCK_RIGHT,
35         BLOCK_MAX
36 };
37
38 struct _Imageslider_Item 
39 {
40         Evas_Object *obj;
41         const char *photo_file;
42         void (*func)(void *data, Evas_Object *obj, void *event_info);
43         void *data;
44         Evas_Coord x, y, w, h;
45         Evas_Coord ox, oy, ow, oh;
46         int moving : 1;
47 };
48
49 struct _Widget_Data
50 {
51         Evas_Object *ly[BLOCK_MAX];
52         Evas_Object *clip;
53         Eina_List *its;
54         Eina_List *cur;
55         Evas_Coord x, y, w, h;
56         Evas_Object *obj;
57
58         Evas_Coord_Point down_pos;
59         Evas_Coord move_x;
60         Evas_Coord move_y;
61         Evas_Coord dest_x;
62         struct timeval tv;
63         unsigned int timestamp;
64         int step;
65         int move_cnt;
66         int ani_lock : 1;
67         int moving : 1;
68
69         Eina_Bool on_zoom : 1;
70         Eina_Bool on_hold : 1;
71         int dx, dy, mx, my;
72         int mdx, mdy, mmx, mmy;
73         int dratio;
74         int ratio;
75 };
76
77
78 static const char *widtype = NULL;
79 static void _del_hook(Evas_Object *obj);
80 static void _theme_hook(Evas_Object *obj);
81 static void _sizing_eval(Evas_Object *obj);
82 static void _imageslider_del_all(Widget_Data *wd);
83 static void _imageslider_move(void *data,Evas *e, Evas_Object *obj, void *event_info);
84 static void _imageslider_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
85 //static void _imageslider_show(Evas_Object *obj);
86 //static void _imageslider_hide(Evas_Object *obj);
87 static void _imageslider_show(void * data, Evas * e, Evas_Object * obj, void * event_info);
88 static void _imageslider_hide(void * data, Evas * e, Evas_Object * obj, void * event_info);
89 static void _imageslider_update(Widget_Data *wd);
90 static void _imageslider_update_pos(Widget_Data *wd, Evas_Coord x, Evas_Coord y, Evas_Coord w);
91 static void _imageslider_update_center_pos(Widget_Data *wd, Evas_Coord x, Evas_Coord my, Evas_Coord y, Evas_Coord w);
92 static Evas_Object *_imageslider_add_obj(Widget_Data *wd);
93 static void _imageslider_obj_shift(Widget_Data *wd, Eina_Bool left);
94 static void _imageslider_obj_move(Widget_Data *wd, Evas_Coord step);
95 static int _icon_to_image(void *data);
96 static int _check_drag(int state, void *data);
97 static void _check_zoom(void *data);
98 static void _anim(Widget_Data *wd);
99 static int _timer_cb(void *data);
100 static void ev_imageslider_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
101 static void ev_imageslider_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
102 static void ev_imageslider_move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
103
104 static void _del_hook(Evas_Object * obj)
105 {
106         int i;
107         Widget_Data * wd;
108         wd = elm_widget_data_get(obj);
109
110         if (!wd) return;
111
112         for (i = 0; i < BLOCK_MAX; i++) {
113                 evas_object_del(wd->ly[i]);
114         }
115
116         if (wd->its) {
117                 eina_list_free(wd->its);
118                 wd->its = NULL;
119         }
120
121         if (wd) free(wd);
122         
123 }
124
125 static void _theme_hook(Evas_Object * obj)
126 {
127         int i;
128         Widget_Data *wd;
129         wd = elm_widget_data_get(obj);
130
131         if (!wd || !wd->ly ) {
132                 return;
133         }
134
135         for (i=0; i < BLOCK_MAX; i++) {
136                 wd->ly[i] = elm_layout_add(obj);
137                 _elm_theme_object_set(obj, wd->ly[i], "imageslider", "base", "default");
138                 elm_widget_resize_object_set(obj, wd->ly[i]);
139                 evas_object_show(wd->ly[i]);                    
140         }
141
142         _sizing_eval(obj);      
143 }
144
145
146 static void _sizing_eval(Evas_Object * obj)
147 {
148         Evas *e;
149         Widget_Data *wd = elm_widget_data_get(obj);
150
151         if (!wd) {
152                 return;
153         }
154
155         e = evas_object_evas_get(wd->obj);
156
157         _imageslider_move(obj, e, obj, NULL);
158         _imageslider_resize(obj, e, obj, NULL);
159
160 }
161
162 static void _imageslider_move(void * data, Evas * e, Evas_Object * obj, void * event_info)
163 {
164         Widget_Data *wd;
165         Evas_Coord x, y;
166
167         if (!data) {
168                 return;
169         }
170         
171         wd = elm_widget_data_get((Evas_Object *) data);
172         if (!wd) {
173                 return;
174         }
175
176         evas_object_geometry_get(obj, &x, &y, NULL, NULL);
177         wd->x = x;
178         wd->y = y;
179         evas_object_move(wd->clip, x, y);
180         
181         _imageslider_update_pos(wd, wd->x, wd->y, wd->w);
182         
183 }
184
185 static void _imageslider_resize(void * data, Evas * e, Evas_Object * obj, void * event_info)
186 {
187         int i;
188         Widget_Data *wd;
189         Evas_Coord w, h;
190
191         if (!data) {
192                 return;
193         }
194                 
195         wd = elm_widget_data_get((Evas_Object *) data);
196         if (!wd || !wd->ly) {
197                 return;         
198         }
199
200         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
201         fprintf( stderr, "%d %d -resize\n" , w, h );
202         wd->w = w;
203         wd->h = h;
204
205         for (i = 0; i < BLOCK_MAX; i++) {
206                 evas_object_resize(wd->ly[i], w, h);
207         }
208
209         evas_object_resize(wd->clip, w, h);
210
211         _imageslider_update_pos(wd, wd->x, wd->y, wd->w);
212         
213 }
214
215
216 //static void _imageslider_show(Evas_Object * obj)
217 static void _imageslider_show(void *data, Evas *e, Evas_Object * obj, void *event_info)
218 {
219         Widget_Data *wd;
220
221         if (!data) {
222                 return;
223         }
224         
225         wd = elm_widget_data_get((Evas_Object *) data);
226         if (!wd) {
227                 return;
228         }
229         
230         evas_object_show(wd->clip);
231 }
232
233 //static void _imageslider_hide(Evas_Object *obj)
234 static void _imageslider_hide(void *data, Evas *e, Evas_Object *obj, void *event_info)
235 {
236         Widget_Data *wd;
237
238         if (!data) {
239                 return;
240         }
241         
242         wd = elm_widget_data_get((Evas_Object *) data);
243         if (!wd) {
244                 return;
245         }
246         evas_object_hide(wd->clip);
247 }
248
249 static void _imageslider_del_all(Widget_Data * wd)
250 {
251         int i;
252         
253         if (!wd) {
254                 return;
255         }
256
257         for (i = 0; i < BLOCK_MAX; i++) {
258                 evas_object_del(wd->ly[i]);
259         }
260 }
261
262 static void _imageslider_update_pos(Widget_Data * wd, Evas_Coord x, Evas_Coord y, Evas_Coord w)
263 {
264         evas_object_move(wd->ly[BLOCK_LEFT], x - (w + INTERVAL_WIDTH), y);
265         evas_object_move(wd->ly[BLOCK_CENTER], x, y);
266         evas_object_move(wd->ly[BLOCK_RIGHT], x + (w + INTERVAL_WIDTH), y);
267         evas_render_idle_flush(evas_object_evas_get(wd->obj));
268 }
269
270 static void _imageslider_update_center_pos(Widget_Data * wd, Evas_Coord x, Evas_Coord my, Evas_Coord y, Evas_Coord w)
271 {
272         Evas_Object *eo;
273         Evas_Coord ix, iy, iw, ih;
274
275         eo = edje_object_part_swallow_get(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "swl.photo");
276         evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
277
278         if ((ix > 0) || (ix + iw < wd->w)) {
279                 edje_object_signal_emit(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "block.on", "block");
280 //              edje_freeze();
281 //              evas_event_feed_mouse_cancel(evas_object_evas_get(wd->obj), NULL, NULL);
282 //              evas_event_feed_mouse_down(evas_object_evas_get(wd->obj), 1, EVAS_BUTTON_NONE, NULL, NULL);             
283
284                 _imageslider_update_pos(wd, x, y, w);
285                 wd->on_zoom = EINA_FALSE;
286         }
287 }
288
289 static Evas_Object *_imageslider_add_obj(Widget_Data *wd)
290 {
291         Evas_Object *eo;
292         eo = elm_layout_add(wd->obj);
293         elm_layout_theme_set(eo, "imageslider", "base", "default");
294         elm_widget_resize_object_set(wd->obj, eo);
295 //      evas_object_smart_member_add(eo, wd->obj);
296         evas_object_event_callback_add(eo, EVAS_CALLBACK_MOUSE_DOWN, ev_imageslider_down_cb, wd);
297         evas_object_event_callback_add(eo, EVAS_CALLBACK_MOUSE_UP, ev_imageslider_up_cb, wd);
298         evas_object_event_callback_add(eo, EVAS_CALLBACK_MOUSE_MOVE, ev_imageslider_move_cb, wd);
299         evas_object_resize(eo, wd->w, wd->h);
300         evas_object_move(eo, wd->w + INTERVAL_WIDTH, wd->y);
301         evas_object_clip_set(eo, wd->clip);
302         evas_object_show(eo);
303
304         return eo;
305 }
306
307 static void _imageslider_obj_shift(Widget_Data *wd, Eina_Bool left)
308 {
309         if (!left) {
310                 if (wd->ly[BLOCK_LEFT]) {
311                         evas_object_del(wd->ly[BLOCK_LEFT]);
312                         wd->ly[BLOCK_LEFT] = NULL;
313                 }
314
315                 wd->ly[BLOCK_LEFT] = wd->ly[BLOCK_CENTER];
316                 wd->ly[BLOCK_CENTER]= wd->ly[BLOCK_RIGHT];
317                 wd->ly[BLOCK_RIGHT] = _imageslider_add_obj(wd);
318         } else {
319                 if (wd->ly[BLOCK_RIGHT]) {
320                         evas_object_del(wd->ly[BLOCK_RIGHT]);
321                         wd->ly[BLOCK_RIGHT] = NULL;
322                 }
323
324                 wd->ly[BLOCK_RIGHT]= wd->ly[BLOCK_CENTER];
325                 wd->ly[BLOCK_CENTER]= wd->ly[BLOCK_LEFT];
326                 wd->ly[BLOCK_LEFT]= _imageslider_add_obj(wd);
327         }
328 }
329
330
331 static void _imageslider_obj_move(Widget_Data * wd, Evas_Coord step)
332 {
333         if (step > 0) {
334                 wd->cur = eina_list_next(wd->cur);
335                 if (wd->cur == NULL) {
336                         wd->cur = eina_list_last(wd->its);
337                         wd->step = ANI_STEP;
338                 } else {
339                         wd->step = -ANI_STEP;
340                         wd->move_x += wd->w;
341                         _imageslider_obj_shift(wd, 0);
342                 }
343                 wd->moving = 1;         
344         } else if (step < 0) {
345                 wd->cur = eina_list_prev(wd->cur);
346                 if (wd->cur == NULL) {
347                         wd->cur = wd->its;
348                         wd->step = -ANI_STEP;
349                 } else {
350                         wd->step = ANI_STEP;
351                         wd->move_x -= wd->w;
352                         _imageslider_obj_shift(wd, 1);
353                 }
354                 wd->moving = 1;
355         } else {
356                 if (wd->move_x < 0) wd->step = ANI_STEP;
357                 else wd->step = -ANI_STEP;
358                 wd->moving = 0;
359         }
360
361         _imageslider_update(wd);
362 }
363
364 static void ev_imageslider_down_cb(void * data, Evas * e, Evas_Object * obj, void * event_info)
365 {
366         Widget_Data *wd = data;
367         Evas_Event_Mouse_Down *ev = event_info;
368         Evas_Coord ix, iy, iw, ih;
369         Evas_Object *eo = NULL;
370
371         if (wd->ani_lock) return;
372
373         wd->down_pos = ev->canvas;
374         wd->timestamp = ev->timestamp;
375         wd->move_cnt = MOVE_STEP;
376
377         wd->dx = ev->canvas.x;
378         wd->dy = ev->canvas.y;
379         wd->mx = ev->canvas.x;
380         wd->my = ev->canvas.y;
381
382         wd->dratio = 1;
383         wd->ratio = 1;
384
385         eo = edje_object_part_swallow_get(elm_layout_edje_get(obj), "swl.photo");
386         if (eo) evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
387
388         if (iw != wd->w) {
389                 wd->on_zoom = EINA_TRUE;
390                 edje_object_signal_emit(elm_layout_edje_get(obj), "block.off", "block");
391 //              edje_thaw();            
392         }
393
394         fprintf( stderr, "down!\n" );
395
396 }
397
398 static void ev_imageslider_up_cb(void * data, Evas * e, Evas_Object * obj, void * event_info)
399 {
400         Widget_Data *wd = data;
401         Evas_Event_Mouse_Up *ev = event_info;
402         Evas_Coord step;
403         int interval;
404
405         if (wd->ani_lock) return;
406
407         if (wd->on_zoom) {              
408         } else {
409                 step = wd->down_pos.x - ev->canvas.x;
410                 interval = ev->timestamp - wd->timestamp;
411                 if (step == 0 || interval == 0) return;
412
413                 if (interval < FLICK_TIME_MAX) {
414                         if (step < FLICK_WIDTH_MIN && step > FLICK_WIDTH_MIN) _imageslider_obj_move(wd, 0);
415                         else _imageslider_obj_move(wd, step);
416                 } else {
417                         step = (wd->x - wd->move_x) << 1;
418                         if (step <= wd->w && step >= -(wd->w)) _imageslider_obj_move(wd, 0);
419                         else _imageslider_obj_move(wd, step);
420                 }
421         }
422
423 }
424
425 static void ev_imageslider_move_cb(void * data, Evas * e, Evas_Object * obj, void * event_info)
426 {
427         int idx;
428         Evas_Object *eo;
429         Evas_Coord step;
430         Widget_Data *wd = data;
431         Evas_Event_Mouse_Move *ev = event_info;
432         Elm_Imageslider_Item *it;
433
434         if (wd->ani_lock) return;
435
436         if (wd->move_cnt == MOVE_STEP) {
437                 if (wd->on_hold == EINA_FALSE) {
438                         wd->move_cnt = 0;
439
440                         if (ev->buttons) {
441                                 step = ev->cur.canvas.x - wd->down_pos.x;
442                                 if (step > 0) idx = BLOCK_LEFT;
443                                 else idx = BLOCK_RIGHT;
444
445                                 wd->move_x = wd->x + ((ev->cur.canvas.x - wd->down_pos.x));
446                                 wd->move_y = wd->y + ((ev->cur.canvas.y - wd->down_pos.y));
447
448                                 if (wd->on_zoom) {
449                                         _imageslider_update_center_pos(wd, wd->move_x, wd->move_y, wd->y, wd->w);
450                                 } else {
451                                         _imageslider_update_pos(wd, wd->move_x, wd->y, wd->w);
452                                 }
453                         }
454                 } else {
455                         wd->mx = ev->cur.canvas.x;
456                         wd->my = ev->cur.canvas.y;
457
458                         wd->ratio = sqrt((wd->mx -wd->mmx)*(wd->mx -wd->mmx) + (wd->my - wd->mmy)*(wd->my - wd->mmy));
459
460                         eo = edje_object_part_swallow_get(elm_layout_edje_get(obj), "swl.photo");
461                         if (eo) {
462                                 it = eina_list_data_get(wd->cur);
463                                 if (((it->w * wd->ratio/wd->dratio)/it->ow) < MAX_ZOOM_SIZE ) {
464                                         edje_object_part_unswallow(elm_layout_edje_get(obj), eo);
465                                         evas_object_resize(eo, it->w * wd->ratio/wd->dratio, it->h * wd->ratio/wd->dratio);
466                                         evas_object_size_hint_min_set(eo, it->w * wd->ratio/wd->dratio, it->h * wd->ratio/wd->dratio);
467                                         edje_object_part_swallow(elm_layout_edje_get(obj), "swl.photo", eo);
468                                 }
469                         }                       
470                 }
471         }
472
473         wd->move_cnt++;
474
475 }
476
477
478 #if 0 // REMOVED about Multi-touch.
479 static void ev_imageslider_multi_down_cb(void * data, Evas * e, Evas_Object * obj, void * event_info)
480 {
481         Evas_Event_Multi_Down *ev = event_info;
482         Widget_Data *wd = data;
483
484         if (ev->device == MULTITOUCHDEVICE) return;
485
486         wd->on_hold = EINA_TRUE;
487         wd->mdx = ev->canvas.x;
488         wd->mdy = ev->canvas.y;
489         wd->mmx = ev->canvas.x;
490         wd->mmy = ev->canvas.y;
491
492         wd->dratio = sqrt((wd->mx - wd->mmx)*(wd->mx - wd->mmx) + (wd->my - wd->mmy)*(wd->my - wd->mmy));
493         wd->ratio = sqrt((wd->mx - wd->mmx)*(wd->mx - wd->mmx)+ (wd->my - wd->mmy)*(wd->my - wd->mmy));
494
495         if (wd->on_zoom){
496                 wd->on_zoom = EINA_FALSE;
497                 edje_object_signal_emit(elm_layout_edje_get(obj), "block.on", "block");
498 //              edje_freeze();
499         }
500 }
501
502 static void ev_imageslider_multi_up_cb(void * data, Evas * e, Evas_Object * obj, void * event_info)
503 {
504         Evas_Event_Multi_Up *ev = event_info;
505         Widget_Data *wd = data;
506         Elm_Imageslider_Item *it;
507
508         if (ev->device == MULTITOUCHDEVICE) return;
509
510         it = eina_list_data_get(wd->cur);
511         it->w = (int)it->w * wd->ratio/wd->dratio;
512         it->h = (int)it->h * wd->ratio/wd->dratio;
513
514         if (it->w != it->ow) {
515                 wd->on_zoom = EINA_TRUE;
516                 edje_object_signal_emit(elm_layout_edje_get(obj), "block.off", "block");
517 //              edje_thaw();
518         } else {
519                 wd->on_zoom = EINA_FALSE;
520         }
521
522         wd->on_hold = EINA_FALSE;
523         wd->mdx = 0;
524         wd->mdy = 0;
525         wd->mmx = 0;
526         wd->mmy = 0;
527         wd->ratio = 0;
528         wd->dratio = 0;
529         
530 }
531
532 static void ev_imageslider_multi_move_cb(void * data, Evas * e, Evas_Object * obj, void * event_info)
533 {
534         Evas_Event_Multi_Move *ev = event_info;
535         Widget_Data *wd = data;
536         Evas_Object *eo = NULL;
537         Elm_Imageslider_Item *it;
538
539         if (ev->device == MULTITOUCHDEVICE) return;
540
541         if ((wd->mdx == 0) && (wd->mdy == 0) && (wd->mmx == 0) && (wd->mmy == 0)) {
542                 wd->mdx = ev->cur.canvas.x;
543                 wd->mdy = ev->cur.canvas.y;
544                 wd->mmx = ev->cur.canvas.x;
545                 wd->mmy = ev->cur.canvas.y;
546
547                 wd->dratio = sqrt((wd->dx - wd->mdx)*(wd->dx - wd->mdx) + (wd->dy - wd->mdy)*(wd->dy - wd->mdy));
548         }
549
550         wd->mmx = ev->cur.canvas.x;
551         wd->mmy = ev->cur.canvas.y;
552         wd->ratio = sqrt((wd->mx - wd->mmx)*(wd->mx - wd->mmx) + (wd->my - wd->mmy)*(wd->my - wd->mmy));
553
554         eo = edje_object_part_swallow_get(elm_layout_edje_get(obj), "swl.photo");
555
556         if (eo) {
557                 it = eina_list_data_get(wd->cur);
558                 if (((it->w * wd->ratio/wd->dratio)/it->ow) < MAX_ZOOM_SIZE) {
559                         edje_object_part_unswallow(elm_layout_edje_get(obj), eo);
560                         evas_object_resize(eo, it->w * wd->ratio/wd->dratio, it->h * wd->ratio/wd->dratio);
561                         evas_object_size_hint_min_set(eo, it->w * wd->ratio/wd->dratio, it->h * wd->ratio/wd->dratio);
562                         edje_object_part_swallow(elm_layout_edje_get(obj), "swl.photo", eo);
563                 }
564         }       
565 }
566
567 #endif // about Multi-touch.
568
569 static inline double time_get(Evas_Coord x, Evas_Coord w)
570 {
571         double time;
572         time = (-sin(x / w) + 1) / 500;
573
574         if (time == 0) time = ANI_TIME;
575         
576         return time;
577 }
578
579 static int _icon_to_image(void *data)
580 {
581         Widget_Data *wd = data;
582         wd->moving = 0;
583         _imageslider_update(wd);
584
585         return 0;
586 }
587
588 static int _check_drag(int state, void *data)
589 {
590         Widget_Data *wd = data;
591         Elm_Imageslider_Item *it;
592         Evas_Coord ix, iy, iw, ih;
593         double dx, dy = 0;
594         Eina_List *l[BLOCK_MAX];
595         Evas_Object *eo = NULL;
596         l[BLOCK_LEFT] = eina_list_prev(wd->cur);
597         l[BLOCK_CENTER] = wd->cur;
598         l[BLOCK_RIGHT] = eina_list_next(wd->cur);
599
600         it = eina_list_data_get(l[state]);
601
602         eo = edje_object_part_swallow_get(elm_layout_edje_get(wd->ly[state]), "swl.photo");
603         if (eo) evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
604         evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
605         edje_object_part_drag_value_get(elm_layout_edje_get(wd->ly[state]), "swl.photo", &dx, &dy);
606
607         if ((iw != wd->w) || ((dx != 0 ) || (dy != 0 ))) {
608                 if (wd->ly[state]) {
609                         evas_object_del(wd->ly[state]);
610                         wd->ly[state] = NULL;
611                 }
612                 wd->ly[state] = _imageslider_add_obj(wd);
613         } else {
614                 return 1;
615         }
616
617         return 0;
618 }
619
620
621 static void _check_zoom(void *data)
622 {
623         Widget_Data *wd = data;
624         Elm_Imageslider_Item *it;
625         Evas_Coord ix, iy, iw, ih;
626         double dx, dy = 0;
627         Evas_Object *eo = NULL;
628
629         it = eina_list_data_get(wd->cur);
630
631         eo = edje_object_part_swallow_get(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "swl.photo");
632         if (eo) evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
633         evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
634         edje_object_part_drag_value_get(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "swl.photo", &dx, &dy);
635
636         if ((iw != wd->w) || ((dx != 0) || (dy != 0))) {
637                 wd->on_zoom = EINA_TRUE;
638                 edje_object_signal_emit(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "block.off", "block");
639 //              edje_thaw();
640         } else {
641                 wd->on_zoom = EINA_FALSE;
642                 edje_object_signal_emit(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "block.on", "block");
643 //              edje_freeze();
644         }
645 }
646
647
648 static int _timer_cb(void *data)
649 {
650         Widget_Data *wd;
651         Elm_Imageslider_Item *it;
652         struct timeval tv;
653         int t;
654         int ret;
655         wd = data;
656         if (wd->ani_lock == 0 ) return 0;
657
658         gettimeofday(&tv, NULL);
659
660         t = (tv.tv_sec - wd->tv.tv_sec) * 1000 + (tv.tv_usec - wd->tv.tv_usec) / 1000;
661         gettimeofday(&wd->tv, NULL);
662
663         t = t / ANI_TIME_MSEC;
664         if (t <= STEP_WEIGHT_MIN) t = STEP_WEIGHT_DEF;
665         else if (t >  STEP_WEIGHT_MAX) t = STEP_WEIGHT_MAX;
666
667         wd->move_x += (wd->step) * t;
668
669         if (wd->step < 0 && wd->move_x < wd->x) wd->move_x = wd->x;
670         else if (wd->step > 0 && wd->move_x > wd->x) wd->move_x = wd->x;
671
672         _imageslider_update_pos(wd, wd->move_x, wd->y, wd->w);
673
674         if (wd->move_x == wd->x) {
675                 wd->ani_lock = 0;
676                 if (wd->cur) {
677                         it = eina_list_data_get(wd->cur);
678                         if (it->func) it->func(it->data, wd->obj, it);
679                 }
680                 if (wd->cur) {
681                         it = eina_list_data_get(wd->cur);
682                         evas_object_smart_callback_call(wd->obj, "changed", it);
683                 }
684
685                 ret = _check_drag(BLOCK_LEFT, wd);
686                 ret = _check_drag(BLOCK_RIGHT, wd);
687                 _check_zoom(wd);
688
689                 ecore_idler_add(_icon_to_image, wd);
690
691                 return 0;
692         }
693
694         return 1;       
695 }
696
697 static void _anim(Widget_Data *wd)
698 {
699         Evas_Coord w;
700
701         if (wd->x == wd->move_x) {
702                 _imageslider_update_pos(wd, wd->move_x, wd->y, wd->w);
703                 return;
704         }
705
706         wd->ani_lock = 1;
707
708         w = wd->move_x;
709         gettimeofday(&wd->tv, NULL);
710         ecore_timer_add(ANI_TIME, _timer_cb, wd);
711 }
712
713 static void _imageslider_update(Widget_Data *wd)
714 {
715         int i;
716         Eina_List *l[BLOCK_MAX];
717         Elm_Imageslider_Item *it;
718         Evas_Object *eo;
719
720         if (!wd) {
721                 return;
722         }
723
724         if (!wd->cur) {
725                 _imageslider_del_all(wd);
726                 return;
727         }
728
729         l[BLOCK_LEFT] = eina_list_prev(wd->cur);
730         l[BLOCK_CENTER] = wd->cur;
731         l[BLOCK_RIGHT] = eina_list_next(wd->cur);
732
733         for (i = 0; i < BLOCK_MAX; i++) {
734                 eo = edje_object_part_swallow_get(elm_layout_edje_get(wd->ly[i]), "swl.photo");
735                 if (!l[i]) {
736                         elm_layout_content_set(wd->ly[i], "swl.photo", NULL);
737                         evas_object_del(eo);
738                 } else {
739                         it = eina_list_data_get(l[i]);
740                         if (!it) return;
741
742                         if (!eo) {
743                                 eo = elm_image_add(wd->obj);
744                                 elm_layout_content_set(wd->ly[i], "swl.photo", eo);
745                                 elm_image_prescale_set(eo, wd->w);
746                                 elm_image_file_set(eo, it->photo_file, NULL);
747                                 elm_image_object_size_get(eo, &it->w, &it->h);
748                                 evas_object_geometry_get(eo, &it->ox, &it->oy, &it->ow, &it->oh);
749                                 it->ow = it->w;
750                                 it->oh = it->h;
751                         }
752
753                         if (wd->moving != it->moving) {
754                                 it->moving = wd->moving;
755                                 if (wd->moving) {
756                                         elm_image_prescale_set(eo, MOVING_IMAGE_SIZE);
757                                 } else {
758                                         elm_image_prescale_set(eo, it->w > it->h ? it->w : it->h);
759                                 }
760                         }
761                 }
762         }
763
764         _anim(wd);
765
766 }
767
768
769 /** 
770 * Add imageslider widget 
771
772 * @param        obj     The parent object 
773 * @return       The new object or NULL if it cannot be created 
774
775 * @ingroup Imageslider 
776 */
777 EAPI Evas_Object *
778 elm_imageslider_add(Evas_Object * parent)
779 {
780         int i;
781         Evas_Object *obj = NULL;
782         Widget_Data *wd = NULL;
783         Evas *e;
784
785         if (!parent) {
786                 return NULL;
787         }
788
789         wd = ELM_NEW(Widget_Data);
790         e = evas_object_evas_get(parent);
791         if (e == NULL ) {
792                 return NULL;
793         }
794         
795         obj = elm_widget_add(e);
796         ELM_SET_WIDTYPE(widtype, "imageslider");
797         elm_widget_type_set(obj, "imageslider");
798         elm_widget_sub_object_add(parent, obj);
799         elm_widget_data_set(obj, wd);
800         //wd->parent = parent;
801         elm_widget_del_hook_set(obj, _del_hook);
802         //elm_widget_theme_hook_set(obj, _theme_hook);
803
804         wd->clip = evas_object_rectangle_add(e);
805         
806         for (i=0; i < BLOCK_MAX; i++) {
807                 wd->ly[i] = elm_layout_add(obj);
808                 elm_layout_theme_set(wd->ly[i], "imageslider", "base", "default");
809                 elm_widget_resize_object_set(obj, wd->ly[i]);
810                 evas_object_smart_member_add(wd->ly[i], obj);
811                 evas_object_event_callback_add(wd->ly[i], EVAS_CALLBACK_MOUSE_DOWN, ev_imageslider_down_cb, wd);
812                 evas_object_event_callback_add(wd->ly[i], EVAS_CALLBACK_MOUSE_UP, ev_imageslider_up_cb, wd);
813                 evas_object_event_callback_add(wd->ly[i], EVAS_CALLBACK_MOUSE_MOVE, ev_imageslider_move_cb, wd);
814                 evas_object_clip_set(wd->ly[i], wd->clip);
815                 evas_object_show(wd->ly[i]);                    
816         }
817
818         wd->obj = obj;
819
820         evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _imageslider_resize, obj);
821         evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _imageslider_move, obj);
822         evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _imageslider_show, obj);
823         evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _imageslider_hide, obj);
824         
825         _sizing_eval(obj);
826
827    return obj;  
828 }
829
830
831 /** 
832 * Append imageslider item 
833
834 * @param        obj          The photoslider object 
835 * @param        photo_file   photo file path 
836 * @param        func         callback function 
837 * @param        data         callback data 
838 * @return       The photoslider item handle or NULL 
839
840 * @ingroup Imageslider 
841 */
842 EAPI Elm_Imageslider_Item *
843 elm_imageslider_item_append(Evas_Object * obj, const char * photo_file, Elm_Imageslider_Cb func, void * data)
844 {
845         ELM_CHECK_WIDTYPE(obj, widtype) NULL;
846         Widget_Data *wd;
847         Elm_Imageslider_Item *it;
848
849         if (!obj || !(wd = elm_widget_data_get(obj))) {
850                 return NULL;
851         }
852
853         it = (Elm_Imageslider_Item *)calloc(1, sizeof(Elm_Imageslider_Item));
854         if (!it) return NULL;
855         it->photo_file = eina_stringshare_add(photo_file);
856         it->func = func;
857         it->data = data;
858         it->obj = obj;
859         wd->its = eina_list_append(wd->its, it);
860
861         if (!wd->cur) wd->cur = wd->its;
862
863         _imageslider_update(wd);
864
865         return it; 
866 }
867
868
869 /** 
870 * Prepend imageslider item 
871
872 * @param        obj          The imageslider object 
873 * @param        photo_file   photo file path 
874 * @param        func         callback function 
875 * @param        data         callback data 
876 * @return       The imageslider item handle or NULL 
877
878 * @ingroup Imageslider 
879 */
880 EAPI Elm_Imageslider_Item *
881 elm_imageslider_item_prepend(Evas_Object * obj, const char * photo_file, Elm_Imageslider_Cb func, void * data)
882 {
883         ELM_CHECK_WIDTYPE(obj, widtype) NULL;
884         Widget_Data *wd;
885         Elm_Imageslider_Item *it;
886
887         if (!obj || !(wd = elm_widget_data_get(obj))) {
888                 return NULL;
889         }
890
891         it = (Elm_Imageslider_Item *)calloc(1, sizeof(Elm_Imageslider_Item));
892         it->photo_file = eina_stringshare_add(photo_file);
893         it->func = func;
894         it->data = data;
895         it->obj = obj;
896         wd->its = eina_list_prepend(wd->its, it );
897
898         if (!wd->cur) wd->cur = wd->its;
899
900         _imageslider_update(wd);
901
902         return it;
903 }
904
905
906
907 /**
908 * Delete imageslider item
909 *
910 * @param it imageslider item handle
911 *
912 * @ingroup Imageslider
913 */
914 EAPI void
915 elm_imageslider_item_del(Elm_Imageslider_Item * it)
916 {
917         Widget_Data *wd;
918         Elm_Imageslider_Item *_it;
919         Eina_List *l;
920
921         if (!it || !(wd = elm_widget_data_get(it->obj))) {
922                 return ;
923         }
924
925         EINA_LIST_FOREACH(wd->its, l, _it) {
926                 if (_it == it ) {
927                         if (l == wd->cur) wd->cur = eina_list_prev(wd->cur);
928                         wd->its = eina_list_remove(wd->its, it);
929                         if (!wd->cur) wd->cur = wd->its;
930                         break;
931                 }
932         }
933
934         _imageslider_update(wd);
935         
936 }
937
938
939 /**
940 * Get selected item
941 *
942 * @param obj The imageslider object
943 * @return The selected item or NULL
944 *
945 * @ingroup Imageslider
946 */
947 EAPI Elm_Imageslider_Item *
948 elm_imageslider_selected_item_get(Evas_Object * obj)
949 {
950         ELM_CHECK_WIDTYPE(obj, widtype) NULL;
951         Widget_Data *wd;
952
953         if (!obj || (!(wd = elm_widget_data_get(obj)))) {
954                 return NULL;
955         }
956
957         if (!wd->cur) return NULL;
958
959         return eina_list_data_get(wd->cur);
960 }
961
962 /**
963 * Get whether item is selected or not
964 *
965 * @param it the item
966 * @return EINA_TRUE or EINA_FALSE
967 *
968 * @ingroup Imageslider
969 */
970 EAPI Eina_Bool
971 elm_imageslider_item_selected_get(Elm_Imageslider_Item * it)
972 {
973         Widget_Data *wd;
974         
975         if (!it || !it->obj || (!(wd = elm_widget_data_get(it->obj)))) {
976                 return EINA_FALSE;
977         }
978
979         if (!wd->cur) return EINA_FALSE;
980
981         if (eina_list_data_get(wd->cur) == it ) return EINA_TRUE;
982         else return EINA_FALSE;
983         
984 }
985
986 /**
987 * Set selected item
988 *
989 * @param it the item
990 *
991 * @ingroup Imageslider
992 */
993 EAPI void
994 elm_imageslider_item_selected_set(Elm_Imageslider_Item * it)
995 {
996         int i;
997         Widget_Data *wd;
998         Elm_Imageslider_Item *_it;
999         Eina_List *l;
1000         Evas_Object *eo;
1001
1002         if (!it || !it->obj || (!(wd = elm_widget_data_get(it->obj)))) {
1003                 return ;
1004         }
1005
1006         EINA_LIST_FOREACH(wd->its, l, _it) {
1007                 if (_it == it ) {
1008                         wd->cur = l;
1009                 }
1010         }
1011
1012         for (i = 0; i < BLOCK_MAX; i++) {
1013                 eo = edje_object_part_swallow_get(elm_layout_edje_get(wd->ly[i]), "swl.photo");
1014                 if (eo) {
1015                         elm_layout_content_set(wd->ly[i], "swl.photo", NULL);
1016                         evas_object_del(eo);
1017                 }
1018         }
1019
1020         _imageslider_update(wd);
1021         
1022 }
1023
1024
1025 /**
1026 * Get photo file path of give item
1027 *
1028 * @param it item
1029 * @return The photo file path or NULL;
1030 *
1031 * @ingroup Imageslider
1032 */
1033 EAPI const char *
1034 elm_imageslider_item_photo_file_get(Elm_Imageslider_Item * it)
1035 {
1036         if (!it) {
1037                 return NULL;
1038         }
1039
1040         return it->photo_file;
1041 }
1042
1043
1044 /**
1045 * Get the previous imageslider item
1046 *
1047 * @param it     item
1048 * @return The previous item or NULL
1049 *
1050 * @ingroup Imageslider
1051 */
1052 EAPI Elm_Imageslider_Item *
1053 elm_imageslider_item_prev(Elm_Imageslider_Item * it)
1054 {
1055         Widget_Data *wd;
1056         Elm_Imageslider_Item *_it;
1057         Eina_List *l;
1058
1059         if (!it || (!(wd = elm_widget_data_get(it->obj)))) {
1060                 return NULL;
1061         }
1062
1063         EINA_LIST_FOREACH(wd->its, l, _it) {
1064                 if (_it == it) {
1065                         l = eina_list_prev(l);
1066                         if (!l) break;
1067                         return eina_list_data_get(l);
1068                 }
1069         }
1070
1071         return NULL;    
1072 }
1073
1074
1075 /**
1076 * Get the next imageslider item
1077 *
1078 * @param it     item
1079 * @return The next item or NULL
1080 *
1081 * @ingroup Imageslider
1082 */
1083 EAPI Elm_Imageslider_Item *
1084 elm_imageslider_item_next(Elm_Imageslider_Item * it)
1085 {
1086         Widget_Data *wd;
1087         Elm_Imageslider_Item *_it;
1088         Eina_List *l;
1089
1090         if (!it || (!(wd = elm_widget_data_get(it->obj)))) {
1091                 return NULL;
1092         }
1093
1094         EINA_LIST_FOREACH(wd->its, l, _it) {
1095                 if (_it == it) {
1096                         l = eina_list_next(l);
1097                         if (!l) break;
1098                         return eina_list_data_get(l);
1099                 }
1100         }
1101
1102         return NULL;
1103 }
1104
1105
1106 /**
1107 * Move to the previous imageslider item
1108 *
1109 * @param obj imageslider object
1110 *
1111 * @ingroup Imageslider
1112 */
1113 EAPI void 
1114 elm_imageslider_prev(Evas_Object * obj)
1115 {
1116         ELM_CHECK_WIDTYPE(obj, widtype);
1117         Widget_Data *wd;
1118         
1119         if (!obj || (!(wd = elm_widget_data_get(obj)))) {
1120                 return;
1121         }
1122
1123         if (wd->ani_lock) return;
1124
1125         _imageslider_obj_move(wd, -1);
1126 }
1127
1128
1129 /**
1130 * Move to the next imageslider item
1131 *
1132 * @param obj imageslider object
1133 *
1134 * @ingroup Imageslider
1135 */
1136 EAPI void
1137 elm_imageslider_next(Evas_Object * obj)
1138 {
1139         ELM_CHECK_WIDTYPE(obj, widtype);
1140         Widget_Data *wd;
1141         
1142         if (!obj || (!(wd = elm_widget_data_get(obj)))) {
1143                 return;
1144         }
1145
1146         if (wd->ani_lock) return;
1147
1148         _imageslider_obj_move(wd, 1);
1149         
1150 }
1151
1152
1153
1154
1155