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