Dear all,
This is a patch for elm_map pinch zoom.
you can zoom in/out using two fingers.
- add event handler for multi touch.
Index: src/lib/elm_map.c
===================================================================
--- src/lib/elm_map.c (리비전 55695)
+++ src/lib/elm_map.c (작업 사본)
@@ -67,6 +67,7 @@ typedef struct _Map_Sources_Tab
} Map_Sources_Tab;
#define ZOOM_MAX 18
+#define TOUCH_HOLD_RANGE 40
//Zemm min is supposed to be 0
static char * _mapnik_url_cb(void *data ,int x, int y, int zoom);
static char * _osmarender_url_cb(void *data ,int x, int y, int zoom);
@@ -229,6 +230,7 @@ struct _Widget_Data
Eina_Bool on_hold : 1;
Eina_Bool paused : 1;
Eina_Bool paused_markers : 1;
+ Eina_Bool pinch_zoom : 1;
struct {
Eina_Bool enabled;
@@ -264,6 +266,24 @@ struct _Pan
Widget_Data *wd;
};
+struct event_t
+{
+ int device;
+
+ struct prev {
+ Evas_Coord x, y;
+ } prev;
+
+ Evas_Coord x, y, w, h;
+
+ Evas_Object *object;
+ Ecore_Timer *hold_timer;
+
+ int pinch_dis;
+};
+static int dis_old = 0;
+static Eina_List *s_event_list;
+
static const char *widtype = NULL;
static const char SIG_CHANGED[] = "changed";
@@ -298,6 +318,8 @@ static const Evas_Smart_Cb_Description _signals[]
static void _pan_calculate(Evas_Object *obj);
+static Eina_Bool _hold_timer_cb(void *data);
+static void _rect_resize_cb(void *data, Evas *e, Evas_Object *obj, void
*event_info);
static void _del_hook(Evas_Object *obj);
static void _theme_hook(Evas_Object *obj);
static void _on_focus_hook(void *data, Evas_Object *obj);
@@ -308,7 +330,6 @@ static void grid_clear(Evas_Object *obj, Grid *g);
static Grid *grid_create(Evas_Object *obj);
static void grid_load(Evas_Object *obj, Grid *g);
-
static void _group_object_create(Marker_Group *group);
static void _group_object_free(Marker_Group *group);
static void _group_open_cb(void *data, Evas_Object *obj, const char *emission,
const char *soure);
@@ -322,6 +343,89 @@ static void _group_bubble_content_free(Marker_Grou
static void marker_place(Evas_Object *obj, Grid *g, Evas_Coord px, Evas_Coord
py, Evas_Coord ox, Evas_Coord oy, Evas_Coord ow, Evas_Coord oh);
static void _bubble_sc_hits_changed_cb(void *data, Evas *e, Evas_Object *obj,
void *event_info);
+static void _mouse_down(void *data, Evas *evas, Evas_Object *obj, void
*event_info);
+static void _mouse_up(void *data, Evas *evas, Evas_Object *obj, void
*event_info);
+static void _mouse_move(void *data, Evas *evas, Evas_Object *obj, void
*event_info);
+
+static void _mouse_multi_down(void *data, Evas *evas, Evas_Object *obj, void
*event_info);
+static void _mouse_multi_up(void *data, Evas *evas, Evas_Object *obj, void
*event_info);
+static void _mouse_multi_move(void *data, Evas *evas, Evas_Object *obj, void
*event_info);
+
+static int
+get_multi_device(void)
+{
+ Eina_List *l;
+ struct event_t *ev = NULL;
+
+ EINA_LIST_FOREACH(s_event_list, l, ev)
+ {
+ if (ev->device) return ev->device;
+ }
+
+ return 0;
+}
+
+static int
+get_distance(Evas_Coord x1, Evas_Coord y1, Evas_Coord x2, Evas_Coord y2)
+{
+ int dis, dx, dy;
+
+ dx = x1 - x2;
+ dy = y1 - y2;
+
+ dis = (int)sqrt(dx * dx + dy * dy);
+ return dis;
+}
+
+static struct event_t*
+get_event_object(int device)
+{
+ Eina_List *l;
+ struct event_t *ev = NULL;
+
+ EINA_LIST_FOREACH(s_event_list, l, ev)
+ {
+ if (ev->device == device) break;
+ ev = NULL;
+ }
+ return ev;
+}
+
+static struct event_t *
+create_event_object(Evas_Object *object, int device)
+{
+ struct event_t *ev;
+
+ ev = calloc(1, sizeof(struct event_t));
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ev, NULL);
+
+ ev->object = object;
+ ev->device = device;
+
+ evas_object_geometry_get(object, &ev->x, &ev->y, &ev->w, &ev->h);
+
+ s_event_list = eina_list_append(s_event_list, ev);
+
+ return ev;
+}
+
+static void
+destroy_event_object(struct event_t *ev)
+{
+ EINA_SAFETY_ON_NULL_RETURN(ev);
+
+ ev->pinch_dis = 0;
+
+ s_event_list = eina_list_remove(s_event_list, ev);
+
+ if (ev->hold_timer)
+ {
+ ecore_timer_del(ev->hold_timer);
+ ev->hold_timer = NULL;
+ }
+ free(ev);
+}
+
static Mod_Api *
module(Evas_Object *obj __UNUSED__)
{
@@ -859,6 +963,7 @@ grid_load(Evas_Object *obj, Grid *g)
snprintf(buf2, sizeof(buf2), DEST_FILE_PATH, buf, y);
source = map_sources_tab[wd->source].url_cb(obj, x, y,
g->zoom);
+ if (strlen(source)==0) continue;
eina_stringshare_replace(&gi->file, buf2);
@@ -1059,28 +1164,81 @@ _long_press(void *data)
}
static void
-_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__,
void *event_info)
+_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void
*event_info)
{
Widget_Data *wd = elm_widget_data_get(data);
Evas_Event_Mouse_Down *ev = event_info;
+ struct event_t *ev0;
+
+ ev0 = get_event_object(0);
+ if (ev0) return;
+ ev0 = create_event_object(obj, 0);
+ if (!ev0) return;
+
+ ev0->hold_timer = NULL;
+ ev0->prev.x = ev->output.x;
+ ev0->prev.y = ev->output.y;
+
if (!wd) return;
if (ev->button != 1) return;
if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) wd->on_hold = EINA_TRUE;
else wd->on_hold = EINA_FALSE;
if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
- evas_object_smart_callback_call(data, SIG_CLICKED_DOUBLE, NULL);
+ evas_object_smart_callback_call(data, SIG_CLICKED_DOUBLE, ev);
else
- evas_object_smart_callback_call(data, SIG_PRESS, NULL);
+ evas_object_smart_callback_call(data, SIG_PRESS, ev);
wd->longpressed = EINA_FALSE;
if (wd->long_timer) ecore_timer_del(wd->long_timer);
wd->long_timer = ecore_timer_add(_elm_config->longpress_timeout,
_long_press, data);
}
static void
+_mouse_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__,
void *event_info)
+{
+ Widget_Data *wd = elm_widget_data_get(data);
+ Evas_Event_Mouse_Move *move = (Evas_Event_Mouse_Move *)event_info;
+ struct event_t *ev0;
+ if (wd->pinch_zoom) return;
+ ev0 = get_event_object(0);
+ if (!ev0) return;
+
+ ev0->prev.x = move->cur.output.x;
+ ev0->prev.y = move->cur.output.y;
+}
+
+static void
_mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void
*event_info)
{
Widget_Data *wd = elm_widget_data_get(data);
Evas_Event_Mouse_Up *ev = event_info;
+
+ int mdevice;
+ struct event_t *ev0;
+ struct event_t *ev1;
+
+ ev0 = get_event_object(0);
+ if (ev0)
+ {
+ mdevice = get_multi_device();
+ if (mdevice == 0)
+ {
+ if (ev0->hold_timer)
+ {
+ ecore_timer_del(ev0->hold_timer);
+ ev0->hold_timer = NULL;
+ }
+ elm_smart_scroller_hold_set(wd->scr, 0);
+ elm_smart_scroller_freeze_set(wd->scr, 0);
+ wd->pinch_zoom = EINA_FALSE;
+ }
+ else
+ {
+ ev1 = get_event_object(mdevice);
+ if (ev1) ev1->hold_timer = ecore_timer_add(0.35f, _hold_timer_cb,
ev1);
+ }
+ destroy_event_object(ev0);
+ }
+
if (!wd) return;
if (ev->button != 1) return;
if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) wd->on_hold = EINA_TRUE;
@@ -1090,13 +1248,137 @@ _mouse_up(void *data, Evas *evas __UNUSED__, Evas_
ecore_timer_del(wd->long_timer);
wd->long_timer = NULL;
}
- if (!wd->on_hold)
- evas_object_smart_callback_call(data, SIG_CLICKED, NULL);
+ if (!wd->on_hold) evas_object_smart_callback_call(data, SIG_CLICKED, ev);
wd->on_hold = EINA_FALSE;
}
+static void
+_mouse_multi_down(void *data, Evas *evas, Evas_Object *obj, void *event_info)
+{
+ Widget_Data *wd = elm_widget_data_get(data);
+ struct event_t *ev;
+ Evas_Event_Multi_Down *down = event_info;
+
+ elm_smart_scroller_hold_set(wd->scr, 1);
+ elm_smart_scroller_freeze_set(wd->scr, 1);
+
+ ev = get_event_object(down->device);
+ if (ev) goto done;
+
+ ev = create_event_object(obj, down->device);
+ if (!ev)
+ {
+ DBG("Failed : create_event_object");
+ goto done;
+ }
+
+ wd->pinch_zoom = EINA_FALSE;
+
+ ev->hold_timer = NULL;
+ ev->prev.x = down->output.x;
+ ev->prev.y = down->output.y;
+
+done:
+ return;
+}
+
+static void
+_mouse_multi_move(void *data, Evas *evas, Evas_Object *obj, void *event_info)
+{
+ Widget_Data *wd = elm_widget_data_get(data);
+ Evas_Event_Multi_Move *move = (Evas_Event_Multi_Move *)event_info;
+ int dis_new;
+ struct event_t *ev0;
+ struct event_t *ev;
+
+ if (wd->pinch_zoom) return;
+ ev = get_event_object(move->device);
+ if (!ev) return;
+
+ ev->prev.x = move->cur.output.x;
+ ev->prev.y = move->cur.output.y;
+
+ ev0 = get_event_object(0);
+ if (!ev0) return;
+
+ dis_new = get_distance(ev0->prev.x, ev0->prev.y, ev->prev.x, ev->prev.y);
+ int zoom = wd->zoom;
+
+ if (dis_old)
+ {
+ if (dis_old - dis_new > 0 && ev->pinch_dis > TOUCH_HOLD_RANGE)
+ {
+ wd->pinch_zoom = EINA_TRUE;
+ --zoom;
+ elm_map_zoom_set(data, zoom);
+ ev->pinch_dis = 0;
+ }
+ else if (dis_old - dis_new < 0 && ev->pinch_dis < -TOUCH_HOLD_RANGE)
+ {
+ wd->pinch_zoom = EINA_TRUE;
+ ++zoom;
+ elm_map_zoom_set(data, zoom);
+ ev->pinch_dis = 0;
+ }
+ ev->pinch_dis += (dis_old - dis_new);
+ }
+ dis_old = dis_new;
+}
+
+static void
+_mouse_multi_up(void *data, Evas *evas, Evas_Object *obj, void *event_info)
+{
+ Evas_Event_Multi_Up *up = (Evas_Event_Multi_Up *)event_info;
+ struct event_t *ev0;
+ struct event_t *ev;
+
+ ev = get_event_object(up->device);
+ if (!ev)
+ {
+ DBG("Cannot get multi device");
+ return;
+ }
+ dis_old = 0;
+
+ ev0 = get_event_object(0);
+ if (ev0)
+ {
+ ev0->hold_timer = ecore_timer_add(0.35f, _hold_timer_cb, ev0);
+ }
+ else
+ {
+ if (ev->hold_timer)
+ {
+ ecore_timer_del(ev->hold_timer);
+ ev->hold_timer = NULL;
+ }
+ }
+ destroy_event_object(ev);
+}
+
static Evas_Smart_Class _pan_sc = EVAS_SMART_CLASS_INIT_NULL;
+static Eina_Bool
+_hold_timer_cb(void *data)
+{
+ struct event_t *ev0 = (struct event_t *)data;
+ ev0->hold_timer = NULL;
+
+ return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_rect_resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+ Widget_Data *wd = elm_widget_data_get(data);
+ int x,y,w,h;
+
+ evas_object_geometry_get(wd->rect,&x,&y,&w,&h);
+ evas_object_geometry_get(wd->pan_smart,&x,&y,&w,&h);
+ evas_object_resize(wd->rect,w,h);
+ evas_object_move(wd->rect,x,y);
+}
+
static void
_del_hook(Evas_Object *obj)
{
@@ -1784,10 +2066,21 @@ elm_map_add(Evas_Object *parent)
_pan_min_get, _pan_child_size_get);
wd->rect = evas_object_rectangle_add(e);
+ evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_RESIZE,
+ _rect_resize_cb, obj);
evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MOUSE_DOWN,
_mouse_down, obj);
+ evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MOUSE_MOVE,
+ _mouse_move, obj);
evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MOUSE_UP,
_mouse_up, obj);
+ evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MULTI_DOWN,
+ _mouse_multi_down, obj);
+ evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MULTI_MOVE,
+ _mouse_multi_move, obj);
+ evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MULTI_UP,
+ _mouse_multi_up, obj);
+
evas_object_smart_member_add(wd->rect, wd->pan_smart);
elm_widget_sub_object_add(obj, wd->rect);
evas_object_show(wd->rect);
@@ -1849,7 +2142,7 @@ elm_map_zoom_set(Evas_Object *obj, int zoom)
if (zoom < map_sources_tab[wd->source].zoom_min)
zoom = map_sources_tab[wd->source].zoom_min;
if (zoom == wd->zoom) return;
-
+
wd->zoom = zoom;
wd->size.ow = wd->size.w;
wd->size.oh = wd->size.h;
@@ -3151,11 +3444,11 @@ _module_url_cb(void *data, int x, int y, int zoom)
{
char *buf = NULL;
Widget_Data *wd = elm_widget_data_get(data);
- if(elm_map_source_get(data) == ELM_MAP_SOURCE_MODULE)
+ if (elm_map_source_get(data) == ELM_MAP_SOURCE_MODULE)
if ((wd->api) && (wd->api->obj_url_request))
buf = wd->api->obj_url_request(data, x, y, zoom);
- if(!buf) buf = strdup("");
+ if (!buf) buf = strdup("");
return buf;
}
------------------------------------------------------------------------------
Forrester recently released a report on the Return on Investment (ROI) of
Google Apps. They found a 300% ROI, 38%-56% cost savings, and break-even
within 7 months. Over 3 million businesses have gone Google with Google Apps:
an online email calendar, and document program that's accessible from your
browser. Read the Forrester report: http://p.sf.net/sfu/googleapps-sfnew
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel