From 3b92431f3dee734bd57fdbcc0ca414591067cf60 Mon Sep 17 00:00:00 2001 From: gouache Date: Mon, 18 Apr 2011 06:42:47 +0000 Subject: [PATCH] This is a patch for elm_map name(address) feature. I added some APIs for name to elm_map.c and added some test code to test_map.c I used nominatim OSM service. (http://http://nominatim.openstreetmap.org/) as i felt, it's response time was very good to use. git-svn-id: https://svn.enlightenment.org/svn/e/trunk/elementary@58703 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- src/bin/test_map.c | 98 ++++++++++- src/lib/Elementary.h.in | 33 +++- src/lib/elm_map.c | 437 ++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 526 insertions(+), 42 deletions(-) diff --git a/src/bin/test_map.c b/src/bin/test_map.c index 9efddd3..6df16a0 100644 --- a/src/bin/test_map.c +++ b/src/bin/test_map.c @@ -5,6 +5,7 @@ #ifndef ELM_LIB_QUICKLAUNCH #define MARKER_MAX 1000 +#define NAME_ENTRY_TEXT "Enter freeform address" typedef struct Marker_Data { @@ -20,6 +21,8 @@ static int nb_elts; static Elm_Map_Marker *markers[MARKER_MAX]; static Elm_Map_Marker *route_from, *route_to; static Elm_Map_Route *route; +static Elm_Map_Name *name; +static Eina_List *names; Marker_Data data1 = {PACKAGE_DATA_DIR"/images/logo.png"}; Marker_Data data2 = {PACKAGE_DATA_DIR"/images/logo_small.png"}; @@ -51,9 +54,35 @@ my_map_press(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_inf } static void -my_map_longpressed(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +my_map_longpressed(void *data, Evas_Object *obj __UNUSED__, void *event_info) { - printf("longpressed\n"); + double lon, lat; + Evas_Coord ox, oy, x, y, w, h; + int zoom; + Evas_Event_Mouse_Down *down = (Evas_Event_Mouse_Down *)event_info; + if (!down) return; + + evas_object_geometry_get(data, &ox, &oy, &w, &h); + zoom = elm_map_zoom_get(data); + elm_map_geo_region_get(obj, &lon, &lat); + elm_map_utils_convert_geo_into_coord(obj, lon, lat, pow(2.0, zoom)*256, &x, &y); + x += down->output.x - (w / 2) - ox; + y += down->output.y - (h / 2) - oy; + elm_map_utils_convert_coord_into_geo(obj, x, y, pow(2.0, zoom)*256, &lon, &lat); + + name = elm_map_utils_convert_coord_into_name(data, lon, lat); + + itc1 = elm_map_marker_class_new(data); + + elm_map_marker_class_del_cb_set(itc1, NULL); + + itc_group1 = elm_map_group_class_new(data); + elm_map_group_class_icon_cb_set(itc_group1, _group_icon_get); + elm_map_group_class_data_set(itc_group1, (void *)PACKAGE_DATA_DIR"/images/bubble.png"); + elm_map_group_class_style_set(itc_group1, "empty"); + elm_map_group_class_zoom_displayed_set(itc_group1, 5); + + names = eina_list_append(names, elm_map_marker_add(data, lon, lat, itc1, itc_group1, NULL)); } static void @@ -63,7 +92,7 @@ my_map_clicked_double(void *data, Evas_Object *obj, void *event_info) double flon, flat, tlon, tlat; Evas_Coord ox, oy, x, y, w, h; int zoom; - Evas_Event_Mouse_Up *down = (Evas_Event_Mouse_Up *)event_info; + Evas_Event_Mouse_Down *down = (Evas_Event_Mouse_Down *)event_info; if (!down) return; evas_object_geometry_get(data, &ox, &oy, &w, &h); @@ -198,6 +227,35 @@ my_map_route_loaded(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *ev } static void +my_map_name_load(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + printf("name_load\n"); + } + +static void +my_map_name_loaded(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + if (!name) return; + double lon, lat; + const char *addr = elm_map_name_address_get(name); + elm_map_name_region_get(name, &lon, &lat); + if (addr) + { + printf("name of [lon = %lf, lat = %lf] is %s\n", lon, lat, addr); + if ((lon != 0.0) && (lat !=0.0)) + { + Eina_Bool b = elm_map_paused_get(data); + elm_map_paused_set(data, EINA_TRUE); + elm_map_zoom_mode_set(data, ELM_MAP_ZOOM_MODE_MANUAL); + elm_map_geo_region_show(data, lon, lat); + elm_map_zoom_set(data, 18); + elm_map_paused_set(data, b); + } + } + elm_map_name_remove(name); +} + +static void my_bt_show_reg(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) { Eina_Bool b = elm_map_paused_get(data); @@ -345,6 +403,22 @@ my_bt_remove(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_inf } } +static void +my_map_entry_focused(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) +{ + const char *s = elm_scrolled_entry_entry_get(obj); + if (!strcmp(s, NAME_ENTRY_TEXT)) elm_scrolled_entry_entry_set(obj, ""); +} + +static void +my_map_entry_activated(void *data, Evas_Object *obj, void *event_info __UNUSED__) +{ + const char *s = elm_scrolled_entry_entry_get(obj); + char *addr = strdup(s); + name = elm_map_utils_convert_name_into_coord(data, addr); + if (addr) free (addr); +} + static Evas_Object * _marker_get(Evas_Object *obj, Elm_Map_Marker *marker __UNUSED__, void *data) { @@ -439,7 +513,7 @@ _map_move_resize_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void test_map(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) { - Evas_Object *win, *bg, *map, *tb2, *bt, *bx; + Evas_Object *win, *bg, *map, *tb2, *bt, *bx, *en; win = elm_win_add(NULL, "map", ELM_WIN_BASIC); elm_win_title_set(win, "Map"); @@ -524,7 +598,7 @@ test_map(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __ evas_object_smart_callback_add(map, "clicked", my_map_clicked, win); evas_object_smart_callback_add(map, "press", my_map_press, win); - evas_object_smart_callback_add(map, "longpressed", my_map_longpressed, win); + evas_object_smart_callback_add(map, "longpressed", my_map_longpressed, map); evas_object_smart_callback_add(map, "clicked,double", my_map_clicked_double, map); evas_object_smart_callback_add(map, "load,detail", my_map_load_detail, win); evas_object_smart_callback_add(map, "loaded,detail", my_map_loaded_detail, win); @@ -539,6 +613,8 @@ test_map(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __ evas_object_smart_callback_add(map, "downloaded", my_map_downloaded, map); evas_object_smart_callback_add(map, "route,load", my_map_route_load, map); evas_object_smart_callback_add(map, "route,loaded", my_map_route_loaded, map); + evas_object_smart_callback_add(map, "name,load", my_map_name_load, map); + evas_object_smart_callback_add(map, "name,loaded", my_map_name_loaded, map); evas_object_show(map); @@ -569,6 +645,18 @@ test_map(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __ elm_table_pack(tb2, bx, 1, 0, 1, 1); // + en = elm_scrolled_entry_add(win); + evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(en, EVAS_HINT_FILL, 0.5); + elm_scrolled_entry_scrollbar_policy_set(en, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF); + elm_scrolled_entry_entry_set(en, NAME_ENTRY_TEXT); + elm_scrolled_entry_single_line_set(en, 1); + elm_box_pack_end(bx, en); + evas_object_smart_callback_add(en, "focused", my_map_entry_focused, win); + evas_object_smart_callback_add(en, "activated", my_map_entry_activated, map); + evas_object_show(en); + + // bt = elm_button_add(win); elm_button_label_set(bt, "Add 1000 markers"); evas_object_smart_callback_add(bt, "clicked", my_bt_add, map); diff --git a/src/lib/Elementary.h.in b/src/lib/Elementary.h.in index 4356636..158517e 100644 --- a/src/lib/Elementary.h.in +++ b/src/lib/Elementary.h.in @@ -2203,6 +2203,19 @@ extern "C" { ELM_MAP_ROUTE_SOURCE_LAST } Elm_Map_Route_Sources; + typedef enum _Elm_Map_Name_Sources + { + ELM_MAP_NAME_SOURCE_NOMINATIM, + ELM_MAP_NAME_SOURCE_CUSTOM_1, + ELM_MAP_NAME_SOURCE_CUSTOM_2, + ELM_MAP_NAME_SOURCE_CUSTOM_3, + ELM_MAP_NAME_SOURCE_CUSTOM_4, + ELM_MAP_NAME_SOURCE_CUSTOM_5, + ELM_MAP_NAME_SOURCE_CUSTOM_6, + ELM_MAP_NAME_SOURCE_MODULE, + ELM_MAP_NAME_SOURCE_LAST + } Elm_Map_Name_Sources; + typedef enum _Elm_Map_Route_Type { ELM_MAP_ROUTE_TYPE_MOTOCAR, @@ -2218,16 +2231,25 @@ extern "C" { ELM_MAP_ROUTE_METHOD_LAST } Elm_Map_Route_Method; + typedef enum _Elm_Map_Name_Method + { + ELM_MAP_NAME_METHOD_SEARCH, + ELM_MAP_NAME_METHOD_REVERSE, + ELM_MAP_NAME_METHOD_LAST + } Elm_Map_Name_Method; + typedef struct _Elm_Map_Marker Elm_Map_Marker; typedef struct _Elm_Map_Marker_Class Elm_Map_Marker_Class; typedef struct _Elm_Map_Group_Class Elm_Map_Group_Class; typedef struct _Elm_Map_Route Elm_Map_Route; + typedef struct _Elm_Map_Name Elm_Map_Name; typedef Evas_Object *(*ElmMapMarkerGetFunc) (Evas_Object *obj, Elm_Map_Marker *marker, void *data); typedef void (*ElmMapMarkerDelFunc) (Evas_Object *obj, Elm_Map_Marker *marker, void *data, Evas_Object *o); typedef Evas_Object *(*ElmMapMarkerIconGetFunc) (Evas_Object *obj, Elm_Map_Marker *marker, void *data); typedef Evas_Object *(*ElmMapGroupIconGetFunc) (Evas_Object *obj, void *data); typedef char *(*ElmMapSourceURLFunc) (Evas_Object *obj, int x, int y, int zoom); typedef char *(*ElmMapRouteSourceURLFunc) (Evas_Object *obj, char *type_name, int method, double flon, double flat, double tlon, double tlat); + typedef char *(*ElmMapNameSourceURLFunc) (Evas_Object *obj, int method, char *name, double lon, double lat); EAPI Evas_Object *elm_map_add(Evas_Object *parent) EINA_ARG_NONNULL(1); EAPI void elm_map_zoom_set(Evas_Object *obj, int zoom) EINA_ARG_NONNULL(1); @@ -2242,8 +2264,10 @@ extern "C" { EAPI void elm_map_paused_markers_set(Evas_Object *obj, Eina_Bool paused) EINA_ARG_NONNULL(1); EAPI Eina_Bool elm_map_paused_markers_get(const Evas_Object *obj) EINA_ARG_NONNULL(1); EAPI void elm_map_utils_downloading_status_get(const Evas_Object *obj, int *try_num, int *finish_num) EINA_ARG_NONNULL(1, 2, 3); - EAPI void elm_map_utils_convert_coord_into_geo(const Evas_Object *obj, int x, int y, int size, double *lon, double *lat); - EAPI void elm_map_utils_convert_geo_into_coord(const Evas_Object *obj, double lon, double lat, int size, int *x, int *y); + EAPI void elm_map_utils_convert_coord_into_geo(const Evas_Object *obj, int x, int y, int size, double *lon, double *lat) EINA_ARG_NONNULL(1, 5, 6); + EAPI void elm_map_utils_convert_geo_into_coord(const Evas_Object *obj, double lon, double lat, int size, int *x, int *y) EINA_ARG_NONNULL(1, 5, 6); + EAPI Elm_Map_Name *elm_map_utils_convert_coord_into_name(const Evas_Object *obj, double lon, double lat) EINA_ARG_NONNULL(1); + EAPI Elm_Map_Name *elm_map_utils_convert_name_into_coord(const Evas_Object *obj, char *address) EINA_ARG_NONNULL(1, 2); EAPI Elm_Map_Marker *elm_map_marker_add(Evas_Object *obj, double lon, double lat, Elm_Map_Marker_Class *clas, Elm_Map_Group_Class *clas_group, void *data) EINA_ARG_NONNULL(1, 4, 5); EAPI void elm_map_max_marker_per_group_set(Evas_Object *obj, int max) EINA_ARG_NONNULL(1); EAPI void elm_map_marker_remove(Elm_Map_Marker *marker) EINA_ARG_NONNULL(1); @@ -2270,7 +2294,7 @@ extern "C" { EAPI void elm_map_route_source_set(Evas_Object *obj, Elm_Map_Route_Sources source) EINA_ARG_NONNULL(1); EAPI Elm_Map_Sources elm_map_source_get(const Evas_Object *obj) EINA_ARG_NONNULL(1); EAPI Elm_Map_Route_Sources elm_map_route_source_get(const Evas_Object *obj) EINA_ARG_NONNULL(1); - EAPI void elm_map_source_custom_api_set(Elm_Map_Sources source, const char *label, int zoom_min, int zoom_max, ElmMapSourceURLFunc url_cb, ElmMapRouteSourceURLFunc route_url_cb) EINA_ARG_NONNULL(2, 5, 6); + EAPI void elm_map_source_custom_api_set(Elm_Map_Sources source, const char *label, int zoom_min, int zoom_max, ElmMapSourceURLFunc url_cb, ElmMapRouteSourceURLFunc route_url_cb, ElmMapNameSourceURLFunc name_url_cb) EINA_ARG_NONNULL(2, 5, 6, 7); EAPI int elm_map_source_zoom_min_get(Elm_Map_Sources source); EAPI int elm_map_source_zoom_max_get(Elm_Map_Sources source); EAPI const char *elm_map_source_name_get(Elm_Map_Sources source); @@ -2283,6 +2307,9 @@ extern "C" { EAPI double elm_map_route_distance_get(Elm_Map_Route *route) EINA_ARG_NONNULL(1); EAPI const char *elm_map_route_node_get(Elm_Map_Route *route) EINA_ARG_NONNULL(1); EAPI const char *elm_map_route_waypoint_get(Elm_Map_Route *route) EINA_ARG_NONNULL(1); + EAPI const char *elm_map_name_address_get(Elm_Map_Name *name) EINA_ARG_NONNULL(1); + EAPI void elm_map_name_region_get(Elm_Map_Name *name, double *lon, double *lat) EINA_ARG_NONNULL(1); + EAPI void elm_map_name_remove(Elm_Map_Name *name) EINA_ARG_NONNULL(1); /* smart callbacks called: * "clicked" - when image clicked diff --git a/src/lib/elm_map.c b/src/lib/elm_map.c index 8194c8d..b8984dd 100644 --- a/src/lib/elm_map.c +++ b/src/lib/elm_map.c @@ -31,6 +31,8 @@ * "downloaded" - This is called when map images are downloaded * "route,load" - This is called when route request begins * "route,loaded" - This is called when route request ends + * "name,load" - This is called when name request begins + * "name,loaded- This is called when name request ends * * TODO : doxygen */ @@ -47,11 +49,13 @@ typedef struct _Route_Node Route_Node; typedef struct _Route_Waypoint Route_Waypoint; typedef struct _Url_Data Url_Data; typedef struct _Route_Dump Route_Dump; +typedef struct _Name_Dump Name_Dump; #define DEST_DIR_ZOOM_PATH "/tmp/elm_map/%d/%d/" #define DEST_DIR_PATH DEST_DIR_ZOOM_PATH"%d/" #define DEST_FILE_PATH "%s%d.png" -#define DEST_XML_FILE "/tmp/elm_map-XXXXXX" +#define DEST_ROUTE_XML_FILE "/tmp/elm_map-route-XXXXXX" +#define DEST_NAME_XML_FILE "/tmp/elm_map-name-XXXXXX" #define ROUTE_YOURS_URL "http://www.yournavigation.org/api/dev/route.php" #define ROUTE_TYPE_MOTORCAR "motocar" @@ -65,6 +69,12 @@ typedef struct _Route_Dump Route_Dump; #define ROUTE_MONAV_URL "http://" #define ROUTE_ORS_URL "http:///" +#define NAME_NOMINATIM_URL "http://nominatim.openstreetmap.org" +#define NOMINATIM_RESULT "result" +#define NOMINATIM_PLACE "place" +#define NOMINATIM_ATTR_LON "lon" +#define NOMINATIM_ATTR_LAT "lat" + // Map sources // Currently the size of a tile must be 256*256 // and the size of the map must be pow(2.0, z)*tile_size @@ -77,6 +87,7 @@ typedef struct _Map_Sources_Tab ElmMapSourceURLFunc url_cb; Elm_Map_Route_Sources route_source; ElmMapRouteSourceURLFunc route_url_cb; + ElmMapNameSourceURLFunc name_url_cb; } Map_Sources_Tab; #define ZOOM_MAX 18 @@ -109,19 +120,27 @@ static char *_route_custom6_url_cb(Evas_Object *obj __UNUSED__, char *type_name, static char *_route_module_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat); */ +static char *_nominatim_url_cb(Evas_Object *obj, int method, char *name, double lon, double lat); +static char *_name_custom1_url_cb(Evas_Object *obj __UNUSED__, int method __UNUSED__, char *name __UNUSED__, double lon __UNUSED__, double lat __UNUSED__); +static char *_name_custom2_url_cb(Evas_Object *obj __UNUSED__, int method __UNUSED__, char *name __UNUSED__, double lon __UNUSED__, double lat __UNUSED__); +static char *_name_custom3_url_cb(Evas_Object *obj __UNUSED__, int method __UNUSED__, char *name __UNUSED__, double lon __UNUSED__, double lat __UNUSED__); +static char *_name_custom4_url_cb(Evas_Object *obj __UNUSED__, int method __UNUSED__, char *name __UNUSED__, double lon __UNUSED__, double lat __UNUSED__); +static char *_name_custom5_url_cb(Evas_Object *obj __UNUSED__, int method __UNUSED__, char *name __UNUSED__, double lon __UNUSED__, double lat __UNUSED__); +static char *_name_custom6_url_cb(Evas_Object *obj __UNUSED__, int method __UNUSED__, char *name __UNUSED__, double lon __UNUSED__, double lat __UNUSED__); + static Map_Sources_Tab map_sources_tab[] = { - {ELM_MAP_SOURCE_MAPNIK, "Mapnik", 0, 18, _mapnik_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb}, - {ELM_MAP_SOURCE_OSMARENDER, "Osmarender", 0, 17, _osmarender_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb}, - {ELM_MAP_SOURCE_CYCLEMAP, "Cycle Map", 0, 17, _cyclemap_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb}, - {ELM_MAP_SOURCE_MAPLINT, "Maplint", 12, 16, _maplint_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb}, - {ELM_MAP_SOURCE_CUSTOM_1, "Custom 1", 0, 18, _custom1_url_cb, ELM_MAP_ROUTE_SOURCE_CUSTOM_1, _route_custom1_url_cb}, - {ELM_MAP_SOURCE_CUSTOM_2, "Custom 2", 0, 18, _custom2_url_cb, ELM_MAP_ROUTE_SOURCE_CUSTOM_2, _route_custom2_url_cb}, - {ELM_MAP_SOURCE_CUSTOM_3, "Custom 3", 0, 18, _custom3_url_cb, ELM_MAP_ROUTE_SOURCE_CUSTOM_3, _route_custom3_url_cb}, - {ELM_MAP_SOURCE_CUSTOM_4, "Custom 4", 0, 18, _custom4_url_cb, ELM_MAP_ROUTE_SOURCE_CUSTOM_4, _route_custom4_url_cb}, - {ELM_MAP_SOURCE_CUSTOM_5, "Custom 5", 0, 18, _custom5_url_cb, ELM_MAP_ROUTE_SOURCE_CUSTOM_5, _route_custom5_url_cb}, - {ELM_MAP_SOURCE_CUSTOM_6, "Custom 6", 0, 18, _custom6_url_cb, ELM_MAP_ROUTE_SOURCE_CUSTOM_6, _route_custom6_url_cb}, - {ELM_MAP_SOURCE_MODULE, "Module", 0, 18, _module_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb} + {ELM_MAP_SOURCE_MAPNIK, "Mapnik", 0, 18, _mapnik_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb, _nominatim_url_cb}, + {ELM_MAP_SOURCE_OSMARENDER, "Osmarender", 0, 17, _osmarender_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb, _nominatim_url_cb}, + {ELM_MAP_SOURCE_CYCLEMAP, "Cycle Map", 0, 17, _cyclemap_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb, _nominatim_url_cb}, + {ELM_MAP_SOURCE_MAPLINT, "Maplint", 12, 16, _maplint_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb, _nominatim_url_cb}, + {ELM_MAP_SOURCE_CUSTOM_1, "Custom 1", 0, 18, _custom1_url_cb, ELM_MAP_ROUTE_SOURCE_CUSTOM_1, _route_custom1_url_cb, _name_custom1_url_cb}, + {ELM_MAP_SOURCE_CUSTOM_2, "Custom 2", 0, 18, _custom2_url_cb, ELM_MAP_ROUTE_SOURCE_CUSTOM_2, _route_custom2_url_cb, _name_custom2_url_cb}, + {ELM_MAP_SOURCE_CUSTOM_3, "Custom 3", 0, 18, _custom3_url_cb, ELM_MAP_ROUTE_SOURCE_CUSTOM_3, _route_custom3_url_cb, _name_custom3_url_cb}, + {ELM_MAP_SOURCE_CUSTOM_4, "Custom 4", 0, 18, _custom4_url_cb, ELM_MAP_ROUTE_SOURCE_CUSTOM_4, _route_custom4_url_cb, _name_custom4_url_cb}, + {ELM_MAP_SOURCE_CUSTOM_5, "Custom 5", 0, 18, _custom5_url_cb, ELM_MAP_ROUTE_SOURCE_CUSTOM_5, _route_custom5_url_cb, _name_custom5_url_cb}, + {ELM_MAP_SOURCE_CUSTOM_6, "Custom 6", 0, 18, _custom6_url_cb, ELM_MAP_ROUTE_SOURCE_CUSTOM_6, _route_custom6_url_cb, _name_custom6_url_cb}, + {ELM_MAP_SOURCE_MODULE, "Module", 0, 18, _module_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb, _nominatim_url_cb} }; struct _Url_Data @@ -262,6 +281,18 @@ struct _Route_Waypoint const char *point; }; +struct _Elm_Map_Name +{ + Widget_Data *wd; + + Ecore_Con_Url *con_url; + int method; + char *address; + double lon, lat; + Url_Data ud; + Ecore_Event_Handler *handler; +}; + struct _Grid_Item { Widget_Data *wd; @@ -300,7 +331,6 @@ struct _Widget_Data Evas_Coord pan_x, pan_y, minw, minh; int id; - int fid; int zoom; Elm_Map_Zoom_Mode mode; @@ -325,7 +355,6 @@ struct _Widget_Data int preload_num; Eina_List *grids; Eina_Bool resized : 1; - Eina_Bool longpressed : 1; Eina_Bool on_hold : 1; Eina_Bool paused : 1; Eina_Bool paused_markers : 1; @@ -357,6 +386,8 @@ struct _Widget_Data Eina_Hash *ua; const char *user_agent; Eina_List *route; + Evas_Event_Mouse_Down ev; + Eina_List *names; }; struct _Mod_Api @@ -407,6 +438,23 @@ enum _Route_Xml_Attribute ROUTE_XML_LAST } Route_Xml_Attibute; +struct _Name_Dump +{ + int id; + char *address; + double lon; + double lat; +}; + +enum _Name_Xml_Attribute +{ + NAME_XML_NONE, + NAME_XML_NAME, + NAME_XML_LON, + NAME_XML_LAT, + NAME_XML_LAST +} Name_Xml_Attibute; + static int dis_old = 0; static const char *widtype = NULL; @@ -426,6 +474,8 @@ static const char SIG_ZOOM_STOP[] = "zoom,stop"; static const char SIG_DOWNLOADED[] = "downloaded"; static const char SIG_ROUTE_LOAD[] = "route,load"; static const char SIG_ROUTE_LOADED[] = "route,loaded"; +static const char SIG_NAME_LOAD[] = "name,load"; +static const char SIG_NAME_LOADED[] = "name,loaded"; static const Evas_Smart_Cb_Description _signals[] = { {SIG_CHANGED, ""}, {SIG_CLICKED, ""}, @@ -443,6 +493,8 @@ static const Evas_Smart_Cb_Description _signals[] = { {SIG_DOWNLOADED, ""}, {SIG_ROUTE_LOAD, ""}, {SIG_ROUTE_LOADED, ""}, + {SIG_NAME_LOAD, ""}, + {SIG_NAME_LOADED, ""}, {NULL, NULL} }; @@ -1359,8 +1411,7 @@ _long_press(void *data) Widget_Data *wd = elm_widget_data_get(data); if (!wd) return ECORE_CALLBACK_CANCEL; wd->long_timer = NULL; - wd->longpressed = EINA_TRUE; - evas_object_smart_callback_call(data, SIG_LONGPRESSED, NULL); + evas_object_smart_callback_call(data, SIG_LONGPRESSED, &wd->ev); return ECORE_CALLBACK_CANCEL; } @@ -1388,8 +1439,9 @@ _mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event_inf evas_object_smart_callback_call(data, SIG_CLICKED_DOUBLE, ev); else evas_object_smart_callback_call(data, SIG_PRESS, ev); - wd->longpressed = EINA_FALSE; if (wd->long_timer) ecore_timer_del(wd->long_timer); + wd->ev.output.x = ev->output.x; + wd->ev.output.y = ev->output.y; wd->long_timer = ecore_timer_add(_elm_config->longpress_timeout, _long_press, data); } @@ -1593,6 +1645,7 @@ _del_hook(Evas_Object *obj) Route_Waypoint *w; Ecore_Event_Handler *h; Elm_Map_Route *r; + Elm_Map_Name *na; if (!wd) return; @@ -1643,6 +1696,19 @@ _del_hook(Evas_Object *obj) if (r->info.nodes) eina_stringshare_del(r->info.nodes); if (r->info.waypoints) eina_stringshare_del(r->info.waypoints); } + + EINA_LIST_FREE(wd->names, na) + { + if (na->address) free(na->address); + if (na->handler) ecore_event_handler_del(na->handler); + if (na->ud.fname) + { + ecore_file_remove(na->ud.fname); + free(na->ud.fname); + na->ud.fname = NULL; + } + } + 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); @@ -2294,16 +2360,23 @@ _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type ty } static Eina_Bool -cb_dump_attrs(void *data __UNUSED__, const char *key __UNUSED__, const char *value __UNUSED__) +cb_dump_name_attrs(void *data, const char *key, const char *value) { + Name_Dump *dump = (Name_Dump*)data; + if (!dump) return EINA_FALSE; + + if (!strncmp(key, NOMINATIM_ATTR_LON, sizeof(NOMINATIM_ATTR_LON))) dump->lon = atof(value); + else if (!strncmp(key, NOMINATIM_ATTR_LAT, sizeof(NOMINATIM_ATTR_LAT))) dump->lat = atof(value); + return EINA_TRUE; } static Eina_Bool -cb_dump(void *data, Eina_Simple_XML_Type type, const char *value, unsigned offset __UNUSED__, unsigned length) +cb_route_dump(void *data, Eina_Simple_XML_Type type, const char *value, unsigned offset __UNUSED__, unsigned length) { Route_Dump *dump = data; + if (!dump) return EINA_FALSE; switch (type) { @@ -2320,12 +2393,7 @@ cb_dump(void *data, Eina_Simple_XML_Type type, const char *value, unsigned offse else if (!strncmp(value, YOURS_COORDINATES, length)) dump->id = ROUTE_XML_COORDINATES; else dump->id = ROUTE_XML_NONE; } - else - { - eina_simple_xml_attributes_parse - (attrs, length - (attrs - value), cb_dump_attrs, dump); - } - } + } break; case EINA_SIMPLE_XML_DATA: { @@ -2345,6 +2413,45 @@ cb_dump(void *data, Eina_Simple_XML_Type type, const char *value, unsigned offse return EINA_TRUE; } +static Eina_Bool +cb_name_dump(void *data, Eina_Simple_XML_Type type, const char *value, unsigned offset __UNUSED__, unsigned length) +{ + Name_Dump *dump = data; + if (!dump) return EINA_FALSE; + + switch (type) + { + case EINA_SIMPLE_XML_OPEN: + case EINA_SIMPLE_XML_OPEN_EMPTY: + { + const char *attrs; + attrs = eina_simple_xml_tag_attributes_find(value, length); + if (attrs) + { + if (!strncmp(value, NOMINATIM_RESULT, sizeof(NOMINATIM_RESULT)-1)) dump->id = NAME_XML_NAME; + else dump->id = NAME_XML_NONE; + + eina_simple_xml_attributes_parse + (attrs, length - (attrs - value), cb_dump_name_attrs, dump); + } + } + break; + case EINA_SIMPLE_XML_DATA: + { + char *buf = malloc(length + 1); + if (!buf) return EINA_FALSE; + snprintf(buf, length + 1, "%s", value); + if (dump->id == NAME_XML_NAME) dump->address = strdup(buf); + free(buf); + } + break; + default: + break; + } + + return EINA_TRUE; +} + static void _parse_kml(void *data) { @@ -2376,7 +2483,7 @@ _parse_kml(void *data) { if (fread(buf, 1, sz, f)) { - eina_simple_xml_parse(buf, sz, EINA_TRUE, cb_dump, &dump); + eina_simple_xml_parse(buf, sz, EINA_TRUE, cb_route_dump, &dump); free(buf); } } @@ -2441,8 +2548,52 @@ _parse_kml(void *data) } } +static void +_parse_name(void *data) +{ + Elm_Map_Name *n = (Elm_Map_Name*)data; + if (!n && !n->ud.fname) return; + + FILE *f; + + Name_Dump dump = {0, NULL, 0.0, 0.0}; + + f = fopen(n->ud.fname, "rb"); + if (f) + { + long sz; + + fseek(f, 0, SEEK_END); + sz = ftell(f); + if (sz > 0) + { + char *buf; + + fseek(f, 0, SEEK_SET); + buf = malloc(sz); + if (buf) + { + if (fread(buf, 1, sz, f)) + { + eina_simple_xml_parse(buf, sz, EINA_TRUE, cb_name_dump, &dump); + free(buf); + } + } + } + fclose(f); + + if (dump.address) + { + INF("[%lf : %lf] ADDRESS : %s", n->lon, n->lat, dump.address); + n->address = strdup(dump.address); + } + n->lon = dump.lon; + n->lat = dump.lat; + } +} + static Eina_Bool -_common_complete_cb(void *data, int ev_type __UNUSED__, void *event) +_route_complete_cb(void *data, int ev_type __UNUSED__, void *event) { Ecore_Con_Event_Url_Complete *ev = event; Elm_Map_Route *r = (Elm_Map_Route*)data; @@ -2468,6 +2619,85 @@ _common_complete_cb(void *data, int ev_type __UNUSED__, void *event) return EINA_TRUE; } +static Eina_Bool +_name_complete_cb(void *data, int ev_type __UNUSED__, void *event) +{ + Ecore_Con_Event_Url_Complete *ev = event; + Elm_Map_Name *n = (Elm_Map_Name*)data; + Widget_Data *wd = n->wd; + + if ((!n) || (!ev)) return EINA_TRUE; + Elm_Map_Name *nn = ecore_con_url_data_get(n->con_url); + ecore_con_url_data_set(n->con_url, NULL); + if (n!=nn) return EINA_TRUE; + + if (n->ud.fd) fclose(n->ud.fd); + _parse_name(n); + + edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), + "elm,state,busy,stop", "elm"); + evas_object_smart_callback_call(wd->obj, SIG_NAME_LOADED, NULL); + return EINA_TRUE; +} + +static Elm_Map_Name * +_utils_convert_name(const Evas_Object *obj, int method, char *address, double lon, double lat) +{ + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return NULL; + + char buf[PATH_MAX]; + char *source; + int fd; + Elm_Map_Name *name = ELM_NEW(Elm_Map_Name); + if (!name) return NULL; + + snprintf(buf, sizeof(buf), DEST_NAME_XML_FILE); + fd = mkstemp(buf); + if (fd < 0) + { + free(name); + return NULL; + } + + name->con_url = ecore_con_url_new(NULL); + name->ud.fname = strdup(buf); + INF("xml file : %s", name->ud.fname); + + name->ud.fd = fdopen(fd, "w+"); + if ((!name->con_url) || (!name->ud.fd)) + { + ecore_con_url_free(name->con_url); + free(name); + return NULL; + } + + name->wd = wd; + name->handler = ecore_event_handler_add (ECORE_CON_EVENT_URL_COMPLETE, _name_complete_cb, name); + name->method = method; + if (method == ELM_MAP_NAME_METHOD_SEARCH) name->address = strdup(address); + else if (method == ELM_MAP_NAME_METHOD_REVERSE) name->address = NULL; + name->lon = lon; + name->lat = lat; + + source = map_sources_tab[wd->source].name_url_cb(wd->obj, method, address, lon, lat); + INF("name url = %s", source); + + wd->names = eina_list_append(wd->names, name); + ecore_con_url_url_set(name->con_url, source); + ecore_con_url_fd_set(name->con_url, fileno(name->ud.fd)); + ecore_con_url_data_set(name->con_url, name); + + edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), + "elm,state,busy,start", "elm"); + evas_object_smart_callback_call(wd->obj, SIG_NAME_LOAD, NULL); + ecore_con_url_get(name->con_url); + if (source) free(source); + + return name; + +} + static int idnum = 1; /** @@ -2578,7 +2808,6 @@ elm_map_add(Evas_Object *parent) wd->zoom = -1; wd->mode = ELM_MAP_ZOOM_MODE_MANUAL; - wd->fid = 0; wd->id = ((int)getpid() << 16) | idnum; idnum++; @@ -3174,7 +3403,40 @@ elm_map_utils_convert_geo_into_coord(const Evas_Object *obj, double lon, double *y = floor((1.0 - log( tan(lat * ELM_PI/180.0) + 1.0 / cos(lat * ELM_PI/180.0)) / ELM_PI) / 2.0 * size); } +/** + * Convert a geographic coordinate (longitude, latitude) into a name (address). + * + * @param obj The map object + * @param lon the longitude + * @param lat the latitude + * @param name the adress + * + * @ingroup Map + */ +EAPI Elm_Map_Name * +elm_map_utils_convert_coord_into_name(const Evas_Object *obj, double lon, double lat) +{ + ELM_CHECK_WIDTYPE(obj, widtype) NULL; + return _utils_convert_name(obj, ELM_MAP_NAME_METHOD_REVERSE, NULL, lon, lat); +} +/** + * Convert a name (address) into a geographic coordinate (longitude, latitude). + * + * @param obj The map object + * @param name the adress + * @param lon the longitude correspond to x + * @param lat the latitude correspond to y + * + * @ingroup Map + */ +EAPI Elm_Map_Name * +elm_map_utils_convert_name_into_coord(const Evas_Object *obj, char *address) +{ + ELM_CHECK_WIDTYPE(obj, widtype) NULL; + if (!address) return NULL; + return _utils_convert_name(obj, ELM_MAP_NAME_METHOD_SEARCH, address, 0.0, 0.0); +} /** * Add a marker on the map @@ -3865,6 +4127,7 @@ elm_map_source_set(Evas_Object *obj, Elm_Map_Sources source) if (!wd) return; if (wd->source == source ) return; if (!map_sources_tab[source].url_cb) return; + _elm_config_sub_init(); EINA_LIST_FREE(wd->grids, grid) grid_clear(obj, grid); @@ -3889,9 +4152,12 @@ elm_map_source_set(Evas_Object *obj, Elm_Map_Sources source) * @ingroup Map */ EAPI void -elm_map_route_source_set(Evas_Object *obj, Elm_Map_Route_Sources source __UNUSED__) +elm_map_route_source_set(Evas_Object *obj, Elm_Map_Route_Sources source) { ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + wd->source = source; } /** @@ -3942,7 +4208,7 @@ elm_map_route_source_get(const Evas_Object *obj) * @ingroup Map */ EAPI void -elm_map_source_custom_api_set(Elm_Map_Sources source, const char *name, int zoom_min, int zoom_max, ElmMapSourceURLFunc url_cb, ElmMapRouteSourceURLFunc route_url_cb) +elm_map_source_custom_api_set(Elm_Map_Sources source, const char *name, int zoom_min, int zoom_max, ElmMapSourceURLFunc url_cb, ElmMapRouteSourceURLFunc route_url_cb, ElmMapNameSourceURLFunc name_url_cb) { EINA_SAFETY_ON_NULL_RETURN(name); EINA_SAFETY_ON_NULL_RETURN(url_cb); @@ -3951,6 +4217,7 @@ elm_map_source_custom_api_set(Elm_Map_Sources source, const char *name, int zoom map_sources_tab[source].zoom_max = zoom_max; map_sources_tab[source].url_cb = url_cb; map_sources_tab[source].route_url_cb = route_url_cb; + map_sources_tab[source].name_url_cb = name_url_cb; } /** @@ -4069,7 +4336,7 @@ elm_map_route_add(Evas_Object *obj, Elm_Map_Route *route = ELM_NEW(Elm_Map_Route); if (!route) return NULL; - snprintf(buf, sizeof(buf), DEST_XML_FILE); + snprintf(buf, sizeof(buf), DEST_ROUTE_XML_FILE); fd = mkstemp(buf); if (fd < 0) { @@ -4081,7 +4348,6 @@ elm_map_route_add(Evas_Object *obj, route->ud.fname = strdup(buf); INF("xml file : %s", route->ud.fname); - wd->fid++; route->ud.fd = fdopen(fd, "w+"); if ((!route->con_url) || (!route->ud.fd)) { @@ -4097,7 +4363,7 @@ elm_map_route_add(Evas_Object *obj, route->color.a = 255; route->handlers = eina_list_append (route->handlers, (void *)ecore_event_handler_add - (ECORE_CON_EVENT_URL_COMPLETE, _common_complete_cb, route)); + (ECORE_CON_EVENT_URL_COMPLETE, _route_complete_cb, route)); route->inbound = EINA_FALSE; route->type = type; @@ -4279,6 +4545,45 @@ elm_map_route_waypoint_get(Elm_Map_Route *route) return route->info.waypoints; } + +EAPI const char * +elm_map_name_address_get(Elm_Map_Name *name) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL); + return name->address; +} + +EAPI void +elm_map_name_region_get(Elm_Map_Name *name, double *lon, double *lat) +{ + EINA_SAFETY_ON_NULL_RETURN(name); + if (*lon) *lon = name->lon; + if (*lat) *lat = name->lat; +} + +EAPI void +elm_map_name_remove(Elm_Map_Name *name) +{ + EINA_SAFETY_ON_NULL_RETURN(name); + if (name->address) + { + free(name->address); + name->address = NULL; + } + if (name->handler) + { + ecore_event_handler_del(name->handler); + name->handler = NULL; + } + if (name->ud.fname) + { + ecore_file_remove(name->ud.fname); + free(name->ud.fname); + name->ud.fname = NULL; + } +} + + static char * _mapnik_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom) { @@ -4372,7 +4677,7 @@ static char *_yours_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int met { char buf[PATH_MAX]; snprintf(buf, sizeof(buf), - "%s?flat=%f&flon=%f&tlat=%f&tlon=%f&v=%s&fast=%d&instructions=1", + "%s?flat=%lf&flon=%lf&tlat=%lf&tlon=%lf&v=%s&fast=%d&instructions=1", ROUTE_YOURS_URL, flat, flon, tlat, tlon, type_name, method); return strdup(buf); @@ -4440,3 +4745,67 @@ static char *_route_module_url_cb(Evas_Object *obj __UNUSED__, char *type_name _ return strdup(""); } */ + +static char * +_nominatim_url_cb(Evas_Object *obj, int method, char *name, double lon, double lat) +{ + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return strdup(""); + char **str; + unsigned int ele, idx; + + char search_url[PATH_MAX]; + char buf[PATH_MAX]; + if (method == ELM_MAP_NAME_METHOD_SEARCH) + { + search_url[0] = '\0'; + str = eina_str_split_full(name, " ", 0, &ele); + for (idx = 0 ; idx < ele ; idx++) + { + eina_strlcat(search_url, str[idx], sizeof(search_url)); + if (!(idx == (ele-1))) eina_strlcat(search_url, "+", sizeof(search_url)); + } + snprintf(buf, sizeof(buf), "%s/search?q=%s&format=xml&polygon=0&addressdetails=0", NAME_NOMINATIM_URL, search_url); + } + else if (method == ELM_MAP_NAME_METHOD_REVERSE) snprintf(buf, sizeof(buf), "%s/reverse?format=xml&lat=%lf&lon=%lf&zoom=%d&addressdetails=0", NAME_NOMINATIM_URL, lat, lon, wd->zoom); + else strcpy(buf, ""); + + return strdup(buf); +} + +static char * +_name_custom1_url_cb(Evas_Object *obj __UNUSED__, int method __UNUSED__, char *name __UNUSED__, double lon __UNUSED__, double lat __UNUSED__) +{ + return strdup(""); +} + +static char * +_name_custom2_url_cb(Evas_Object *obj __UNUSED__, int method __UNUSED__, char *name __UNUSED__, double lon __UNUSED__, double lat __UNUSED__) +{ + return strdup(""); +} + +static char * +_name_custom3_url_cb(Evas_Object *obj __UNUSED__, int method __UNUSED__, char *name __UNUSED__, double lon __UNUSED__, double lat __UNUSED__) +{ + return strdup(""); +} + +static char * +_name_custom4_url_cb(Evas_Object *obj __UNUSED__, int method __UNUSED__, char *name __UNUSED__, double lon __UNUSED__, double lat __UNUSED__) +{ + return strdup(""); +} + +static char * +_name_custom5_url_cb(Evas_Object *obj __UNUSED__, int method __UNUSED__, char *name __UNUSED__, double lon __UNUSED__, double lat __UNUSED__) +{ + return strdup(""); +} + +static char * +_name_custom6_url_cb(Evas_Object *obj __UNUSED__, int method __UNUSED__, char *name __UNUSED__, double lon __UNUSED__, double lat __UNUSED__) +{ + return strdup(""); +} + -- 2.7.4