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.


SVN revision: 58703
This commit is contained in:
Sangho Park 2011-04-18 06:42:47 +00:00
parent ef3bc9a48d
commit fe580b2fdb
3 changed files with 526 additions and 42 deletions

View File

@ -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);
@ -197,6 +226,35 @@ my_map_route_loaded(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *ev
if (n) printf("[nodes]\n%s\n", n);
}
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__)
{
@ -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);
@ -568,6 +644,18 @@ test_map(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __
evas_object_size_hint_align_set(bx, 0.5, 0.1);
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");

View File

@ -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

View File

@ -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("");
}