3 #include <Elementary.h>
6 typedef struct _Widget_Data Widget_Data;
8 #define ANI_STEP (14 * elm_scale_get())
9 #define ANI_TIME (0.005)
10 #define ANI_TIME_MSEC (12)
11 #define CLICK_TIME_MAX (180)
12 #define CLICK_WIDTH_MIN (elm_finger_size_get() >> 1)
13 #define FLICK_TIME_MAX (200)
14 #define FLICK_WIDTH_MIN (elm_finger_size_get() >> 2)
16 #define STEP_WEIGHT_DEF (1)
17 #define STEP_WEIGHT_MAX (2)
18 #define STEP_WEIGHT_MIN (0)
19 #define MOVING_IMAGE_SIZE (128)
20 #define MAX_ZOOM_SIZE (6)
21 #define INTERVAL_WIDTH (15)
22 #define MULTITOUCHDEVICE (11)
24 // Enumeration for layout.
34 struct _Imageslider_Item
37 const char *photo_file;
38 void (*func) (void *data, Evas_Object *obj, void *event_info);
42 // Image Slider Widget Data.
45 Evas_Object *ly[BLOCK_MAX];
49 Evas_Coord x, y, w, h;
51 Ecore_Idler *queue_idler;
52 Ecore_Timer *anim_timer;
54 Evas_Coord_Point down_pos;
59 unsigned int timestamp;
66 // Global value declaration.
67 static const char *widtype = NULL;
69 static const char SIG_CLICKED[] = "clicked";
71 // Internal function declaration.
72 static void _del_hook(Evas_Object *obj);
74 static void _theme_hook(Evas_Object *obj);
76 static void _sizing_eval(Evas_Object *obj);
78 static void _imageslider_move(void *data, Evas * e, Evas_Object *obj, void *event_info);
79 static void _imageslider_resize(void *data, Evas * e, Evas_Object *obj, void *event_info);
80 static void _imageslider_show(void *data, Evas * e, Evas_Object *obj, void *event_info);
81 static void _imageslider_hide(void *data, Evas * e, Evas_Object *obj, void *event_info);
82 static void _imageslider_update(Widget_Data * wd);
84 static void _imageslider_update_pos(Widget_Data * wd, Evas_Coord x, Evas_Coord y, Evas_Coord w);
86 static void _imageslider_obj_shift(Widget_Data * wd, Eina_Bool left);
88 static void _imageslider_obj_move(Widget_Data * wd, Evas_Coord step);
90 static Eina_Bool _icon_to_image(void *data);
92 static int _check_drag(int state, void *data);
94 static void _anim(Widget_Data * wd);
96 static Eina_Bool _timer_cb(void *data);
98 static void _ev_imageslider_down_cb(void *data, Evas * e, Evas_Object *obj, void *event_info);
99 static void _ev_imageslider_up_cb(void *data, Evas * e, Evas_Object *obj, void *event_info);
100 static void _ev_imageslider_move_cb(void *data, Evas * e, Evas_Object *obj, void *event_info);
102 // Whenever the Image Slider item is deleted, Call this funtion.
104 _del_hook(Evas_Object *obj)
108 wd = elm_widget_data_get(obj);
114 eina_list_free(wd->its);
120 ecore_idler_del(wd->queue_idler);
121 wd->queue_idler = NULL;
126 ecore_timer_del(wd->anim_timer);
127 wd->anim_timer = NULL;
133 // Whenever require processing theme, Call this function
135 _theme_hook(Evas_Object *obj)
138 Widget_Data *wd = elm_widget_data_get(obj);
142 for (i = 0; i < BLOCK_MAX; i++)
145 elm_layout_theme_set(wd->ly[i], "imageslider", "base",
146 elm_object_style_get(obj));
147 evas_object_show(wd->ly[i]);
149 _imageslider_update(wd);
153 // Resize Image Slider item.
155 _sizing_eval(Evas_Object *obj)
159 Widget_Data *wd = elm_widget_data_get(obj);
164 e = evas_object_evas_get(wd->obj);
166 _imageslider_move(obj, e, obj, NULL);
167 _imageslider_resize(obj, e, obj, NULL);
170 // Whenever MOVE event occurs, Call this function.
172 _imageslider_move(void *data, Evas * e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
181 wd = elm_widget_data_get((Evas_Object *) data);
185 evas_object_geometry_get(obj, &x, &y, NULL, NULL);
189 _imageslider_update_pos(wd, wd->x, wd->y, wd->w);
192 // Whenever RESIZE event occurs, Call this fucntion.
194 _imageslider_resize(void *data, Evas * e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
205 wd = elm_widget_data_get((Evas_Object *) data);
209 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
210 DBG("%d %d -resize\n", w, h);
214 for (i = 0; i < BLOCK_MAX; i++)
216 evas_object_resize(wd->ly[i], w, h);
219 _imageslider_update_pos(wd, wd->x, wd->y, wd->w);
223 // Whenever SHOW event occurs, Call this function.
225 _imageslider_show(void *data, Evas * e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
234 wd = elm_widget_data_get((Evas_Object *) data);
237 evas_object_show(wd->clip);
240 // Whenever HIDE event occurs, Call this function.
242 _imageslider_hide(void *data, Evas * e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
248 wd = elm_widget_data_get((Evas_Object *) data);
250 evas_object_hide(wd->clip);
253 // Update Image Slider item position.
255 _imageslider_update_pos(Widget_Data * wd, Evas_Coord x, Evas_Coord y, Evas_Coord w)
257 evas_object_move(wd->ly[BLOCK_LEFT], x - (w + INTERVAL_WIDTH), y);
258 evas_object_move(wd->ly[BLOCK_CENTER], x, y);
259 evas_object_move(wd->ly[BLOCK_RIGHT], x + (w + INTERVAL_WIDTH), y);
262 // Shift next/previous Image Slider item in layouts.
264 _imageslider_obj_shift(Widget_Data * wd, Eina_Bool left)
268 Evas_Object *ly_temp;
269 ly_temp = wd->ly[BLOCK_LEFT];
270 wd->ly[BLOCK_LEFT] = wd->ly[BLOCK_CENTER];
271 wd->ly[BLOCK_CENTER] = wd->ly[BLOCK_RIGHT];
272 wd->ly[BLOCK_RIGHT] = ly_temp;
273 elm_object_part_content_set(wd->ly[BLOCK_RIGHT], "swl.photo", NULL);
277 Evas_Object *ly_temp;
278 ly_temp = wd->ly[BLOCK_RIGHT];
279 wd->ly[BLOCK_RIGHT] = wd->ly[BLOCK_CENTER];
280 wd->ly[BLOCK_CENTER] = wd->ly[BLOCK_LEFT];
281 wd->ly[BLOCK_LEFT] = ly_temp;
282 elm_object_part_content_set(wd->ly[BLOCK_LEFT], "swl.photo", NULL);
286 // Move the current Image Slider item and update.
288 _imageslider_obj_move(Widget_Data * wd, Evas_Coord step)
292 wd->cur = eina_list_next(wd->cur);
295 wd->cur = eina_list_last(wd->its);
300 wd->step = -ANI_STEP;
302 _imageslider_obj_shift(wd, EINA_FALSE);
304 wd->moving = EINA_TRUE;
308 wd->cur = eina_list_prev(wd->cur);
312 wd->step = -ANI_STEP;
318 _imageslider_obj_shift(wd, EINA_TRUE);
320 wd->moving = EINA_TRUE;
327 wd->step = -ANI_STEP;
328 wd->moving = EINA_FALSE;
331 _imageslider_update(wd);
334 // Whenever MOUSE DOWN event occurs, Call this function.
336 _ev_imageslider_down_cb(void *data, Evas * e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
338 Widget_Data *wd = data;
339 Evas_Event_Mouse_Down *ev = event_info;
344 wd->down_pos = ev->canvas;
345 wd->timestamp = ev->timestamp;
346 wd->move_cnt = MOVE_STEP;
349 // Whenever MOUSE UP event occurs, Call this function.
350 // And make Click Event also.
352 _ev_imageslider_up_cb(void *data, Evas * e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
354 Widget_Data *wd = data;
356 Evas_Event_Mouse_Up *ev = event_info;
362 if (wd->ani_lock) return;
364 step = wd->down_pos.x - ev->canvas.x;
365 interval = ev->timestamp - wd->timestamp;
366 if (step == 0 || interval == 0)
368 DBG("case1: emit CLICK event\n");
369 evas_object_smart_callback_call(wd->obj, SIG_CLICKED, NULL);
372 if (interval < CLICK_TIME_MAX)
374 if (step < CLICK_WIDTH_MIN && step > CLICK_WIDTH_MIN)
376 DBG("case2: emit CLICK event\n");
377 evas_object_smart_callback_call(wd->obj, SIG_CLICKED, NULL);
382 if (interval < FLICK_TIME_MAX)
384 if (step < FLICK_WIDTH_MIN && step > FLICK_WIDTH_MIN)
386 DBG("ev_imageslider_up_cb-black zone (1)\n");
388 _imageslider_obj_move(wd, 0);
392 DBG("ev_imageslider_up_cb-black zone (2)\n");
394 _imageslider_obj_move(wd, step);
400 step = (wd->x - wd->move_x) << 1;
401 if (step <= wd->w && step >= -(wd->w))
403 DBG("ev_imageslider_up_cb-white zone (1)\n");
405 _imageslider_obj_move(wd, 0);
409 DBG("ev_imageslider_up_cb-white zone (2)\n");
411 _imageslider_obj_move(wd, step);
416 // Whenever MOUSE MOVE event occurs, Call this
418 _ev_imageslider_move_cb(void *data, Evas * e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
422 Widget_Data *wd = data;
423 Evas_Event_Mouse_Move *ev = event_info;
425 if (wd->ani_lock) return;
426 if (wd->move_cnt == MOVE_STEP)
432 step = ev->cur.canvas.x - wd->down_pos.x;
437 wd->move_x = wd->x + ((ev->cur.canvas.x - wd->down_pos.x));
438 wd->move_y = wd->y + ((ev->cur.canvas.y - wd->down_pos.y));
439 _imageslider_update_pos(wd, wd->move_x, wd->y, wd->w);
446 time_get(Evas_Coord x, Evas_Coord w)
450 time = (-sin(x / w) + 1) / 500;
459 _icon_to_image(void *data)
461 Widget_Data *wd = data;
464 _imageslider_update(wd);
467 wd->queue_idler = NULL;
468 return ECORE_CALLBACK_CANCEL;
472 _check_drag(int state, void *data)
474 Widget_Data *wd = data;
476 Elm_Imageslider_Item *it;
478 Evas_Coord ix = 0, iy = 0, iw = 0, ih = 0;
480 double dx = 0, dy = 0;
482 Eina_List *l[BLOCK_MAX];
484 Evas_Object *eo = NULL;
486 l[BLOCK_LEFT] = eina_list_prev(wd->cur);
487 l[BLOCK_CENTER] = wd->cur;
488 l[BLOCK_RIGHT] = eina_list_next(wd->cur);
490 it = eina_list_data_get(l[state]);
492 eo = elm_object_part_content_get(wd->ly[state], "swl.photo");
494 evas_object_geometry_get(eo, &ix, &iy, &iw, &ih);
495 edje_object_part_drag_value_get(elm_layout_edje_get(wd->ly[state]), "swl.photo", &dx, &dy);
497 if ((iw != wd->w) || ((dx != 0) || (dy != 0)))
499 elm_object_part_content_set(wd->ly[state], "swl.photo", NULL);
508 _timer_cb(void *data)
512 Elm_Imageslider_Item *it;
523 wd->anim_timer = NULL;
524 return ECORE_CALLBACK_CANCEL;
526 gettimeofday(&tv, NULL);
528 t = (tv.tv_sec - wd->tv.tv_sec) * 1000 + (tv.tv_usec - wd->tv.tv_usec) / 1000;
529 gettimeofday(&wd->tv, NULL);
531 t = t / ANI_TIME_MSEC;
532 if (t <= STEP_WEIGHT_MIN)
534 else if (t > STEP_WEIGHT_MAX)
537 wd->move_x += (wd->step) * t;
539 if (wd->step < 0 && wd->move_x < wd->x)
541 else if (wd->step > 0 && wd->move_x > wd->x)
544 _imageslider_update_pos(wd, wd->move_x, wd->y, wd->w);
546 if (wd->move_x == wd->x)
548 wd->ani_lock = EINA_FALSE;
551 it = eina_list_data_get(wd->cur);
553 it->func(it->data, wd->obj, it);
557 it = eina_list_data_get(wd->cur);
558 evas_object_smart_callback_call(wd->obj, "changed", it);
561 ret = _check_drag(BLOCK_LEFT, wd);
562 ret = _check_drag(BLOCK_RIGHT, wd);
564 if (!wd->queue_idler)
565 wd->queue_idler = ecore_idler_add(_icon_to_image, wd);
568 wd->anim_timer = NULL;
570 return ECORE_CALLBACK_CANCEL;
573 return ECORE_CALLBACK_RENEW;
577 _anim(Widget_Data * wd)
581 if (wd->x == wd->move_x)
583 _imageslider_update_pos(wd, wd->move_x, wd->y, wd->w);
587 wd->ani_lock = EINA_TRUE;
590 gettimeofday(&wd->tv, NULL);
593 wd->anim_timer = ecore_timer_add(ANI_TIME, _timer_cb, wd);
596 // Update Image Slider Items.
598 _imageslider_update(Widget_Data * wd)
602 Eina_List *l[BLOCK_MAX];
604 Elm_Imageslider_Item *it;
610 if (!wd->cur) return;
612 l[BLOCK_LEFT] = eina_list_prev(wd->cur);
613 l[BLOCK_CENTER] = wd->cur;
614 l[BLOCK_RIGHT] = eina_list_next(wd->cur);
616 for (i = 0; i < BLOCK_MAX; i++)
618 eo = elm_object_part_content_get((const Evas_Object*)wd->ly[i], "swl.photo");
621 elm_object_part_content_set(wd->ly[i], "swl.photo", NULL);
625 it = eina_list_data_get(l[i]);
631 eo = elm_image_add(wd->obj);
632 //elm_image_prescale_set(eo, wd->w);
633 elm_image_file_set(eo, it->photo_file, NULL);
634 elm_object_part_content_set(wd->ly[i], "swl.photo", eo);
642 elm_imageslider_add(Evas_Object *parent)
650 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
652 ELM_SET_WIDTYPE(widtype, "imageslider");
653 elm_widget_type_set(obj, "imageslider");
654 elm_widget_sub_object_add(parent, obj);
655 elm_widget_data_set(obj, wd);
656 elm_widget_del_hook_set(obj, _del_hook);
657 elm_widget_theme_hook_set(obj, _theme_hook);
659 wd->clip = evas_object_rectangle_add(e);
660 elm_widget_sub_object_add(obj, wd->clip);
661 elm_widget_resize_object_set(obj, wd->clip);
663 for (i = 0; i < BLOCK_MAX; i++)
665 wd->ly[i] = elm_layout_add(obj);
666 elm_layout_theme_set(wd->ly[i], "imageslider", "base", "default");
667 elm_widget_sub_object_add(obj, wd->ly[i]);
668 evas_object_smart_member_add(wd->ly[i], obj);
670 evas_object_event_callback_add(wd->ly[i], EVAS_CALLBACK_MOUSE_DOWN, _ev_imageslider_down_cb, wd);
671 evas_object_event_callback_add(wd->ly[i], EVAS_CALLBACK_MOUSE_UP, _ev_imageslider_up_cb, wd);
672 evas_object_event_callback_add(wd->ly[i], EVAS_CALLBACK_MOUSE_MOVE, _ev_imageslider_move_cb, wd);
673 evas_object_clip_set(wd->ly[i], wd->clip);
674 evas_object_show(wd->ly[i]);
678 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _imageslider_resize, obj);
679 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _imageslider_move, obj);
680 evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _imageslider_show, obj);
681 evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _imageslider_hide, obj);
687 EAPI Elm_Imageslider_Item *
688 elm_imageslider_item_append(Evas_Object *obj, const char *photo_file, Elm_Imageslider_Cb func, void *data)
690 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
693 Elm_Imageslider_Item *it;
695 if (!obj || !(wd = elm_widget_data_get(obj)))
698 it = (Elm_Imageslider_Item *) calloc(1, sizeof(Elm_Imageslider_Item));
701 it->photo_file = eina_stringshare_add(photo_file);
705 wd->its = eina_list_append(wd->its, it);
709 _imageslider_update(wd);
713 EAPI Elm_Imageslider_Item *
714 elm_imageslider_item_append_relative(Evas_Object *obj, const char *photo_file, Elm_Imageslider_Cb func, unsigned int index, void *data)
716 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
719 Elm_Imageslider_Item *it;
721 DBG("New elm_imageslider_item_append_relative()\n");
723 if (!obj || !(wd = elm_widget_data_get(obj)))
726 it = (Elm_Imageslider_Item *) calloc(1, sizeof(Elm_Imageslider_Item));
731 it->photo_file = eina_stringshare_add(photo_file);
735 wd->its = eina_list_append_relative(wd->its, it, eina_list_nth(wd->its,
740 _imageslider_update(wd);
744 EAPI Elm_Imageslider_Item *
745 elm_imageslider_item_prepend(Evas_Object *obj, const char *photo_file, Elm_Imageslider_Cb func, void *data)
747 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
750 Elm_Imageslider_Item *it;
752 if (!obj || !(wd = elm_widget_data_get(obj)))
755 it = (Elm_Imageslider_Item *) calloc(1, sizeof(Elm_Imageslider_Item));
756 it->photo_file = eina_stringshare_add(photo_file);
760 wd->its = eina_list_prepend(wd->its, it);
763 _imageslider_update(wd);
768 elm_imageslider_item_del(Elm_Imageslider_Item * it)
772 Elm_Imageslider_Item *_it;
776 if (!it || !(wd = elm_widget_data_get(it->obj)))
779 EINA_LIST_FOREACH(wd->its, l, _it)
784 wd->cur = eina_list_prev(wd->cur);
785 wd->its = eina_list_remove(wd->its, it);
791 _imageslider_update(wd);
794 EAPI Elm_Imageslider_Item *
795 elm_imageslider_selected_item_get(Evas_Object *obj)
797 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
800 if (!obj || (!(wd = elm_widget_data_get(obj))))
806 return eina_list_data_get(wd->cur);
810 elm_imageslider_item_selected_get(Elm_Imageslider_Item * it)
814 if (!it || !it->obj || (!(wd = elm_widget_data_get(it->obj))))
820 if (eina_list_data_get(wd->cur) == it)
827 elm_imageslider_item_selected_set(Elm_Imageslider_Item * it)
833 Elm_Imageslider_Item *_it;
839 if (!it || !it->obj || (!(wd = elm_widget_data_get(it->obj))))
842 EINA_LIST_FOREACH(wd->its, l, _it)
848 for (i = 0; i < BLOCK_MAX; i++)
850 eo = elm_object_part_content_get(wd->ly[i], "swl.photo");
852 elm_object_part_content_set(wd->ly[i], "swl.photo", NULL);
854 _imageslider_update(wd);
858 elm_imageslider_item_photo_file_get(Elm_Imageslider_Item * it)
860 if (!it) return NULL;
862 return it->photo_file;
866 elm_imageslider_item_photo_file_set(Elm_Imageslider_Item *it, const char *photo_file)
869 ELM_CHECK_WIDTYPE(it->obj, widtype);
873 eina_stringshare_replace(&(it->photo_file), photo_file);
874 elm_imageslider_item_update(it);
878 EAPI Elm_Imageslider_Item *
879 elm_imageslider_item_prev(Elm_Imageslider_Item * it)
883 Elm_Imageslider_Item *_it;
887 if (!it || (!(wd = elm_widget_data_get(it->obj))))
890 EINA_LIST_FOREACH(wd->its, l, _it)
894 l = eina_list_prev(l);
897 return eina_list_data_get(l);
903 EAPI Elm_Imageslider_Item *
904 elm_imageslider_item_next(Elm_Imageslider_Item * it)
908 Elm_Imageslider_Item *_it;
912 if (!it || (!(wd = elm_widget_data_get(it->obj))))
915 EINA_LIST_FOREACH(wd->its, l, _it)
919 l = eina_list_next(l);
922 return eina_list_data_get(l);
929 elm_imageslider_prev(Evas_Object *obj)
931 ELM_CHECK_WIDTYPE(obj, widtype);
934 if (!obj || (!(wd = elm_widget_data_get(obj))))
938 _imageslider_obj_move(wd, -1);
942 elm_imageslider_next(Evas_Object * obj)
944 ELM_CHECK_WIDTYPE(obj, widtype);
947 if (!obj || (!(wd = elm_widget_data_get(obj))))
951 _imageslider_obj_move(wd, 1);
955 elm_imageslider_item_update(Elm_Imageslider_Item *it)
959 if (!it || (!(wd = elm_widget_data_get(it->obj)))) return;
960 ELM_CHECK_WIDTYPE(it->obj, widtype);
962 if (wd->ani_lock) return;
963 if (it == eina_list_data_get(eina_list_prev(wd->cur)))
964 elm_object_part_content_set(wd->ly[BLOCK_LEFT], "swl.photo", NULL);
965 else if (it == eina_list_data_get(wd->cur))
966 elm_object_part_content_set(wd->ly[BLOCK_CENTER], "swl.photo", NULL);
967 else if (it == eina_list_data_get(eina_list_next(wd->cur)))
968 elm_object_part_content_set(wd->ly[BLOCK_RIGHT], "swl.photo", NULL);
969 _imageslider_update(wd);