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