[*]Un-Rollback to 'Merge [elm_multibuttonentry]Changed edc TEXT part to TEXTBLOCK...
[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    int dx, dy, mx, my;
82    int mdx, mdy, mmx, mmy;
83    int dratio;
84    int ratio;
85 };
86
87 // Global value declaration.
88 static const char *widtype = NULL;
89
90 static const char SIG_CLICKED[] = "clicked";
91
92 // Internal function declaration.
93 static void _del_hook(Evas_Object *obj);
94
95 static void _theme_hook(Evas_Object *obj);
96
97 static void _sizing_eval(Evas_Object *obj);
98
99 static void _imageslider_move(void *data, Evas * e, Evas_Object *obj, void *event_info);
100 static void _imageslider_resize(void *data, Evas * e, Evas_Object *obj, void *event_info);
101 static void _imageslider_show(void *data, Evas * e, Evas_Object *obj, void *event_info);
102 static void _imageslider_hide(void *data, Evas * e, Evas_Object *obj, void *event_info);
103 static void _imageslider_update(Widget_Data * wd);
104
105 static void _imageslider_update_pos(Widget_Data * wd, Evas_Coord x, Evas_Coord y, Evas_Coord w);
106 static void _imageslider_update_center_pos(Widget_Data * wd, Evas_Coord x, Evas_Coord my, Evas_Coord y, Evas_Coord w);
107
108 static void _imageslider_obj_shift(Widget_Data * wd, Eina_Bool left);
109
110 static void _imageslider_obj_move(Widget_Data * wd, Evas_Coord step);
111
112 static Eina_Bool _icon_to_image(void *data);
113
114 static int _check_drag(int state, void *data);
115
116 static void _check_zoom(void *data);
117
118 static void _anim(Widget_Data * wd);
119
120 static Eina_Bool _timer_cb(void *data);
121
122 //static void _signal_clicked(void *data, Evas_Object *obj, const char *emission, const char *source);
123 static void _ev_imageslider_down_cb(void *data, Evas * e, Evas_Object *obj, void *event_info);
124 static void _ev_imageslider_up_cb(void *data, Evas * e, Evas_Object *obj, void *event_info);
125 static void _ev_imageslider_move_cb(void *data, Evas * e, Evas_Object *obj, void *event_info);
126
127 // Whenever the Image Slider item is deleted, Call this funtion.
128 static void
129 _del_hook(Evas_Object *obj)
130 {
131    int i;
132
133    Widget_Data *wd;
134
135    wd = elm_widget_data_get(obj);
136
137    if (!wd)
138       return;
139
140    for (i = 0; i < BLOCK_MAX; i++)
141      {
142        elm_widget_sub_object_del(wd->obj, wd->ly[i]);
143        evas_object_del(wd->ly[i]);
144      }
145
146    if (wd->its)
147      {
148         eina_list_free(wd->its);
149         wd->its = NULL;
150      }
151
152    if (wd->queue_idler)
153      {
154         ecore_idler_del(wd->queue_idler);
155         wd->queue_idler = NULL;
156      }
157
158    if (wd->anim_timer)
159      {
160         ecore_timer_del(wd->anim_timer);
161         wd->anim_timer = NULL;
162      }
163
164    if (wd)
165       free(wd);
166
167 }
168
169 // Whenever require processing theme, Call this function
170 static void
171 _theme_hook(Evas_Object *obj)
172 {
173    int i = 0;
174    Widget_Data *wd = elm_widget_data_get(obj);
175
176    if (!wd) return;
177
178    for (i = 0; i < BLOCK_MAX; i++)
179      {
180         if (wd->ly[i])
181            elm_layout_theme_set(wd->ly[i], "imageslider", "base",
182                                 elm_object_style_get(obj));
183         evas_object_show(wd->ly[i]);
184      }
185    _imageslider_update(wd);
186    _sizing_eval(obj);
187 }
188
189 // Resize Image Slider item.
190 static void
191 _sizing_eval(Evas_Object *obj)
192 {
193    Evas *e;
194
195    Widget_Data *wd = elm_widget_data_get(obj);
196
197    if (!wd)
198      return;
199
200    e = evas_object_evas_get(wd->obj);
201
202    _imageslider_move(obj, e, obj, NULL);
203    _imageslider_resize(obj, e, obj, NULL);
204
205 }
206
207 // Whenever MOVE event occurs, Call this function.
208 static void
209 _imageslider_move(void *data, Evas * e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
210 {
211    Widget_Data *wd;
212
213    Evas_Coord x, y;
214
215    if (!data)
216      return;
217
218    wd = elm_widget_data_get((Evas_Object *) data);
219    if (!wd)
220      return;
221
222    evas_object_geometry_get(obj, &x, &y, NULL, NULL);
223    wd->x = x;
224    wd->y = y;
225
226    _imageslider_update_pos(wd, wd->x, wd->y, wd->w);
227
228 }
229
230 // Whenever RESIZE event occurs, Call this fucntion.
231 static void
232 _imageslider_resize(void *data, Evas * e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
233 {
234    int i;
235
236    Widget_Data *wd;
237
238    Evas_Coord w, h;
239
240    if (!data)
241      return;
242
243    wd = elm_widget_data_get((Evas_Object *) data);
244    if (!wd)
245      return;
246
247    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
248    fprintf(stderr, "%d %d -resize\n", w, h);
249    wd->w = w;
250    wd->h = h;
251
252    for (i = 0; i < BLOCK_MAX; i++)
253      {
254         evas_object_resize(wd->ly[i], w, h);
255      }
256
257    _imageslider_update_pos(wd, wd->x, wd->y, wd->w);
258
259 }
260
261 // Whenever SHOW event occurs, Call this function.
262 static void
263 _imageslider_show(void *data, Evas * e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
264 {
265    Widget_Data *wd;
266
267    if (!data)
268      {
269         return;
270      }
271
272    wd = elm_widget_data_get((Evas_Object *) data);
273    if (!wd) return;
274
275    evas_object_show(wd->clip);
276 }
277
278 // Whenever HIDE event occurs, Call this function.
279 static void
280 _imageslider_hide(void *data, Evas * e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
281 {
282    Widget_Data *wd;
283
284    if (!data) return;
285
286    wd = elm_widget_data_get((Evas_Object *) data);
287    if (!wd) return;
288    evas_object_hide(wd->clip);
289 }
290
291 // Update Image Slider item position.
292 static void
293 _imageslider_update_pos(Widget_Data * wd, Evas_Coord x, Evas_Coord y, Evas_Coord w)
294 {
295    int i = 0;
296    evas_object_move(wd->ly[BLOCK_LEFT], x - (w + INTERVAL_WIDTH), y);
297    evas_object_move(wd->ly[BLOCK_CENTER], x, y);
298    evas_object_move(wd->ly[BLOCK_RIGHT], x + (w + INTERVAL_WIDTH), y);
299    //making sure that the clipping happens for all three layouts based on clipper's geometry
300    for (i = 0; i < BLOCK_MAX; i++)
301      evas_object_clip_set(wd->ly[i], wd->clip);
302    evas_render_idle_flush(evas_object_evas_get(wd->obj));
303 }
304
305 // Update the center position of Image Slider item.
306 static void
307 _imageslider_update_center_pos(Widget_Data * wd, Evas_Coord x, Evas_Coord my __UNUSED__, Evas_Coord y, Evas_Coord w)
308 {
309    Evas_Coord ix = 0, iy = 0, iw = 0, ih = 0;
310    const Evas_Object *eo = elm_layout_content_get((const Evas_Object*)(wd->ly[BLOCK_CENTER]), "swl.photo");
311    if (eo)
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, EINA_FALSE);
362           }
363         wd->moving = EINA_TRUE;
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, EINA_TRUE);
378           }
379         wd->moving = EINA_TRUE;
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 = EINA_FALSE;
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 = 0, iy = 0, iw = 0, ih = 0;
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         printf("Zooming\n");
424         wd->on_zoom = EINA_TRUE;
425         edje_object_signal_emit(elm_layout_edje_get(obj), "block.off", "block");
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
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         wd->move_cnt = 0;
526
527         if (ev->buttons)
528           {
529              step = ev->cur.canvas.x - wd->down_pos.x;
530              if (step > 0)
531                idx = BLOCK_LEFT;
532              else
533                idx = BLOCK_RIGHT;
534
535              wd->move_x = wd->x + ((ev->cur.canvas.x - wd->down_pos.x));
536              wd->move_y = wd->y + ((ev->cur.canvas.y - wd->down_pos.y));
537
538              /*if (wd->on_zoom)
539                {
540                   _imageslider_update_center_pos(wd, wd->move_x, wd->move_y, wd->y, wd->w);
541                }
542              else
543                {*/
544                   _imageslider_update_pos(wd, wd->move_x, wd->y, wd->w);
545                //}
546           }
547      }
548    wd->move_cnt++;
549
550 }
551
552 #if 0
553 // Whenever CLICK event occurs, Call this API
554 // But, DONOT emit CLICK event.
555 // DO NOT use this callback function. Remove later.
556 static void
557 _signal_clicked(void *data, Evas_Object *obj, const char *emission, const char *source)
558 {
559    fprintf(stderr, "[[[ DEBUG ]]]: Call the callback function about Click event!, But DONOT emit CLICK event in the callback function!\n");
560 }
561 #endif
562
563 static inline double
564 time_get(Evas_Coord x, Evas_Coord w)
565 {
566    double time;
567
568    time = (-sin(x / w) + 1) / 500;
569
570    if (time == 0)
571       time = ANI_TIME;
572
573    return time;
574 }
575
576 static Eina_Bool
577 _icon_to_image(void *data)
578 {
579    Widget_Data *wd = data;
580
581    wd->moving = 0;
582    _imageslider_update(wd);
583
584    if (wd->queue_idler)
585      {
586         ecore_idler_del(wd->queue_idler);
587         wd->queue_idler = NULL;
588      }
589    return ECORE_CALLBACK_CANCEL;
590 }
591
592 static int
593 _check_drag(int state, void *data)
594 {
595    Widget_Data *wd = data;
596
597    Elm_Imageslider_Item *it;
598
599    Evas_Coord ix = 0, iy = 0, iw = 0, ih = 0;
600
601    double dx = 0, dy = 0;
602
603    Eina_List *l[BLOCK_MAX];
604
605    Evas_Object *eo = NULL;
606
607    l[BLOCK_LEFT] = eina_list_prev(wd->cur);
608    l[BLOCK_CENTER] = wd->cur;
609    l[BLOCK_RIGHT] = eina_list_next(wd->cur);
610
611    it = eina_list_data_get(l[state]);
612
613    eo = (Evas_Object*)elm_layout_content_get(wd->ly[state], "swl.photo");
614    if (eo)
615      evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
616    edje_object_part_drag_value_get(elm_layout_edje_get(wd->ly[state]), "swl.photo", &dx, &dy);
617
618    if ((iw != wd->w) || ((dx != 0) || (dy != 0)))
619      {
620         elm_layout_content_set(wd->ly[state], "swl.photo", NULL);
621      }
622    else
623      return 1;
624
625    return 0;
626 }
627
628 static void
629 _check_zoom(void *data)
630 {
631    Widget_Data *wd = data;
632
633    Elm_Imageslider_Item *it;
634
635    Evas_Coord ix = 0, iy = 0, iw = 0, ih = 0;
636
637    double dx = 0, dy = 0;
638
639    Evas_Object *eo = NULL;
640
641    it = eina_list_data_get(wd->cur);
642
643    eo = (Evas_Object*)elm_layout_content_get(wd->ly[BLOCK_CENTER], "swl.photo");
644    if (eo)
645       evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
646    edje_object_part_drag_value_get(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "swl.photo", &dx, &dy);
647
648    if ((iw != wd->w) || ((dx != 0) || (dy != 0)))
649      {
650         wd->on_zoom = EINA_TRUE;
651         //edje_object_signal_emit(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "block.off", "block");
652      }
653    else
654      {
655         wd->on_zoom = EINA_FALSE;
656         edje_object_signal_emit(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "block.on", "block");
657      }
658 }
659
660 static Eina_Bool
661 _timer_cb(void *data)
662 {
663    Widget_Data *wd;
664
665    Elm_Imageslider_Item *it;
666
667    struct timeval tv;
668
669    int t;
670
671    int ret;
672
673    wd = data;
674    if (wd->ani_lock == EINA_FALSE)
675       return EINA_FALSE;
676
677    gettimeofday(&tv, NULL);
678
679    t = (tv.tv_sec - wd->tv.tv_sec) * 1000 + (tv.tv_usec - wd->tv.tv_usec) / 1000;
680    gettimeofday(&wd->tv, NULL);
681
682    t = t / ANI_TIME_MSEC;
683    if (t <= STEP_WEIGHT_MIN)
684      t = STEP_WEIGHT_DEF;
685    else if (t > STEP_WEIGHT_MAX)
686      t = STEP_WEIGHT_MAX;
687
688    wd->move_x += (wd->step) * t;
689
690    if (wd->step < 0 && wd->move_x < wd->x)
691      wd->move_x = wd->x;
692    else if (wd->step > 0 && wd->move_x > wd->x)
693      wd->move_x = wd->x;
694
695    _imageslider_update_pos(wd, wd->move_x, wd->y, wd->w);
696
697    if (wd->move_x == wd->x)
698      {
699         wd->ani_lock = EINA_FALSE;
700         if (wd->cur)
701           {
702              it = eina_list_data_get(wd->cur);
703              if (it->func)
704                it->func(it->data, wd->obj, it);
705           }
706         if (wd->cur)
707           {
708              it = eina_list_data_get(wd->cur);
709              evas_object_smart_callback_call(wd->obj, "changed", it);
710           }
711
712         ret = _check_drag(BLOCK_LEFT, wd);
713         ret = _check_drag(BLOCK_RIGHT, wd);
714         //_check_zoom(wd);
715
716         if (!wd->queue_idler)
717           wd->queue_idler = ecore_idler_add(_icon_to_image, wd);
718
719         if (wd->anim_timer)
720           {
721              ecore_timer_del(wd->anim_timer);
722              wd->anim_timer = NULL;
723           }
724
725         return ECORE_CALLBACK_CANCEL;
726      }
727
728    return ECORE_CALLBACK_RENEW;
729 }
730
731 static void
732 _anim(Widget_Data * wd)
733 {
734    Evas_Coord w;
735
736    if (wd->x == wd->move_x)
737      {
738         _imageslider_update_pos(wd, wd->move_x, wd->y, wd->w);
739         return;
740      }
741
742    wd->ani_lock = EINA_TRUE;
743
744    w = wd->move_x;
745    gettimeofday(&wd->tv, NULL);
746
747    if (!wd->anim_timer)
748      wd->anim_timer = ecore_timer_add(ANI_TIME, _timer_cb, wd);
749 }
750
751 // Update Image Slider Items.
752 static void
753 _imageslider_update(Widget_Data * wd)
754 {
755    int i;
756
757    Eina_List *l[BLOCK_MAX];
758
759    Elm_Imageslider_Item *it;
760
761    Evas_Object *eo;
762
763    if (!wd)
764      return;
765
766    if (!wd->cur) return;
767
768    l[BLOCK_LEFT] = eina_list_prev(wd->cur);
769    l[BLOCK_CENTER] = wd->cur;
770    l[BLOCK_RIGHT] = eina_list_next(wd->cur);
771
772    for (i = 0; i < BLOCK_MAX; i++)
773      {
774         eo = (Evas_Object*)elm_layout_content_get((const Evas_Object*)wd->ly[i], "swl.photo");
775         if (!l[i])
776           {
777              elm_layout_content_set(wd->ly[i], "swl.photo", NULL);
778           }
779         else
780           {
781              it = eina_list_data_get(l[i]);
782              if (!it)
783                return;
784
785              if (!eo)
786                {
787                   eo = elm_image_add(wd->obj);
788                   //elm_image_prescale_set(eo, wd->w);
789                   elm_image_file_set(eo, it->photo_file, NULL);
790                   elm_layout_content_set(wd->ly[i], "swl.photo", eo);
791                   //elm_image_object_size_get(eo, &it->w, &it->h);
792                   //evas_object_geometry_get(eo, &it->ox, &it->oy, &it->ow, &it->oh);
793                   //it->ow = it->w;
794                   //it->oh = it->h;
795                }
796              /*if (wd->moving != it->moving)
797                {
798                   it->moving = wd->moving;
799                   if (wd->moving)
800                     {
801                        //elm_image_prescale_set(eo, MOVING_IMAGE_SIZE);
802                     }
803                   else
804                     {
805                        //elm_image_prescale_set(eo, it->w > it->h ? it->w : it->h);
806                     }
807                }*/
808           }
809      }
810
811    _anim(wd);
812 }
813
814 /**
815 * Add an Image Slider widget
816 *
817 * @param        parent  The parent object
818 * @return       The new Image slider object or NULL if it cannot be created
819 *
820 * @ingroup Imageslider
821 */
822 EAPI Evas_Object *
823 elm_imageslider_add(Evas_Object *parent)
824 {
825    int i;
826
827    Evas_Object *obj;
828    Evas *e;
829    Widget_Data *wd;
830
831    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
832
833    ELM_SET_WIDTYPE(widtype, "imageslider");
834    elm_widget_type_set(obj, "imageslider");
835    elm_widget_sub_object_add(parent, obj);
836    elm_widget_data_set(obj, wd);
837    elm_widget_del_hook_set(obj, _del_hook);
838    elm_widget_theme_hook_set(obj, _theme_hook);
839
840    wd->clip = evas_object_rectangle_add(e);
841    elm_widget_sub_object_add(obj, wd->clip);
842    elm_widget_resize_object_set(obj, wd->clip);
843
844    for (i = 0; i < BLOCK_MAX; i++)
845      {
846         wd->ly[i] = elm_layout_add(obj);
847         elm_layout_theme_set(wd->ly[i], "imageslider", "base", "default");
848         elm_widget_sub_object_add(obj, wd->ly[i]);
849         evas_object_smart_member_add(wd->ly[i], obj);
850
851         //edje_object_signal_callback_add(elm_layout_edje_get(wd->ly[i]), "elm,photo,clicked", "", _signal_clicked, obj);
852         evas_object_event_callback_add(wd->ly[i], EVAS_CALLBACK_MOUSE_DOWN, _ev_imageslider_down_cb, wd);
853         evas_object_event_callback_add(wd->ly[i], EVAS_CALLBACK_MOUSE_UP, _ev_imageslider_up_cb, wd);
854         evas_object_event_callback_add(wd->ly[i], EVAS_CALLBACK_MOUSE_MOVE, _ev_imageslider_move_cb, wd);
855         evas_object_clip_set(wd->ly[i], wd->clip);
856         evas_object_show(wd->ly[i]);
857      }
858
859    wd->obj = obj;
860
861    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _imageslider_resize, obj);
862    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _imageslider_move, obj);
863    evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _imageslider_show, obj);
864    evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _imageslider_hide, obj);
865
866    _sizing_eval(obj);
867
868    return obj;
869 }
870
871 /**
872 * Append an Image Slider item
873 *
874 * @param        obj          The Image Slider object
875 * @param        photo_file   photo file path
876 * @param        func         callback function
877 * @param        data         callback data
878 * @return       The Image Slider item handle or NULL
879 *
880 * @ingroup Imageslider
881 */
882 EAPI Elm_Imageslider_Item *
883 elm_imageslider_item_append(Evas_Object *obj, const char *photo_file, Elm_Imageslider_Cb func, void *data)
884 {
885    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
886    Widget_Data *wd;
887
888    Elm_Imageslider_Item *it;
889
890    if (!obj || !(wd = elm_widget_data_get(obj)))
891      return NULL;
892
893    it = (Elm_Imageslider_Item *) calloc(1, sizeof(Elm_Imageslider_Item));
894    if (!it)
895       return NULL;
896    it->photo_file = eina_stringshare_add(photo_file);
897    it->func = func;
898    it->data = data;
899    it->obj = obj;
900    wd->its = eina_list_append(wd->its, it);
901
902    if (!wd->cur)
903       wd->cur = wd->its;
904
905    _imageslider_update(wd);
906
907    return it;
908 }
909
910 /**
911 * Insert an Image Slider item into the Image Slider Widget by using the given index.
912 *
913 * @param        obj                     The Image Slider object
914 * @param        photo_file      photo file path
915 * @param        func            callback function
916 * @param        index           required position
917 * @param        data            callback data
918 * @return       The Image Slider item handle or NULL
919 *
920 * @ingroup      Imageslider
921 */
922 EAPI Elm_Imageslider_Item *
923 elm_imageslider_item_append_relative(Evas_Object *obj, const char *photo_file, Elm_Imageslider_Cb func, unsigned int index, void *data)
924 {
925    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
926    Widget_Data *wd;
927
928    Elm_Imageslider_Item *it;
929
930    fprintf(stderr, "[[[ DEBUG ]]]:: New elm_imageslider_item_append_relative()\n");
931
932    if (!obj || !(wd = elm_widget_data_get(obj)))
933      return NULL;
934
935    it = (Elm_Imageslider_Item *) calloc(1, sizeof(Elm_Imageslider_Item));
936    if (!it)
937       return NULL;
938
939    it->obj = obj;
940    it->photo_file = eina_stringshare_add(photo_file);
941    it->func = func;
942    it->data = data;
943
944    wd->its =
945       eina_list_append_relative(wd->its, it, eina_list_nth(wd->its, index - 2));
946
947    if (!wd->cur)
948       wd->cur = wd->its;
949
950    _imageslider_update(wd);
951
952    return it;
953 }
954
955 /**
956 * Prepend Image Slider item
957 *
958 * @param        obj          The Image Slider object
959 * @param        photo_file   photo file path
960 * @param        func         callback function
961 * @param        data         callback data
962 * @return       The imageslider item handle or NULL
963 *
964 * @ingroup Imageslider
965 */
966 EAPI Elm_Imageslider_Item *
967 elm_imageslider_item_prepend(Evas_Object *obj, const char *photo_file, Elm_Imageslider_Cb func, void *data)
968 {
969    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
970    Widget_Data *wd;
971
972    Elm_Imageslider_Item *it;
973
974    if (!obj || !(wd = elm_widget_data_get(obj)))
975      return NULL;
976
977    it = (Elm_Imageslider_Item *) calloc(1, sizeof(Elm_Imageslider_Item));
978    it->photo_file = eina_stringshare_add(photo_file);
979    it->func = func;
980    it->data = data;
981    it->obj = obj;
982    wd->its = eina_list_prepend(wd->its, it);
983
984    if (!wd->cur)
985       wd->cur = wd->its;
986
987    _imageslider_update(wd);
988
989    return it;
990 }
991
992 /**
993 * Delete the selected Image Slider item
994 *
995 * @param it             The selected Image Slider item handle
996 *
997 * @ingroup Imageslider
998 */
999 EAPI void
1000 elm_imageslider_item_del(Elm_Imageslider_Item * it)
1001 {
1002    Widget_Data *wd;
1003
1004    Elm_Imageslider_Item *_it;
1005
1006    Eina_List *l;
1007
1008    if (!it || !(wd = elm_widget_data_get(it->obj)))
1009      return;
1010
1011    EINA_LIST_FOREACH(wd->its, l, _it)
1012      {
1013         if (_it == it)
1014           {
1015              if (l == wd->cur)
1016                 wd->cur = eina_list_prev(wd->cur);
1017              wd->its = eina_list_remove(wd->its, it);
1018              if (!wd->cur)
1019                 wd->cur = wd->its;
1020              break;
1021           }
1022      }
1023
1024    _imageslider_update(wd);
1025
1026 }
1027
1028 /**
1029 * Get the selected Image Slider item
1030 *
1031 * @param obj            The Image Slider object
1032 * @return The selected Image Slider item or NULL
1033 *
1034 * @ingroup Imageslider
1035 */
1036 EAPI Elm_Imageslider_Item *
1037 elm_imageslider_selected_item_get(Evas_Object *obj)
1038 {
1039    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1040    Widget_Data *wd;
1041
1042    if (!obj || (!(wd = elm_widget_data_get(obj))))
1043      return NULL;
1044
1045    if (!wd->cur)
1046       return NULL;
1047
1048    return eina_list_data_get(wd->cur);
1049 }
1050
1051 /**
1052 * Get whether an Image Slider item is selected or not
1053 *
1054 * @param it              the selected Image Slider item
1055 * @return EINA_TRUE or EINA_FALSE
1056 *
1057 * @ingroup Imageslider
1058 */
1059 EAPI Eina_Bool
1060 elm_imageslider_item_selected_get(Elm_Imageslider_Item * it)
1061 {
1062    Widget_Data *wd;
1063
1064    if (!it || !it->obj || (!(wd = elm_widget_data_get(it->obj))))
1065      return EINA_FALSE;
1066
1067    if (!wd->cur)
1068       return EINA_FALSE;
1069
1070    if (eina_list_data_get(wd->cur) == it)
1071       return EINA_TRUE;
1072    else
1073       return EINA_FALSE;
1074
1075 }
1076
1077 /**
1078 * Set the selected Image Slider item
1079 *
1080 * @param it             The Imaga Slider item
1081 *
1082 * @ingroup Imageslider
1083 */
1084 EAPI void
1085 elm_imageslider_item_selected_set(Elm_Imageslider_Item * it)
1086 {
1087    int i;
1088
1089    Widget_Data *wd;
1090
1091    Elm_Imageslider_Item *_it;
1092
1093    Eina_List *l;
1094
1095    Evas_Object *eo;
1096
1097    if (!it || !it->obj || (!(wd = elm_widget_data_get(it->obj))))
1098      return;
1099
1100    EINA_LIST_FOREACH(wd->its, l, _it)
1101      {
1102         if (_it == it)
1103           wd->cur = l;
1104      }
1105
1106    for (i = 0; i < BLOCK_MAX; i++)
1107      {
1108        eo = (Evas_Object*)elm_layout_content_get(wd->ly[i], "swl.photo");
1109        if (eo)
1110           {
1111              elm_layout_content_set(wd->ly[i], "swl.photo", NULL);
1112           }
1113      }
1114
1115    _imageslider_update(wd);
1116
1117 }
1118
1119 /**
1120 * Get the photo file path of given Image Slider item
1121 *
1122 * @param it             The Image Slider item
1123 * @return The photo file path or NULL;
1124 *
1125 * @ingroup Imageslider
1126 */
1127 EAPI const char *
1128 elm_imageslider_item_photo_file_get(Elm_Imageslider_Item * it)
1129 {
1130    if (!it) return NULL;
1131
1132    return it->photo_file;
1133 }
1134
1135 /**
1136 * Sets the photo file path of given Image Slider item
1137 *
1138 * @param it         The Image Slider item
1139 * @param photo_file The photo file path or NULL;
1140 *
1141 * @ingroup Imageslider
1142 */
1143 EAPI void
1144 elm_imageslider_item_photo_file_set(Elm_Imageslider_Item *it, const char *photo_file)
1145 {
1146    if (!it) return;
1147    ELM_CHECK_WIDTYPE(it->obj, widtype);
1148
1149    if (photo_file)
1150      {
1151         eina_stringshare_replace(&(it->photo_file), photo_file);
1152         elm_imageslider_item_update(it);
1153      }
1154 }
1155
1156 /**
1157 * Get the previous Image Slider item
1158 *
1159 * @param it             The Image Slider item
1160 * @return The previous Image Slider item or NULL
1161 *
1162 * @ingroup Imageslider
1163 */
1164 EAPI Elm_Imageslider_Item *
1165 elm_imageslider_item_prev(Elm_Imageslider_Item * it)
1166 {
1167    Widget_Data *wd;
1168
1169    Elm_Imageslider_Item *_it;
1170
1171    Eina_List *l;
1172
1173    if (!it || (!(wd = elm_widget_data_get(it->obj))))
1174      return NULL;
1175
1176    EINA_LIST_FOREACH(wd->its, l, _it)
1177      {
1178         if (_it == it)
1179           {
1180              l = eina_list_prev(l);
1181              if (!l)
1182                break;
1183              return eina_list_data_get(l);
1184           }
1185      }
1186
1187    return NULL;
1188 }
1189
1190 /**
1191 * Get the next Image Slider item
1192 *
1193 * @param it             The Image Slider item
1194 * @return The next Image Slider item or NULL
1195 *
1196 * @ingroup Imageslider
1197 */
1198 EAPI Elm_Imageslider_Item *
1199 elm_imageslider_item_next(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_next(l);
1215              if (!l)
1216                break;
1217              return eina_list_data_get(l);
1218           }
1219      }
1220
1221    return NULL;
1222 }
1223
1224 /**
1225 * Move to the previous Image Slider item
1226 *
1227 * @param obj    The Image Slider object
1228 *
1229 * @ingroup Imageslider
1230 */
1231 EAPI void
1232 elm_imageslider_prev(Evas_Object *obj)
1233 {
1234    ELM_CHECK_WIDTYPE(obj, widtype);
1235    Widget_Data *wd;
1236
1237    if (!obj || (!(wd = elm_widget_data_get(obj))))
1238      return;
1239
1240    if (wd->ani_lock)
1241      return;
1242
1243    _imageslider_obj_move(wd, -1);
1244 }
1245
1246 /**
1247 * Move to the next Image Slider item
1248 *
1249 * @param obj The Image Slider object
1250 *
1251 * @ingroup Imageslider
1252 */
1253 EAPI void
1254 elm_imageslider_next(Evas_Object * obj)
1255 {
1256    ELM_CHECK_WIDTYPE(obj, widtype);
1257    Widget_Data *wd;
1258
1259    if (!obj || (!(wd = elm_widget_data_get(obj))))
1260      return;
1261
1262    if (wd->ani_lock)
1263      return;
1264
1265    _imageslider_obj_move(wd, 1);
1266
1267 }
1268
1269 /**
1270 * Updates an Image Slider item
1271 *
1272 * @param it The Image Slider item
1273 *
1274 * @ingroup Imageslider
1275 */
1276 EAPI void
1277 elm_imageslider_item_update(Elm_Imageslider_Item *it)
1278 {
1279    Widget_Data *wd;
1280
1281    if (!it || (!(wd = elm_widget_data_get(it->obj)))) return;
1282    ELM_CHECK_WIDTYPE(it->obj, widtype);
1283
1284    if (wd->ani_lock == EINA_TRUE) return;
1285    if (it == eina_list_data_get(eina_list_prev(wd->cur)))
1286      elm_layout_content_set(wd->ly[BLOCK_LEFT], "swl.photo", NULL);
1287    else if (it == eina_list_data_get(wd->cur))
1288      elm_layout_content_set(wd->ly[BLOCK_CENTER], "swl.photo", NULL);
1289    else if (it == eina_list_data_get(eina_list_next(wd->cur)))
1290      elm_layout_content_set(wd->ly[BLOCK_RIGHT], "swl.photo", NULL);
1291    _imageslider_update(wd);
1292 }