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