Merge branch 'master' of 165.213.180.234:/git/slp/pkgs/elementary
[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         edje_object_signal_callback_add(elm_layout_edje_get(eo), "elm,photo,clicked", "", _signal_clicked, wd->obj);
324 //      evas_object_smart_member_add(eo, wd->obj);
325         evas_object_event_callback_add(eo, EVAS_CALLBACK_MOUSE_DOWN, ev_imageslider_down_cb, wd);
326         evas_object_event_callback_add(eo, EVAS_CALLBACK_MOUSE_UP, ev_imageslider_up_cb, wd);
327         evas_object_event_callback_add(eo, EVAS_CALLBACK_MOUSE_MOVE, ev_imageslider_move_cb, wd);
328         evas_object_resize(eo, wd->w, wd->h);
329         evas_object_move(eo, wd->w + INTERVAL_WIDTH, wd->y);
330         evas_object_clip_set(eo, wd->clip);
331         evas_object_show(eo);
332
333         return eo;
334 }
335
336 // Shift next/previous Image Slider item in layouts.
337 static void _imageslider_obj_shift(Widget_Data *wd, Eina_Bool left)
338 {
339         if (!left) {
340                 if (wd->ly[BLOCK_LEFT]) {
341                         evas_object_del(wd->ly[BLOCK_LEFT]);
342                         wd->ly[BLOCK_LEFT] = NULL;
343                 }
344
345                 wd->ly[BLOCK_LEFT] = wd->ly[BLOCK_CENTER];
346                 wd->ly[BLOCK_CENTER]= wd->ly[BLOCK_RIGHT];
347                 wd->ly[BLOCK_RIGHT] = _imageslider_add_obj(wd);
348         } else {
349                 if (wd->ly[BLOCK_RIGHT]) {
350                         evas_object_del(wd->ly[BLOCK_RIGHT]);
351                         wd->ly[BLOCK_RIGHT] = NULL;
352                 }
353
354                 wd->ly[BLOCK_RIGHT]= wd->ly[BLOCK_CENTER];
355                 wd->ly[BLOCK_CENTER]= wd->ly[BLOCK_LEFT];
356                 wd->ly[BLOCK_LEFT]= _imageslider_add_obj(wd);
357         }
358 }
359
360 // Move the current Image Slider item and update.
361 static void _imageslider_obj_move(Widget_Data * wd, Evas_Coord step)
362 {
363         if (step > 0) {
364                 wd->cur = eina_list_next(wd->cur);
365                 if (wd->cur == NULL) {
366                         wd->cur = eina_list_last(wd->its);
367                         wd->step = ANI_STEP;
368                 } else {
369                         wd->step = -ANI_STEP;
370                         wd->move_x += wd->w;
371                         _imageslider_obj_shift(wd, 0);
372                 }
373                 wd->moving = 1;         
374         } else if (step < 0) {
375                 wd->cur = eina_list_prev(wd->cur);
376                 if (wd->cur == NULL) {
377                         wd->cur = wd->its;
378                         wd->step = -ANI_STEP;
379                 } else {
380                         wd->step = ANI_STEP;
381                         wd->move_x -= wd->w;
382                         _imageslider_obj_shift(wd, 1);
383                 }
384                 wd->moving = 1;
385         } else {
386                 if (wd->move_x < 0) wd->step = ANI_STEP;
387                 else wd->step = -ANI_STEP;
388                 wd->moving = 0;
389         }
390
391         _imageslider_update(wd);
392 }
393
394 // Whenever MOUSE DOWN event occurs, Call this function.
395 static void ev_imageslider_down_cb(void * data, Evas * e, Evas_Object * obj, void * event_info)
396 {
397         Widget_Data *wd = data;
398         Evas_Event_Mouse_Down *ev = event_info;
399         Evas_Coord ix, iy, iw, ih;
400         Evas_Object *eo = NULL;
401
402         if (wd->ani_lock) return;
403
404         wd->down_pos = ev->canvas;
405         wd->timestamp = ev->timestamp;
406         wd->move_cnt = MOVE_STEP;
407
408         wd->dx = ev->canvas.x;
409         wd->dy = ev->canvas.y;
410         wd->mx = ev->canvas.x;
411         wd->my = ev->canvas.y;
412
413         wd->dratio = 1;
414         wd->ratio = 1;
415
416         eo = edje_object_part_swallow_get(elm_layout_edje_get(obj), "swl.photo");
417         if (eo) evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
418
419         if (iw != wd->w) {
420                 wd->on_zoom = EINA_TRUE;
421                 edje_object_signal_emit(elm_layout_edje_get(obj), "block.off", "block");
422 //              edje_thaw();            
423         }
424
425 }
426
427 // Whenever MOUSE UP event occurs, Call this function.
428 static void ev_imageslider_up_cb(void * data, Evas * e, Evas_Object * obj, void * event_info)
429 {
430         Widget_Data *wd = data;
431         Evas_Event_Mouse_Up *ev = event_info;
432         Evas_Coord step;
433         int interval;
434
435         if (wd->ani_lock) return;
436
437         if (wd->on_zoom) {              
438         } else {
439                 step = wd->down_pos.x - ev->canvas.x;
440                 interval = ev->timestamp - wd->timestamp;
441                 if (step == 0 || interval == 0) {
442                      fprintf(stderr, "[[[ DEBUG ]]]: case1: emit CLICK event\n");
443                      evas_object_smart_callback_call(data, SIG_CLICKED, NULL);
444                      return;
445                 }
446                 if (interval < CLICK_TIME_MAX) {
447                         if (step < CLICK_WIDTH_MIN && step > CLICK_WIDTH_MIN) {
448                                 fprintf(stderr, "[[[ DEBUG ]]]: case2: emit CLICK event\n");
449                                 evas_object_smart_callback_call(data, SIG_CLICKED, NULL);                       
450                                 return;
451                         }
452                 }
453
454                 if (interval < FLICK_TIME_MAX) {
455                       
456                         if (step < FLICK_WIDTH_MIN && step > FLICK_WIDTH_MIN) {
457                              fprintf(stderr, "[[[ DEBUG ]]]:ev_imageslider_up_cb-black zone (1)\n");
458                              
459                              _imageslider_obj_move(wd, 0);
460                         } else {
461                              fprintf(stderr, "[[[ DEBUG ]]]:ev_imageslider_up_cb-black zone (2)\n");
462                              _imageslider_obj_move(wd, step);
463                         }
464                         
465                 } else {
466                         step = (wd->x - wd->move_x) << 1;
467                         if (step <= wd->w && step >= -(wd->w)) {
468                              fprintf(stderr, "[[[ DEBUG ]]]:ev_imageslider_up_cb-white zone (1)\n");
469                              _imageslider_obj_move(wd, 0);
470                         } else {
471                              fprintf(stderr, "[[[ DEBUG ]]]:ev_imageslider_up_cb-white zone (2)\n");
472                              _imageslider_obj_move(wd, step);
473                         }
474                 }
475         }
476
477 }
478
479 // Whenever MOUSE MOVE event occurs, Call this API.
480 static void ev_imageslider_move_cb(void * data, Evas * e, Evas_Object * obj, void * event_info)
481 {
482         int idx;
483         Evas_Object *eo;
484         Evas_Coord step;
485         Widget_Data *wd = data;
486         Evas_Event_Mouse_Move *ev = event_info;
487         Elm_Imageslider_Item *it;
488
489         if (wd->ani_lock) return;
490
491         if (wd->move_cnt == MOVE_STEP) {
492                 if (wd->on_hold == EINA_FALSE) {
493                         wd->move_cnt = 0;
494
495                         if (ev->buttons) {
496                                 step = ev->cur.canvas.x - wd->down_pos.x;
497                                 if (step > 0) idx = BLOCK_LEFT;
498                                 else idx = BLOCK_RIGHT;
499
500                                 wd->move_x = wd->x + ((ev->cur.canvas.x - wd->down_pos.x));
501                                 wd->move_y = wd->y + ((ev->cur.canvas.y - wd->down_pos.y));
502
503                                 if (wd->on_zoom) {
504                                         _imageslider_update_center_pos(wd, wd->move_x, wd->move_y, wd->y, wd->w);
505                                 } else {
506                                         _imageslider_update_pos(wd, wd->move_x, wd->y, wd->w);
507                                 }
508                         }
509                 } else {
510                         wd->mx = ev->cur.canvas.x;
511                         wd->my = ev->cur.canvas.y;
512
513                         wd->ratio = sqrt((wd->mx -wd->mmx)*(wd->mx -wd->mmx) + (wd->my - wd->mmy)*(wd->my - wd->mmy));
514
515                         eo = edje_object_part_swallow_get(elm_layout_edje_get(obj), "swl.photo");
516                         if (eo) {
517                                 it = eina_list_data_get(wd->cur);
518                                 if (((it->w * wd->ratio/wd->dratio)/it->ow) < MAX_ZOOM_SIZE ) {
519                                         edje_object_part_unswallow(elm_layout_edje_get(obj), eo);
520                                         evas_object_resize(eo, it->w * wd->ratio/wd->dratio, it->h * wd->ratio/wd->dratio);
521                                         evas_object_size_hint_min_set(eo, it->w * wd->ratio/wd->dratio, it->h * wd->ratio/wd->dratio);
522                                         edje_object_part_swallow(elm_layout_edje_get(obj), "swl.photo", eo);
523                                 }
524                         }                       
525                 }
526         }
527
528         wd->move_cnt++;
529
530 }
531
532 // Whenever CLICK event occurs, Call this API
533 // But, DONOT emit CLICK event.
534 static void
535 _signal_clicked(void *data, Evas_Object *obj, const char *emission, const char *source)
536 {
537         fprintf(stderr, "[[[ DEBUG ]]]: Call the callback function about Click event!, But DONOT emit CLICK event in the callback function!\n");
538         //evas_object_smart_callback_call(data, SIG_CLICKED, NULL);     
539 }
540
541
542 static inline double time_get(Evas_Coord x, Evas_Coord w)
543 {
544         double time;
545         time = (-sin(x / w) + 1) / 500;
546
547         if (time == 0) time = ANI_TIME;
548         
549         return time;
550 }
551
552 static Eina_Bool _icon_to_image(void *data)
553 {
554         Widget_Data *wd = data;
555         wd->moving = 0;
556         _imageslider_update(wd);
557
558         if (wd->queue_idler) {
559                 ecore_idler_del(wd->queue_idler);
560                 wd->queue_idler = NULL;
561         }
562         return ECORE_CALLBACK_CANCEL;
563 }
564
565 static int _check_drag(int state, void *data)
566 {
567         Widget_Data *wd = data;
568         Elm_Imageslider_Item *it;
569         Evas_Coord ix, iy, iw, ih;
570         double dx, dy = 0;
571         Eina_List *l[BLOCK_MAX];
572         Evas_Object *eo = NULL;
573         l[BLOCK_LEFT] = eina_list_prev(wd->cur);
574         l[BLOCK_CENTER] = wd->cur;
575         l[BLOCK_RIGHT] = eina_list_next(wd->cur);
576
577         it = eina_list_data_get(l[state]);
578
579         eo = edje_object_part_swallow_get(elm_layout_edje_get(wd->ly[state]), "swl.photo");
580         if (eo) evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
581         evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
582         edje_object_part_drag_value_get(elm_layout_edje_get(wd->ly[state]), "swl.photo", &dx, &dy);
583
584         if ((iw != wd->w) || ((dx != 0 ) || (dy != 0 ))) {
585                 if (wd->ly[state]) {
586                         evas_object_del(wd->ly[state]);
587                         wd->ly[state] = NULL;
588                 }
589                 wd->ly[state] = _imageslider_add_obj(wd);
590         } else {
591                 return 1;
592         }
593
594         return 0;
595 }
596
597
598 static void _check_zoom(void *data)
599 {
600         Widget_Data *wd = data;
601         Elm_Imageslider_Item *it;
602         Evas_Coord ix, iy, iw, ih;
603         double dx, dy = 0;
604         Evas_Object *eo = NULL;
605
606         it = eina_list_data_get(wd->cur);
607
608         eo = edje_object_part_swallow_get(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "swl.photo");
609         if (eo) evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
610         evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
611         edje_object_part_drag_value_get(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "swl.photo", &dx, &dy);
612
613         if ((iw != wd->w) || ((dx != 0) || (dy != 0))) {
614                 wd->on_zoom = EINA_TRUE;
615                 edje_object_signal_emit(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "block.off", "block");
616 //              edje_thaw();
617         } else {
618                 wd->on_zoom = EINA_FALSE;
619                 edje_object_signal_emit(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "block.on", "block");
620 //              edje_freeze();
621         }
622 }
623
624 static Eina_Bool _timer_cb(void *data)
625 {
626         Widget_Data *wd;
627         Elm_Imageslider_Item *it;
628         struct timeval tv;
629         int t;
630         int ret;
631         wd = data;
632         if (wd->ani_lock == 0 ) return 0;
633
634         gettimeofday(&tv, NULL);
635
636         t = (tv.tv_sec - wd->tv.tv_sec) * 1000 + (tv.tv_usec - wd->tv.tv_usec) / 1000;
637         gettimeofday(&wd->tv, NULL);
638
639         t = t / ANI_TIME_MSEC;
640         if (t <= STEP_WEIGHT_MIN) t = STEP_WEIGHT_DEF;
641         else if (t >  STEP_WEIGHT_MAX) t = STEP_WEIGHT_MAX;
642
643         wd->move_x += (wd->step) * t;
644
645         if (wd->step < 0 && wd->move_x < wd->x) wd->move_x = wd->x;
646         else if (wd->step > 0 && wd->move_x > wd->x) wd->move_x = wd->x;
647
648         _imageslider_update_pos(wd, wd->move_x, wd->y, wd->w);
649
650         if (wd->move_x == wd->x) {
651                 wd->ani_lock = 0;
652                 if (wd->cur) {
653                         it = eina_list_data_get(wd->cur);
654                         if (it->func) it->func(it->data, wd->obj, it);
655                 }
656                 if (wd->cur) {
657                         it = eina_list_data_get(wd->cur);
658                         evas_object_smart_callback_call(wd->obj, "changed", it);
659                 }
660
661                 ret = _check_drag(BLOCK_LEFT, wd);
662                 ret = _check_drag(BLOCK_RIGHT, wd);
663                 _check_zoom(wd);
664
665                 if (!wd->queue_idler) wd->queue_idler = ecore_idler_add(_icon_to_image, wd);
666
667                 if(wd->anim_timer) {
668                         ecore_timer_del(wd->anim_timer);
669                         wd->anim_timer = NULL;
670                 }
671
672                 return ECORE_CALLBACK_CANCEL;
673         }
674
675         return ECORE_CALLBACK_RENEW;    
676 }
677
678
679 static void _anim(Widget_Data *wd)
680 {
681         Evas_Coord w;
682
683         if (wd->x == wd->move_x) {
684                 _imageslider_update_pos(wd, wd->move_x, wd->y, wd->w);
685                 return;
686         }
687
688         wd->ani_lock = 1;
689
690         w = wd->move_x;
691         gettimeofday(&wd->tv, NULL);
692
693         if (!wd->anim_timer) {
694                 wd->anim_timer = ecore_timer_add(ANI_TIME, _timer_cb, wd); 
695         }       
696 }
697
698 // Update Image Slider Items.
699 static void _imageslider_update(Widget_Data *wd)
700 {
701         int i;
702         Eina_List *l[BLOCK_MAX];
703         Elm_Imageslider_Item *it;
704         Evas_Object *eo;
705
706         if (!wd) {
707                 return;
708         }
709
710         if (!wd->cur) {
711                 _imageslider_del_all(wd);
712                 return;
713         }
714
715         l[BLOCK_LEFT] = eina_list_prev(wd->cur);
716         l[BLOCK_CENTER] = wd->cur;
717         l[BLOCK_RIGHT] = eina_list_next(wd->cur);
718
719         for (i = 0; i < BLOCK_MAX; i++) {
720                 eo = edje_object_part_swallow_get(elm_layout_edje_get(wd->ly[i]), "swl.photo");
721                 if (!l[i]) {
722                         elm_layout_content_set(wd->ly[i], "swl.photo", NULL);
723                         evas_object_del(eo);
724                 } else {
725                         it = eina_list_data_get(l[i]);
726                         if (!it) return;
727
728                         if (!eo) {
729                                 eo = elm_image_add(wd->obj);
730                                 elm_layout_content_set(wd->ly[i], "swl.photo", eo);
731                                 elm_image_prescale_set(eo, wd->w);
732                                 elm_image_file_set(eo, it->photo_file, NULL);
733                                 elm_image_object_size_get(eo, &it->w, &it->h);
734                                 evas_object_geometry_get(eo, &it->ox, &it->oy, &it->ow, &it->oh);
735                                 it->ow = it->w;
736                                 it->oh = it->h;
737                         }
738
739                         if (wd->moving != it->moving) {
740                                 it->moving = wd->moving;
741                                 if (wd->moving) {
742                                         elm_image_prescale_set(eo, MOVING_IMAGE_SIZE);
743                                 } else {
744                                         elm_image_prescale_set(eo, it->w > it->h ? it->w : it->h);
745                                 }
746                         }
747                 }
748         }
749
750         _anim(wd);
751
752 }
753
754
755 /** 
756 * Add an Image Slider widget 
757
758 * @param        parent  The parent object 
759 * @return       The new Image slider object or NULL if it cannot be created 
760
761 * @ingroup Imageslider 
762 */
763 EAPI Evas_Object *
764 elm_imageslider_add(Evas_Object * parent)
765 {
766         int i;
767         Evas_Object *obj = NULL;
768         Widget_Data *wd = NULL;
769         Evas *e;
770
771         if (!parent) {
772                 return NULL;
773         }
774
775         wd = ELM_NEW(Widget_Data);
776         e = evas_object_evas_get(parent);
777         if (e == NULL ) {
778                 return NULL;
779         }
780         
781         obj = elm_widget_add(e);
782         ELM_SET_WIDTYPE(widtype, "imageslider");
783         elm_widget_type_set(obj, "imageslider");
784         elm_widget_sub_object_add(parent, obj);
785         elm_widget_data_set(obj, wd);
786         //wd->parent = parent;
787         elm_widget_del_hook_set(obj, _del_hook);
788         //elm_widget_theme_hook_set(obj, _theme_hook);
789
790         wd->clip = evas_object_rectangle_add(e);
791         
792         for (i=0; i < BLOCK_MAX; i++) {
793                 wd->ly[i] = elm_layout_add(obj);
794                 elm_layout_theme_set(wd->ly[i], "imageslider", "base", "default");
795                 elm_widget_resize_object_set(obj, wd->ly[i]);
796                 evas_object_smart_member_add(wd->ly[i], obj);
797                 
798                 edje_object_signal_callback_add(elm_layout_edje_get(wd->ly[i]), "elm,photo,clicked", "", _signal_clicked, obj);
799                 
800                 evas_object_event_callback_add(wd->ly[i], EVAS_CALLBACK_MOUSE_DOWN, ev_imageslider_down_cb, wd);
801                 evas_object_event_callback_add(wd->ly[i], EVAS_CALLBACK_MOUSE_UP, ev_imageslider_up_cb, wd);
802                 evas_object_event_callback_add(wd->ly[i], EVAS_CALLBACK_MOUSE_MOVE, ev_imageslider_move_cb, wd);
803                 evas_object_clip_set(wd->ly[i], wd->clip);
804                 evas_object_show(wd->ly[i]);                    
805         }
806
807         wd->obj = obj;
808
809         evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _imageslider_resize, obj);
810         evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _imageslider_move, obj);
811         evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _imageslider_show, obj);
812         evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _imageslider_hide, obj);
813         
814         _sizing_eval(obj);
815
816    return obj;  
817 }
818
819
820 /** 
821 * Append an Image Slider item 
822
823 * @param        obj          The Image Slider object 
824 * @param        photo_file   photo file path 
825 * @param        func         callback function 
826 * @param        data         callback data 
827 * @return       The Image Slider item handle or NULL 
828
829 * @ingroup Imageslider 
830 */
831 EAPI Elm_Imageslider_Item *
832 elm_imageslider_item_append(Evas_Object * obj, const char * photo_file, Elm_Imageslider_Cb func, void * data)
833 {
834         ELM_CHECK_WIDTYPE(obj, widtype) NULL;
835         Widget_Data *wd;
836         Elm_Imageslider_Item *it;
837
838         if (!obj || !(wd = elm_widget_data_get(obj))) {
839                 return NULL;
840         }
841
842         it = (Elm_Imageslider_Item *)calloc(1, sizeof(Elm_Imageslider_Item));
843         if (!it) return NULL;
844         it->photo_file = eina_stringshare_add(photo_file);
845         it->func = func;
846         it->data = data;
847         it->obj = obj;
848         wd->its = eina_list_append(wd->its, it);
849
850         if (!wd->cur) wd->cur = wd->its;
851
852         _imageslider_update(wd);
853
854         return it; 
855 }
856
857 /**
858 * Insert an Image Slider item into the Image Slider Widget by using the given index.
859 *
860 * @param        obj                     The Image Slider object
861 * @param        photo_file      photo file path
862 * @param        func            callback function
863 * @param        index           required position
864 * @param        data            callback data
865 * @return       The Image Slider item handle or NULL
866 *
867 * @ingroup      Imageslider
868 */
869 EAPI Elm_Imageslider_Item *
870 elm_imageslider_item_append_relative(Evas_Object *obj, const char *photo_file, Elm_Imageslider_Cb func, unsigned int n, void *data)
871 {
872         ELM_CHECK_WIDTYPE(obj, widtype) NULL;
873         Widget_Data *wd;
874         Elm_Imageslider_Item *it;
875
876         fprintf(stderr, "[[[ DEBUG ]]]:: New elm_imageslider_item_append_relative()\n");
877
878         if (!obj || !(wd = elm_widget_data_get(obj))) {
879                 return NULL;
880         }
881
882         it = (Elm_Imageslider_Item *)calloc(1, sizeof(Elm_Imageslider_Item));
883         if (!it) return NULL;
884         
885         it->obj = obj;
886         it->photo_file = eina_stringshare_add(photo_file);
887         it->func = func;
888         it->data = data;
889
890         wd->its = eina_list_append_relative(wd->its, it, eina_list_nth(wd->its, n-2));
891
892         if (!wd->cur) wd->cur = wd->its;
893
894         _imageslider_update(wd);
895
896         return it;
897 }
898
899
900 /** 
901 * Prepend Image Slider item 
902
903 * @param        obj          The Image Slider object 
904 * @param        photo_file   photo file path 
905 * @param        func         callback function 
906 * @param        data         callback data 
907 * @return       The imageslider item handle or NULL 
908
909 * @ingroup Imageslider 
910 */
911 EAPI Elm_Imageslider_Item *
912 elm_imageslider_item_prepend(Evas_Object * obj, const char * photo_file, Elm_Imageslider_Cb func, void * data)
913 {
914         ELM_CHECK_WIDTYPE(obj, widtype) NULL;
915         Widget_Data *wd;
916         Elm_Imageslider_Item *it;
917
918         if (!obj || !(wd = elm_widget_data_get(obj))) {
919                 return NULL;
920         }
921
922         it = (Elm_Imageslider_Item *)calloc(1, sizeof(Elm_Imageslider_Item));
923         it->photo_file = eina_stringshare_add(photo_file);
924         it->func = func;
925         it->data = data;
926         it->obj = obj;
927         wd->its = eina_list_prepend(wd->its, it );
928
929         if (!wd->cur) wd->cur = wd->its;
930
931         _imageslider_update(wd);
932
933         return it;
934 }
935
936
937
938 /**
939 * Delete the selected Image Slider item
940 *
941 * @param it             The selected Image Slider item handle
942 *
943 * @ingroup Imageslider
944 */
945 EAPI void
946 elm_imageslider_item_del(Elm_Imageslider_Item * it)
947 {
948         Widget_Data *wd;
949         Elm_Imageslider_Item *_it;
950         Eina_List *l;
951
952         if (!it || !(wd = elm_widget_data_get(it->obj))) {
953                 return ;
954         }
955
956         EINA_LIST_FOREACH(wd->its, l, _it) {
957                 if (_it == it ) {
958                         if (l == wd->cur) wd->cur = eina_list_prev(wd->cur);
959                         wd->its = eina_list_remove(wd->its, it);
960                         if (!wd->cur) wd->cur = wd->its;
961                         break;
962                 }
963         }
964
965         _imageslider_update(wd);
966         
967 }
968
969
970 /**
971 * Get the selected Image Slider item
972 *
973 * @param obj            The Image Slider object
974 * @return The selected Image Slider item or NULL
975 *
976 * @ingroup Imageslider
977 */
978 EAPI Elm_Imageslider_Item *
979 elm_imageslider_selected_item_get(Evas_Object * obj)
980 {
981         ELM_CHECK_WIDTYPE(obj, widtype) NULL;
982         Widget_Data *wd;
983
984         if (!obj || (!(wd = elm_widget_data_get(obj)))) {
985                 return NULL;
986         }
987
988         if (!wd->cur) return NULL;
989
990         return eina_list_data_get(wd->cur);
991 }
992
993 /**
994 * Get whether an Image Slider item is selected or not
995 *
996 * @param it              the selected Image Slider item
997 * @return EINA_TRUE or EINA_FALSE
998 *
999 * @ingroup Imageslider
1000 */
1001 EAPI Eina_Bool
1002 elm_imageslider_item_selected_get(Elm_Imageslider_Item * it)
1003 {
1004         Widget_Data *wd;
1005         
1006         if (!it || !it->obj || (!(wd = elm_widget_data_get(it->obj)))) {
1007                 return EINA_FALSE;
1008         }
1009
1010         if (!wd->cur) return EINA_FALSE;
1011
1012         if (eina_list_data_get(wd->cur) == it ) return EINA_TRUE;
1013         else return EINA_FALSE;
1014         
1015 }
1016
1017 /**
1018 * Set the selected Image Slider item
1019 *
1020 * @param it             The Imaga Slider item
1021 *
1022 * @ingroup Imageslider
1023 */
1024 EAPI void
1025 elm_imageslider_item_selected_set(Elm_Imageslider_Item * it)
1026 {
1027         int i;
1028         Widget_Data *wd;
1029         Elm_Imageslider_Item *_it;
1030         Eina_List *l;
1031         Evas_Object *eo;
1032
1033         if (!it || !it->obj || (!(wd = elm_widget_data_get(it->obj)))) {
1034                 return ;
1035         }
1036
1037         EINA_LIST_FOREACH(wd->its, l, _it) {
1038                 if (_it == it ) {
1039                         wd->cur = l;
1040                 }
1041         }
1042
1043         for (i = 0; i < BLOCK_MAX; i++) {
1044                 eo = edje_object_part_swallow_get(elm_layout_edje_get(wd->ly[i]), "swl.photo");
1045                 if (eo) {
1046                         elm_layout_content_set(wd->ly[i], "swl.photo", NULL);
1047                         evas_object_del(eo);
1048                 }
1049         }
1050
1051         _imageslider_update(wd);
1052         
1053 }
1054
1055
1056 /**
1057 * Get the photo file path of given Image Slider item
1058 *
1059 * @param it             The Image Slider item
1060 * @return The photo file path or NULL;
1061 *
1062 * @ingroup Imageslider
1063 */
1064 EAPI const char *
1065 elm_imageslider_item_photo_file_get(Elm_Imageslider_Item * it)
1066 {
1067         if (!it) {
1068                 return NULL;
1069         }
1070
1071         return it->photo_file;
1072 }
1073
1074
1075 /**
1076 * Get the previous Image Slider item
1077 *
1078 * @param it             The Image Slider item
1079 * @return The previous Image Slider item or NULL
1080 *
1081 * @ingroup Imageslider
1082 */
1083 EAPI Elm_Imageslider_Item *
1084 elm_imageslider_item_prev(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_prev(l);
1097                         if (!l) break;
1098                         return eina_list_data_get(l);
1099                 }
1100         }
1101
1102         return NULL;    
1103 }
1104
1105
1106 /**
1107 * Get the next Image Slider item
1108 *
1109 * @param it             The Image Slider item
1110 * @return The next Image Slider item or NULL
1111 *
1112 * @ingroup Imageslider
1113 */
1114 EAPI Elm_Imageslider_Item *
1115 elm_imageslider_item_next(Elm_Imageslider_Item * it)
1116 {
1117         Widget_Data *wd;
1118         Elm_Imageslider_Item *_it;
1119         Eina_List *l;
1120
1121         if (!it || (!(wd = elm_widget_data_get(it->obj)))) {
1122                 return NULL;
1123         }
1124
1125         EINA_LIST_FOREACH(wd->its, l, _it) {
1126                 if (_it == it) {
1127                         l = eina_list_next(l);
1128                         if (!l) break;
1129                         return eina_list_data_get(l);
1130                 }
1131         }
1132
1133         return NULL;
1134 }
1135
1136
1137 /**
1138 * Move to the previous Image Slider item
1139 *
1140 * @param obj    The Image Slider object
1141 *
1142 * @ingroup Imageslider
1143 */
1144 EAPI void 
1145 elm_imageslider_prev(Evas_Object * obj)
1146 {
1147         ELM_CHECK_WIDTYPE(obj, widtype);
1148         Widget_Data *wd;
1149         
1150         if (!obj || (!(wd = elm_widget_data_get(obj)))) {
1151                 return;
1152         }
1153
1154         if (wd->ani_lock) return;
1155
1156         _imageslider_obj_move(wd, -1);
1157 }
1158
1159
1160 /**
1161 * Move to the next Image Slider item
1162 *
1163 * @param obj The Image Slider object
1164 *
1165 * @ingroup Imageslider
1166 */
1167 EAPI void
1168 elm_imageslider_next(Evas_Object * obj)
1169 {
1170         ELM_CHECK_WIDTYPE(obj, widtype);
1171         Widget_Data *wd;
1172         
1173         if (!obj || (!(wd = elm_widget_data_get(obj)))) {
1174                 return;
1175         }
1176
1177         if (wd->ani_lock) return;
1178
1179         _imageslider_obj_move(wd, 1);
1180         
1181 }
1182
1183
1184
1185
1186