Merge branch 'master' of 165.213.180.234:/git/slp/pkgs/elementary
[framework/uifw/elementary.git] / src / lib / elm_imageslider.c
1 /* 
2
3 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 
4 */
5 #include <stdio.h>
6 #include <math.h>
7 #include <Elementary.h>
8 #include "elm_priv.h"
9
10 /**
11 * @defgroup Imageslider Imageslider
12 * @ingroup Elementary
13 *
14 * By flicking images on the screen, 
15 * you can see the images in specific path.
16 */
17
18 typedef struct _Widget_Data Widget_Data;
19
20 #define ANI_STEP                                (14 * elm_scale_get())
21 #define ANI_TIME                                (0.005)
22 #define ANI_TIME_MSEC           (12)
23 #define FLICK_TIME_MAX          (200)
24 #define FLICK_WIDTH_MIN (elm_finger_size_get() >> 2)
25 #define MOVE_STEP                       (3)
26 #define STEP_WEIGHT_DEF (1)
27 #define STEP_WEIGHT_MAX (2)
28 #define STEP_WEIGHT_MIN (0)
29 #define MOVING_IMAGE_SIZE       (128)
30 #define MAX_ZOOM_SIZE           (6)
31 #define INTERVAL_WIDTH          (15)
32 #define MULTITOUCHDEVICE        (11)
33
34 enum {
35         BLOCK_LEFT = 0,
36         BLOCK_CENTER,
37         BLOCK_RIGHT,
38         BLOCK_MAX
39 };
40
41 struct _Imageslider_Item 
42 {
43         Evas_Object *obj;
44         const char *photo_file;
45         void (*func)(void *data, Evas_Object *obj, void *event_info);
46         void *data;
47         Evas_Coord x, y, w, h;
48         Evas_Coord ox, oy, ow, oh;
49         int moving : 1;
50 };
51
52 struct _Widget_Data
53 {
54         Evas_Object *ly[BLOCK_MAX];
55         Evas_Object *clip;
56         Eina_List *its;
57         Eina_List *cur;
58         Evas_Coord x, y, w, h;
59         Evas_Object *obj;
60         Ecore_Idler *queue_idler;
61         Ecore_Timer *anim_timer;
62
63         Evas_Coord_Point down_pos;
64         Evas_Coord move_x;
65         Evas_Coord move_y;
66         Evas_Coord dest_x;
67         struct timeval tv;
68         unsigned int timestamp;
69         int step;
70         int move_cnt;
71         int ani_lock : 1;
72         int moving : 1;
73
74         Eina_Bool on_zoom : 1;
75         Eina_Bool on_hold : 1;
76         int dx, dy, mx, my;
77         int mdx, mdy, mmx, mmy;
78         int dratio;
79         int ratio;
80 };
81
82 static const char *widtype = NULL;
83 static const char SIG_CLICKED[] = "clicked";
84
85 static void _del_hook(Evas_Object *obj);
86 static void _theme_hook(Evas_Object *obj);
87 static void _sizing_eval(Evas_Object *obj);
88 static void _imageslider_del_all(Widget_Data *wd);
89 static void _imageslider_move(void *data,Evas *e, Evas_Object *obj, void *event_info);
90 static void _imageslider_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
91 //static void _imageslider_show(Evas_Object *obj);
92 //static void _imageslider_hide(Evas_Object *obj);
93 static void _imageslider_show(void * data, Evas * e, Evas_Object * obj, void * event_info);
94 static void _imageslider_hide(void * data, Evas * e, Evas_Object * obj, void * event_info);
95 static void _imageslider_update(Widget_Data *wd);
96 static void _imageslider_update_pos(Widget_Data *wd, Evas_Coord x, Evas_Coord y, Evas_Coord w);
97 static void _imageslider_update_center_pos(Widget_Data *wd, Evas_Coord x, Evas_Coord my, Evas_Coord y, Evas_Coord w);
98 static Evas_Object *_imageslider_add_obj(Widget_Data *wd);
99 static void _imageslider_obj_shift(Widget_Data *wd, Eina_Bool left);
100 static void _imageslider_obj_move(Widget_Data *wd, Evas_Coord step);
101 static Eina_Bool _icon_to_image(void *data);
102 static int _check_drag(int state, void *data);
103 static void _check_zoom(void *data);
104 static void _anim(Widget_Data *wd);
105 static Eina_Bool _timer_cb(void *data);
106 static void _signal_clicked(void *data, Evas_Object *obj, const char *emission, const char *source);
107 static void ev_imageslider_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
108 static void ev_imageslider_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
109 static void ev_imageslider_move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
110
111
112 static void _del_hook(Evas_Object * obj)
113 {
114         int i;
115         Widget_Data * wd;
116         wd = elm_widget_data_get(obj);
117         
118         //fprintf( stderr, "Call imageslider del hook!\n" );
119         
120         if (!wd) return;
121
122         for (i = 0; i < BLOCK_MAX; i++) {
123                 evas_object_del(wd->ly[i]);
124         }
125
126         if (wd->its) {
127                 eina_list_free(wd->its);
128                 wd->its = NULL;
129         }
130
131         if (wd->queue_idler) {
132                 ecore_idler_del(wd->queue_idler);
133                 wd->queue_idler = NULL;         
134         }
135
136         if (wd->anim_timer) {
137                 ecore_timer_del(wd->anim_timer);
138                 wd->anim_timer = NULL;
139         }
140
141         if (wd) free(wd);
142         
143 }
144
145 static void _theme_hook(Evas_Object * obj)
146 {
147         int i;
148         Widget_Data *wd;
149         wd = elm_widget_data_get(obj);
150
151         if (!wd || !wd->ly ) {
152                 return;
153         }
154
155         for (i=0; i < BLOCK_MAX; i++) {
156                 wd->ly[i] = elm_layout_add(obj);
157                 _elm_theme_object_set(obj, wd->ly[i], "imageslider", "base", "default");
158                 elm_widget_resize_object_set(obj, wd->ly[i]);
159                 evas_object_show(wd->ly[i]);                    
160         }
161
162         _sizing_eval(obj);      
163 }
164
165
166 static void _sizing_eval(Evas_Object * obj)
167 {
168         Evas *e;
169         Widget_Data *wd = elm_widget_data_get(obj);
170
171         if (!wd) {
172                 return;
173         }
174
175         e = evas_object_evas_get(wd->obj);
176
177         _imageslider_move(obj, e, obj, NULL);
178         _imageslider_resize(obj, e, obj, NULL);
179
180 }
181
182 static void _imageslider_move(void * data, Evas * e, Evas_Object * obj, void * event_info)
183 {
184         Widget_Data *wd;
185         Evas_Coord x, y;
186
187         if (!data) {
188                 return;
189         }
190         
191         wd = elm_widget_data_get((Evas_Object *) data);
192         if (!wd) {
193                 return;
194         }
195
196         evas_object_geometry_get(obj, &x, &y, NULL, NULL);
197         wd->x = x;
198         wd->y = y;
199         evas_object_move(wd->clip, x, y);
200         
201         _imageslider_update_pos(wd, wd->x, wd->y, wd->w);
202         
203 }
204
205 static void _imageslider_resize(void * data, Evas * e, Evas_Object * obj, void * event_info)
206 {
207         int i;
208         Widget_Data *wd;
209         Evas_Coord w, h;
210
211         if (!data) {
212                 return;
213         }
214                 
215         wd = elm_widget_data_get((Evas_Object *) data);
216         if (!wd || !wd->ly) {
217                 return;         
218         }
219
220         evas_object_geometry_get(obj, NULL, NULL, &w, &h);
221         fprintf( stderr, "%d %d -resize\n" , w, h );
222         wd->w = w;
223         wd->h = h;
224
225         for (i = 0; i < BLOCK_MAX; i++) {
226                 evas_object_resize(wd->ly[i], w, h);
227         }
228
229         evas_object_resize(wd->clip, w, h);
230
231         _imageslider_update_pos(wd, wd->x, wd->y, wd->w);
232         
233 }
234
235
236 //static void _imageslider_show(Evas_Object * obj)
237 static void _imageslider_show(void *data, Evas *e, Evas_Object * obj, void *event_info)
238 {
239         Widget_Data *wd;
240
241         if (!data) {
242                 return;
243         }
244         
245         wd = elm_widget_data_get((Evas_Object *) data);
246         if (!wd) {
247                 return;
248         }
249         
250         evas_object_show(wd->clip);
251 }
252
253 //static void _imageslider_hide(Evas_Object *obj)
254 static void _imageslider_hide(void *data, Evas *e, Evas_Object *obj, void *event_info)
255 {
256         Widget_Data *wd;
257
258         if (!data) {
259                 return;
260         }
261         
262         wd = elm_widget_data_get((Evas_Object *) data);
263         if (!wd) {
264                 return;
265         }
266         evas_object_hide(wd->clip);
267 }
268
269 static void _imageslider_del_all(Widget_Data * wd)
270 {
271    
272         int i;
273
274         if (!wd) {
275                 return;
276         }
277
278         for (i = 0; i < BLOCK_MAX; i++) {
279                 evas_object_del(wd->ly[i]);
280         }
281 }
282
283 static void _imageslider_update_pos(Widget_Data * wd, Evas_Coord x, Evas_Coord y, Evas_Coord w)
284 {
285         evas_object_move(wd->ly[BLOCK_LEFT], x - (w + INTERVAL_WIDTH), y);
286         evas_object_move(wd->ly[BLOCK_CENTER], x, y);
287         evas_object_move(wd->ly[BLOCK_RIGHT], x + (w + INTERVAL_WIDTH), y);
288         evas_render_idle_flush(evas_object_evas_get(wd->obj));
289 }
290
291 static void _imageslider_update_center_pos(Widget_Data * wd, Evas_Coord x, Evas_Coord my, Evas_Coord y, Evas_Coord w)
292 {
293         Evas_Object *eo;
294         Evas_Coord ix, iy, iw, ih;
295
296         eo = edje_object_part_swallow_get(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "swl.photo");
297         evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
298
299         if ((ix > 0) || (ix + iw < wd->w)) {
300                 edje_object_signal_emit(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "block.on", "block");
301 //              edje_freeze();
302 //              evas_event_feed_mouse_cancel(evas_object_evas_get(wd->obj), NULL, NULL);
303 //              evas_event_feed_mouse_down(evas_object_evas_get(wd->obj), 1, EVAS_BUTTON_NONE, NULL, NULL);             
304
305                 _imageslider_update_pos(wd, x, y, w);
306                 wd->on_zoom = EINA_FALSE;
307         }
308 }
309
310 static Evas_Object *_imageslider_add_obj(Widget_Data *wd)
311 {
312         Evas_Object *eo;
313         eo = elm_layout_add(wd->obj);
314         elm_layout_theme_set(eo, "imageslider", "base", "default");
315         elm_widget_resize_object_set(wd->obj, eo);
316         edje_object_signal_callback_add(elm_layout_edje_get(eo), "elm,photo,clicked", "", _signal_clicked, wd->obj);
317 //      evas_object_smart_member_add(eo, wd->obj);
318         evas_object_event_callback_add(eo, EVAS_CALLBACK_MOUSE_DOWN, ev_imageslider_down_cb, wd);
319         evas_object_event_callback_add(eo, EVAS_CALLBACK_MOUSE_UP, ev_imageslider_up_cb, wd);
320         evas_object_event_callback_add(eo, EVAS_CALLBACK_MOUSE_MOVE, ev_imageslider_move_cb, wd);
321         evas_object_resize(eo, wd->w, wd->h);
322         evas_object_move(eo, wd->w + INTERVAL_WIDTH, wd->y);
323         evas_object_clip_set(eo, wd->clip);
324         evas_object_show(eo);
325
326         return eo;
327 }
328
329 static void _imageslider_obj_shift(Widget_Data *wd, Eina_Bool left)
330 {
331         if (!left) {
332                 if (wd->ly[BLOCK_LEFT]) {
333                         evas_object_del(wd->ly[BLOCK_LEFT]);
334                         wd->ly[BLOCK_LEFT] = NULL;
335                 }
336
337                 wd->ly[BLOCK_LEFT] = wd->ly[BLOCK_CENTER];
338                 wd->ly[BLOCK_CENTER]= wd->ly[BLOCK_RIGHT];
339                 wd->ly[BLOCK_RIGHT] = _imageslider_add_obj(wd);
340         } else {
341                 if (wd->ly[BLOCK_RIGHT]) {
342                         evas_object_del(wd->ly[BLOCK_RIGHT]);
343                         wd->ly[BLOCK_RIGHT] = NULL;
344                 }
345
346                 wd->ly[BLOCK_RIGHT]= wd->ly[BLOCK_CENTER];
347                 wd->ly[BLOCK_CENTER]= wd->ly[BLOCK_LEFT];
348                 wd->ly[BLOCK_LEFT]= _imageslider_add_obj(wd);
349         }
350 }
351
352
353 static void _imageslider_obj_move(Widget_Data * wd, Evas_Coord step)
354 {
355         if (step > 0) {
356                 wd->cur = eina_list_next(wd->cur);
357                 if (wd->cur == NULL) {
358                         wd->cur = eina_list_last(wd->its);
359                         wd->step = ANI_STEP;
360                 } else {
361                         wd->step = -ANI_STEP;
362                         wd->move_x += wd->w;
363                         _imageslider_obj_shift(wd, 0);
364                 }
365                 wd->moving = 1;         
366         } else if (step < 0) {
367                 wd->cur = eina_list_prev(wd->cur);
368                 if (wd->cur == NULL) {
369                         wd->cur = wd->its;
370                         wd->step = -ANI_STEP;
371                 } else {
372                         wd->step = ANI_STEP;
373                         wd->move_x -= wd->w;
374                         _imageslider_obj_shift(wd, 1);
375                 }
376                 wd->moving = 1;
377         } else {
378                 if (wd->move_x < 0) wd->step = ANI_STEP;
379                 else wd->step = -ANI_STEP;
380                 wd->moving = 0;
381         }
382
383         _imageslider_update(wd);
384 }
385
386 static void ev_imageslider_down_cb(void * data, Evas * e, Evas_Object * obj, void * event_info)
387 {
388         Widget_Data *wd = data;
389         Evas_Event_Mouse_Down *ev = event_info;
390         Evas_Coord ix, iy, iw, ih;
391         Evas_Object *eo = NULL;
392
393         if (wd->ani_lock) return;
394
395         wd->down_pos = ev->canvas;
396         wd->timestamp = ev->timestamp;
397         wd->move_cnt = MOVE_STEP;
398
399         wd->dx = ev->canvas.x;
400         wd->dy = ev->canvas.y;
401         wd->mx = ev->canvas.x;
402         wd->my = ev->canvas.y;
403
404         wd->dratio = 1;
405         wd->ratio = 1;
406
407         eo = edje_object_part_swallow_get(elm_layout_edje_get(obj), "swl.photo");
408         if (eo) evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
409
410         if (iw != wd->w) {
411                 wd->on_zoom = EINA_TRUE;
412                 edje_object_signal_emit(elm_layout_edje_get(obj), "block.off", "block");
413 //              edje_thaw();            
414         }
415
416         //fprintf( stderr, "-- down! --\n" );
417
418 }
419
420 static void ev_imageslider_up_cb(void * data, Evas * e, Evas_Object * obj, void * event_info)
421 {
422         Widget_Data *wd = data;
423         Evas_Event_Mouse_Up *ev = event_info;
424         Evas_Coord step;
425         int interval;
426
427         if (wd->ani_lock) return;
428
429         if (wd->on_zoom) {              
430         } else {
431                 step = wd->down_pos.x - ev->canvas.x;
432                 interval = ev->timestamp - wd->timestamp;
433                 if (step == 0 || interval == 0) return;
434
435                 if (interval < FLICK_TIME_MAX) {
436                         if (step < FLICK_WIDTH_MIN && step > FLICK_WIDTH_MIN) _imageslider_obj_move(wd, 0);
437                         else _imageslider_obj_move(wd, step);
438                 } else {
439                         step = (wd->x - wd->move_x) << 1;
440                         if (step <= wd->w && step >= -(wd->w)) _imageslider_obj_move(wd, 0);
441                         else _imageslider_obj_move(wd, step);
442                 }
443         }
444
445         //fprintf( stderr, "-- up! --\n" );
446
447 }
448
449 static void ev_imageslider_move_cb(void * data, Evas * e, Evas_Object * obj, void * event_info)
450 {
451         int idx;
452         Evas_Object *eo;
453         Evas_Coord step;
454         Widget_Data *wd = data;
455         Evas_Event_Mouse_Move *ev = event_info;
456         Elm_Imageslider_Item *it;
457
458         if (wd->ani_lock) return;
459
460         if (wd->move_cnt == MOVE_STEP) {
461                 if (wd->on_hold == EINA_FALSE) {
462                         wd->move_cnt = 0;
463
464                         if (ev->buttons) {
465                                 step = ev->cur.canvas.x - wd->down_pos.x;
466                                 if (step > 0) idx = BLOCK_LEFT;
467                                 else idx = BLOCK_RIGHT;
468
469                                 wd->move_x = wd->x + ((ev->cur.canvas.x - wd->down_pos.x));
470                                 wd->move_y = wd->y + ((ev->cur.canvas.y - wd->down_pos.y));
471
472                                 if (wd->on_zoom) {
473                                         _imageslider_update_center_pos(wd, wd->move_x, wd->move_y, wd->y, wd->w);
474                                 } else {
475                                         _imageslider_update_pos(wd, wd->move_x, wd->y, wd->w);
476                                 }
477                         }
478                 } else {
479                         wd->mx = ev->cur.canvas.x;
480                         wd->my = ev->cur.canvas.y;
481
482                         wd->ratio = sqrt((wd->mx -wd->mmx)*(wd->mx -wd->mmx) + (wd->my - wd->mmy)*(wd->my - wd->mmy));
483
484                         eo = edje_object_part_swallow_get(elm_layout_edje_get(obj), "swl.photo");
485                         if (eo) {
486                                 it = eina_list_data_get(wd->cur);
487                                 if (((it->w * wd->ratio/wd->dratio)/it->ow) < MAX_ZOOM_SIZE ) {
488                                         edje_object_part_unswallow(elm_layout_edje_get(obj), eo);
489                                         evas_object_resize(eo, it->w * wd->ratio/wd->dratio, it->h * wd->ratio/wd->dratio);
490                                         evas_object_size_hint_min_set(eo, it->w * wd->ratio/wd->dratio, it->h * wd->ratio/wd->dratio);
491                                         edje_object_part_swallow(elm_layout_edje_get(obj), "swl.photo", eo);
492                                 }
493                         }                       
494                 }
495         }
496
497         wd->move_cnt++;
498
499 }
500
501
502 static void
503 _signal_clicked(void *data, Evas_Object *obj, const char *emission, const char *source)
504 {
505         //fprintf(stderr, "[[[ DEBUG ]]]: (EFL) SIGNAL CLICKED!!\n");
506         evas_object_smart_callback_call(data, SIG_CLICKED, NULL);       
507 }
508
509 #if 0 // REMOVED about Multi-touch.
510 static void ev_imageslider_multi_down_cb(void * data, Evas * e, Evas_Object * obj, void * event_info)
511 {
512         Evas_Event_Multi_Down *ev = event_info;
513         Widget_Data *wd = data;
514
515         if (ev->device == MULTITOUCHDEVICE) return;
516
517         wd->on_hold = EINA_TRUE;
518         wd->mdx = ev->canvas.x;
519         wd->mdy = ev->canvas.y;
520         wd->mmx = ev->canvas.x;
521         wd->mmy = ev->canvas.y;
522
523         wd->dratio = sqrt((wd->mx - wd->mmx)*(wd->mx - wd->mmx) + (wd->my - wd->mmy)*(wd->my - wd->mmy));
524         wd->ratio = sqrt((wd->mx - wd->mmx)*(wd->mx - wd->mmx)+ (wd->my - wd->mmy)*(wd->my - wd->mmy));
525
526         if (wd->on_zoom){
527                 wd->on_zoom = EINA_FALSE;
528                 edje_object_signal_emit(elm_layout_edje_get(obj), "block.on", "block");
529 //              edje_freeze();
530         }
531 }
532
533 static void ev_imageslider_multi_up_cb(void * data, Evas * e, Evas_Object * obj, void * event_info)
534 {
535         Evas_Event_Multi_Up *ev = event_info;
536         Widget_Data *wd = data;
537         Elm_Imageslider_Item *it;
538
539         if (ev->device == MULTITOUCHDEVICE) return;
540
541         it = eina_list_data_get(wd->cur);
542         it->w = (int)it->w * wd->ratio/wd->dratio;
543         it->h = (int)it->h * wd->ratio/wd->dratio;
544
545         if (it->w != it->ow) {
546                 wd->on_zoom = EINA_TRUE;
547                 edje_object_signal_emit(elm_layout_edje_get(obj), "block.off", "block");
548 //              edje_thaw();
549         } else {
550                 wd->on_zoom = EINA_FALSE;
551         }
552
553         wd->on_hold = EINA_FALSE;
554         wd->mdx = 0;
555         wd->mdy = 0;
556         wd->mmx = 0;
557         wd->mmy = 0;
558         wd->ratio = 0;
559         wd->dratio = 0;
560         
561 }
562
563 static void ev_imageslider_multi_move_cb(void * data, Evas * e, Evas_Object * obj, void * event_info)
564 {
565         Evas_Event_Multi_Move *ev = event_info;
566         Widget_Data *wd = data;
567         Evas_Object *eo = NULL;
568         Elm_Imageslider_Item *it;
569
570         if (ev->device == MULTITOUCHDEVICE) return;
571
572         if ((wd->mdx == 0) && (wd->mdy == 0) && (wd->mmx == 0) && (wd->mmy == 0)) {
573                 wd->mdx = ev->cur.canvas.x;
574                 wd->mdy = ev->cur.canvas.y;
575                 wd->mmx = ev->cur.canvas.x;
576                 wd->mmy = ev->cur.canvas.y;
577
578                 wd->dratio = sqrt((wd->dx - wd->mdx)*(wd->dx - wd->mdx) + (wd->dy - wd->mdy)*(wd->dy - wd->mdy));
579         }
580
581         wd->mmx = ev->cur.canvas.x;
582         wd->mmy = ev->cur.canvas.y;
583         wd->ratio = sqrt((wd->mx - wd->mmx)*(wd->mx - wd->mmx) + (wd->my - wd->mmy)*(wd->my - wd->mmy));
584
585         eo = edje_object_part_swallow_get(elm_layout_edje_get(obj), "swl.photo");
586
587         if (eo) {
588                 it = eina_list_data_get(wd->cur);
589                 if (((it->w * wd->ratio/wd->dratio)/it->ow) < MAX_ZOOM_SIZE) {
590                         edje_object_part_unswallow(elm_layout_edje_get(obj), eo);
591                         evas_object_resize(eo, it->w * wd->ratio/wd->dratio, it->h * wd->ratio/wd->dratio);
592                         evas_object_size_hint_min_set(eo, it->w * wd->ratio/wd->dratio, it->h * wd->ratio/wd->dratio);
593                         edje_object_part_swallow(elm_layout_edje_get(obj), "swl.photo", eo);
594                 }
595         }       
596 }
597
598 #endif // about Multi-touch.
599
600 static inline double time_get(Evas_Coord x, Evas_Coord w)
601 {
602         double time;
603         time = (-sin(x / w) + 1) / 500;
604
605         if (time == 0) time = ANI_TIME;
606         
607         return time;
608 }
609
610 static Eina_Bool _icon_to_image(void *data)
611 {
612         Widget_Data *wd = data;
613         wd->moving = 0;
614         _imageslider_update(wd);
615
616         if (wd->queue_idler) {
617                 ecore_idler_del(wd->queue_idler);
618                 wd->queue_idler = NULL;
619         }
620         return ECORE_CALLBACK_CANCEL;
621 }
622
623 static int _check_drag(int state, void *data)
624 {
625         Widget_Data *wd = data;
626         Elm_Imageslider_Item *it;
627         Evas_Coord ix, iy, iw, ih;
628         double dx, dy = 0;
629         Eina_List *l[BLOCK_MAX];
630         Evas_Object *eo = NULL;
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 = edje_object_part_swallow_get(elm_layout_edje_get(wd->ly[state]), "swl.photo");
638         if (eo) evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
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                 if (wd->ly[state]) {
644                         evas_object_del(wd->ly[state]);
645                         wd->ly[state] = NULL;
646                 }
647                 wd->ly[state] = _imageslider_add_obj(wd);
648         } else {
649                 return 1;
650         }
651
652         return 0;
653 }
654
655
656 static void _check_zoom(void *data)
657 {
658         Widget_Data *wd = data;
659         Elm_Imageslider_Item *it;
660         Evas_Coord ix, iy, iw, ih;
661         double dx, dy = 0;
662         Evas_Object *eo = NULL;
663
664         it = eina_list_data_get(wd->cur);
665
666         eo = edje_object_part_swallow_get(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "swl.photo");
667         if (eo) evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
668         evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
669         edje_object_part_drag_value_get(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "swl.photo", &dx, &dy);
670
671         if ((iw != wd->w) || ((dx != 0) || (dy != 0))) {
672                 wd->on_zoom = EINA_TRUE;
673                 edje_object_signal_emit(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "block.off", "block");
674 //              edje_thaw();
675         } else {
676                 wd->on_zoom = EINA_FALSE;
677                 edje_object_signal_emit(elm_layout_edje_get(wd->ly[BLOCK_CENTER]), "block.on", "block");
678 //              edje_freeze();
679         }
680 }
681
682
683 static Eina_Bool _timer_cb(void *data)
684 {
685         Widget_Data *wd;
686         Elm_Imageslider_Item *it;
687         struct timeval tv;
688         int t;
689         int ret;
690         wd = data;
691         if (wd->ani_lock == 0 ) return 0;
692
693         gettimeofday(&tv, NULL);
694
695         t = (tv.tv_sec - wd->tv.tv_sec) * 1000 + (tv.tv_usec - wd->tv.tv_usec) / 1000;
696         gettimeofday(&wd->tv, NULL);
697
698         t = t / ANI_TIME_MSEC;
699         if (t <= STEP_WEIGHT_MIN) t = STEP_WEIGHT_DEF;
700         else if (t >  STEP_WEIGHT_MAX) t = STEP_WEIGHT_MAX;
701
702         wd->move_x += (wd->step) * t;
703
704         if (wd->step < 0 && wd->move_x < wd->x) wd->move_x = wd->x;
705         else if (wd->step > 0 && wd->move_x > wd->x) wd->move_x = wd->x;
706
707         _imageslider_update_pos(wd, wd->move_x, wd->y, wd->w);
708
709         if (wd->move_x == wd->x) {
710                 wd->ani_lock = 0;
711                 if (wd->cur) {
712                         it = eina_list_data_get(wd->cur);
713                         if (it->func) it->func(it->data, wd->obj, it);
714                 }
715                 if (wd->cur) {
716                         it = eina_list_data_get(wd->cur);
717                         evas_object_smart_callback_call(wd->obj, "changed", it);
718                 }
719
720                 ret = _check_drag(BLOCK_LEFT, wd);
721                 ret = _check_drag(BLOCK_RIGHT, wd);
722                 _check_zoom(wd);
723
724                 if (!wd->queue_idler) wd->queue_idler = ecore_idler_add(_icon_to_image, wd);
725
726                 if(wd->anim_timer) {
727                         ecore_timer_del(wd->anim_timer);
728                         wd->anim_timer = NULL;
729                 }
730
731                 return ECORE_CALLBACK_CANCEL;
732         }
733
734         return ECORE_CALLBACK_RENEW;    
735 }
736
737         
738 static void _anim(Widget_Data *wd)
739 {
740         Evas_Coord w;
741
742         if (wd->x == wd->move_x) {
743                 _imageslider_update_pos(wd, wd->move_x, wd->y, wd->w);
744                 return;
745         }
746
747         wd->ani_lock = 1;
748
749         w = wd->move_x;
750         gettimeofday(&wd->tv, NULL);
751
752         if (!wd->anim_timer) {
753                 wd->anim_timer = ecore_timer_add(ANI_TIME, _timer_cb, wd); 
754         }       
755 }
756
757 static void _imageslider_update(Widget_Data *wd)
758 {
759         int i;
760         Eina_List *l[BLOCK_MAX];
761         Elm_Imageslider_Item *it;
762         Evas_Object *eo;
763
764         if (!wd) {
765                 return;
766         }
767
768         if (!wd->cur) {
769                 _imageslider_del_all(wd);
770                 return;
771         }
772
773         l[BLOCK_LEFT] = eina_list_prev(wd->cur);
774         l[BLOCK_CENTER] = wd->cur;
775         l[BLOCK_RIGHT] = eina_list_next(wd->cur);
776
777         for (i = 0; i < BLOCK_MAX; i++) {
778                 eo = edje_object_part_swallow_get(elm_layout_edje_get(wd->ly[i]), "swl.photo");
779                 if (!l[i]) {
780                         elm_layout_content_set(wd->ly[i], "swl.photo", NULL);
781                         evas_object_del(eo);
782                 } else {
783                         it = eina_list_data_get(l[i]);
784                         if (!it) return;
785
786                         if (!eo) {
787                                 eo = elm_image_add(wd->obj);
788                                 elm_layout_content_set(wd->ly[i], "swl.photo", eo);
789                                 elm_image_prescale_set(eo, wd->w);
790                                 elm_image_file_set(eo, it->photo_file, NULL);
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
797                         if (wd->moving != it->moving) {
798                                 it->moving = wd->moving;
799                                 if (wd->moving) {
800                                         elm_image_prescale_set(eo, MOVING_IMAGE_SIZE);
801                                 } else {
802                                         elm_image_prescale_set(eo, it->w > it->h ? it->w : it->h);
803                                 }
804                         }
805                 }
806         }
807
808         _anim(wd);
809
810 }
811
812
813 /** 
814 * Add an Image Slider widget 
815
816 * @param        parent  The parent object 
817 * @return       The new Image slider object or NULL if it cannot be created 
818
819 * @ingroup Imageslider 
820 */
821 EAPI Evas_Object *
822 elm_imageslider_add(Evas_Object * parent)
823 {
824         int i;
825         Evas_Object *obj = NULL;
826         Widget_Data *wd = NULL;
827         Evas *e;
828
829         if (!parent) {
830                 return NULL;
831         }
832
833         wd = ELM_NEW(Widget_Data);
834         e = evas_object_evas_get(parent);
835         if (e == NULL ) {
836                 return NULL;
837         }
838         
839         obj = elm_widget_add(e);
840         ELM_SET_WIDTYPE(widtype, "imageslider");
841         elm_widget_type_set(obj, "imageslider");
842         elm_widget_sub_object_add(parent, obj);
843         elm_widget_data_set(obj, wd);
844         //wd->parent = parent;
845         elm_widget_del_hook_set(obj, _del_hook);
846         //elm_widget_theme_hook_set(obj, _theme_hook);
847
848         wd->clip = evas_object_rectangle_add(e);
849         
850         for (i=0; i < BLOCK_MAX; i++) {
851                 wd->ly[i] = elm_layout_add(obj);
852                 elm_layout_theme_set(wd->ly[i], "imageslider", "base", "default");
853                 elm_widget_resize_object_set(obj, wd->ly[i]);
854                 evas_object_smart_member_add(wd->ly[i], obj);
855                 
856                 edje_object_signal_callback_add(elm_layout_edje_get(wd->ly[i]), "elm,photo,clicked", "", _signal_clicked, obj);
857                 
858                 evas_object_event_callback_add(wd->ly[i], EVAS_CALLBACK_MOUSE_DOWN, ev_imageslider_down_cb, wd);
859                 evas_object_event_callback_add(wd->ly[i], EVAS_CALLBACK_MOUSE_UP, ev_imageslider_up_cb, wd);
860                 evas_object_event_callback_add(wd->ly[i], EVAS_CALLBACK_MOUSE_MOVE, ev_imageslider_move_cb, wd);
861                 evas_object_clip_set(wd->ly[i], wd->clip);
862                 evas_object_show(wd->ly[i]);                    
863         }
864
865         wd->obj = obj;
866
867         evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _imageslider_resize, obj);
868         evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _imageslider_move, obj);
869         evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _imageslider_show, obj);
870         evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _imageslider_hide, obj);
871         
872         _sizing_eval(obj);
873
874    return obj;  
875 }
876
877
878 /** 
879 * Append an Image Slider item 
880
881 * @param        obj          The Image Slider object 
882 * @param        photo_file   photo file path 
883 * @param        func         callback function 
884 * @param        data         callback data 
885 * @return       The Image Slider item handle or NULL 
886
887 * @ingroup Imageslider 
888 */
889 EAPI Elm_Imageslider_Item *
890 elm_imageslider_item_append(Evas_Object * obj, const char * photo_file, Elm_Imageslider_Cb func, void * data)
891 {
892         ELM_CHECK_WIDTYPE(obj, widtype) NULL;
893         Widget_Data *wd;
894         Elm_Imageslider_Item *it;
895
896         if (!obj || !(wd = elm_widget_data_get(obj))) {
897                 return NULL;
898         }
899
900         it = (Elm_Imageslider_Item *)calloc(1, sizeof(Elm_Imageslider_Item));
901         if (!it) return NULL;
902         it->photo_file = eina_stringshare_add(photo_file);
903         it->func = func;
904         it->data = data;
905         it->obj = obj;
906         wd->its = eina_list_append(wd->its, it);
907
908         if (!wd->cur) wd->cur = wd->its;
909
910         _imageslider_update(wd);
911
912         return it; 
913 }
914
915
916 /** 
917 * Prepend Image Slider item 
918
919 * @param        obj          The Image Slider object 
920 * @param        photo_file   photo file path 
921 * @param        func         callback function 
922 * @param        data         callback data 
923 * @return       The imageslider item handle or NULL 
924
925 * @ingroup Imageslider 
926 */
927 EAPI Elm_Imageslider_Item *
928 elm_imageslider_item_prepend(Evas_Object * obj, const char * photo_file, Elm_Imageslider_Cb func, void * data)
929 {
930         ELM_CHECK_WIDTYPE(obj, widtype) NULL;
931         Widget_Data *wd;
932         Elm_Imageslider_Item *it;
933
934         if (!obj || !(wd = elm_widget_data_get(obj))) {
935                 return NULL;
936         }
937
938         it = (Elm_Imageslider_Item *)calloc(1, sizeof(Elm_Imageslider_Item));
939         it->photo_file = eina_stringshare_add(photo_file);
940         it->func = func;
941         it->data = data;
942         it->obj = obj;
943         wd->its = eina_list_prepend(wd->its, it );
944
945         if (!wd->cur) wd->cur = wd->its;
946
947         _imageslider_update(wd);
948
949         return it;
950 }
951
952
953
954 /**
955 * Delete the selected Image Slider item
956 *
957 * @param it             The selected Image Slider item handle
958 *
959 * @ingroup Imageslider
960 */
961 EAPI void
962 elm_imageslider_item_del(Elm_Imageslider_Item * it)
963 {
964         Widget_Data *wd;
965         Elm_Imageslider_Item *_it;
966         Eina_List *l;
967
968         if (!it || !(wd = elm_widget_data_get(it->obj))) {
969                 return ;
970         }
971
972         EINA_LIST_FOREACH(wd->its, l, _it) {
973                 if (_it == it ) {
974                         if (l == wd->cur) wd->cur = eina_list_prev(wd->cur);
975                         wd->its = eina_list_remove(wd->its, it);
976                         if (!wd->cur) wd->cur = wd->its;
977                         break;
978                 }
979         }
980
981         _imageslider_update(wd);
982         
983 }
984
985
986 /**
987 * Get the selected Image Slider item
988 *
989 * @param obj            The Image Slider object
990 * @return The selected Image Slider item or NULL
991 *
992 * @ingroup Imageslider
993 */
994 EAPI Elm_Imageslider_Item *
995 elm_imageslider_selected_item_get(Evas_Object * obj)
996 {
997         ELM_CHECK_WIDTYPE(obj, widtype) NULL;
998         Widget_Data *wd;
999
1000         if (!obj || (!(wd = elm_widget_data_get(obj)))) {
1001                 return NULL;
1002         }
1003
1004         if (!wd->cur) return NULL;
1005
1006         return eina_list_data_get(wd->cur);
1007 }
1008
1009 /**
1010 * Get whether an Image Slider item is selected or not
1011 *
1012 * @param it              the selected Image Slider item
1013 * @return EINA_TRUE or EINA_FALSE
1014 *
1015 * @ingroup Imageslider
1016 */
1017 EAPI Eina_Bool
1018 elm_imageslider_item_selected_get(Elm_Imageslider_Item * it)
1019 {
1020         Widget_Data *wd;
1021         
1022         if (!it || !it->obj || (!(wd = elm_widget_data_get(it->obj)))) {
1023                 return EINA_FALSE;
1024         }
1025
1026         if (!wd->cur) return EINA_FALSE;
1027
1028         if (eina_list_data_get(wd->cur) == it ) return EINA_TRUE;
1029         else return EINA_FALSE;
1030         
1031 }
1032
1033 /**
1034 * Set the selected Image Slider item
1035 *
1036 * @param it             The Imaga Slider item
1037 *
1038 * @ingroup Imageslider
1039 */
1040 EAPI void
1041 elm_imageslider_item_selected_set(Elm_Imageslider_Item * it)
1042 {
1043         int i;
1044         Widget_Data *wd;
1045         Elm_Imageslider_Item *_it;
1046         Eina_List *l;
1047         Evas_Object *eo;
1048
1049         if (!it || !it->obj || (!(wd = elm_widget_data_get(it->obj)))) {
1050                 return ;
1051         }
1052
1053         EINA_LIST_FOREACH(wd->its, l, _it) {
1054                 if (_it == it ) {
1055                         wd->cur = l;
1056                 }
1057         }
1058
1059         for (i = 0; i < BLOCK_MAX; i++) {
1060                 eo = edje_object_part_swallow_get(elm_layout_edje_get(wd->ly[i]), "swl.photo");
1061                 if (eo) {
1062                         elm_layout_content_set(wd->ly[i], "swl.photo", NULL);
1063                         evas_object_del(eo);
1064                 }
1065         }
1066
1067         _imageslider_update(wd);
1068         
1069 }
1070
1071
1072 /**
1073 * Get the photo file path of given Image Slider item
1074 *
1075 * @param it             The Image Slider item
1076 * @return The photo file path or NULL;
1077 *
1078 * @ingroup Imageslider
1079 */
1080 EAPI const char *
1081 elm_imageslider_item_photo_file_get(Elm_Imageslider_Item * it)
1082 {
1083         if (!it) {
1084                 return NULL;
1085         }
1086
1087         return it->photo_file;
1088 }
1089
1090
1091 /**
1092 * Get the previous Image Slider item
1093 *
1094 * @param it             The Image Slider item
1095 * @return The previous Image Slider item or NULL
1096 *
1097 * @ingroup Imageslider
1098 */
1099 EAPI Elm_Imageslider_Item *
1100 elm_imageslider_item_prev(Elm_Imageslider_Item * it)
1101 {
1102         Widget_Data *wd;
1103         Elm_Imageslider_Item *_it;
1104         Eina_List *l;
1105
1106         if (!it || (!(wd = elm_widget_data_get(it->obj)))) {
1107                 return NULL;
1108         }
1109
1110         EINA_LIST_FOREACH(wd->its, l, _it) {
1111                 if (_it == it) {
1112                         l = eina_list_prev(l);
1113                         if (!l) break;
1114                         return eina_list_data_get(l);
1115                 }
1116         }
1117
1118         return NULL;    
1119 }
1120
1121
1122 /**
1123 * Get the next Image Slider item
1124 *
1125 * @param it             The Image Slider item
1126 * @return The next Image Slider item or NULL
1127 *
1128 * @ingroup Imageslider
1129 */
1130 EAPI Elm_Imageslider_Item *
1131 elm_imageslider_item_next(Elm_Imageslider_Item * it)
1132 {
1133         Widget_Data *wd;
1134         Elm_Imageslider_Item *_it;
1135         Eina_List *l;
1136
1137         if (!it || (!(wd = elm_widget_data_get(it->obj)))) {
1138                 return NULL;
1139         }
1140
1141         EINA_LIST_FOREACH(wd->its, l, _it) {
1142                 if (_it == it) {
1143                         l = eina_list_next(l);
1144                         if (!l) break;
1145                         return eina_list_data_get(l);
1146                 }
1147         }
1148
1149         return NULL;
1150 }
1151
1152
1153 /**
1154 * Move to the previous Image Slider item
1155 *
1156 * @param obj    The Image Slider object
1157 *
1158 * @ingroup Imageslider
1159 */
1160 EAPI void 
1161 elm_imageslider_prev(Evas_Object * obj)
1162 {
1163         ELM_CHECK_WIDTYPE(obj, widtype);
1164         Widget_Data *wd;
1165         
1166         if (!obj || (!(wd = elm_widget_data_get(obj)))) {
1167                 return;
1168         }
1169
1170         if (wd->ani_lock) return;
1171
1172         _imageslider_obj_move(wd, -1);
1173 }
1174
1175
1176 /**
1177 * Move to the next Image Slider item
1178 *
1179 * @param obj The Image Slider object
1180 *
1181 * @ingroup Imageslider
1182 */
1183 EAPI void
1184 elm_imageslider_next(Evas_Object * obj)
1185 {
1186         ELM_CHECK_WIDTYPE(obj, widtype);
1187         Widget_Data *wd;
1188         
1189         if (!obj || (!(wd = elm_widget_data_get(obj)))) {
1190                 return;
1191         }
1192
1193         if (wd->ani_lock) return;
1194
1195         _imageslider_obj_move(wd, 1);
1196         
1197 }
1198
1199
1200
1201
1202