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