Evas_Object *obj;
Evas_Object *scr;
Evas_Object *pan_smart;
+ Evas_Object *gest;
+ double gest_start;
+
Pan *pan;
Evas_Coord pan_x, pan_y, minw, minh;
double zoom;
Elm_Photocam_Zoom_Mode mode;
+ Evas_Coord pvx, pvy, px, py, zoom_point_x, zoom_point_y;
+ struct
+ {
+ int imx, imy;
+ struct
+ {
+ int x_start, y_start;
+ int x_end, y_end;
+ double t_start;
+ double t_end;
+ Ecore_Animator *animator;
+ } bounce;
+ } gzoom;
const char *file;
Ecore_Job *calc_job;
Eina_Bool longpressed : 1;
Eina_Bool on_hold : 1;
Eina_Bool paused : 1;
+ Eina_Bool do_region : 1;
+ Eina_Bool do_gesture : 1;
+ Eina_Bool zoom_gest : 1;
};
struct _Pan
ay = 0;
gw = wd->size.w;
gh = wd->size.h;
- if (ow > gw) ax = (ow - gw) / 2;
- if (oh > gh) ay = (oh - gh) / 2;
+ if (!wd->zoom_gest)
+ {
+ if (ow > gw) ax = (ow - gw) / 2;
+ if (oh > gh) ay = (oh - gh) / 2;
+ }
evas_object_move(wd->img, ox + 0 - px + ax, oy + 0 - py + ay);
evas_object_resize(wd->img, gw, gh);
ay = 0;
gw = wd->size.w;
gh = wd->size.h;
- if (ow > gw) ax = (ow - gw) / 2;
- if (oh > gh) ay = (oh - gh) / 2;
+ if (!wd->zoom_gest)
+ {
+ if (ow > gw) ax = (ow - gw) / 2;
+ if (oh > gh) ay = (oh - gh) / 2;
+ }
for (y = 0; y < g->gh; y++)
{
for (x = 0; x < g->gw; x++)
if (!wd) return NULL;
g = calloc(1, sizeof(Grid));
- if (!g) return;
+ if (!g) return NULL;
g->zoom = grid_zoom_calc(wd->zoom);
g->tsize = wd->tsize;
free(g);
return NULL;
}
- g->gw = (g->w + g->tsize - 1) / g->tsize;
- g->gh = (g->h + g->tsize - 1) / g->tsize;
+ if (wd->do_region)
+ {
+ g->gw = (g->w + g->tsize - 1) / g->tsize;
+ g->gh = (g->h + g->tsize - 1) / g->tsize;
+ }
+ else
+ {
+ g->gw = 1;
+ g->gh = 1;
+ }
g->grid = calloc(1, sizeof(Grid_Item) * g->gw * g->gh);
if (!g->grid)
{
if (wd->calc_job) ecore_job_del(wd->calc_job);
if (wd->scr_timer) ecore_timer_del(wd->scr_timer);
if (wd->zoom_animator) ecore_animator_del(wd->zoom_animator);
+ if (wd->gzoom.bounce.animator) ecore_animator_del(wd->gzoom.bounce.animator);
if (wd->long_timer) ecore_timer_del(wd->long_timer);
free(wd);
}
Grid *g;
if (!sd) return;
evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
- img_place(sd->wd->obj, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh);
+ img_place(sd->wd->obj, sd->wd->pan_x, sd->wd->pan_y,
+ ox - sd->wd->gzoom.imx, oy - sd->wd->gzoom.imy, ow, oh);
EINA_LIST_FOREACH(sd->wd->grids, l, g)
{
grid_load(sd->wd->obj, g);
- grid_place(sd->wd->obj, g, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh);
+ grid_place(sd->wd->obj, g, sd->wd->pan_x, sd->wd->pan_y,
+ ox - sd->wd->gzoom.imx, oy - sd->wd->gzoom.imy, ow, oh);
}
}
elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h);
if ((!strcmp(ev->keyname, "Left")) ||
- (!strcmp(ev->keyname, "KP_Left")))
+ ((!strcmp(ev->keyname, "KP_Left")) && (!ev->string)))
{
x -= step_x;
}
else if ((!strcmp(ev->keyname, "Right")) ||
- (!strcmp(ev->keyname, "KP_Right")))
+ ((!strcmp(ev->keyname, "KP_Right")) && (!ev->string)))
{
x += step_x;
}
else if ((!strcmp(ev->keyname, "Up")) ||
- (!strcmp(ev->keyname, "KP_Up")))
+ ((!strcmp(ev->keyname, "KP_Up")) && (!ev->string)))
{
y -= step_y;
}
else if ((!strcmp(ev->keyname, "Down")) ||
- (!strcmp(ev->keyname, "KP_Down")))
+ ((!strcmp(ev->keyname, "KP_Down")) && (!ev->string)))
{
y += step_y;
}
else if ((!strcmp(ev->keyname, "Prior")) ||
- (!strcmp(ev->keyname, "KP_Prior")))
+ ((!strcmp(ev->keyname, "KP_Prior")) && (!ev->string)))
{
if (page_y < 0)
y -= -(page_y * v_h) / 100;
y -= page_y;
}
else if ((!strcmp(ev->keyname, "Next")) ||
- (!strcmp(ev->keyname, "KP_Next")))
+ ((!strcmp(ev->keyname, "KP_Next")) && (!ev->string)))
{
if (page_y < 0)
y += -(page_y * v_h) / 100;
return EINA_TRUE;
}
+Eina_Bool
+_bounce_eval(void *_wd)
+{
+ Widget_Data *wd = (Widget_Data *)_wd;
+ double t, tt;
+
+ if (!wd) return ECORE_CALLBACK_CANCEL;
+ if ((wd->gzoom.imx == wd->gzoom.bounce.x_end) &&
+ (wd->gzoom.imy == wd->gzoom.bounce.y_end))
+ {
+ wd->gzoom.imx = 0;
+ wd->gzoom.imy = 0;
+ wd->zoom_gest = EINA_FALSE;
+ wd->gzoom.bounce.animator = NULL;
+ _freeze_off(NULL, wd->obj, NULL);
+ return ECORE_CALLBACK_CANCEL;
+ }
+
+ t = ecore_loop_time_get();
+ tt = (t - wd->gzoom.bounce.t_start) / (wd->gzoom.bounce.t_end - wd->gzoom.bounce.t_start);
+ tt = 1.0 - tt;
+ tt = 1.0 - (tt * tt);
+
+ if (t > wd->gzoom.bounce.t_end)
+ {
+ wd->gzoom.imx = 0;
+ wd->gzoom.imy = 0;
+ wd->zoom_gest = EINA_FALSE;
+ _freeze_off(NULL, wd->obj, NULL);
+ zoom_do(wd->obj, 1.0);
+ wd->gzoom.bounce.animator = NULL;
+ return ECORE_CALLBACK_CANCEL;
+ }
+
+ if (wd->gzoom.imx != wd->gzoom.bounce.x_end)
+ wd->gzoom.imx = wd->gzoom.bounce.x_start * (1.0 - tt) + wd->gzoom.bounce.x_end * tt;
+
+ if (wd->gzoom.imy != wd->gzoom.bounce.y_end)
+ wd->gzoom.imy = wd->gzoom.bounce.y_start * (1.0 - tt) + wd->gzoom.bounce.y_end * tt;
+
+ zoom_do(wd->obj, 1.0 - (1.0 - tt));
+ return ECORE_CALLBACK_RENEW;
+}
+
+static void
+_gzoom(Widget_Data *_wd, Evas_Coord px, Evas_Coord py, Elm_Gesture_Zoom_Info* gest)
+{
+ Widget_Data *wd = (Widget_Data *)_wd;
+ Evas_Coord rx, ry, rw, rh;
+ int regx, regy, regw, regh, ix, iy, iw, ih;
+ int xx, yy;
+
+ if (!wd) return;
+ wd->mode = ELM_PHOTOCAM_ZOOM_MODE_MANUAL;
+ wd->zoom = wd->gest_start / gest->zoom;
+ wd->size.ow = wd->size.w;
+ wd->size.oh = wd->size.h;
+ elm_smart_scroller_child_pos_get(wd->scr, &rx, &ry);
+ elm_smart_scroller_child_viewport_size_get(wd->scr, &rw, &rh);
+ if ((rw <= 0) || (rh <= 0)) return;
+
+ wd->size.nw = (double)wd->size.imw / wd->zoom;
+ wd->size.nh = (double)wd->size.imh / wd->zoom;
+
+ elm_photocam_image_region_get(wd->obj, ®x, ®y, ®w, ®h);
+ evas_object_geometry_get(wd->img, &ix, &iy, &iw, &ih);
+
+ wd->pvx = gest->x;
+ wd->pvy = gest->y;
+
+ xx = (px / wd->zoom) - wd->pvx;
+ yy = (py / wd->zoom) - wd->pvy;
+ wd->gzoom.imx = 0;
+ wd->gzoom.imy = 0;
+
+ if ((xx < 0) || (rw > wd->size.nw))
+ {
+ wd->gzoom.imx = xx;
+ xx = 0;
+ }
+ else if ((xx + rw) > wd->size.nw)
+ {
+ wd->gzoom.imx = xx + rw - wd->size.nw;
+ xx = wd->size.nw - rw;
+ }
+
+ if ((yy < 0) || (rh > wd->size.nh))
+ {
+ wd->gzoom.imy = yy;
+ yy = 0;
+ }
+ else if ((yy + rh) > wd->size.nh)
+ {
+ wd->gzoom.imy = yy + rh - wd->size.nh;
+ yy = wd->size.nh - rh;
+ }
+
+ wd->size.spos.x = (double)(xx + (rw / 2)) / (double)(wd->size.nw);
+ wd->size.spos.y = (double)(yy + (rh / 2)) / (double)(wd->size.nh);
+
+ zoom_do(wd->obj, 1.0);
+}
+
+static Evas_Event_Flags
+_gzoom_start(void *_wd, void *event_info)
+{
+ Widget_Data *wd = (Widget_Data *)_wd;
+ Elm_Gesture_Zoom_Info *p = (Elm_Gesture_Zoom_Info *) event_info;
+ Evas_Coord rw, rh;
+ int x,y,w,h;
+ double marginx = 0, marginy = 0;
+
+ if (wd->gzoom.bounce.animator)
+ {
+ ecore_animator_del(wd->gzoom.bounce.animator);
+ wd->gzoom.bounce.animator = NULL;
+ }
+ wd->zoom_gest = EINA_TRUE;
+ _freeze_on(NULL, wd->obj, NULL);
+
+ elm_photocam_image_region_get(wd->obj, &x, &y, &w, &h);
+ elm_smart_scroller_child_viewport_size_get(wd->scr, &rw, &rh);
+
+ if (rw > wd->size.nw)
+ marginx = (rw - wd->size.nw) / 2;
+ if (rh > wd->size.nh)
+ marginy = (rh - wd->size.nh) / 2;
+
+ wd->gest_start = wd->zoom;
+
+ wd->zoom_point_x = x + ((p->x - marginx) * wd->zoom) + wd->gzoom.imx;
+ wd->zoom_point_y = y + ((p->y - marginy) * wd->zoom) + wd->gzoom.imy;
+
+ return EVAS_EVENT_FLAG_NONE;
+}
+
+static Evas_Event_Flags
+_gzoom_move(void *_wd, void *event_info)
+{
+ Widget_Data *wd = (Widget_Data *)_wd;
+ Elm_Gesture_Zoom_Info *p = (Elm_Gesture_Zoom_Info *) event_info;
+
+ _gzoom(wd, wd->zoom_point_x, wd->zoom_point_y, p);
+ return EVAS_EVENT_FLAG_NONE;
+}
+
+static Evas_Event_Flags
+_gzoom_end(void *_wd, void *event_info __UNUSED__)
+{
+ Widget_Data *wd = (Widget_Data *)_wd;
+ Evas_Coord rw, rh;
+
+ elm_smart_scroller_child_viewport_size_get(wd->scr, &rw, &rh);
+ wd->gest_start = 1.0;
+
+ if (wd->gzoom.imx || wd->gzoom.imy)
+ {
+ double t;
+
+ t = ecore_loop_time_get();
+ wd->gzoom.bounce.x_start = wd->gzoom.imx;
+ wd->gzoom.bounce.y_start = wd->gzoom.imy;
+ wd->gzoom.bounce.x_end = 0;
+ wd->gzoom.bounce.y_end = 0;
+
+ if (rw > wd->size.nw &&
+ rh > wd->size.nh)
+ {
+ Evas_Coord pw, ph;
+ double z;
+
+ if ((wd->size.imw < rw) && (wd->size.imh < rh))
+ {
+ wd->zoom = 1;
+ wd->size.nw = wd->size.imw;
+ wd->size.nh = wd->size.imh;
+ }
+ else
+ {
+ ph = (wd->size.imh * rw) / wd->size.imw;
+ if (ph > rh)
+ {
+ pw = (wd->size.imw * rh) / wd->size.imh;
+ ph = rh;
+ }
+ else
+ {
+ pw = rw;
+ }
+ if (wd->size.imw > wd->size.imh)
+ z = (double)wd->size.imw / pw;
+ else
+ z = (double)wd->size.imh / ph;
+
+ wd->zoom = z;
+ wd->size.nw = pw;
+ wd->size.nh = ph;
+ }
+ wd->gzoom.bounce.x_end = (wd->size.nw - rw) / 2;
+ wd->gzoom.bounce.y_end = (wd->size.nh - rh) / 2;
+ }
+ else
+ {
+ int xx, yy;
+
+ xx = (wd->zoom_point_x / wd->zoom) - wd->pvx;
+ yy = (wd->zoom_point_y / wd->zoom) - wd->pvy;
+
+ if (xx < 0) xx = 0;
+ if (yy < 0) yy = 0;
+
+ if (rw > wd->size.nw)
+ wd->gzoom.bounce.x_end = (wd->size.nw -rw) / 2;
+ if ((xx + rw) > wd->size.nw)
+ xx = wd->size.nw - rw;
+
+ if (rh > wd->size.nh)
+ wd->gzoom.bounce.y_end = (wd->size.nh - rh) / 2;
+ if ((yy + rh) > wd->size.nh)
+ yy = wd->size.nh - rh;
+
+ wd->size.spos.x = (double)(xx + (rw / 2)) / (double)(wd->size.nw);
+ wd->size.spos.y = (double)(yy + (rh / 2)) / (double)(wd->size.nh);
+ }
+
+ wd->gzoom.bounce.t_start = t;
+ wd->gzoom.bounce.t_end = t + _elm_config->page_scroll_friction;
+
+ wd->gzoom.bounce.animator = ecore_animator_add(_bounce_eval, wd);
+ }
+ else
+ {
+ _freeze_off(NULL, wd->obj, NULL);
+ wd->zoom_gest = EINA_FALSE;
+ }
+
+ return EVAS_EVENT_FLAG_NONE;
+}
+
EAPI Evas_Object *
elm_photocam_add(Evas_Object *parent)
{
_pan_set, _pan_get, _pan_max_get,
_pan_min_get, _pan_child_size_get);
+ wd->zoom_gest = EINA_FALSE;
+ wd->gest_start = 1.0;
wd->zoom = 1;
wd->mode = ELM_PHOTOCAM_ZOOM_MODE_MANUAL;
-
wd->tsize = 512;
wd->img = evas_object_image_add(e);
evas_object_image_load_scale_down_set(wd->img, 0);
evas_object_image_file_set(wd->img, wd->file, NULL);
evas_object_image_size_get(wd->img, &w, &h);
+ wd->do_region = evas_object_image_region_support_get(wd->img);
wd->size.imw = w;
wd->size.imh = h;
wd->size.w = wd->size.imw / wd->zoom;
wd->size.h = wd->size.imh / wd->zoom;
+ if (wd->gzoom.bounce.animator)
+ {
+ ecore_animator_del(wd->gzoom.bounce.animator);
+ wd->gzoom.bounce.animator = NULL;
+ }
if (wd->zoom_animator)
{
wd->nosmooth--;
"elm,state,busy,start", "elm");
evas_object_smart_callback_call(obj, SIG_LOAD_DETAIL, NULL);
}
- {
- double tz = wd->zoom;
- wd->zoom = 0.0;
- elm_photocam_zoom_set(wd->obj, tz);
- }
+ {
+ double tz = wd->zoom;
+ wd->zoom = 0.0;
+ elm_photocam_zoom_set(wd->obj, tz);
+ }
return evas_object_image_load_error_get(wd->img);
}
Eina_List *l;
Grid *g, *g_zoom = NULL;
Evas_Coord pw, ph, rx, ry, rw, rh;
- int z;
+ double z;
int zoom_changed = 0, started = 0;
Ecore_Animator *an;
if (!wd) return;
pw = rw;
}
if (wd->size.imw > wd->size.imh)
- z = wd->size.imw / pw;
+ z = (double)wd->size.imw / pw;
else
- z = wd->size.imh / ph;
- if (z >= 8) z = 8;
- else if (z >= 4) z = 4;
- else if (z >= 2) z = 2;
- else z = 1;
- if (z != wd->zoom) zoom_changed = 1;
+ z = (double)wd->size.imh / ph;
+ if (z != wd->zoom)
+ zoom_changed = 1;
wd->zoom = z;
wd->size.nw = pw;
wd->size.nh = ph;
pw = rw;
}
if (wd->size.imw > wd->size.imh)
- z = wd->size.imw / pw;
+ z = (double)wd->size.imw / pw;
else
- z = wd->size.imh / ph;
- if (z >= 8) z = 8;
- else if (z >= 4) z = 4;
- else if (z >= 2) z = 2;
- else z = 1;
- if (z != wd->zoom) zoom_changed = 1;
+ z = (double)wd->size.imh / ph;
+ if (z != wd->zoom)
+ zoom_changed = 1;
+ wd->zoom = z;
+ wd->size.nw = pw;
+ wd->size.nh = ph;
+ }
+ }
+ else if (wd->mode == ELM_PHOTOCAM_ZOOM_MODE_AUTO_FIT_IN)
+ {
+ if ((wd->size.imw < 1) || (wd->size.imh < 1))
+ {
+ wd->size.nw = 0;
+ wd->size.nh = 0;
+ }
+ else if ((wd->size.imw < rw) && (wd->size.imh < rh))
+ {
+ if (1 != wd->zoom) zoom_changed = 1;
+ wd->zoom = 1;
+ wd->size.nw = wd->size.imw;
+ wd->size.nh = wd->size.imh;
+ }
+ else
+ {
+ ph = (wd->size.imh * rw) / wd->size.imw;
+ if (ph > rh)
+ {
+ pw = (wd->size.imw * rh) / wd->size.imh;
+ ph = rh;
+ }
+ else
+ pw = rw;
+ if (wd->size.imw > wd->size.imh)
+ z = (double)wd->size.imw / pw;
+ else
+ z = (double)wd->size.imh / ph;
+ if (z != wd->zoom)
+ zoom_changed = 1;
wd->zoom = z;
wd->size.nw = pw;
wd->size.nh = ph;
free(g);
}
}
-done:
+ done:
wd->t_start = ecore_loop_time_get();
wd->t_end = wd->t_start + _elm_config->zoom_friction;
if ((wd->size.w > 0) && (wd->size.h > 0))
if (!wd) return;
if (wd->mode == mode) return;
wd->mode = mode;
- {
- double tz = wd->zoom;
- wd->zoom = 0.0;
- elm_photocam_zoom_set(wd->obj, tz);
- }
+ {
+ double tz = wd->zoom;
+ wd->zoom = 0.0;
+ elm_photocam_zoom_set(wd->obj, tz);
+ }
}
EAPI Elm_Photocam_Zoom_Mode
}
EAPI void
-elm_photocam_region_get(const Evas_Object *obj, int *x, int *y, int *w, int *h)
+elm_photocam_image_region_get(const Evas_Object *obj, int *x, int *y, int *w, int *h)
{
ELM_CHECK_WIDTYPE(obj, widtype);
Widget_Data *wd = elm_widget_data_get(obj);
{
*x = (wd->size.imw * sx) / wd->size.w;
if (*x > wd->size.imw) *x = wd->size.imw;
- else if (*x < 0) *x = 0;
}
if (w)
{
{
*y = (wd->size.imh * sy) / wd->size.h;
if (*y > wd->size.imh) *y = wd->size.imh;
- else if (*y < 0) *y = 0;
}
if (h)
{
if (rh < 1) rh = 1;
if ((rx + rw) > wd->size.w) rx = wd->size.w - rw;
if ((ry + rh) > wd->size.h) ry = wd->size.h - rh;
+ if (wd->gzoom.bounce.animator)
+ {
+ ecore_animator_del(wd->gzoom.bounce.animator);
+ wd->gzoom.bounce.animator = NULL;
+ zoom_do(obj, 1.0);
+ }
if (wd->zoom_animator)
{
wd->nosmooth--;
if (rh < 1) rh = 1;
if ((rx + rw) > wd->size.w) rx = wd->size.w - rw;
if ((ry + rh) > wd->size.h) ry = wd->size.h - rh;
+ if (wd->gzoom.bounce.animator)
+ {
+ ecore_animator_del(wd->gzoom.bounce.animator);
+ wd->gzoom.bounce.animator = NULL;
+ zoom_do(obj, 1.0);
+ }
if (wd->zoom_animator)
{
wd->nosmooth--;
wd->paused = paused;
if (wd->paused)
{
+ if (wd->gzoom.bounce.animator)
+ {
+ ecore_animator_del(wd->gzoom.bounce.animator);
+ wd->gzoom.bounce.animator = NULL;
+ zoom_do(obj, 1.0);
+ }
if (wd->zoom_animator)
{
ecore_animator_del(wd->zoom_animator);
elm_smart_scroller_bounce_allow_get(wd->scr, h_bounce, v_bounce);
}
+EAPI void
+elm_photocam_gesture_enabled_set(Evas_Object *obj, Eina_Bool gesture)
+{
+ ELM_CHECK_WIDTYPE(obj, widtype);
+ Widget_Data *wd = elm_widget_data_get(obj);
+ if (!wd) return;
+ if (wd->do_gesture == !!gesture) return;
+
+ if (wd->gest)
+ {
+ evas_object_del(wd->gest);
+ wd->gest = NULL;
+ }
+
+ if (gesture)
+ {
+ wd->gest = elm_gesture_layer_add(wd->obj);
+ if (!wd->gest) return;
+ elm_gesture_layer_attach(wd->gest, wd->obj);
+ elm_gesture_layer_cb_set(wd->gest, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_START,
+ _gzoom_start, wd);
+ elm_gesture_layer_cb_set(wd->gest, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_MOVE,
+ _gzoom_move, wd);
+ elm_gesture_layer_cb_set(wd->gest, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_END,
+ _gzoom_end, wd);
+ elm_gesture_layer_cb_set(wd->gest, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_ABORT,
+ _gzoom_end, wd);
+ }
+
+ wd->do_gesture = !!gesture;
+}
+
+EAPI Eina_Bool
+elm_photocam_gesture_enabled_get(const Evas_Object *obj)
+{
+ ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
+ Widget_Data *wd = elm_widget_data_get(obj);
+ if (!wd) return EINA_FALSE;
+
+ return wd->do_gesture;
+}