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