1 #include <Elementary.h>
3 #include "els_scroller.h"
6 * TODO (maybe - optional future stuff):
8 * 1. wrap photo in theme edje so u can have styling around photo (like white
11 * 3. rotation flags in exif handling (nasty! should have rot in evas)
14 typedef struct _Widget_Data Widget_Data;
15 typedef struct _Pan Pan;
16 typedef struct _Grid Grid;
17 typedef struct _Grid_Item Grid_Item;
33 int tsize; // size of tile (tsize x tsize pixels)
34 int zoom; // zoom level tiles want for optimal display (1, 2, 4, 8)
35 int iw, ih; // size of image in pixels
36 int w, h; // size of grid image in pixels (represented by grid)
37 int gw, gh; // size of grid in tiles
38 Grid_Item *grid; // the grid (gw * gh items)
39 Eina_Bool dead : 1; // old grid. will die as soon as anim is over
46 Evas_Object *pan_smart;
51 Evas_Coord pan_x, pan_y, minw, minh;
54 Elm_Photocam_Zoom_Mode mode;
55 Evas_Coord pvx, pvy, px, py, zoom_point_x, zoom_point_y;
65 Ecore_Animator *animator;
71 Ecore_Timer *scr_timer;
72 Ecore_Timer *long_timer;
73 Ecore_Animator *zoom_animator;
74 double t_start, t_end;
88 Evas_Coord x, y ,w ,h;
91 Evas_Object *img; // low res version of image (scale down == 8)
95 Eina_Bool main_load_pending : 1;
96 Eina_Bool resized : 1;
97 Eina_Bool longpressed : 1;
98 Eina_Bool on_hold : 1;
100 Eina_Bool do_region : 1;
101 Eina_Bool do_gesture : 1;
102 Eina_Bool zoom_gest : 1;
107 Evas_Object_Smart_Clipped_Data __clipped_data;
111 static const char *widtype = NULL;
112 static void _del_hook(Evas_Object *obj);
113 static void _theme_hook(Evas_Object *obj);
114 static void _on_focus_hook(void *data, Evas_Object *obj);
115 //static void _show_region_hook(void *data, Evas_Object *obj);
116 static void _sizing_eval(Evas_Object *obj);
117 static void _calc_job(void *data);
118 static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__,
119 Evas_Callback_Type type, void *event_info);
120 static void grid_place(Evas_Object *obj, Grid *g, Evas_Coord px, Evas_Coord py, Evas_Coord ox, Evas_Coord oy, Evas_Coord ow, Evas_Coord oh);
121 static void grid_clear(Evas_Object *obj, Grid *g);
122 static Grid *grid_create(Evas_Object *obj);
123 static void grid_load(Evas_Object *obj, Grid *g);
125 static const char SIG_CLICKED[] = "clicked";
126 static const char SIG_PRESS[] = "press";
127 static const char SIG_LONGPRESSED[] = "longpressed";
128 static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
129 static const char SIG_LOAD[] = "load";
130 static const char SIG_LOADED[] = "loaded";
131 static const char SIG_LOAD_DETAIL[] = "load,detail";
132 static const char SIG_LOADED_DETAIL[] = "loaded,detail";
133 static const char SIG_ZOOM_START[] = "zoom,start";
134 static const char SIG_ZOOM_STOP[] = "zoom,stop";
135 static const char SIG_ZOOM_CHANGE[] = "zoom,change";
136 static const char SIG_SCROLL[] = "scroll";
137 static const char SIG_SCROLL_ANIM_START[] = "scroll,anim,start";
138 static const char SIG_SCROLL_ANIM_STOP[] = "scroll,anim,stop";
139 static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start";
140 static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop";
142 static const Evas_Smart_Cb_Description _signals[] = {
145 {SIG_LONGPRESSED, ""},
146 {SIG_CLICKED_DOUBLE, ""},
149 {SIG_LOAD_DETAIL, ""},
150 {SIG_LOADED_DETAIL, ""},
151 {SIG_ZOOM_START, ""},
153 {SIG_ZOOM_CHANGE, ""},
155 {SIG_SCROLL_ANIM_START, ""},
156 {SIG_SCROLL_ANIM_STOP, ""},
157 {SIG_SCROLL_DRAG_START, ""},
158 {SIG_SCROLL_DRAG_STOP, ""},
164 nearest_pow2(int num)
166 unsigned int n = num - 1;
176 img_place(Evas_Object *obj, Evas_Coord px, Evas_Coord py, Evas_Coord ox, Evas_Coord oy, Evas_Coord ow, Evas_Coord oh)
178 Widget_Data *wd = elm_widget_data_get(obj);
179 Evas_Coord ax, ay, gw, gh;
187 if (ow > gw) ax = (ow - gw) / 2;
188 if (oh > gh) ay = (oh - gh) / 2;
190 evas_object_move(wd->img, ox + 0 - px + ax, oy + 0 - py + ay);
191 evas_object_resize(wd->img, gw, gh);
195 wd->show.show = EINA_FALSE;
196 elm_smart_scroller_child_region_show(wd->scr, wd->show.x, wd->show.y, wd->show.w, wd->show.h);
201 grid_place(Evas_Object *obj, Grid *g, Evas_Coord px, Evas_Coord py, Evas_Coord ox, Evas_Coord oy, Evas_Coord ow, Evas_Coord oh)
203 Widget_Data *wd = elm_widget_data_get(obj);
204 Evas_Coord ax, ay, gw, gh, tx, ty;
213 if (ow > gw) ax = (ow - gw) / 2;
214 if (oh > gh) ay = (oh - gh) / 2;
216 for (y = 0; y < g->gh; y++)
218 for (x = 0; x < g->gw; x++)
220 int tn, xx, yy, ww, hh;
222 tn = (y * g->gw) + x;
223 xx = g->grid[tn].out.x;
224 yy = g->grid[tn].out.y;
225 ww = g->grid[tn].out.w;
226 hh = g->grid[tn].out.h;
227 if ((gw != g->w) && (g->w > 0))
230 xx = (gw * xx) / g->w;
231 ww = ((gw * (tx + ww)) / g->w) - xx;
233 if ((gh != g->h) && (g->h > 0))
236 yy = (gh * yy) / g->h;
237 hh = ((gh * (ty + hh)) / g->h) - yy;
239 evas_object_move(g->grid[tn].img,
242 evas_object_resize(g->grid[tn].img, ww, hh);
248 grid_clear(Evas_Object *obj, Grid *g)
250 Widget_Data *wd = elm_widget_data_get(obj);
253 if (!g->grid) return;
254 for (y = 0; y < g->gh; y++)
256 for (x = 0; x < g->gw; x++)
260 tn = (y * g->gw) + x;
261 evas_object_del(g->grid[tn].img);
262 if (g->grid[tn].want)
265 if (!wd->preload_num)
267 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
268 "elm,state,busy,stop", "elm");
269 evas_object_smart_callback_call(obj, SIG_LOAD_DETAIL, NULL);
281 _tile_preloaded(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
283 Grid_Item *git = data;
288 evas_object_show(git->img);
290 git->wd->preload_num--;
291 if (!git->wd->preload_num)
293 edje_object_signal_emit(elm_smart_scroller_edje_object_get(git->wd->scr),
294 "elm,state,busy,stop", "elm");
295 evas_object_smart_callback_call(git->wd->obj, SIG_LOADED_DETAIL, NULL);
301 grid_zoom_calc(double zoom)
305 return nearest_pow2(z);
309 grid_create(Evas_Object *obj)
311 Widget_Data *wd = elm_widget_data_get(obj);
315 if (!wd) return NULL;
316 g = calloc(1, sizeof(Grid));
319 g->zoom = grid_zoom_calc(wd->zoom);
320 g->tsize = wd->tsize;
321 g->iw = wd->size.imw;
322 g->ih = wd->size.imh;
324 g->w = g->iw / g->zoom;
325 g->h = g->ih / g->zoom;
333 g->gw = (g->w + g->tsize - 1) / g->tsize;
334 g->gh = (g->h + g->tsize - 1) / g->tsize;
341 g->grid = calloc(1, sizeof(Grid_Item) * g->gw * g->gh);
348 for (y = 0; y < g->gh; y++)
350 for (x = 0; x < g->gw; x++)
354 tn = (y * g->gw) + x;
355 g->grid[tn].src.x = x * g->tsize;
356 if (x == (g->gw - 1))
357 g->grid[tn].src.w = g->w - ((g->gw - 1) * g->tsize);
359 g->grid[tn].src.w = g->tsize;
360 g->grid[tn].src.y = y * g->tsize;
361 if (y == (g->gh - 1))
362 g->grid[tn].src.h = g->h - ((g->gh - 1) * g->tsize);
364 g->grid[tn].src.h = g->tsize;
366 g->grid[tn].out.x = g->grid[tn].src.x;
367 g->grid[tn].out.y = g->grid[tn].src.y;
368 g->grid[tn].out.w = g->grid[tn].src.w;
369 g->grid[tn].out.h = g->grid[tn].src.h;
373 evas_object_image_add(evas_object_evas_get(obj));
374 evas_object_image_load_orientation_set(g->grid[tn].img, EINA_TRUE);
375 evas_object_image_scale_hint_set
376 (g->grid[tn].img, EVAS_IMAGE_SCALE_HINT_DYNAMIC);
377 evas_object_pass_events_set(g->grid[tn].img, EINA_TRUE);
378 evas_object_smart_member_add(g->grid[tn].img,
380 elm_widget_sub_object_add(obj, g->grid[tn].img);
381 evas_object_image_filled_set(g->grid[tn].img, 1);
382 evas_object_event_callback_add(g->grid[tn].img,
383 EVAS_CALLBACK_IMAGE_PRELOADED,
392 grid_load(Evas_Object *obj, Grid *g)
394 Widget_Data *wd = elm_widget_data_get(obj);
396 Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh, gw, gh, tx, ty;
398 evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
399 evas_output_viewport_get(evas_object_evas_get(wd->obj), &cvx, &cvy, &cvw, &cvh);
402 for (y = 0; y < g->gh; y++)
404 for (x = 0; x < g->gw; x++)
406 int tn, xx, yy, ww, hh;
407 Eina_Bool visible = EINA_FALSE;
409 tn = (y * g->gw) + x;
410 xx = g->grid[tn].out.x;
411 yy = g->grid[tn].out.y;
412 ww = g->grid[tn].out.w;
413 hh = g->grid[tn].out.h;
414 if ((gw != g->w) && (g->w > 0))
417 xx = (gw * xx) / g->w;
418 ww = ((gw * (tx + ww)) / g->w) - xx;
420 if ((gh != g->h) && (g->h > 0))
423 yy = (gh * yy) / g->h;
424 hh = ((gh * (ty + hh)) / g->h) - yy;
426 if (ELM_RECTS_INTERSECT(xx - wd->pan_x + ox,
431 if ((visible) && (!g->grid[tn].have) && (!g->grid[tn].want))
433 g->grid[tn].want = 1;
434 evas_object_hide(g->grid[tn].img);
435 evas_object_image_file_set(g->grid[tn].img, NULL, NULL);
436 evas_object_image_load_scale_down_set(g->grid[tn].img, g->zoom);
437 evas_object_image_load_region_set(g->grid[tn].img,
442 evas_object_image_file_set(g->grid[tn].img, wd->file, NULL);
443 evas_object_image_preload(g->grid[tn].img, 0);
445 if (wd->preload_num == 1)
447 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
448 "elm,state,busy,start", "elm");
449 evas_object_smart_callback_call(obj, SIG_LOAD_DETAIL, NULL);
452 else if ((g->grid[tn].want) && (!visible))
455 if (!wd->preload_num)
457 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
458 "elm,state,busy,stop", "elm");
459 evas_object_smart_callback_call(obj, SIG_LOADED_DETAIL, NULL);
461 g->grid[tn].want = 0;
462 evas_object_hide(g->grid[tn].img);
463 evas_object_image_preload(g->grid[tn].img, 1);
464 evas_object_image_file_set(g->grid[tn].img, NULL, NULL);
466 else if ((g->grid[tn].have) && (!visible))
468 g->grid[tn].have = 0;
469 evas_object_hide(g->grid[tn].img);
470 evas_object_image_preload(g->grid[tn].img, 1);
471 evas_object_image_file_set(g->grid[tn].img, NULL, NULL);
478 grid_clearall(Evas_Object *obj)
480 Widget_Data *wd = elm_widget_data_get(obj);
483 EINA_LIST_FREE(wd->grids, g)
491 _smooth_update(Evas_Object *obj)
493 Widget_Data *wd = elm_widget_data_get(obj);
498 EINA_LIST_FOREACH(wd->grids, l, g)
500 for (y = 0; y < g->gh; y++)
502 for (x = 0; x < g->gw; x++)
506 tn = (y * g->gw) + x;
507 evas_object_image_smooth_scale_set(g->grid[tn].img, (!wd->nosmooth));
511 evas_object_image_smooth_scale_set(wd->img, (!wd->nosmooth));
519 for (y = 0; y < g->gh; y++)
521 for (x = 0; x < g->gw; x++)
525 tn = (y * g->gw) + x;
526 evas_object_raise(g->grid[tn].img);
532 _scr_timeout(void *data)
534 Widget_Data *wd = elm_widget_data_get(data);
535 if (!wd) return ECORE_CALLBACK_CANCEL;
537 if (!wd->nosmooth) _smooth_update(data);
538 wd->scr_timer = NULL;
539 return ECORE_CALLBACK_CANCEL;
543 _scr(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
545 Widget_Data *wd = elm_widget_data_get(data);
550 if (wd->nosmooth == 1) _smooth_update(data);
552 if (wd->scr_timer) ecore_timer_del(wd->scr_timer);
553 wd->scr_timer = ecore_timer_add(0.5, _scr_timeout, data);
557 _main_preloaded(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
559 Evas_Object *obj = data;
560 Widget_Data *wd = elm_widget_data_get(obj);
563 evas_object_show(wd->img);
564 wd->main_load_pending = 0;
565 g = grid_create(obj);
568 wd->grids = eina_list_prepend(wd->grids, g);
569 grid_load(wd->obj, g);
571 if (wd->calc_job) ecore_job_del(wd->calc_job);
572 wd->calc_job = ecore_job_add(_calc_job, wd);
573 evas_object_smart_callback_call(data, SIG_LOADED, NULL);
575 if (!wd->preload_num)
577 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
578 "elm,state,busy,stop", "elm");
579 evas_object_smart_callback_call(obj, SIG_LOADED_DETAIL, NULL);
584 zoom_do(Evas_Object *obj, double t)
586 Widget_Data *wd = elm_widget_data_get(obj);
587 Evas_Coord xx, yy, ow, oh;
588 if (!wd) return ECORE_CALLBACK_CANCEL;
589 wd->size.w = (wd->size.ow * (1.0 - t)) + (wd->size.nw * t);
590 wd->size.h = (wd->size.oh * (1.0 - t)) + (wd->size.nh * t);
591 elm_smart_scroller_child_viewport_size_get(wd->scr, &ow, &oh);
592 xx = (wd->size.spos.x * wd->size.w) - (ow / 2);
593 yy = (wd->size.spos.y * wd->size.h) - (oh / 2);
595 else if (xx > (wd->size.w - ow)) xx = wd->size.w - ow;
597 else if (yy > (wd->size.h - oh)) yy = wd->size.h - oh;
599 wd->show.show = EINA_TRUE;
605 if (wd->calc_job) ecore_job_del(wd->calc_job);
606 wd->calc_job = ecore_job_add(_calc_job, wd);
609 Eina_List *l, *l_next;
612 EINA_LIST_FOREACH_SAFE(wd->grids, l, l_next, g)
616 wd->grids = eina_list_remove_list(wd->grids, l);
621 return ECORE_CALLBACK_CANCEL;
623 return ECORE_CALLBACK_RENEW;
628 _zoom_anim(void *data)
630 Evas_Object *obj = data;
631 Widget_Data *wd = elm_widget_data_get(obj);
634 if (!wd) return ECORE_CALLBACK_CANCEL;
635 t = ecore_loop_time_get();
638 else if (wd->t_end > wd->t_start)
639 t = (t - wd->t_start) / (wd->t_end - wd->t_start);
644 go = zoom_do(obj, t);
648 if (!wd->nosmooth) _smooth_update(data);
649 wd->zoom_animator = NULL;
650 evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL);
656 _mouse_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
658 Widget_Data *wd = elm_widget_data_get(data);
659 // Evas_Event_Mouse_Move *ev = event_info;
664 _long_press(void *data)
666 Widget_Data *wd = elm_widget_data_get(data);
667 if (!wd) return ECORE_CALLBACK_CANCEL;
668 wd->long_timer = NULL;
669 wd->longpressed = EINA_TRUE;
670 evas_object_smart_callback_call(data, SIG_LONGPRESSED, NULL);
671 return ECORE_CALLBACK_CANCEL;
675 _mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
677 Widget_Data *wd = elm_widget_data_get(data);
678 Evas_Event_Mouse_Down *ev = event_info;
680 if (ev->button != 1) return;
681 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) wd->on_hold = EINA_TRUE;
682 else wd->on_hold = EINA_FALSE;
683 if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
684 evas_object_smart_callback_call(data, SIG_CLICKED_DOUBLE, NULL);
686 evas_object_smart_callback_call(data, SIG_PRESS, NULL);
687 wd->longpressed = EINA_FALSE;
688 if (wd->long_timer) ecore_timer_del(wd->long_timer);
689 wd->long_timer = ecore_timer_add(_elm_config->longpress_timeout, _long_press, data);
693 _mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
695 Widget_Data *wd = elm_widget_data_get(data);
696 Evas_Event_Mouse_Up *ev = event_info;
698 if (ev->button != 1) return;
699 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) wd->on_hold = EINA_TRUE;
700 else wd->on_hold = EINA_FALSE;
703 ecore_timer_del(wd->long_timer);
704 wd->long_timer = NULL;
707 evas_object_smart_callback_call(data, SIG_CLICKED, NULL);
708 wd->on_hold = EINA_FALSE;
711 static Evas_Smart_Class _pan_sc = EVAS_SMART_CLASS_INIT_NULL;
714 _del_hook(Evas_Object *obj)
716 Widget_Data *wd = elm_widget_data_get(obj);
719 EINA_LIST_FREE(wd->grids, g)
721 if (g->grid) free(g->grid);
724 evas_object_del(wd->pan_smart);
725 wd->pan_smart = NULL;
726 if (wd->file) eina_stringshare_del(wd->file);
727 if (wd->calc_job) ecore_job_del(wd->calc_job);
728 if (wd->scr_timer) ecore_timer_del(wd->scr_timer);
729 if (wd->zoom_animator) ecore_animator_del(wd->zoom_animator);
730 if (wd->gzoom.bounce.animator) ecore_animator_del(wd->gzoom.bounce.animator);
731 if (wd->long_timer) ecore_timer_del(wd->long_timer);
736 _on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
738 Widget_Data *wd = elm_widget_data_get(obj);
740 if (elm_widget_focus_get(obj))
742 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), "elm,action,focus", "elm");
743 evas_object_focus_set(wd->obj, EINA_TRUE);
747 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), "elm,action,unfocus", "elm");
748 evas_object_focus_set(wd->obj, EINA_FALSE);
753 _theme_hook(Evas_Object *obj)
755 Widget_Data *wd = elm_widget_data_get(obj);
757 elm_smart_scroller_object_theme_set(obj, wd->scr, "photocam", "base", elm_widget_style_get(obj));
758 // edje_object_scale_set(wd->scr, elm_widget_scale_get(obj) * _elm_config->scale);
764 _show_region_hook(void *data, Evas_Object *obj)
766 Widget_Data *wd = elm_widget_data_get(data);
767 Evas_Coord x, y, w, h;
769 elm_widget_show_region_get(obj, &x, &y, &w, &h);
770 elm_smart_scroller_child_region_show(wd->scr, x, y, w, h);
775 _sizing_eval(Evas_Object *obj)
777 Widget_Data *wd = elm_widget_data_get(obj);
778 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
780 // evas_object_size_hint_min_get(wd->scr, &minw, &minh);
781 evas_object_size_hint_max_get(wd->scr, &maxw, &maxh);
784 // if (wd->mode != ELM_LIST_LIMIT) minw = -1;
785 evas_object_size_hint_min_set(obj, minw, minh);
786 evas_object_size_hint_max_set(obj, maxw, maxh);
790 _calc_job(void *data)
792 Widget_Data *wd = data;
793 Evas_Coord minw, minh;
800 if (wd->mode != ELM_PHOTOCAM_ZOOM_MODE_MANUAL)
802 double tz = wd->zoom;
804 elm_photocam_zoom_set(wd->obj, tz);
807 if ((minw != wd->minw) || (minh != wd->minh))
811 evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
812 _sizing_eval(wd->obj);
815 evas_object_smart_changed(wd->pan_smart);
819 _pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
821 Pan *sd = evas_object_smart_data_get(obj);
823 if ((x == sd->wd->pan_x) && (y == sd->wd->pan_y)) return;
826 evas_object_smart_changed(obj);
830 _pan_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
832 Pan *sd = evas_object_smart_data_get(obj);
834 if (x) *x = sd->wd->pan_x;
835 if (y) *y = sd->wd->pan_y;
839 _pan_max_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
841 Pan *sd = evas_object_smart_data_get(obj);
844 evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
845 ow = sd->wd->minw - ow;
847 oh = sd->wd->minh - oh;
854 _pan_min_get(Evas_Object *obj __UNUSED__, Evas_Coord *x, Evas_Coord *y)
861 _pan_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
863 Pan *sd = evas_object_smart_data_get(obj);
865 if (w) *w = sd->wd->minw;
866 if (h) *h = sd->wd->minh;
870 _pan_add(Evas_Object *obj)
873 Evas_Object_Smart_Clipped_Data *cd;
875 cd = evas_object_smart_data_get(obj);
877 sd = calloc(1, sizeof(Pan));
879 sd->__clipped_data = *cd;
881 evas_object_smart_data_set(obj, sd);
885 _pan_del(Evas_Object *obj)
887 Pan *sd = evas_object_smart_data_get(obj);
893 _pan_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
895 Pan *sd = evas_object_smart_data_get(obj);
898 evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
899 if ((ow == w) && (oh == h)) return;
901 if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
902 sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd);
906 _pan_calculate(Evas_Object *obj)
908 Pan *sd = evas_object_smart_data_get(obj);
909 Evas_Coord ox, oy, ow, oh;
913 evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
914 img_place(sd->wd->obj, sd->wd->pan_x, sd->wd->pan_y,
915 ox - sd->wd->gzoom.imx, oy - sd->wd->gzoom.imy, ow, oh);
916 EINA_LIST_FOREACH(sd->wd->grids, l, g)
918 grid_load(sd->wd->obj, g);
919 grid_place(sd->wd->obj, g, sd->wd->pan_x, sd->wd->pan_y,
920 ox - sd->wd->gzoom.imx, oy - sd->wd->gzoom.imy, ow, oh);
925 _pan_move(Evas_Object *obj, Evas_Coord x __UNUSED__, Evas_Coord y __UNUSED__)
927 Pan *sd = evas_object_smart_data_get(obj);
929 if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
930 sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd);
934 _hold_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
936 Widget_Data *wd = elm_widget_data_get(obj);
938 elm_smart_scroller_hold_set(wd->scr, 1);
942 _hold_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
944 Widget_Data *wd = elm_widget_data_get(obj);
946 elm_smart_scroller_hold_set(wd->scr, 0);
950 _freeze_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
952 Widget_Data *wd = elm_widget_data_get(obj);
954 elm_smart_scroller_freeze_set(wd->scr, 1);
958 _freeze_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
960 Widget_Data *wd = elm_widget_data_get(obj);
962 elm_smart_scroller_freeze_set(wd->scr, 0);
966 _scr_anim_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
968 evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_START, NULL);
972 _scr_anim_stop(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
974 evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_STOP, NULL);
978 _scr_drag_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
980 evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_START, NULL);
984 _scr_drag_stop(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
986 evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_STOP, NULL);
990 _scr_scroll(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
992 evas_object_smart_callback_call(data, SIG_SCROLL, NULL);
996 _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__,
997 Evas_Callback_Type type, void *event_info)
1000 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
1001 Evas_Event_Key_Down *ev = event_info;
1002 Widget_Data *wd = elm_widget_data_get(obj);
1003 if (!wd) return EINA_FALSE;
1004 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
1008 Evas_Coord step_x = 0;
1009 Evas_Coord step_y = 0;
1012 Evas_Coord page_x = 0;
1013 Evas_Coord page_y = 0;
1015 elm_smart_scroller_child_pos_get(wd->scr, &x, &y);
1016 elm_smart_scroller_step_size_get(wd->scr, &step_x, &step_y);
1017 elm_smart_scroller_page_size_get(wd->scr, &page_x, &page_y);
1018 elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h);
1020 if ((!strcmp(ev->keyname, "Left")) ||
1021 (!strcmp(ev->keyname, "KP_Left")))
1025 else if ((!strcmp(ev->keyname, "Right")) ||
1026 (!strcmp(ev->keyname, "KP_Right")))
1030 else if ((!strcmp(ev->keyname, "Up")) ||
1031 (!strcmp(ev->keyname, "KP_Up")))
1035 else if ((!strcmp(ev->keyname, "Down")) ||
1036 (!strcmp(ev->keyname, "KP_Down")))
1040 else if ((!strcmp(ev->keyname, "Prior")) ||
1041 (!strcmp(ev->keyname, "KP_Prior")))
1044 y -= -(page_y * v_h) / 100;
1048 else if ((!strcmp(ev->keyname, "Next")) ||
1049 (!strcmp(ev->keyname, "KP_Next")))
1052 y += -(page_y * v_h) / 100;
1056 else if ((!strcmp(ev->keyname, "KP_Add")))
1058 zoom = elm_photocam_zoom_get(obj);
1060 elm_photocam_zoom_mode_set(obj, ELM_PHOTOCAM_ZOOM_MODE_MANUAL);
1061 elm_photocam_zoom_set(obj, zoom);
1064 else if ((!strcmp(ev->keyname, "KP_Subtract")))
1066 zoom = elm_photocam_zoom_get(obj);
1068 elm_photocam_zoom_mode_set(obj, ELM_PHOTOCAM_ZOOM_MODE_MANUAL);
1069 elm_photocam_zoom_set(obj, zoom);
1072 else return EINA_FALSE;
1074 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1075 elm_smart_scroller_child_pos_set(wd->scr, x, y);
1081 _bounce_eval(void *_wd)
1083 Widget_Data *wd = (Widget_Data *)_wd;
1086 if (!wd) return ECORE_CALLBACK_CANCEL;
1087 if ((wd->gzoom.imx == wd->gzoom.bounce.x_end) &&
1088 (wd->gzoom.imy == wd->gzoom.bounce.y_end))
1092 wd->zoom_gest = EINA_FALSE;
1093 wd->gzoom.bounce.animator = NULL;
1094 _freeze_off(NULL, wd->obj, NULL);
1095 return ECORE_CALLBACK_CANCEL;
1098 t = ecore_loop_time_get();
1099 tt = (t - wd->gzoom.bounce.t_start) / (wd->gzoom.bounce.t_end - wd->gzoom.bounce.t_start);
1101 tt = 1.0 - (tt * tt);
1103 if (t > wd->gzoom.bounce.t_end)
1107 wd->zoom_gest = EINA_FALSE;
1108 _freeze_off(NULL, wd->obj, NULL);
1109 zoom_do(wd->obj, 1.0);
1110 wd->gzoom.bounce.animator = NULL;
1111 return ECORE_CALLBACK_CANCEL;
1114 if (wd->gzoom.imx != wd->gzoom.bounce.x_end)
1115 wd->gzoom.imx = wd->gzoom.bounce.x_start * (1.0 - tt) + wd->gzoom.bounce.x_end * tt;
1117 if (wd->gzoom.imy != wd->gzoom.bounce.y_end)
1118 wd->gzoom.imy = wd->gzoom.bounce.y_start * (1.0 - tt) + wd->gzoom.bounce.y_end * tt;
1120 zoom_do(wd->obj, 1.0 - (1.0 - tt));
1121 return ECORE_CALLBACK_RENEW;
1125 _gzoom(Widget_Data *_wd, Evas_Coord px, Evas_Coord py, Elm_Gesture_Zoom_Info* gest)
1127 Widget_Data *wd = (Widget_Data *)_wd;
1128 Evas_Coord rx, ry, rw, rh;
1129 int regx, regy, regw, regh, ix, iy, iw, ih;
1133 wd->mode = ELM_PHOTOCAM_ZOOM_MODE_MANUAL;
1134 wd->zoom = wd->gest_start / gest->zoom;
1135 wd->size.ow = wd->size.w;
1136 wd->size.oh = wd->size.h;
1137 elm_smart_scroller_child_pos_get(wd->scr, &rx, &ry);
1138 elm_smart_scroller_child_viewport_size_get(wd->scr, &rw, &rh);
1139 if ((rw <= 0) || (rh <= 0)) return;
1141 wd->size.nw = (double)wd->size.imw / wd->zoom;
1142 wd->size.nh = (double)wd->size.imh / wd->zoom;
1144 elm_photocam_image_region_get(wd->obj, ®x, ®y, ®w, ®h);
1145 evas_object_geometry_get(wd->img, &ix, &iy, &iw, &ih);
1150 xx = (px / wd->zoom) - wd->pvx;
1151 yy = (py / wd->zoom) - wd->pvy;
1155 if ((xx < 0) || (rw > wd->size.nw))
1160 else if ((xx + rw) > wd->size.nw)
1162 wd->gzoom.imx = xx + rw - wd->size.nw;
1163 xx = wd->size.nw - rw;
1166 if ((yy < 0) || (rh > wd->size.nh))
1171 else if ((yy + rh) > wd->size.nh)
1173 wd->gzoom.imy = yy + rh - wd->size.nh;
1174 yy = wd->size.nh - rh;
1177 wd->size.spos.x = (double)(xx + (rw / 2)) / (double)(wd->size.nw);
1178 wd->size.spos.y = (double)(yy + (rh / 2)) / (double)(wd->size.nh);
1180 zoom_do(wd->obj, 1.0);
1183 static Evas_Event_Flags
1184 _gzoom_start(void *_wd, void *event_info)
1186 Widget_Data *wd = (Widget_Data *)_wd;
1187 Elm_Gesture_Zoom_Info *p = (Elm_Gesture_Zoom_Info *) event_info;
1190 double marginx = 0, marginy = 0;
1192 if (wd->gzoom.bounce.animator)
1194 ecore_animator_del(wd->gzoom.bounce.animator);
1195 wd->gzoom.bounce.animator = NULL;
1197 wd->zoom_gest = EINA_TRUE;
1198 _freeze_on(NULL, wd->obj, NULL);
1200 elm_photocam_image_region_get(wd->obj, &x, &y, &w, &h);
1201 elm_smart_scroller_child_viewport_size_get(wd->scr, &rw, &rh);
1203 if (rw > wd->size.nw)
1204 marginx = (rw - wd->size.nw) / 2;
1205 if (rh > wd->size.nh)
1206 marginy = (rh - wd->size.nh) / 2;
1208 wd->gest_start = wd->zoom;
1210 wd->zoom_point_x = x + ((p->x - marginx) * wd->zoom) + wd->gzoom.imx;
1211 wd->zoom_point_y = y + ((p->y - marginy) * wd->zoom) + wd->gzoom.imy;
1213 return EVAS_EVENT_FLAG_NONE;
1216 static Evas_Event_Flags
1217 _gzoom_move(void *_wd, void *event_info)
1219 Widget_Data *wd = (Widget_Data *)_wd;
1220 Elm_Gesture_Zoom_Info *p = (Elm_Gesture_Zoom_Info *) event_info;
1222 _gzoom(wd, wd->zoom_point_x, wd->zoom_point_y, p);
1223 return EVAS_EVENT_FLAG_NONE;
1226 static Evas_Event_Flags
1227 _gzoom_end(void *_wd, void *event_info __UNUSED__)
1229 Widget_Data *wd = (Widget_Data *)_wd;
1232 elm_smart_scroller_child_viewport_size_get(wd->scr, &rw, &rh);
1233 wd->gest_start = 1.0;
1235 if (wd->gzoom.imx || wd->gzoom.imy)
1239 t = ecore_loop_time_get();
1240 wd->gzoom.bounce.x_start = wd->gzoom.imx;
1241 wd->gzoom.bounce.y_start = wd->gzoom.imy;
1242 wd->gzoom.bounce.x_end = 0;
1243 wd->gzoom.bounce.y_end = 0;
1245 if (rw > wd->size.nw &&
1251 if ((wd->size.imw < rw) && (wd->size.imh < rh))
1254 wd->size.nw = wd->size.imw;
1255 wd->size.nh = wd->size.imh;
1259 ph = (wd->size.imh * rw) / wd->size.imw;
1262 pw = (wd->size.imw * rh) / wd->size.imh;
1269 if (wd->size.imw > wd->size.imh)
1270 z = (double)wd->size.imw / pw;
1272 z = (double)wd->size.imh / ph;
1278 wd->gzoom.bounce.x_end = (wd->size.nw - rw) / 2;
1279 wd->gzoom.bounce.y_end = (wd->size.nh - rh) / 2;
1285 xx = (wd->zoom_point_x / wd->zoom) - wd->pvx;
1286 yy = (wd->zoom_point_y / wd->zoom) - wd->pvy;
1291 if (rw > wd->size.nw)
1292 wd->gzoom.bounce.x_end = (wd->size.nw -rw) / 2;
1293 if ((xx + rw) > wd->size.nw)
1294 xx = wd->size.nw - rw;
1296 if (rh > wd->size.nh)
1297 wd->gzoom.bounce.y_end = (wd->size.nh - rh) / 2;
1298 if ((yy + rh) > wd->size.nh)
1299 yy = wd->size.nh - rh;
1301 wd->size.spos.x = (double)(xx + (rw / 2)) / (double)(wd->size.nw);
1302 wd->size.spos.y = (double)(yy + (rh / 2)) / (double)(wd->size.nh);
1305 wd->gzoom.bounce.t_start = t;
1306 wd->gzoom.bounce.t_end = t + _elm_config->page_scroll_friction;
1308 wd->gzoom.bounce.animator = ecore_animator_add(_bounce_eval, wd);
1312 _freeze_off(NULL, wd->obj, NULL);
1313 wd->zoom_gest = EINA_FALSE;
1316 return EVAS_EVENT_FLAG_NONE;
1320 elm_photocam_add(Evas_Object *parent)
1325 Evas_Coord minw, minh;
1326 static Evas_Smart *smart = NULL;
1327 Eina_Bool bounce = _elm_config->thumbscroll_bounce_enable;
1329 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1331 ELM_SET_WIDTYPE(widtype, "photocam");
1332 elm_widget_type_set(obj, "photocam");
1333 elm_widget_sub_object_add(parent, obj);
1334 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
1335 elm_widget_data_set(obj, wd);
1336 elm_widget_del_hook_set(obj, _del_hook);
1337 elm_widget_theme_hook_set(obj, _theme_hook);
1338 elm_widget_can_focus_set(obj, EINA_TRUE);
1339 elm_widget_event_hook_set(obj, _event_hook);
1341 wd->scr = elm_smart_scroller_add(e);
1342 elm_smart_scroller_widget_set(wd->scr, obj);
1343 elm_smart_scroller_object_theme_set(obj, wd->scr, "photocam", "base", "default");
1344 evas_object_smart_callback_add(wd->scr, "scroll", _scr, obj);
1345 evas_object_smart_callback_add(wd->scr, "drag", _scr, obj);
1346 elm_widget_resize_object_set(obj, wd->scr);
1348 evas_object_smart_callback_add(wd->scr, "animate,start", _scr_anim_start, obj);
1349 evas_object_smart_callback_add(wd->scr, "animate,stop", _scr_anim_stop, obj);
1350 evas_object_smart_callback_add(wd->scr, "drag,start", _scr_drag_start, obj);
1351 evas_object_smart_callback_add(wd->scr, "drag,stop", _scr_drag_stop, obj);
1352 evas_object_smart_callback_add(wd->scr, "scroll", _scr_scroll, obj);
1354 elm_smart_scroller_bounce_allow_set(wd->scr, bounce, bounce);
1358 evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
1359 evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
1360 evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
1361 evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
1365 static Evas_Smart_Class sc;
1367 evas_object_smart_clipped_smart_set(&_pan_sc);
1369 sc.name = "elm_photocam_pan";
1370 sc.version = EVAS_SMART_CLASS_VERSION;
1373 sc.resize = _pan_resize;
1374 sc.move = _pan_move;
1375 sc.calculate = _pan_calculate;
1376 smart = evas_smart_class_new(&sc);
1380 wd->pan_smart = evas_object_smart_add(e, smart);
1381 wd->pan = evas_object_smart_data_get(wd->pan_smart);
1385 elm_smart_scroller_extern_pan_set(wd->scr, wd->pan_smart,
1386 _pan_set, _pan_get, _pan_max_get,
1387 _pan_min_get, _pan_child_size_get);
1389 wd->zoom_gest = EINA_FALSE;
1390 wd->gest_start = 1.0;
1392 wd->mode = ELM_PHOTOCAM_ZOOM_MODE_MANUAL;
1395 wd->img = evas_object_image_add(e);
1396 evas_object_image_load_orientation_set(wd->img, EINA_TRUE);
1397 evas_object_image_scale_hint_set(wd->img, EVAS_IMAGE_SCALE_HINT_DYNAMIC);
1398 evas_object_event_callback_add(wd->img, EVAS_CALLBACK_MOUSE_DOWN,
1400 evas_object_event_callback_add(wd->img, EVAS_CALLBACK_MOUSE_UP,
1402 evas_object_event_callback_add(wd->img, EVAS_CALLBACK_MOUSE_MOVE,
1404 evas_object_image_scale_hint_set(wd->img, EVAS_IMAGE_SCALE_HINT_STATIC);
1405 evas_object_smart_member_add(wd->img, wd->pan_smart);
1406 elm_widget_sub_object_add(obj, wd->img);
1407 evas_object_image_filled_set(wd->img, 1);
1408 evas_object_event_callback_add(wd->img, EVAS_CALLBACK_IMAGE_PRELOADED,
1409 _main_preloaded, obj);
1411 edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
1413 evas_object_size_hint_min_set(obj, minw, minh);
1415 evas_object_smart_callbacks_descriptions_set(obj, _signals);
1421 EAPI Evas_Load_Error
1422 elm_photocam_file_set(Evas_Object *obj, const char *file)
1424 ELM_CHECK_WIDTYPE(obj, widtype) EVAS_LOAD_ERROR_NONE;
1425 Widget_Data *wd = elm_widget_data_get(obj);
1427 if (!wd) return EVAS_LOAD_ERROR_GENERIC;
1428 if (!eina_stringshare_replace(&wd->file, file)) return EVAS_LOAD_ERROR_NONE;
1431 evas_object_hide(wd->img);
1432 evas_object_image_smooth_scale_set(wd->img, (wd->nosmooth == 0));
1433 evas_object_image_file_set(wd->img, NULL, NULL);
1434 evas_object_image_load_scale_down_set(wd->img, 0);
1435 evas_object_image_file_set(wd->img, wd->file, NULL);
1436 evas_object_image_size_get(wd->img, &w, &h);
1437 wd->do_region = evas_object_image_region_support_get(wd->img);
1440 wd->size.w = wd->size.imw / wd->zoom;
1441 wd->size.h = wd->size.imh / wd->zoom;
1442 if (wd->gzoom.bounce.animator)
1444 ecore_animator_del(wd->gzoom.bounce.animator);
1445 wd->gzoom.bounce.animator = NULL;
1447 if (wd->zoom_animator)
1450 if (wd->nosmooth == 0) _smooth_update(obj);
1451 ecore_animator_del(wd->zoom_animator);
1452 wd->zoom_animator = NULL;
1454 evas_object_image_file_set(wd->img, NULL, NULL);
1455 evas_object_image_load_scale_down_set(wd->img, 8);
1456 evas_object_image_file_set(wd->img, wd->file, NULL);
1457 evas_object_image_preload(wd->img, 0);
1458 wd->main_load_pending = 1;
1459 if (wd->calc_job) ecore_job_del(wd->calc_job);
1460 wd->calc_job = ecore_job_add(_calc_job, wd);
1461 evas_object_smart_callback_call(obj, SIG_LOAD, NULL);
1463 if (wd->preload_num == 1)
1465 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
1466 "elm,state,busy,start", "elm");
1467 evas_object_smart_callback_call(obj, SIG_LOAD_DETAIL, NULL);
1470 double tz = wd->zoom;
1472 elm_photocam_zoom_set(wd->obj, tz);
1474 return evas_object_image_load_error_get(wd->img);
1478 elm_photocam_file_get(const Evas_Object *obj)
1480 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1481 Widget_Data *wd = elm_widget_data_get(obj);
1482 if (!wd) return NULL;
1487 elm_photocam_zoom_set(Evas_Object *obj, double zoom)
1489 ELM_CHECK_WIDTYPE(obj, widtype);
1490 Widget_Data *wd = elm_widget_data_get(obj);
1492 Grid *g, *g_zoom = NULL;
1493 Evas_Coord pw, ph, rx, ry, rw, rh;
1495 int zoom_changed = 0, started = 0;
1498 if (zoom <= (1.0 / 256.0)) zoom = (1.0 / 256.0);
1499 if (zoom == wd->zoom) return;
1501 wd->size.ow = wd->size.w;
1502 wd->size.oh = wd->size.h;
1503 elm_smart_scroller_child_pos_get(wd->scr, &rx, &ry);
1504 elm_smart_scroller_child_viewport_size_get(wd->scr, &rw, &rh);
1505 if ((rw <= 0) || (rh <= 0)) return;
1507 if (wd->mode == ELM_PHOTOCAM_ZOOM_MODE_MANUAL)
1509 wd->size.nw = (double)wd->size.imw / wd->zoom;
1510 wd->size.nh = (double)wd->size.imh / wd->zoom;
1512 else if (wd->mode == ELM_PHOTOCAM_ZOOM_MODE_AUTO_FIT)
1514 if ((wd->size.imw < 1) || (wd->size.imh < 1))
1521 ph = (wd->size.imh * rw) / wd->size.imw;
1524 pw = (wd->size.imw * rh) / wd->size.imh;
1531 if (wd->size.imw > wd->size.imh)
1532 z = (double)wd->size.imw / pw;
1534 z = (double)wd->size.imh / ph;
1542 else if (wd->mode == ELM_PHOTOCAM_ZOOM_MODE_AUTO_FILL)
1544 if ((wd->size.imw < 1) || (wd->size.imh < 1))
1551 ph = (wd->size.imh * rw) / wd->size.imw;
1554 pw = (wd->size.imw * rh) / wd->size.imh;
1561 if (wd->size.imw > wd->size.imh)
1562 z = (double)wd->size.imw / pw;
1564 z = (double)wd->size.imh / ph;
1572 else if (wd->mode == ELM_PHOTOCAM_ZOOM_MODE_AUTO_FIT_IN)
1574 if ((wd->size.imw < 1) || (wd->size.imh < 1))
1579 else if ((wd->size.imw < rw) && (wd->size.imh < rh))
1581 if (1 != wd->zoom) zoom_changed = 1;
1583 wd->size.nw = wd->size.imw;
1584 wd->size.nh = wd->size.imh;
1588 ph = (wd->size.imh * rw) / wd->size.imw;
1591 pw = (wd->size.imw * rh) / wd->size.imh;
1596 if (wd->size.imw > wd->size.imh)
1597 z = (double)wd->size.imw / pw;
1599 z = (double)wd->size.imh / ph;
1607 if (wd->main_load_pending)
1609 wd->size.w = wd->size.nw;
1610 wd->size.h = wd->size.nh;
1613 EINA_LIST_FOREACH(wd->grids, l, g)
1615 if (g->zoom == grid_zoom_calc(wd->zoom))
1617 wd->grids = eina_list_remove(wd->grids, g);
1618 wd->grids = eina_list_prepend(wd->grids, g);
1623 g = grid_create(obj);
1626 if (eina_list_count(wd->grids) > 1)
1628 g_zoom = eina_list_last(wd->grids)->data;
1629 wd->grids = eina_list_remove(wd->grids, g_zoom);
1630 grid_clear(obj, g_zoom);
1632 EINA_LIST_FOREACH(wd->grids, l, g_zoom)
1637 wd->grids = eina_list_prepend(wd->grids, g);
1641 EINA_LIST_FREE(wd->grids, g)
1648 wd->t_start = ecore_loop_time_get();
1649 wd->t_end = wd->t_start + _elm_config->zoom_friction;
1650 if ((wd->size.w > 0) && (wd->size.h > 0))
1652 wd->size.spos.x = (double)(rx + (rw / 2)) / (double)wd->size.w;
1653 wd->size.spos.y = (double)(ry + (rh / 2)) / (double)wd->size.h;
1657 wd->size.spos.x = 0.5;
1658 wd->size.spos.y = 0.5;
1660 if (rw > wd->size.w) wd->size.spos.x = 0.5;
1661 if (rh > wd->size.h) wd->size.spos.y = 0.5;
1662 if (wd->size.spos.x > 1.0) wd->size.spos.x = 1.0;
1663 if (wd->size.spos.y > 1.0) wd->size.spos.y = 1.0;
1670 if (!wd->zoom_animator)
1672 wd->zoom_animator = ecore_animator_add(_zoom_anim, obj);
1674 if (wd->nosmooth == 1) _smooth_update(obj);
1678 an = wd->zoom_animator;
1681 if (!_zoom_anim(obj))
1683 ecore_animator_del(an);
1687 if (wd->calc_job) ecore_job_del(wd->calc_job);
1688 wd->calc_job = ecore_job_add(_calc_job, wd);
1692 evas_object_smart_callback_call(obj, SIG_ZOOM_START, NULL);
1694 evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL);
1697 evas_object_smart_callback_call(obj, SIG_ZOOM_CHANGE, NULL);
1701 elm_photocam_zoom_get(const Evas_Object *obj)
1703 ELM_CHECK_WIDTYPE(obj, widtype) 1.0;
1704 Widget_Data *wd = elm_widget_data_get(obj);
1705 if (!wd) return 1.0;
1710 elm_photocam_zoom_mode_set(Evas_Object *obj, Elm_Photocam_Zoom_Mode mode)
1712 ELM_CHECK_WIDTYPE(obj, widtype);
1713 Widget_Data *wd = elm_widget_data_get(obj);
1715 if (wd->mode == mode) return;
1718 double tz = wd->zoom;
1720 elm_photocam_zoom_set(wd->obj, tz);
1724 EAPI Elm_Photocam_Zoom_Mode
1725 elm_photocam_zoom_mode_get(const Evas_Object *obj)
1727 ELM_CHECK_WIDTYPE(obj, widtype) ELM_PHOTOCAM_ZOOM_MODE_LAST;
1728 Widget_Data *wd = elm_widget_data_get(obj);
1729 if (!wd) return ELM_PHOTOCAM_ZOOM_MODE_LAST;
1734 elm_photocam_image_size_get(const Evas_Object *obj, int *w, int *h)
1736 ELM_CHECK_WIDTYPE(obj, widtype);
1737 Widget_Data *wd = elm_widget_data_get(obj);
1739 if (w) *w = wd->size.imw;
1740 if (h) *h = wd->size.imh;
1743 EINA_DEPRECATED EAPI void
1744 elm_photocam_region_get(const Evas_Object *obj, int *x, int *y, int *w, int *h)
1746 return elm_photocam_image_region_get(obj, x, y, w, h);
1750 elm_photocam_image_region_get(const Evas_Object *obj, int *x, int *y, int *w, int *h)
1752 ELM_CHECK_WIDTYPE(obj, widtype);
1753 Widget_Data *wd = elm_widget_data_get(obj);
1754 Evas_Coord sx, sy, sw, sh;
1756 elm_smart_scroller_child_pos_get(wd->scr, &sx, &sy);
1757 elm_smart_scroller_child_viewport_size_get(wd->scr, &sw, &sh);
1762 *x = (wd->size.imw * sx) / wd->size.w;
1763 if (*x > wd->size.imw) *x = wd->size.imw;
1767 *w = (wd->size.imw * sw) / wd->size.w;
1768 if (*w > wd->size.imw) *w = wd->size.imw;
1769 else if (*w < 0) *w = 0;
1782 *y = (wd->size.imh * sy) / wd->size.h;
1783 if (*y > wd->size.imh) *y = wd->size.imh;
1787 *h = (wd->size.imh * sh) / wd->size.h;
1788 if (*h > wd->size.imh) *h = wd->size.imh;
1789 else if (*h < 0) *h = 0;
1800 elm_photocam_image_region_show(Evas_Object *obj, int x, int y, int w, int h __UNUSED__)
1802 ELM_CHECK_WIDTYPE(obj, widtype);
1803 Widget_Data *wd = elm_widget_data_get(obj);
1806 if ((wd->size.imw < 1) || (wd->size.imh < 1)) return;
1807 rx = (x * wd->size.w) / wd->size.imw;
1808 ry = (y * wd->size.h) / wd->size.imh;
1809 rw = (w * wd->size.w) / wd->size.imw;
1810 rh = (h * wd->size.h) / wd->size.imh;
1813 if ((rx + rw) > wd->size.w) rx = wd->size.w - rw;
1814 if ((ry + rh) > wd->size.h) ry = wd->size.h - rh;
1815 if (wd->gzoom.bounce.animator)
1817 ecore_animator_del(wd->gzoom.bounce.animator);
1818 wd->gzoom.bounce.animator = NULL;
1821 if (wd->zoom_animator)
1824 ecore_animator_del(wd->zoom_animator);
1825 wd->zoom_animator = NULL;
1827 evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL);
1829 elm_smart_scroller_child_region_show(wd->scr, rx, ry, rw, rh);
1833 elm_photocam_image_region_bring_in(Evas_Object *obj, int x, int y, int w, int h __UNUSED__)
1835 ELM_CHECK_WIDTYPE(obj, widtype);
1836 Widget_Data *wd = elm_widget_data_get(obj);
1839 if ((wd->size.imw < 1) || (wd->size.imh < 1)) return;
1840 rx = (x * wd->size.w) / wd->size.imw;
1841 ry = (y * wd->size.h) / wd->size.imh;
1842 rw = (w * wd->size.w) / wd->size.imw;
1843 rh = (h * wd->size.h) / wd->size.imh;
1846 if ((rx + rw) > wd->size.w) rx = wd->size.w - rw;
1847 if ((ry + rh) > wd->size.h) ry = wd->size.h - rh;
1848 if (wd->gzoom.bounce.animator)
1850 ecore_animator_del(wd->gzoom.bounce.animator);
1851 wd->gzoom.bounce.animator = NULL;
1854 if (wd->zoom_animator)
1857 if (!wd->nosmooth) _smooth_update(obj);
1858 ecore_animator_del(wd->zoom_animator);
1859 wd->zoom_animator = NULL;
1861 evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL);
1863 elm_smart_scroller_region_bring_in(wd->scr, rx, ry, rw, rh);
1867 elm_photocam_paused_set(Evas_Object *obj, Eina_Bool paused)
1869 ELM_CHECK_WIDTYPE(obj, widtype);
1870 Widget_Data *wd = elm_widget_data_get(obj);
1872 if (wd->paused == !!paused) return;
1873 wd->paused = paused;
1876 if (wd->gzoom.bounce.animator)
1878 ecore_animator_del(wd->gzoom.bounce.animator);
1879 wd->gzoom.bounce.animator = NULL;
1882 if (wd->zoom_animator)
1884 ecore_animator_del(wd->zoom_animator);
1885 wd->zoom_animator = NULL;
1887 evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL);
1893 elm_photocam_paused_get(const Evas_Object *obj)
1895 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1896 Widget_Data *wd = elm_widget_data_get(obj);
1897 if (!wd) return EINA_FALSE;
1902 elm_photocam_internal_image_get(const Evas_Object *obj)
1904 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1905 Widget_Data *wd = elm_widget_data_get(obj);
1906 if (!wd) return NULL;
1911 elm_photocam_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce)
1913 ELM_CHECK_WIDTYPE(obj, widtype);
1914 Widget_Data *wd = elm_widget_data_get(obj);
1916 elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce);
1920 elm_photocam_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce)
1922 ELM_CHECK_WIDTYPE(obj, widtype);
1923 Widget_Data *wd = elm_widget_data_get(obj);
1925 elm_smart_scroller_bounce_allow_get(wd->scr, h_bounce, v_bounce);
1929 elm_photocam_gesture_enabled_set(Evas_Object *obj, Eina_Bool gesture)
1931 ELM_CHECK_WIDTYPE(obj, widtype);
1932 Widget_Data *wd = elm_widget_data_get(obj);
1934 if (wd->do_gesture == !!gesture) return;
1938 evas_object_del(wd->gest);
1944 wd->gest = elm_gesture_layer_add(wd->obj);
1945 if (!wd->gest) return;
1946 elm_gesture_layer_attach(wd->gest, wd->obj);
1947 elm_gesture_layer_cb_set(wd->gest, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_START,
1949 elm_gesture_layer_cb_set(wd->gest, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_MOVE,
1951 elm_gesture_layer_cb_set(wd->gest, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_END,
1953 elm_gesture_layer_cb_set(wd->gest, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_ABORT,
1957 wd->do_gesture = !!gesture;
1961 elm_photocam_gesture_enabled_get(const Evas_Object *obj)
1963 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1964 Widget_Data *wd = elm_widget_data_get(obj);
1965 if (!wd) return EINA_FALSE;
1967 return wd->do_gesture;