From 9bf7d3d8fd72a726eb8930170f9d8b6cb646a5f7 Mon Sep 17 00:00:00 2001 From: raster Date: Tue, 21 Feb 2012 08:01:22 +0000 Subject: [PATCH] From: Bluezery Subject: [E-devel] [Patch][elm_map] Refactoring Elementary Map I have done refactoring & code clean-up in elm_map. Event if this patch have much changes, refactoring & code clean-up jobs almost always do. Anyway, code is shortened and optimized I think. I have done following jobs in my patch. (1) Always change child size Scroller Child size is changed when integer zoom level is changed before. This makes bugs which mouse pointer is not correct on the map when map is dragging. Now, scroller child size is always changed when double zoom level is changed. (2) Evas map Evas map is used for rotation & zooming before. But now it is used for only rotation. evas_object_resize() can do zooming because (1) makes child size always changed. (3) Grid & Marker & Route, etc. Because of (1), all coordinate calculations are all changed. So grid & marker & route should be changed. When I have fixed these, I have these split into small function (create, free, update, place, etc.) So these can be easily reused for other purpose ( I will add overlay later.) Also marker size is not changed and is not rotated anymore because marker's coordinate is just rotated and evas_map is not used for marker. And grouping algorithm is somewhat changed. Each marker can be group leader and if other markers (followers) are closed to leader, markers are grouped. Actually _marker_place() function do almost everything. (place marker, bubble, group & make group, etc.) Bubbles go along with parent object. (show, hide, move) and this is created when marker & group are opened. At now, bubble display bugs are all fixed. As before, grid is created when elm_map_add() or tile source is changed. And I add _grid_item_* functions for each 256x256 tile management. So grid_place() function can be simple now. (4) Download idler Before download is not a job or idler and is integrated with grid calculation. I have separated this into independent idler. So now, download idler do download jobs when idler time. (5) Zoom I have made one zoom_do() function. This does all zoom jobs. At now, pinch_zoom & wheel_zoom & animated zoom do not much jobs. just call zoom_do(). (6) Delayed jobs As I know, evas is based on a retained mode and calculation can be do later. So sometimes elm_map APIs can not do the jobs correctly. For example, elm_map_marker_list_show() or elm_map_zoom_set() can not be used right after elm_map_add() because window size and pan size can be 0. (refer map_example_02.c) So when APIs related such calculation are called. These are deferred and calculated later when _pan_calculate() is called. 5) Code clean-up I have removed unused variables & functions. and rearranged struct & functions & declaration & static variables, etc. Instead of "if (!wd) return; ", I changed this by macro, "EINA_SAFETY_ON_NULL_RETURN(wd);". This is better for function entrance check. Also ELM_NEW is used instead of calloc or malloc. Aboves are all related each other. So it can be hard to split this file. If these should be splitted, I'm going to freak ;D. This patch does no harm!!!! :D. After this patch, I will add overlay APIs based on this patch. I doubt whether I will add this before elementary 1.0 release. :( git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/elementary@68207 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- src/bin/test_map.c | 65 +- src/examples/map_example_02.c | 8 - src/lib/elm_map.c | 4469 +++++++++++++++++------------------------ 3 files changed, 1910 insertions(+), 2632 deletions(-) diff --git a/src/bin/test_map.c b/src/bin/test_map.c index 7f2da19..8600469 100644 --- a/src/bin/test_map.c +++ b/src/bin/test_map.c @@ -20,10 +20,9 @@ typedef struct Map_Source } Map_Source; static Elm_Map_Marker_Class *itc1, *itc2, *itc_parking; -static Elm_Map_Group_Class *itc_group1, *itc_group2, *itc_group_parking; +static Elm_Map_Group_Class *itc_group1, *itc_group2, *itc_group_parking, *route_group; -static Evas_Object *rect, *menu, *fs_win; -static int nb_elts; +static Evas_Object *menu, *fs_win; /*static Elm_Map_Marker *markers[MARKER_MAX];*/ static Elm_Map_Marker *route_from, *route_to; static Elm_Map_Route *route; @@ -88,14 +87,14 @@ my_map_press(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_inf static void my_map_longpressed(void *data __UNUSED__, Evas_Object *obj, void *event_info) { - printf("longpressed\n"); + if (!event_info) return; double lon, lat; Evas_Event_Mouse_Down *down = (Evas_Event_Mouse_Down *)event_info; - if (!down) return; - if (elm_map_zoom_get(obj) < 5) return; - elm_map_canvas_to_geo_convert(obj, down->canvas.x, down->canvas.y, &lon, &lat); - printf("x:%d, y:%d, lon:%lf, lat:%lf\n", down->canvas.x, down->canvas.y, lon, lat); + printf("longpressed, x:%d, y:%d, lon:%lf, lat:%lf\n", down->canvas.x, down->canvas.y, lon, lat); + + if (elm_map_zoom_get(obj) < 5) return; + if (name) elm_map_name_remove(name); name = elm_map_utils_convert_coord_into_name(obj, lon, lat); } @@ -111,15 +110,18 @@ my_map_clicked_double(void *data __UNUSED__, Evas_Object *obj, void *event_info) elm_map_canvas_to_geo_convert(obj, down->canvas.x, down->canvas.y, &lon, &lat); printf("x:%d, y:%d, lon:%lf, lat:%lf\n", down->canvas.x, down->canvas.y, lon, lat); - itc1 = elm_map_marker_class_new(obj); + if (!itc1) itc1 = elm_map_marker_class_new(obj); elm_map_marker_class_del_cb_set(itc1, NULL); - itc_group1 = elm_map_group_class_new(obj); - 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); + if (!route_group) + { + route_group = elm_map_group_class_new(obj); + elm_map_group_class_icon_cb_set(route_group, _group_icon_get); + elm_map_group_class_data_set(route_group, (void *)PACKAGE_DATA_DIR"/images/bubble.png"); + elm_map_group_class_style_set(route_group, "empty"); + elm_map_group_class_zoom_displayed_set(route_group, 5); + } if (route_from && route_to) { @@ -130,8 +132,8 @@ my_map_clicked_double(void *data __UNUSED__, Evas_Object *obj, void *event_info) elm_map_route_remove(route); } - if (!route_from) route_from = elm_map_marker_add(obj, lon, lat, itc1, itc_group1, NULL); - else route_to = elm_map_marker_add(obj, lon, lat, itc1, itc_group1, NULL); + if (!route_from) route_from = elm_map_marker_add(obj, lon, lat, itc1, route_group, NULL); + else route_to = elm_map_marker_add(obj, lon, lat, itc1, route_group, NULL); if (route_from && route_to) { @@ -201,10 +203,9 @@ my_map_drag_stop(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNU static void my_map_scroll(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) { - printf("scroll\n"); double lon, lat; elm_map_geo_region_get(obj, &lon, &lat); - printf("scroll longitude : %f latitude : %f\n", lon, lat); + printf("scroll, longitude: %f latitude: %f\n", lon, lat); } static void @@ -582,16 +583,6 @@ _group_icon_get(Evas_Object *obj, void *data) } static void -_map_move_resize_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) -{ - int x,y,w,h; - - evas_object_geometry_get(data,&x,&y,&w,&h); - evas_object_resize(rect,w,h); - evas_object_move(rect,x,y); -} - -static void _populate(void *data, Elm_Object_Item *menu_it) { int idx; @@ -729,7 +720,6 @@ test_map(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __ elm_win_resize_object_add(win, map); evas_object_data_set(map, "window", win); - // itc1 = elm_map_marker_class_new(map); elm_map_marker_class_get_cb_set(itc1, _marker_get); elm_map_marker_class_del_cb_set(itc1, NULL); @@ -744,9 +734,7 @@ test_map(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __ elm_map_marker_class_del_cb_set(itc_parking, NULL); elm_map_marker_class_icon_cb_set(itc_parking, _icon_get); elm_map_marker_class_style_set(itc_parking, "empty"); - // - // itc_group1 = elm_map_group_class_new(map); elm_map_group_class_data_set(itc_group1, (void *)PACKAGE_DATA_DIR"/images/plant_01.jpg"); @@ -759,18 +747,7 @@ test_map(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __ elm_map_group_class_data_set(itc_group_parking, (void *)PACKAGE_DATA_DIR"/images/parking.png"); elm_map_group_class_style_set(itc_group_parking, "empty"); elm_map_group_class_zoom_displayed_set(itc_group_parking, 5); - // - - rect = evas_object_rectangle_add(evas_object_evas_get(win)); - evas_object_color_set(rect, 0, 0, 0, 0); - evas_object_repeat_events_set(rect,1); - evas_object_show(rect); - evas_object_raise(rect); - - evas_object_event_callback_add(map, EVAS_CALLBACK_RESIZE, - _map_move_resize_cb, map); - evas_object_event_callback_add(map, EVAS_CALLBACK_MOVE, - _map_move_resize_cb, map); + evas_object_event_callback_add(map, EVAS_CALLBACK_MOUSE_DOWN, _map_mouse_down, map); evas_object_event_callback_add(map, EVAS_CALLBACK_MOUSE_MOVE, @@ -793,8 +770,6 @@ test_map(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __ elm_map_marker_add(map, 7.3165409990833, 48.856078, itc2, itc_group1, &data11); elm_map_marker_add(map, 7.319812, 48.856561, itc2, itc_group2, &data10); - nb_elts = 13; - evas_object_smart_callback_add(map, "clicked", my_map_clicked, map); evas_object_smart_callback_add(map, "press", my_map_press, map); evas_object_smart_callback_add(map, "longpressed", my_map_longpressed, map); diff --git a/src/examples/map_example_02.c b/src/examples/map_example_02.c index 7557f20..0a8a8c0 100644 --- a/src/examples/map_example_02.c +++ b/src/examples/map_example_02.c @@ -94,13 +94,6 @@ _group_country_content_get(Evas_Object *obj, void *data __UNUSED__) } static void -_map_downloaded(void *data __UNUSED__, Evas_Object *obj, void *ev __UNUSED__) -{ - elm_map_zoom_set(obj, 3); - evas_object_smart_callback_del(obj, "downloaded", _map_downloaded); -} - -static void _bt_zoom_in(void *data, Evas_Object *obj __UNUSED__, void *ev __UNUSED__) { Evas_Object *map = data; @@ -241,7 +234,6 @@ elm_main(int argc __UNUSED__, char **argv __UNUSED__) markers = eina_list_append(markers, m); elm_map_markers_list_show(markers); - evas_object_smart_callback_add(map, "downloaded", _map_downloaded, NULL); evas_object_resize(win, 512, 512); evas_object_show(win); diff --git a/src/lib/elm_map.c b/src/lib/elm_map.c index d9adef9..8c4733b 100644 --- a/src/lib/elm_map.c +++ b/src/lib/elm_map.c @@ -13,14 +13,20 @@ typedef struct _Pan Pan; typedef struct _Grid Grid; typedef struct _Grid_Item Grid_Item; typedef struct _Marker_Group Marker_Group; -typedef struct _Event Event; +typedef struct _Marker_Bubble Marker_Bubble; typedef struct _Path_Node Path_Node; typedef struct _Path_Waypoint Path_Waypoint; typedef struct _Url_Data Url_Data; typedef struct _Route_Dump Route_Dump; typedef struct _Name_Dump Name_Dump; typedef struct _Track_Dump Track_Dump; +typedef struct _Delayed_Data Delayed_Data; +typedef struct _Map_Sources_Tab Map_Sources_Tab; +#define ROUND(z) (((z) < 0) ? (int)ceil((z) - 0.005) : (int)floor((z) + 0.005)) +#define EVAS_MAP_POINT 4 +#define DEFAULT_TILE_SIZE 256 +#define MARER_MAX_NUMBER 30 #define CACHE_ROOT_PATH "/tmp/elm_map" #define CACHE_PATH CACHE_ROOT_PATH"/%d/%d/%d" #define CACHE_FILE_PATH "%s/%d.png" @@ -35,31 +41,62 @@ typedef struct _Track_Dump Track_Dump; #define YOURS_DESCRIPTION "description" #define YOURS_COORDINATES "coordinates" -// TODO: fix monav & ors url -#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" -#define PINCH_ZOOM_MIN 0.25 -#define PINCH_ZOOM_MAX 4.0 #define MAX_CONCURRENT_DOWNLOAD 10 +/* FIXME: This is unused currently #define GPX_NAME "name>" #define GPX_COORDINATES "trkpt " #define GPX_LON "lon" #define GPX_LAT "lat" #define GPX_ELE "ele>" #define GPX_TIME "time>" +*/ + +enum _Route_Xml_Attribute +{ + ROUTE_XML_NONE, + ROUTE_XML_DISTANCE, + ROUTE_XML_DESCRIPTION, + ROUTE_XML_COORDINATES, + ROUTE_XML_LAST +} Route_Xml_Attibute; + +enum _Name_Xml_Attribute +{ + NAME_XML_NONE, + NAME_XML_NAME, + NAME_XML_LON, + NAME_XML_LAT, + NAME_XML_LAST +} Name_Xml_Attibute; + +enum _Track_Xml_Attribute +{ + TRACK_XML_NONE, + TRACK_XML_COORDINATES, + TRACK_XML_LAST +} Track_Xml_Attibute; + +struct _Delayed_Data +{ + void (*func)(void *data); + Widget_Data *wd; + Elm_Map_Zoom_Mode mode; + int zoom; + double lon, lat; + Eina_List *markers; +}; // 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 -typedef struct _Map_Sources_Tab +struct _Map_Sources_Tab { const char *name; int zoom_min; @@ -70,29 +107,6 @@ typedef struct _Map_Sources_Tab ElmMapModuleNameUrlFunc name_url_cb; ElmMapModuleGeoIntoCoordFunc geo_into_coord; ElmMapModuleCoordIntoGeoFunc coord_into_geo; -} Map_Sources_Tab; - -//Zemm min is supposed to be 0 -static char *_mapnik_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom); -static char *_osmarender_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom); -static char *_cyclemap_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom); -static char *_mapquest_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom); -static char *_mapquest_aerial_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom); - -static char *_yours_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat); -/* -static char *_monav_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat) -static char *_ors_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 Map_Sources_Tab default_map_sources_tab[] = -{ - {"Mapnik", 0, 18, _mapnik_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb, _nominatim_url_cb, NULL, NULL}, - {"Osmarender", 0, 17, _osmarender_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb, _nominatim_url_cb, NULL, NULL}, - {"CycleMap", 0, 16, _cyclemap_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb, _nominatim_url_cb, NULL, NULL}, - {"MapQuest", 0, 18, _mapquest_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb, _nominatim_url_cb, NULL, NULL}, - {"MapQuest Open Aerial", 0, 11, _mapquest_aerial_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb, _nominatim_url_cb, NULL, NULL}, }; struct _Url_Data @@ -106,78 +120,68 @@ struct _Url_Data struct _Elm_Map_Marker_Class { const char *style; - int zoom_displayed; - struct _Elm_Map_Marker_Class_Func { ElmMapMarkerGetFunc get; ElmMapMarkerDelFunc del; //if NULL the object will be destroyed with evas_object_del() ElmMapMarkerIconGetFunc icon_get; } func; - - struct - { //this part is private, do not modify these values - Eina_Bool set : 1; - Evas_Coord edje_w, edje_h; - } priv; }; -struct _Elm_Map_Marker +struct _Elm_Map_Group_Class { Widget_Data *wd; - Elm_Map_Marker_Class *clas; - Elm_Map_Group_Class *clas_group; - double longitude, latitude; - - Evas_Coord map_size; - Evas_Coord *x, *y; - void *data; - Marker_Group **groups; - Evas_Object *content; -}; -struct _Elm_Map_Group_Class -{ + Eina_List *markers; + int zoom_displayed; // display the group if the zoom is >= to zoom_display + int zoom_grouped; // group the markers only if the zoom is <= to zoom_groups const char *style; void *data; - int zoom_displayed; // display the group if the zoom is >= to zoom_display - int zoom_grouped; // group the markers only if the zoom is <= to zoom_groups - Eina_Bool hide : 1; - struct { ElmMapGroupIconGetFunc icon_get; } func; - struct - { //this part is private, do not modify these values - Eina_Bool set : 1; - Evas_Coord edje_w, edje_h; - Evas_Coord edje_max_w, edje_max_h; - - Eina_List *objs_used; - Eina_List *objs_notused; - } priv; + Eina_Bool hide : 1; +}; + +struct _Marker_Bubble +{ + Widget_Data *wd; + Evas_Object *pobj; + Evas_Object *obj, *sc, *bx; +}; + +struct _Elm_Map_Marker +{ + Widget_Data *wd; + Elm_Map_Marker_Class *clas; + Elm_Map_Group_Class *group_clas; + double longitude, latitude; + Evas_Coord w, h; + Evas_Object *obj; + + Evas_Coord x, y; + Eina_Bool grouped : 1; + Eina_Bool leader : 1; // if marker is group leader + Marker_Group *group; + + Marker_Bubble *bubble; + Evas_Object *content; + void *data; }; struct _Marker_Group { Widget_Data *wd; - Eina_Matrixsparse_Cell *cell; Elm_Map_Group_Class *clas; + Evas_Coord w, h; + Evas_Object *obj; - Eina_List *markers; - long long sum_x, sum_y; Evas_Coord x, y; - Evas_Coord w, h; + Eina_List *markers; - Evas_Object *obj, *bubble, *sc, *bx, *rect; - Eina_Bool open : 1; - Eina_Bool bringin : 1; - Eina_Bool update_nbelems : 1; - Eina_Bool update_resize : 1; - Eina_Bool update_raise : 1; - Eina_Bool delete_object : 1; + Marker_Bubble *bubble; }; struct _Elm_Map_Route @@ -250,218 +254,152 @@ struct _Elm_Map_Name Ecore_Event_Handler *handler; }; +struct _Route_Dump +{ + int id; + char *fname; + double distance; + char *description; + char *coordinates; +}; + +struct _Name_Dump +{ + int id; + char *address; + double lon; + double lat; +}; + struct _Grid_Item { - Widget_Data *wd; Grid *g; - int zoom; + + Widget_Data *wd; Evas_Object *img; - //Evas_Object *txt; const char *file; const char *source; - struct - { - int x, y, w, h; - } src, out; - + int x, y; // Tile coordinate Eina_Bool file_have : 1; + Ecore_File_Download_Job *job; - int try_num; }; struct _Grid { Widget_Data *wd; - int tsize; // size of tile (tsize x tsize pixels) int zoom; // zoom level tiles want for optimal display (1, 2, 4, 8) - int iw, ih; // size of image in pixels - int w, h; // size of grid image in pixels (represented by grid) - int gw, gh; // size of grid in tiles + int tw, th; // size of grid in tiles Eina_Matrixsparse *grid; }; +struct _Pan +{ + Evas_Object_Smart_Clipped_Data __clipped_data; + Widget_Data *wd; +}; + struct _Widget_Data { Evas_Object *obj; Evas_Object *scr; Evas_Object *ges; Evas_Object *pan_smart; - Evas_Object *rect; - Evas_Object *sep_maps_markers; //map objects are below this object and marker objects are on top - Pan *pan; - Evas_Coord pan_x, pan_y, minw, minh; + Evas_Object *sep_maps_markers; // Tiles are below this and overlays are on top + Evas_Map *map; + + Map_Sources_Tab *src; + Eina_List *srcs; + const char **src_names; + int zoom_min, zoom_max; + int tsize; int id; - int zoom; - int zoom_method; - Elm_Map_Zoom_Mode mode; + Eina_List *grids; - Ecore_Job *calc_job; - Ecore_Timer *scr_timer; - Ecore_Timer *long_timer; - Ecore_Animator *zoom_animator; - double t; + int zoom; + double zoom_detail; + double prev_lon, prev_lat; + Evas_Coord ox, oy; struct { - int w, h; - int ow, oh, nw, nh; - struct - { - double x, y; - } spos; + int w, h; // Current pixel width, heigth of a grid + int tile; // Current pixel size of a grid item } size; + Elm_Map_Zoom_Mode mode; struct { - Eina_Bool show : 1; - Evas_Coord x, y ,w ,h; - } show; - int tsize; - int nosmooth; - Eina_List *grids; - Eina_Bool resized : 1; - Eina_Bool on_hold : 1; - Eina_Bool paused : 1; - Eina_Bool paused_markers : 1; - - struct - { - Eina_Bool enabled; - double lon, lat; - } center_on; - - Ecore_Job *markers_place_job; - Eina_Matrixsparse **markers; - Eina_List *cells_displayed; // list of Eina_Matrixsparse_Cell - Evas_Coord markers_max_num; - int marker_max_w, marker_max_h; - int marker_zoom; - Eina_List *opened_bubbles; //opened bubbles, list of Map_Group * - - Eina_List *groups_clas; // list of Elm_Map_Group_Class* - Eina_List *markers_clas; // list of Elm_Map_Markers_Class* + double zoom; + double diff; + int cnt; + } ani; + Ecore_Timer *zoom_timer; + Ecore_Animator *zoom_animator; - Elm_Map_Route_Sources route_source; - Eina_List *s_event_list; int try_num; int finish_num; - + int download_num; + Eina_List *download_list; + Ecore_Idler *download_idler; Eina_Hash *ua; const char *user_agent; - Eina_List *route; - Eina_List *track; - Evas_Event_Mouse_Down ev; - Eina_List *names; - int multi_count; - struct - { - Evas_Coord cx, cy; - double level, diff; - } pinch; + Evas_Coord pan_x, pan_y; + Eina_List *delayed_jobs; + + Ecore_Timer *scr_timer; + Ecore_Timer *long_timer; + Evas_Event_Mouse_Down ev; + Eina_Bool on_hold : 1; + Eina_Bool paused : 1; + double pinch_zoom; struct { Evas_Coord cx, cy; double a, d; } rotate; - int wheel_diff; Eina_Bool wheel_disabled : 1; - Eina_Bool scr_started : 1; - Eina_Array *modules; - Eina_List *map_sources_tab; - const char **source_names; - Evas_Map *map; - Ecore_Timer *zoom_timer; - Map_Sources_Tab *src; - const char *gpx_file; - int zoom_min, zoom_max; - Eina_List *download_list; - int download_num; -}; + unsigned int markers_max_num; + Eina_Bool paused_markers : 1; + Eina_List *group_classes; + Eina_List *marker_classes; + Eina_List *markers; -struct _Pan -{ - Evas_Object_Smart_Clipped_Data __clipped_data; - Widget_Data *wd; + Elm_Map_Route_Sources route_source; + Eina_List *route; + Eina_List *track; + Eina_List *names; }; -struct _Event -{ - int device; - - struct - { - Evas_Coord x, y; - } start; - - struct - { - Evas_Coord x, y; - } prev; - - Evas_Coord x, y, w, h; - - Evas_Object *object; - - int pinch_start_dis; - int pinch_dis; -}; +static char *_mapnik_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom); +static char *_osmarender_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom); +static char *_cyclemap_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom); +static char *_mapquest_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom); +static char *_mapquest_aerial_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom); +static char *_yours_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 *_monav_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat) +static char *_ors_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat); +*/ -struct _Route_Dump +static Map_Sources_Tab default_map_sources_tab[] = { - int id; - char *fname; - double distance; - char *description; - char *coordinates; + {"Mapnik", 0, 18, _mapnik_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb, _nominatim_url_cb, NULL, NULL}, + {"Osmarender", 0, 17, _osmarender_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb, _nominatim_url_cb, NULL, NULL}, + {"CycleMap", 0, 16, _cyclemap_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb, _nominatim_url_cb, NULL, NULL}, + {"MapQuest", 0, 18, _mapquest_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb, _nominatim_url_cb, NULL, NULL}, + {"MapQuest Open Aerial", 0, 11, _mapquest_aerial_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb, _nominatim_url_cb, NULL, NULL}, }; -enum _Route_Xml_Attribute -{ - ROUTE_XML_NONE, - ROUTE_XML_DISTANCE, - ROUTE_XML_DESCRIPTION, - ROUTE_XML_COORDINATES, - 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; - -enum _Zoom_Method -{ - ZOOM_METHOD_NONE, - ZOOM_METHOD_IN, - ZOOM_METHOD_OUT, - ZOOM_METHOD_LAST -} Zoom_Mode; - -enum _Track_Xml_Attribute -{ - TRACK_XML_NONE, - TRACK_XML_COORDINATES, - TRACK_XML_LAST -} Track_Xml_Attibute; - -static Evas_Smart_Class _pan_sc = EVAS_SMART_CLASS_INIT_NULL; -static const char *widtype = NULL; -static int idnum = 1; +static const char *widtype = NULL; +static Evas_Smart_Class parent_sc = EVAS_SMART_CLASS_INIT_NULL; +static Evas_Smart_Class sc; +static Evas_Smart *smart; +static int idnum = 1; static const char SIG_CHANGED[] = "changed"; static const char SIG_CLICKED[] = "clicked"; @@ -503,46 +441,12 @@ static const Evas_Smart_Cb_Description _signals[] = { {NULL, NULL} }; -static void _pan_calculate(Evas_Object *obj); - -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); -static void _sizing_eval(Evas_Object *obj); -static void _calc_job(void *data); -static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src, - Evas_Callback_Type type, void *event_info); -static void grid_place(Evas_Object *obj, Grid *g, Evas_Coord px, Evas_Coord py, Evas_Coord ox, Evas_Coord oy, Evas_Coord ow, Evas_Coord oh); -static void grid_load(Evas_Object *obj, Grid *g); - -static void _process_download_list(Evas_Object *obj); -static void _add_download_list(Evas_Object *obj, Grid_Item *gi); - -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); -static void _group_bringin_cb(void *data, Evas_Object *obj, const char *emission, const char *soure); -static void _group_bubble_create(Marker_Group *group); -static void _group_bubble_free(Marker_Group *group); -static void _group_bubble_place(Marker_Group *group); - -static int _group_bubble_content_update(Marker_Group *group); -static void _group_bubble_content_free(Marker_Group *group); -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_hints_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 route_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 track_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 Eina_Bool module_list_cb(Eina_Module *m, void *data) { - ELM_CHECK_WIDTYPE(data, widtype) EINA_FALSE; - Widget_Data *wd = elm_widget_data_get(data); + EINA_SAFETY_ON_NULL_RETURN_VAL(data,EINA_FALSE); + Widget_Data *wd = data; + Map_Sources_Tab *s; ElmMapModuleSourceFunc source; ElmMapModuleZoomMinFunc zoom_min; @@ -555,12 +459,11 @@ module_list_cb(Eina_Module *m, void *data) ElmMapModuleCoordIntoGeoFunc coord_into_geo; const char *file; - if (!wd) return EINA_FALSE; - file = eina_module_file_get(m); if (!eina_module_load(m)) { - ERR("could not load module \"%s\": %s", file, eina_error_msg_get(eina_error_get())); + ERR("could not load module \"%s\": %s", file, + eina_error_msg_get(eina_error_get())); return EINA_FALSE; } @@ -573,14 +476,15 @@ module_list_cb(Eina_Module *m, void *data) name_url = eina_module_symbol_get(m, "map_module_name_url_get"); geo_into_coord = eina_module_symbol_get(m, "map_module_geo_into_coord"); coord_into_geo = eina_module_symbol_get(m, "map_module_coord_into_geo"); - if ((!source) || (!zoom_min) || (!zoom_max) || (!url) || (!route_source) || (!route_url) || (!name_url) || (!geo_into_coord) || (!coord_into_geo)) + if ((!source) || (!zoom_min) || (!zoom_max) || (!url) || (!route_source) || + (!route_url) || (!name_url) || (!geo_into_coord) || (!coord_into_geo)) { - WRN("could not find map_module_source_get() in module \"%s\": %s", file, eina_error_msg_get(eina_error_get())); + WRN("could not find map_module_source_get() in module \"%s\": %s", + file, eina_error_msg_get(eina_error_get())); eina_module_unload(m); return EINA_FALSE; } - s = calloc(1, sizeof(Map_Sources_Tab)); - EINA_SAFETY_ON_NULL_RETURN_VAL(s, EINA_FALSE); + s = ELM_NEW(Map_Sources_Tab); s->name = source(); s->zoom_min = zoom_min(); s->zoom_max = zoom_max(); @@ -590,35 +494,25 @@ module_list_cb(Eina_Module *m, void *data) s->name_url_cb = name_url; s->geo_into_coord = geo_into_coord; s->coord_into_geo = coord_into_geo; - wd->map_sources_tab = eina_list_append(wd->map_sources_tab, s); + wd->srcs = eina_list_append(wd->srcs, s); + eina_module_unload(m); return EINA_TRUE; } static void -module_init(void *data) +source_init(Widget_Data *wd) { - ELM_CHECK_WIDTYPE(data, widtype); - Widget_Data *wd = elm_widget_data_get(data); - - if (!wd) return; - wd->modules = eina_module_list_get(wd->modules, MODULES_PATH, 1, &module_list_cb, data); -} + EINA_SAFETY_ON_NULL_RETURN(wd); -static void -source_init(void *data) -{ - ELM_CHECK_WIDTYPE(data, widtype); - Widget_Data *wd = elm_widget_data_get(data); Map_Sources_Tab *s; - Eina_List *l; unsigned int idx; + Eina_Array *modules = NULL; + Eina_List *l; - if (!wd) return; - for (idx = 0; idx < sizeof(default_map_sources_tab)/sizeof(Map_Sources_Tab); idx++) + for (idx = 0; idx < (sizeof(default_map_sources_tab) / sizeof(Map_Sources_Tab)); idx++) { - s = calloc(1, sizeof(Map_Sources_Tab)); - EINA_SAFETY_ON_NULL_RETURN(s); + s = ELM_NEW(Map_Sources_Tab); s->name = default_map_sources_tab[idx].name; s->zoom_min = default_map_sources_tab[idx].zoom_min; s->zoom_max = default_map_sources_tab[idx].zoom_max; @@ -628,1310 +522,1317 @@ source_init(void *data) s->name_url_cb = default_map_sources_tab[idx].name_url_cb; s->geo_into_coord = default_map_sources_tab[idx].geo_into_coord; s->coord_into_geo = default_map_sources_tab[idx].coord_into_geo; - wd->map_sources_tab = eina_list_append(wd->map_sources_tab, s); - if (!idx) wd->src = s; + wd->srcs = eina_list_append(wd->srcs, s); + if (!idx) + { + wd->src = s; + wd->zoom_min = s->zoom_min; + wd->zoom_max = s->zoom_max; + } } - module_init(data); + modules = eina_module_list_get(modules, MODULES_PATH, 1, &module_list_cb, wd); + eina_array_free(modules); - int n = eina_list_count(wd->map_sources_tab); - wd->source_names = malloc(sizeof(char *) * (n + 1)); - if (!wd->source_names) - { - ERR("init source names failed."); - return; - } + wd->src_names = calloc((eina_list_count(wd->srcs) + 1), sizeof(char *)); idx = 0; - EINA_LIST_FOREACH(wd->map_sources_tab, l, s) + EINA_LIST_FOREACH(wd->srcs, l, s) { - wd->source_names[idx] = strdup(s->name); - INF("source : %s", wd->source_names[idx]); - if (s->zoom_min < wd->zoom_min) wd->zoom_min = s->zoom_min; - if (s->zoom_max > wd->zoom_max) wd->zoom_max = s->zoom_max; + eina_stringshare_replace(&wd->src_names[idx], s->name); + INF("source : %s", wd->src_names[idx]); idx++; } - wd->source_names[idx] = NULL; } static void -obj_rotate_zoom(void *data, Evas_Object *obj) +_edj_marker_size_get(Widget_Data *wd, Evas_Coord *w, Evas_Coord *h) { - ELM_CHECK_WIDTYPE(data, widtype); - Widget_Data *wd = elm_widget_data_get(data); - int ow, oh, iw, ih; - if ((!wd->pinch.cx) && (!wd->pinch.cy)) - { - wd->pinch.cx = wd->rotate.cx; - wd->pinch.cy = wd->rotate.cy; - } + EINA_SAFETY_ON_NULL_RETURN(wd); + EINA_SAFETY_ON_NULL_RETURN(w); + EINA_SAFETY_ON_NULL_RETURN(h); - evas_map_util_points_populate_from_object_full(wd->map, obj, 0); - evas_object_image_size_get(obj, &iw, &ih); - evas_object_geometry_get(obj, NULL, NULL, &ow, &oh); - if ((ow < iw) || (oh < ih)) - { - ow *= (double)iw / ow; - oh *= (double)ih / oh; - evas_map_point_image_uv_set(wd->map, 1, ow, 0); - evas_map_point_image_uv_set(wd->map, 2, ow, oh); - evas_map_point_image_uv_set(wd->map, 3, 0, oh); - } - evas_map_util_zoom(wd->map, wd->pinch.level, wd->pinch.level, wd->pinch.cx, wd->pinch.cy); - evas_map_util_rotate(wd->map, wd->rotate.d, wd->rotate.cx, wd->rotate.cy); - evas_object_map_enable_set(obj, EINA_TRUE); - evas_object_map_set(obj, wd->map); + Evas_Object *edj; + const char *s; + + edj = edje_object_add(evas_object_evas_get(wd->obj)); + _elm_theme_object_set(wd->obj, edj, "map/marker", "radio", + elm_widget_style_get(wd->obj)); + s = edje_object_data_get(edj, "size_w"); + if (s) *w = atoi(s); + else *w = 0; + s = edje_object_data_get(edj, "size_h"); + if (s) *h = atoi(s); + else *h = 0; + evas_object_del(edj); } static void -#ifdef ELM_EMAP -track_place(Evas_Object *obj, Grid *g __UNUSED__, Evas_Coord px, Evas_Coord py, Evas_Coord ox __UNUSED__, Evas_Coord oy __UNUSED__, Evas_Coord ow, Evas_Coord oh) -#else -track_place(Evas_Object *obj __UNUSED__, Grid *g __UNUSED__, Evas_Coord px __UNUSED__, Evas_Coord py __UNUSED__, Evas_Coord ox __UNUSED__, Evas_Coord oy __UNUSED__, Evas_Coord ow __UNUSED__, Evas_Coord oh __UNUSED__) -#endif +_coord_rotate(const Evas_Coord x, const Evas_Coord y, const Evas_Coord cx, const Evas_Coord cy, const double degree, Evas_Coord *xx, Evas_Coord *yy) { -#ifdef ELM_EMAP - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - Eina_List *l; - Evas_Object *route; - int xmin, xmax, ymin, ymax; - - if (!wd) return; - Evas_Coord size = pow(2.0, wd->zoom)*wd->tsize; + EINA_SAFETY_ON_NULL_RETURN(xx); + EINA_SAFETY_ON_NULL_RETURN(yy); - EINA_LIST_FOREACH(wd->track, l, route) - { - elm_map_utils_convert_geo_into_coord(wd->obj, elm_route_lon_min_get(route), elm_route_lat_max_get(route), size, &xmin, &ymin); - elm_map_utils_convert_geo_into_coord(wd->obj, elm_route_lon_max_get(route), elm_route_lat_min_get(route), size, &xmax, &ymax); + double r = (degree * M_PI) / 180.0; + double tx, ty, ttx, tty; - if( !(xmin < px && xmax < px) && !(xmin > px+ow && xmax > px+ow)) - { - if( !(ymin < py && ymax < py) && !(ymin > py+oh && ymax > py+oh)) - { - //display the route - evas_object_move(route, xmin - px + ox, ymin - py + oy); - evas_object_resize(route, xmax - xmin, ymax - ymin); + tx = x - cx; + ty = y - cy; - evas_object_raise(route); - obj_rotate_zoom(obj, route); - evas_object_show(route); + ttx = tx * cos(r); + tty = tx * sin(r); + tx = ttx + (ty * cos(r + M_PI_2)); + ty = tty + (ty * sin(r + M_PI_2)); - continue; - } - } - //the route is not display - evas_object_hide(route); - } -#endif + *xx = tx + cx; + *yy = ty + cy; } + static void -route_place(Evas_Object *obj, Grid *g __UNUSED__, Evas_Coord px, Evas_Coord py, Evas_Coord ox __UNUSED__, Evas_Coord oy __UNUSED__, Evas_Coord ow, Evas_Coord oh) +_viewport_size_get(Widget_Data *wd, Evas_Coord *vw, Evas_Coord *vh) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - Eina_List *lr, *lp, *ln; - Path_Node *n; - Evas_Object *p; - Elm_Map_Route *r; - int nodes; - int x, y, rx, ry; - double a; - - if (!wd) return; - Evas_Coord size = pow(2.0, wd->zoom)*wd->tsize; - - EINA_LIST_FOREACH(wd->route, lr, r) - { - EINA_LIST_FOREACH(r->path, lp, p) - { - evas_object_polygon_points_clear(p); - } - - evas_object_geometry_get(wd->rect, &rx, &ry, NULL, NULL); - nodes = eina_list_count(r->nodes); - - EINA_LIST_FOREACH(r->nodes, ln, n) - { - if ((!wd->zoom) || ((n->idx) && - ((n->idx % (int)ceil((double)nodes/(double)size*100.0))))) continue; - if (r->inbound) - { - elm_map_utils_convert_geo_into_coord(wd->obj, n->pos.lon, n->pos.lat, size, &x, &y); - if ((x >= px - ow) && (x <= (px + ow*2)) && - (y >= py - oh) && (y <= (py + oh*2))) - { - x = x - px + rx; - y = y - py + ry; - - p = eina_list_nth(r->path, n->idx); - a = (double)(y - r->y) / (double)(x - r->x); - if ((abs(a) >= 1) || (r->x == x)) - { - evas_object_polygon_point_add(p, r->x - 3, r->y); - evas_object_polygon_point_add(p, r->x + 3, r->y); - evas_object_polygon_point_add(p, x + 3, y); - evas_object_polygon_point_add(p, x - 3, y); - } - else - { - evas_object_polygon_point_add(p, r->x, r->y - 3); - evas_object_polygon_point_add(p, r->x, r->y + 3); - evas_object_polygon_point_add(p, x, y + 3); - evas_object_polygon_point_add(p, x, y - 3); - } + EINA_SAFETY_ON_NULL_RETURN(wd); - evas_object_color_set(p, r->color.r, r->color.g, r->color.b, r->color.a); - evas_object_raise(p); - obj_rotate_zoom(obj, p); - evas_object_show(p); - r->x = x; - r->y = y; - } - else r->inbound = EINA_FALSE; - } - else - { - elm_map_utils_convert_geo_into_coord(wd->obj, n->pos.lon, n->pos.lat, size, &x, &y); - if ((x >= px - ow) && (x <= (px + ow*2)) && - (y >= py - oh) && (y <= (py + oh*2))) - { - r->x = x - px + rx; - r->y = y - py + ry; - r->inbound = EINA_TRUE; - } - else r->inbound = EINA_FALSE; - } - } - r->inbound = EINA_FALSE; - } + Evas_Coord x, y, w, h; + evas_object_geometry_get(wd->pan_smart, &x, &y, &w, &h); + if (vw) *vw = (x * 2) + w; + if (vh) *vh = (y * 2) + h; } static void -rect_place(Evas_Object *obj, Evas_Coord px, Evas_Coord py, Evas_Coord ox, Evas_Coord oy, Evas_Coord ow, Evas_Coord oh) +_pan_geometry_get(Widget_Data *wd, Evas_Coord *px, Evas_Coord *py) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - Evas_Coord ax, ay, gw, gh, hh, ww; - - if (!wd) return; - evas_object_geometry_get(wd->rect, NULL, NULL, &ww, &hh); - - ax = 0; - ay = 0; - gw = wd->size.w; - gh = wd->size.h; + EINA_SAFETY_ON_NULL_RETURN(wd); - if ((ww == gw) && (hh == gh)) return; + Evas_Coord x, y, vx, vy, vw, vh; + elm_smart_scroller_child_pos_get(wd->scr, &x, &y); + evas_object_geometry_get(wd->pan_smart, &vx, &vy, &vw, &vh); + x = -x; + y = -y; + if (vw > wd->size.w) x += (((vw - wd->size.w) / 2) + vx); + else x -= vx; + if (vh > wd->size.h) y += (((vh - wd->size.h) / 2) + vy); + else y -= vy; + if (px) *px = x; + if (py) *py = y; + } - if (ow > gw) ax = (ow - gw) / 2; - if (oh > gh) ay = (oh - gh) / 2; - evas_object_move(wd->rect, - ox + 0 - px + ax, - oy + 0 - py + ay); - evas_object_resize(wd->rect, gw, gh); +static void +_obj_rotate(Widget_Data *wd, Evas_Object *obj) +{ + Evas_Coord w, h, ow, oh; + evas_map_util_points_populate_from_object(wd->map, obj); - if (wd->show.show) + evas_object_geometry_get(obj, NULL, NULL, &ow, &oh); + evas_object_image_size_get(obj, &w, &h); + if ((w > ow) || (h > oh)) { - wd->show.show = EINA_FALSE; - elm_smart_scroller_child_region_show(wd->scr, wd->show.x, wd->show.y, wd->show.w, wd->show.h); + evas_map_point_image_uv_set(wd->map, 0, 0, 0); + evas_map_point_image_uv_set(wd->map, 1, w, 0); + evas_map_point_image_uv_set(wd->map, 2, w, h); + evas_map_point_image_uv_set(wd->map, 3, 0, h); } + evas_map_util_rotate(wd->map, wd->rotate.d, wd->rotate.cx, wd->rotate.cy); + + evas_object_map_set(obj, wd->map); + evas_object_map_enable_set(obj, EINA_TRUE); } 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) +_obj_place(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - Evas_Coord ax, ay, gw, gh, tx, ty; - Eina_List *l, *markers; - Eina_Matrixsparse_Cell *cell; - Marker_Group *group; - int xx, yy, ww, hh; - char buf[PATH_MAX]; - int y, x; - int g_xx, g_yy, g_hh, g_ww; + EINA_SAFETY_ON_NULL_RETURN(obj); - if (!wd) return; + evas_object_move(obj, x, y); + evas_object_resize(obj, w, h); + evas_object_show(obj); +} - ax = 0; - ay = 0; - gw = wd->size.w; - gh = wd->size.h; - if (ow > gw) ax = (ow - gw) / 2; - if (oh > gh) ay = (oh - gh) / 2; +static void +_bubble_update(Marker_Bubble *bubble, Eina_List *contents) +{ + EINA_SAFETY_ON_NULL_RETURN(bubble); + EINA_SAFETY_ON_NULL_RETURN(contents); - if (wd->zoom != wd->marker_zoom) - { - EINA_LIST_FREE(wd->cells_displayed, cell) - { - EINA_LIST_FOREACH(eina_matrixsparse_cell_data_get(cell), l, group) - { - if (group->obj) _group_object_free(group); - } - } - } - wd->marker_zoom = wd->zoom; - - if ((wd->paused_markers) - && ((wd->size.nw != wd->size.w) || (wd->size.nh != wd->size.h)) ) - return; - - g_xx = wd->pan_x / wd->tsize; - if (g_xx < 0) g_xx = 0; - g_yy = wd->pan_y / wd->tsize; - if (g_yy < 0) g_yy = 0; - g_ww = (ow / wd->tsize) + 1; - if (g_xx + g_ww >= g->gw) g_ww = g->gw - g_xx - 1; - g_hh = (oh / wd->tsize) + 1; - if (g_yy + g_hh >= g->gh) g_hh = g->gh - g_yy - 1; - - //hide groups no more displayed - EINA_LIST_FREE(wd->cells_displayed, cell) - { - eina_matrixsparse_cell_position_get(cell, (unsigned long *)&y, (unsigned long *)&x); - if ((y < g_yy) || (y > g_yy + g_hh) || (x < g_xx) || (x > g_xx + g_ww)) - { - EINA_LIST_FOREACH(eina_matrixsparse_cell_data_get(cell), l, group) - { - if (group->obj) _group_object_free(group); - } - } - } + Eina_List *l; + Evas_Object *c; - if (!wd->marker_zoom) - { - g_ww = 0; - g_hh = 0; - } + elm_box_clear(bubble->bx); + EINA_LIST_FOREACH(contents, l, c) elm_box_pack_end(bubble->bx, c); +} - for (y = g_yy; y <= g_yy + g_hh; y++) - { - for (x = g_xx; x <= g_xx + g_ww; x++) - { - if (!wd->markers[wd->zoom]) continue; - eina_matrixsparse_cell_idx_get(wd->markers[wd->zoom], y, x, &cell); - if (!cell) continue; - wd->cells_displayed = eina_list_append(wd->cells_displayed, cell); - markers = eina_matrixsparse_cell_data_get(cell); - EINA_LIST_FOREACH(markers, l, group) - { - if (!group->markers) continue; - if (group->clas->zoom_displayed > wd->zoom) continue; +static void +_bubble_place(Marker_Bubble *bubble) +{ + EINA_SAFETY_ON_NULL_RETURN(bubble); - xx = group->x; - yy = group->y; - ww = group->w; - hh = group->h; + Evas_Coord x, y, w, h; + Evas_Coord xx, yy, ww, hh; + const char *s; - if (eina_list_count(group->markers) == 1) - { - Elm_Map_Marker *m = eina_list_data_get(group->markers); - ww = m->clas->priv.edje_w; - hh = m->clas->priv.edje_h; - } + if ((!bubble->obj) || (!bubble->pobj)) return; + evas_object_geometry_get(bubble->pobj, &x, &y, &w, NULL); - if (ww <= 0) ww = 1; - if (hh <= 0) hh = 1; + s = edje_object_data_get(bubble->obj, "size_w"); + if (s) ww = atoi(s); + else ww = 0; - if ((gw != g->w) && (g->w > 0)) - { - tx = xx; - xx = ((long long )gw * xx) / g->w; - ww = (((long long)gw * (tx + ww)) / g->w) - xx; - } - if ((gh != g->h) && (g->h > 0)) - { - ty = yy; - yy = ((long long)gh * yy) / g->h; - hh = (((long long)gh * (ty + hh)) / g->h) - yy; - } + edje_object_size_min_calc(bubble->obj, NULL, &hh); + s = edje_object_data_get(bubble->obj, "size_h"); + if (s) h = atoi(s); + else h = 0; + if (hh < h) hh = h; - if ((!group->clas->hide) - && (xx-px+ax+ox >= ox) && (xx-px+ax+ox<= ox+ow) - && (yy-py+ay+oy >= oy) && (yy-py+ay+oy<= oy+oh)) - { - if (!group->obj) _group_object_create(group); + xx = x + (w / 2) - (ww / 2); + yy = y - hh; - if (group->update_nbelems) - { - group->update_nbelems = EINA_FALSE; - if (eina_list_count(group->markers) > 1) - { - snprintf(buf, sizeof(buf), "%d", eina_list_count(group->markers)); - edje_object_part_text_set(elm_layout_edje_get(group->obj), "elm.text", buf); - } - else - edje_object_part_text_set(elm_layout_edje_get(group->obj), "elm.text", ""); - } - evas_object_move(group->obj, - xx - px + ax + ox - ww/2, - yy - py + ay + oy - hh/2); - if ((!wd->paused_markers) || (group->update_resize)) - { - group->update_resize = EINA_FALSE; - evas_object_resize(group->obj, ww, hh); - obj_rotate_zoom(obj, group->obj); - } - if (group->update_raise) - { - group->update_raise = EINA_FALSE; - evas_object_raise(group->obj); - obj_rotate_zoom(obj, group->obj); - evas_object_show(group->obj); - } - if (group->bubble) _group_bubble_place(group); - } - else if (group->obj) - { - _group_object_free(group); - } - } - } - } + _obj_place(bubble->obj, xx, yy, ww, hh); + evas_object_raise(bubble->obj); } static void -grid_place(Evas_Object *obj, Grid *g, Evas_Coord px, Evas_Coord py, Evas_Coord ox, Evas_Coord oy, Evas_Coord ow, Evas_Coord oh) +_bubble_sc_hints_changed_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - Evas_Coord ax, ay, gw, gh, tx, ty; - int xx, yy, ww, hh; + Marker_Bubble *bubble = data; + EINA_SAFETY_ON_NULL_RETURN(bubble); + _bubble_place(data); +} - if (!wd) return; - ax = 0; - ay = 0; - gw = wd->size.w; - gh = wd->size.h; - if (ow > gw) ax = (ow - gw) / 2; - if (oh > gh) ay = (oh - gh) / 2; +static void +_bubble_mouse_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Marker_Bubble *bubble = data; + EINA_SAFETY_ON_NULL_RETURN(bubble); + _bubble_place(bubble); +} - Eina_Iterator *it = eina_matrixsparse_iterator_new(g->grid); - Eina_Matrixsparse_Cell *cell; +static void +_bubble_hide_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Marker_Bubble *bubble = data; + EINA_SAFETY_ON_NULL_RETURN(bubble); + evas_object_hide(bubble->obj); +} - EINA_ITERATOR_FOREACH(it, cell) - { - Grid_Item *gi = eina_matrixsparse_cell_data_get(cell); +static void +_bubble_show_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Marker_Bubble *bubble = data; + EINA_SAFETY_ON_NULL_RETURN(bubble); + _bubble_place(bubble); +} - xx = gi->out.x; - yy = gi->out.y; - ww = gi->out.w; - hh = gi->out.h; - if ((gw != g->w) && (g->w > 0)) - { - tx = xx; - xx = ((long long )gw * xx) / g->w; - ww = (((long long)gw * (tx + ww)) / g->w) - xx; - } - if ((gh != g->h) && (g->h > 0)) - { - ty = yy; - yy = ((long long)gh * yy) / g->h; - hh = (((long long)gh * (ty + hh)) / g->h) - yy; - } - evas_object_move(gi->img, - xx - px + ax + ox, - yy - py + ay + oy); +static void +_bubble_move_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Marker_Bubble *bubble = data; + EINA_SAFETY_ON_NULL_RETURN(bubble); + _bubble_place(bubble); +} - evas_object_resize(gi->img, ww, hh); +static void +_bubble_free(Marker_Bubble* bubble) +{ + EINA_SAFETY_ON_NULL_RETURN(bubble); - obj_rotate_zoom(obj, gi->img); - /*evas_object_move(gi->txt, - xx - px + ax + ox, - yy - py + ay + oy); + evas_object_del(bubble->bx); + evas_object_del(bubble->sc); + evas_object_del(bubble->obj); + free(bubble); +} - evas_object_resize(gi->txt, ww, hh); - */ - } - eina_iterator_free(it); +static Marker_Bubble* +_bubble_create(Evas_Object *pobj, Widget_Data *wd) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(pobj, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL); + + Marker_Bubble *bubble = ELM_NEW(Marker_Bubble); + EINA_SAFETY_ON_NULL_RETURN_VAL(bubble, NULL); + + bubble->wd = wd; + bubble->pobj = pobj; + evas_object_event_callback_add(pobj, EVAS_CALLBACK_HIDE, _bubble_hide_cb, + bubble); + evas_object_event_callback_add(pobj, EVAS_CALLBACK_SHOW, _bubble_show_cb, + bubble); + evas_object_event_callback_add(pobj, EVAS_CALLBACK_MOVE, _bubble_move_cb, + bubble); + + bubble->obj = edje_object_add(evas_object_evas_get(pobj)); + _elm_theme_object_set(wd->obj, bubble->obj , "map", "marker_bubble", + elm_widget_style_get(wd->obj)); + evas_object_event_callback_add(bubble->obj, EVAS_CALLBACK_MOUSE_UP, + _bubble_mouse_up_cb, bubble); + + bubble->sc = elm_scroller_add(bubble->obj); + elm_widget_style_set(bubble->sc, "map_bubble"); + elm_scroller_content_min_limit(bubble->sc, EINA_FALSE, EINA_TRUE); + elm_scroller_policy_set(bubble->sc, ELM_SCROLLER_POLICY_AUTO, + ELM_SCROLLER_POLICY_OFF); + elm_scroller_bounce_set(bubble->sc, _elm_config->thumbscroll_bounce_enable, + EINA_FALSE); + edje_object_part_swallow(bubble->obj, "elm.swallow.content", bubble->sc); + evas_object_event_callback_add(bubble->sc, EVAS_CALLBACK_CHANGED_SIZE_HINTS, + _bubble_sc_hints_changed_cb, bubble); + + bubble->bx = elm_box_add(bubble->sc); + evas_object_size_hint_align_set(bubble->bx, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_size_hint_weight_set(bubble->bx, EVAS_HINT_EXPAND, + EVAS_HINT_EXPAND); + elm_box_horizontal_set(bubble->bx, EINA_TRUE); + elm_object_content_set(bubble->sc, bubble->bx); + + return bubble; } static void -_tile_update(Grid_Item *gi) +_marker_group_update(Marker_Group* group, Elm_Map_Group_Class *clas, Eina_List *markers) { - evas_object_image_file_set(gi->img, gi->file, NULL); - Evas_Load_Error err = evas_object_image_load_error_get(gi->img); - if (err != EVAS_LOAD_ERROR_NONE) - { - ERR("Image loading error (%s): %s", gi->file, evas_load_error_str(err)); - ecore_file_remove(gi->file); - gi->file_have = EINA_FALSE; - } - else + EINA_SAFETY_ON_NULL_RETURN(group); + EINA_SAFETY_ON_NULL_RETURN(clas); + EINA_SAFETY_ON_NULL_RETURN(markers); + Widget_Data *wd = clas->wd; + EINA_SAFETY_ON_NULL_RETURN(wd); + + char buf[PATH_MAX]; + Eina_List *l; + Elm_Map_Marker *marker; + int cnt = 0; + int sum_x = 0, sum_y = 0; + + EINA_LIST_FOREACH(markers, l, marker) { - obj_rotate_zoom(gi->wd->obj, gi->img); - evas_object_show(gi->img); - gi->file_have = EINA_TRUE; - //evas_object_text_text_set(gi->txt, gi->file); - //evas_object_show(gi->txt); + sum_x += marker->x; + sum_y += marker->y; + cnt++; } -} -static void -_tile_downloaded(void *data, const char *file __UNUSED__, int status) -{ - Grid_Item *gi = data; + group->x = sum_x / cnt; + group->y = sum_y / cnt; + _edj_marker_size_get(wd, &group->w, &group->h); + group->w *=2; + group->h *=2; + group->clas = clas; + group->markers = markers; - gi->job = NULL; + if (clas->style) elm_layout_theme_set(group->obj, "map/marker", clas->style, + elm_widget_style_get(wd->obj)); + else elm_layout_theme_set(group->obj, "map/marker", "radio", + elm_widget_style_get(wd->obj)); - if (status == 200) - { - DBG("Download success from %s to %s", gi->source, gi->file); - _tile_update(gi); - gi->wd->finish_num++; - } - else - { - WRN("Download failed from %s to %s (%d) ", gi->source, gi->file, status); - ecore_file_remove(gi->file); - gi->file_have = EINA_FALSE; - } - gi->wd->download_num--; - evas_object_smart_callback_call(gi->wd->obj, SIG_DOWNLOADED, NULL); - if (!gi->wd->download_num) + if (clas->func.icon_get) { - edje_object_signal_emit(elm_smart_scroller_edje_object_get(gi->wd->scr), "elm,state,busy,stop", "elm"); - evas_object_smart_callback_call(gi->wd->obj, SIG_LOADED_DETAIL, NULL); + Evas_Object *icon = NULL; + + icon = elm_object_part_content_get(group->obj, "elm.icon"); + if (icon) evas_object_del(icon); + + icon = clas->func.icon_get(wd->obj, clas->data); + elm_object_part_content_set(group->obj, "elm.icon", icon); } - _process_download_list(gi->wd->obj); + snprintf(buf, sizeof(buf), "%d", cnt); + edje_object_part_text_set(elm_layout_edje_get(group->obj), "elm.text", buf); + + if (group->bubble) + { + Eina_List *l; + Elm_Map_Marker *marker; + Eina_List *contents = NULL; + + EINA_LIST_FOREACH(group->markers, l, marker) + { + Evas_Object *c = marker->clas->func.get(marker->wd->obj, + marker, marker->data); + if (c) contents = eina_list_append(contents, c); + } + _bubble_update(group->bubble, contents); + } } static void -_process_download_list(Evas_Object *obj) +_marker_group_bubble_open_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *soure __UNUSED__) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - Eina_List *l, *ll; - Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh, tx, ty, gw, gh, xx, yy, ww, hh; - Grid_Item *gi; - - evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh); - evas_output_viewport_get(evas_object_evas_get(wd->obj), &cvx, &cvy, &cvw, &cvh); + EINA_SAFETY_ON_NULL_RETURN(data); + Marker_Group *group = data; + Eina_List *l; + Elm_Map_Marker *marker; + Eina_List *contents = NULL; - gw = wd->size.w; - gh = wd->size.h; + if (!group->bubble) group->bubble = _bubble_create(group->obj, group->wd); - EINA_LIST_REVERSE_FOREACH_SAFE(wd->download_list, l, ll, gi) + EINA_LIST_FOREACH(group->markers, l, marker) { - xx = gi->out.x; - yy = gi->out.y; - ww = gi->out.w; - hh = gi->out.h; - - if ((gw != gi->g->w) && (gi->g->w > 0)) - { - tx = xx; - xx = ((long long )gw * xx) / gi->g->w; - ww = (((long long)gw * (tx + ww)) / gi->g->w) - xx; - } - if ((gh != gi->g->h) && (gi->g->h > 0)) - { - ty = yy; - yy = ((long long)gh * yy) / gi->g->h; - hh = (((long long)gh * (ty + hh)) / gi->g->h) - yy; - } - if (!ELM_RECTS_INTERSECT(xx - wd->pan_x + ox, - yy - wd->pan_y + oy, - ww, hh, - cvx, cvy, cvw, cvh) || - (gi->zoom != wd->zoom)) - { - wd->download_list = eina_list_remove(wd->download_list, gi); - continue; - } - - if (gi->wd->download_num >= MAX_CONCURRENT_DOWNLOAD) break; - - Eina_Bool ret = ecore_file_download_full(gi->source, gi->file, _tile_downloaded, NULL, gi, &(gi->job), wd->ua); - if (!ret || !gi->job) ERR("Can't start to download from %s to %s", gi->source, gi->file); - else - { - gi->wd->download_num++; - wd->try_num++; - wd->download_list = eina_list_remove(wd->download_list, gi); - if (wd->download_num == 1) - edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), "elm,state,busy,start", "elm"); - } + if (group->wd->markers_max_num <= eina_list_count(contents)) break; + Evas_Object *c = marker->clas->func.get(marker->wd->obj, + marker, marker->data); + if (c) contents = eina_list_append(contents, c); } + _bubble_update(group->bubble, contents); + _bubble_place(group->bubble); } static void -_add_download_list(Evas_Object *obj, Grid_Item *gi) +_marker_group_bringin_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *soure __UNUSED__) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN(data); - wd->download_list = eina_list_remove(wd->download_list, gi); - wd->download_list = eina_list_append(wd->download_list, gi); - _process_download_list(obj); + double lon, lat; + Marker_Group *group = data; + elm_map_utils_convert_coord_into_geo(group->wd->obj, group->x, group->y, + group->wd->size.w, &lon, &lat); + elm_map_geo_region_bring_in(group->wd->obj, lon, lat); } static void -grid_create_all(Evas_Object *obj) +_marker_group_free(Marker_Group* group) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - Grid *g; - int zoom = 0; + EINA_SAFETY_ON_NULL_RETURN(group); - EINA_SAFETY_ON_NULL_RETURN(wd); - EINA_SAFETY_ON_NULL_RETURN(wd->src); + if (group->bubble) _bubble_free(group->bubble); - for (zoom = wd->src->zoom_min; zoom <= wd->src->zoom_max; zoom++) - { - g = calloc(1, sizeof(Grid)); - EINA_SAFETY_ON_NULL_RETURN(g); - g->zoom = zoom; - g->tsize = wd->tsize; - g->wd = wd; - int size = pow(2.0, g->zoom); - g->gw = size; - g->gh = size; - g->w = g->tsize * g->gw; - g->h = g->tsize * g->gh; + eina_list_free(group->markers); + evas_object_del(group->obj); - g->grid = eina_matrixsparse_new(g->gh, g->gw, NULL, NULL); - wd->grids = eina_list_append(wd->grids, g); - } + free(group); } -static void -grid_clear_all(Evas_Object *obj) +static Marker_Group* +_marker_group_create(Widget_Data *wd) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - Grid *g; - Grid_Item *gi; - - EINA_SAFETY_ON_NULL_RETURN(wd); + EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL); - EINA_LIST_FREE(wd->grids, g) - { - Eina_Iterator *it = eina_matrixsparse_iterator_new(g->grid); - Eina_Matrixsparse_Cell *cell; + Marker_Group *group = ELM_NEW(Marker_Group); - EINA_ITERATOR_FOREACH(it, cell) - { - gi = eina_matrixsparse_cell_data_get(cell); - evas_object_del(gi->img); - //evas_object_del(gi->txt); + group->wd = wd; + group->obj = elm_layout_add(wd->obj); + evas_object_smart_member_add(group->obj, wd->pan_smart); + evas_object_stack_above(group->obj, wd->sep_maps_markers); + elm_layout_theme_set(group->obj, "map/marker", "radio", + elm_widget_style_get(wd->obj)); + edje_object_signal_callback_add(elm_layout_edje_get(group->obj), + "open", "elm", _marker_group_bubble_open_cb, + group); + edje_object_signal_callback_add(elm_layout_edje_get(group->obj), + "bringin", "elm", _marker_group_bringin_cb, + group); + return group; +} - if (gi->job) - { - DBG("DOWNLOAD abort %s", gi->file); - ecore_file_download_abort(gi->job); - ecore_file_remove(gi->file); - gi->file_have = EINA_FALSE; - gi->job = NULL; - wd->try_num--; - } - if (gi->file) eina_stringshare_del(gi->file); - if (gi->source) eina_stringshare_del(gi->source); - free(gi); - } - eina_matrixsparse_free(g->grid); - eina_iterator_free(it); - free(g); - } +static void +_marker_bringin_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *soure __UNUSED__) +{ + Elm_Map_Marker *marker = data; + EINA_SAFETY_ON_NULL_RETURN(marker); + elm_map_geo_region_bring_in(marker->wd->obj, marker->longitude, marker->latitude); +} - EINA_LIST_FREE(wd->download_list, gi); - if (!ecore_file_recursive_rm("/tmp/elm_map/")) WRN("Deletion of /tmp/elm_map/ failed"); +static void +_marker_bubble_open_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *soure __UNUSED__) +{ + EINA_SAFETY_ON_NULL_RETURN(data); + Elm_Map_Marker *marker = data; + if (!marker->bubble) marker->bubble = _bubble_create(marker->obj, marker->wd); + evas_object_smart_changed(marker->wd->pan_smart); } static void -grid_unload(Evas_Object *obj, Grid *g) +_marker_update(Elm_Map_Marker *marker) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - - Eina_Iterator *it; - Eina_Matrixsparse_Cell *cell; - Grid_Item *gi; + EINA_SAFETY_ON_NULL_RETURN(marker); + Elm_Map_Marker_Class *clas = marker->clas; + EINA_SAFETY_ON_NULL_RETURN(clas); - EINA_SAFETY_ON_NULL_RETURN(wd); + if (clas->style) elm_layout_theme_set(marker->obj, "map/marker", clas->style, + elm_widget_style_get(marker->wd->obj)); + else elm_layout_theme_set(marker->obj, "map/marker", "radio", + elm_widget_style_get(marker->wd->obj)); - it = eina_matrixsparse_iterator_new(g->grid); - EINA_ITERATOR_FOREACH(it, cell) + if (clas->func.icon_get) { - gi = eina_matrixsparse_cell_data_get(cell); + Evas_Object *icon = NULL; - if (gi->file_have) - { - evas_object_hide(gi->img); - //evas_object_hide(gi->txt); - evas_object_image_file_set(gi->img, NULL, NULL); - } - else if (gi->job) + icon = elm_object_part_content_get(marker->obj, "elm.icon"); + if (icon) evas_object_del(icon); + + icon = clas->func.icon_get(marker->wd->obj, marker, marker->data); + elm_object_part_content_set(marker->obj, "elm.icon", icon); + } + + elm_map_utils_convert_geo_into_coord(marker->wd->obj, marker->longitude, + marker->latitude, marker->wd->size.w, + &(marker->x), &(marker->y)); + + if (marker->bubble) + { + if (marker->content) evas_object_del(marker->content); + if (marker->clas->func.get) + marker->content = marker->clas->func.get(marker->wd->obj, marker, + marker->data); + if (marker->content) { - DBG("DOWNLOAD abort %s", gi->file); - ecore_file_download_abort(gi->job); - ecore_file_remove(gi->file); - gi->job = NULL; - wd->try_num--; + Eina_List *contents = NULL; + contents = eina_list_append(contents, marker->content); + _bubble_update(marker->bubble, contents); } - } - eina_iterator_free(it); + } } + static void -grid_load(Evas_Object *obj, Grid *g) +_marker_place(Widget_Data *wd) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - int x, y; - int size; - Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh, tx, ty, gw, gh, xx, yy, ww, hh; - Eina_Iterator *it; - Eina_Matrixsparse_Cell *cell; - Grid_Item *gi; - EINA_SAFETY_ON_NULL_RETURN(wd); - EINA_SAFETY_ON_NULL_RETURN(wd->src); - evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh); - evas_output_viewport_get(evas_object_evas_get(wd->obj), &cvx, &cvy, &cvw, &cvh); + Eina_List *l; - gw = wd->size.w; - gh = wd->size.h; + Elm_Map_Marker *marker; + Elm_Map_Group_Class *group_clas; - if ((gw <= 0) || (gh <= 0)) return; + Evas_Coord gw, gh; + Evas_Coord px, py; - size = g->tsize; - if ((gw != g->w) && (g->w > 0)) - size = ((long long)gw * size) / g->w; - if (size < (g->tsize / 2)) return; // else we will load to much tiles + if (wd->paused_markers || (!eina_list_count(wd->markers))) return; - it = eina_matrixsparse_iterator_new(g->grid); + _pan_geometry_get(wd, &px, &py); - EINA_ITERATOR_FOREACH(it, cell) - { - gi = eina_matrixsparse_cell_data_get(cell); + _edj_marker_size_get(wd, &gw, &gh); + gw *= 2; + gh *= 2; - xx = gi->out.x; - yy = gi->out.y; - ww = gi->out.w; - hh = gi->out.h; + EINA_LIST_FOREACH(wd->markers, l, marker) + { + _marker_update(marker); + marker->grouped = EINA_FALSE; + marker->leader = EINA_FALSE; + } - if ((gw != g->w) && (g->w > 0)) - { - tx = xx; - xx = ((long long )gw * xx) / g->w; - ww = (((long long)gw * (tx + ww)) / g->w) - xx; - } - if ((gh != g->h) && (g->h > 0)) + EINA_LIST_FOREACH(wd->group_classes, l, group_clas) + { + Eina_List *ll; + EINA_LIST_FOREACH(group_clas->markers, ll, marker) { - ty = yy; - yy = ((long long)gh * yy) / g->h; - hh = (((long long)gh * (ty + hh)) / g->h) - yy; - } + Eina_List *lll; + Elm_Map_Marker *mm; + Eina_List *markers = NULL; - if (!ELM_RECTS_INTERSECT(xx - wd->pan_x + ox, - yy - wd->pan_y + oy, - ww, hh, - cvx, cvy, cvw, cvh)) - { - if (gi->file_have) + if (marker->grouped) continue; + if (group_clas->zoom_grouped < wd->zoom) { - evas_object_hide(gi->img); - //evas_object_hide(gi->txt); - evas_object_image_file_set(gi->img, NULL, NULL); + marker->grouped = EINA_FALSE; + continue; } - else if (gi->job) + + EINA_LIST_FOREACH(group_clas->markers, lll, mm) { - DBG("Download abort %s", gi->file); - ecore_file_download_abort(gi->job); - ecore_file_remove(gi->file); - gi->job = NULL; - wd->try_num--; + if (marker == mm || mm->grouped) continue; + if (ELM_RECTS_INTERSECT(mm->x, mm->y, mm->w, mm->h, + marker->x, marker->y, gw, gh)) + { + // mm is group follower. + mm->leader = EINA_FALSE; + mm->grouped = EINA_TRUE; + markers = eina_list_append(markers, mm); + } } + if (eina_list_count(markers) >= 1) + { + // marker is group leader. + marker->leader = EINA_TRUE; + marker->grouped = EINA_TRUE; + markers = eina_list_append(markers, marker); + + if (!marker->group) marker->group = _marker_group_create(wd); + _marker_group_update(marker->group, group_clas, markers); + } } } - eina_iterator_free(it); - - xx = wd->pan_x / size - 1; - if (xx < 0) xx = 0; - yy = wd->pan_y / size - 1; - if (yy < 0) yy = 0; - - ww = ow / size + 2; - if (xx + ww >= g->gw) ww = g->gw - xx - 1; + EINA_LIST_FOREACH(wd->markers, l, marker) + { - hh = oh / size + 2; - if (yy + hh >= g->gh) hh = g->gh - yy - 1; + if (marker->grouped || + (marker->group_clas && + (marker->group_clas->hide || + marker->group_clas->zoom_displayed > wd->zoom))) + evas_object_hide(marker->obj); + else + { + Evas_Coord x, y; + _coord_rotate(marker->x + px, marker->y + py, wd->rotate.cx, + wd->rotate.cy, wd->rotate.d, &x, &y); + _obj_place(marker->obj, x - (marker->w / 2), y - (marker->h / 2), + marker->w, marker->h); + } + } - for (y = yy; y <= yy + hh; y++) + EINA_LIST_FOREACH(wd->markers, l, marker) { - for (x = xx; x <= xx + ww; x++) + Marker_Group *group = marker->group; + if (!group) continue; + + if (!marker->leader || (group->clas->hide) || + (group->clas->zoom_displayed > wd->zoom)) + evas_object_hide(group->obj); + else { - gi = eina_matrixsparse_data_idx_get(g->grid, y, x); + Evas_Coord x, y; + _coord_rotate(group->x + px, group->y + py, wd->rotate.cx, + wd->rotate.cy, wd->rotate.d, &x, &y); + _obj_place(group->obj, x - (group->w / 2), y - (group->h / 2), + group->w, group->h); + } + } +} - if (!gi) - { - char buf[PATH_MAX]; - char buf2[PATH_MAX]; - char *source; - - gi = calloc(1, sizeof(Grid_Item)); - EINA_SAFETY_ON_NULL_RETURN(gi); - - gi->wd = wd; - gi->g = g; - gi->zoom = g->zoom; - gi->file_have = EINA_FALSE; - gi->job = NULL; - - gi->src.x = x * g->tsize; - gi->src.y = y * g->tsize; - gi->src.w = g->tsize; - gi->src.h = g->tsize; - - gi->out.x = gi->src.x; - gi->out.y = gi->src.y; - gi->out.w = gi->src.w; - gi->out.h = gi->src.h; - - gi->img = evas_object_image_add(evas_object_evas_get(obj)); - evas_object_image_scale_hint_set(gi->img, EVAS_IMAGE_SCALE_HINT_DYNAMIC); - evas_object_image_filled_set(gi->img, 1); - - evas_object_smart_member_add(gi->img, wd->pan_smart); - elm_widget_sub_object_add(obj, gi->img); - evas_object_pass_events_set(gi->img, EINA_TRUE); - evas_object_stack_below(gi->img, wd->sep_maps_markers); - -/* gi->txt = evas_object_text_add(evas_object_evas_get(obj)); - evas_object_text_font_set(gi->txt, "Vera", 12); - evas_object_color_set(gi->txt, 100, 100, 100, 255); - evas_object_smart_member_add(gi->txt, - wd->pan_smart); - elm_widget_sub_object_add(obj, gi->txt); - evas_object_pass_events_set(gi->txt, EINA_TRUE); -*/ - snprintf(buf, sizeof(buf), CACHE_PATH, wd->id, g->zoom, x); - snprintf(buf2, sizeof(buf2), CACHE_FILE_PATH, buf, y); - if (!ecore_file_exists(buf)) ecore_file_mkpath(buf); - eina_stringshare_replace(&gi->file, buf2); - source = wd->src->url_cb(obj, x, y, g->zoom); - if ((!source) || (strlen(source)==0)) - { - eina_stringshare_replace(&gi->source, NULL); - WRN("Getting source url failed: %s", gi->file); - } - else eina_stringshare_replace(&gi->source, source); - if (source) free(source); +static void +_grid_item_coord_get(Grid_Item *gi, int *x, int *y, int *w, int *h) +{ + EINA_SAFETY_ON_NULL_RETURN(gi); - eina_matrixsparse_data_idx_set(g->grid, y, x, gi); - } + if (x) *x = gi->x * gi->wd->size.tile; + if (y) *y = gi->y * gi->wd->size.tile; + if (w) *w = gi->wd->size.tile; + if (h) *h = gi->wd->size.tile; +} - if (gi->file_have) - { - DBG("File exists: %s", gi->file); - _tile_update(gi); - } - else if (!gi->job) - { - DBG("Added to download list: %s", gi->file); - _add_download_list(obj, gi); - } - } - } +static Eina_Bool +_grid_item_intersect(Grid_Item *gi) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(gi, EINA_FALSE); + + Evas_Coord px, py; + Evas_Coord vw, vh; + Evas_Coord x, y, w, h; + + _pan_geometry_get(gi->wd, &px, &py); + _viewport_size_get(gi->wd, &vw, &vh); + _grid_item_coord_get(gi, &x, &y, &w, &h); + return ELM_RECTS_INTERSECT(x + px, y + py, w, h, 0, 0, vw, vh); } static void -_smooth_update(Evas_Object *obj) +_grid_item_update(Grid_Item *gi) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - Eina_List *l; - Grid *g; + evas_object_image_file_set(gi->img, gi->file, NULL); + if (!gi->wd->zoom_timer && !gi->wd->scr_timer) + evas_object_image_smooth_scale_set(gi->img, EINA_TRUE); + else evas_object_image_smooth_scale_set(gi->img, EINA_FALSE); - if (!wd) return; - EINA_LIST_FOREACH(wd->grids, l, g) + Evas_Load_Error err = evas_object_image_load_error_get(gi->img); + if (err != EVAS_LOAD_ERROR_NONE) { - Eina_Iterator *it = eina_matrixsparse_iterator_new(g->grid); - Eina_Matrixsparse_Cell *cell; + ERR("Image loading error (%s): %s", gi->file, evas_load_error_str(err)); + ecore_file_remove(gi->file); + gi->file_have = EINA_FALSE; + } + else + { + Evas_Coord px, py; + Evas_Coord x, y, w, h; - EINA_ITERATOR_FOREACH(it, cell) - { - Grid_Item *gi = eina_matrixsparse_cell_data_get(cell); - evas_object_image_smooth_scale_set(gi->img, (!wd->nosmooth)); - } - eina_iterator_free(it); + _pan_geometry_get(gi->wd, &px, &py); + _grid_item_coord_get(gi, &x, &y, &w, &h); + + _obj_place(gi->img, x + px, y + py, w, h); + _obj_rotate(gi->wd, gi->img); + gi->file_have = EINA_TRUE; } } -static Eina_Bool -_scr_timeout(void *data) +static void +_grid_item_load(Grid_Item *gi) { - ELM_CHECK_WIDTYPE(data, widtype) ECORE_CALLBACK_CANCEL; - Widget_Data *wd = elm_widget_data_get(data); - - if (!wd) return ECORE_CALLBACK_CANCEL; - wd->nosmooth--; - if (!wd->nosmooth) _smooth_update(data); - wd->scr_timer = NULL; - return ECORE_CALLBACK_CANCEL; + EINA_SAFETY_ON_NULL_RETURN(gi); + if (gi->file_have) _grid_item_update(gi); + else if (!gi->job) + { + gi->wd->download_list = eina_list_remove(gi->wd->download_list, gi); + gi->wd->download_list = eina_list_append(gi->wd->download_list, gi); + } } static void -_scr(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +_grid_item_unload(Grid_Item *gi) { - ELM_CHECK_WIDTYPE(data, widtype); - Widget_Data *wd = elm_widget_data_get(data); + EINA_SAFETY_ON_NULL_RETURN(gi); + if (gi->file_have) + { + evas_object_hide(gi->img); + evas_object_image_file_set(gi->img, NULL, NULL); + } + else if (gi->job) + { + ecore_file_download_abort(gi->job); + ecore_file_remove(gi->file); + gi->job = NULL; + gi->wd->try_num--; + } + else gi->wd->download_list = eina_list_remove(gi->wd->download_list, gi); + +} + +static Grid_Item * +_grid_item_create(Grid *g, Evas_Coord x, Evas_Coord y) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(g, NULL); + char buf[PATH_MAX]; + char buf2[PATH_MAX]; + char *source; + Grid_Item *gi; + + gi = ELM_NEW(Grid_Item); + gi->wd = g->wd; + gi->g = g; + gi->x = x; + gi->y = y; + + gi->file_have = EINA_FALSE; + gi->job = NULL; + + gi->img = evas_object_image_add(evas_object_evas_get(g->wd->obj)); + evas_object_image_smooth_scale_set(gi->img, EINA_FALSE); + evas_object_image_scale_hint_set(gi->img, EVAS_IMAGE_SCALE_HINT_DYNAMIC); + evas_object_image_filled_set(gi->img, 1); + evas_object_smart_member_add(gi->img, g->wd->pan_smart); + evas_object_pass_events_set(gi->img, EINA_TRUE); + evas_object_stack_below(gi->img, g->wd->sep_maps_markers); - if (!wd) return; - if (!wd->scr_timer) + snprintf(buf, sizeof(buf), CACHE_PATH, g->wd->id, g->zoom, x); + snprintf(buf2, sizeof(buf2), CACHE_FILE_PATH, buf, y); + if (!ecore_file_exists(buf)) ecore_file_mkpath(buf); + + eina_stringshare_replace(&gi->file, buf2); + source = g->wd->src->url_cb(g->wd->obj, x, y, g->zoom); + if ((!source) || (!strlen(source))) { - wd->nosmooth++; - if (wd->nosmooth == 1) _smooth_update(data); + eina_stringshare_replace(&gi->source, NULL); + ERR("Getting source url failed: %s", gi->file); } - if (wd->scr_timer) ecore_timer_del(wd->scr_timer); - wd->scr_timer = ecore_timer_add(0.5, _scr_timeout, data); + else eina_stringshare_replace(&gi->source, source); + if (source) free(source); + eina_matrixsparse_data_idx_set(g->grid, y, x, gi); + return gi; } static void -zoom_do(Evas_Object *obj) +_grid_item_free(Grid_Item *gi) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - Evas_Coord xx, yy, ow, oh; + EINA_SAFETY_ON_NULL_RETURN(gi); - if (!wd) return; - wd->size.w = wd->size.nw; - wd->size.h = wd->size.nh; + _grid_item_unload(gi); + if (gi->g && gi->g->grid) eina_matrixsparse_data_idx_set(gi->g->grid, + gi->y, gi->x, NULL); + if (gi->source) eina_stringshare_del(gi->source); + if (gi->file) eina_stringshare_del(gi->file); + if (gi->img) evas_object_del(gi->img); + if (gi->file_have) ecore_file_remove(gi->file); + free(gi); +} - elm_smart_scroller_child_viewport_size_get(wd->scr, &ow, &oh); +static void +_downloaded_cb(void *data, const char *file __UNUSED__, int status) +{ + Grid_Item *gi = data; - if (wd->center_on.enabled) + if (status == 200) { - elm_map_utils_convert_geo_into_coord(obj, wd->center_on.lon, wd->center_on.lat, wd->size.w, &xx, &yy); - xx -= ow / 2; - yy -= oh / 2; + DBG("Download success from %s to %s", gi->source, gi->file); + _grid_item_update(gi); + gi->wd->finish_num++; } else { - xx = (wd->size.spos.x * wd->size.w) - (ow / 2); - yy = (wd->size.spos.y * wd->size.h) - (oh / 2); + WRN("Download failed from %s to %s (%d) ", gi->source, gi->file, status); + ecore_file_remove(gi->file); + gi->file_have = EINA_FALSE; } + gi->job = NULL; + gi->wd->download_num--; + evas_object_smart_callback_call(gi->wd->obj, SIG_DOWNLOADED, NULL); - if (xx < 0) xx = 0; - else if (xx > (wd->size.w - ow)) xx = wd->size.w - ow; - if (yy < 0) yy = 0; - else if (yy > (wd->size.h - oh)) yy = wd->size.h - oh; + if (!gi->wd->download_num) + { + edje_object_signal_emit(elm_smart_scroller_edje_object_get(gi->wd->scr), + "elm,state,busy,stop", "elm"); + evas_object_smart_callback_call(gi->wd->obj, SIG_LOADED_DETAIL, NULL); + } +} + +static Eina_Bool +_download_job(void *data) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(data, ECORE_CALLBACK_CANCEL); + Widget_Data *wd = data; - wd->show.show = EINA_TRUE; - wd->show.x = xx; - wd->show.y = yy; - wd->show.w = ow; - wd->show.h = oh; + Eina_List *l, *ll; + Grid_Item *gi; + + if (!eina_list_count(wd->download_list)) + { + wd->download_idler = NULL; + return ECORE_CALLBACK_CANCEL; + } + + EINA_LIST_REVERSE_FOREACH_SAFE(wd->download_list, l, ll, gi) + { + if (gi->g->zoom != wd->zoom || !_grid_item_intersect(gi)) + { + wd->download_list = eina_list_remove(wd->download_list, gi); + continue; + } + if (wd->download_num >= MAX_CONCURRENT_DOWNLOAD) + return ECORE_CALLBACK_RENEW; + + Eina_Bool ret = ecore_file_download_full(gi->source, gi->file, + _downloaded_cb, NULL, + gi, &(gi->job), wd->ua); + if ((!ret) || (!gi->job)) + ERR("Can't start to download from %s to %s", gi->source, gi->file); + else + { + wd->download_list = eina_list_remove(wd->download_list, gi); - if (wd->calc_job) ecore_job_del(wd->calc_job); - wd->calc_job = ecore_job_add(_calc_job, wd); + wd->try_num++; + wd->download_num++; + if (wd->download_num == 1) + edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), + "elm,state,busy,start", "elm"); + } + } + return ECORE_CALLBACK_RENEW; } -static Eina_Bool -_zoom_timeout(void *data) +static void +_grid_viewport_get(Grid *g, int *x, int *y, int *w, int *h) { - ELM_CHECK_WIDTYPE(data, widtype) ECORE_CALLBACK_CANCEL; - Widget_Data *wd = elm_widget_data_get(data); + EINA_SAFETY_ON_NULL_RETURN(g); + int xx, yy, ww, hh; + Evas_Coord px, py, vw, vh; - if (!wd) return ECORE_CALLBACK_CANCEL; - wd->zoom_timer = NULL; - wd->pinch.level = 1.0; - zoom_do(data); - evas_object_smart_callback_call(data, SIG_ZOOM_STOP, NULL); - return ECORE_CALLBACK_CANCEL; + _pan_geometry_get(g->wd, &px, &py); + _viewport_size_get(g->wd, &vw, &vh); + if (px > 0) px = 0; + if (py > 0) py = 0; + + xx = (-px / g->wd->size.tile) - 1; + if (xx < 0) xx = 0; + + yy = (-py / g->wd->size.tile) - 1; + if (yy < 0) yy = 0; + + ww = (vw / g->wd->size.tile) + 3; + if (xx + ww >= g->tw) ww = g->tw - xx; + + hh = (vh / g->wd->size.tile) + 3; + if (yy + hh >= g->th) hh = g->th - yy; + + if (x) *x = xx; + if (y) *y = yy; + if (w) *w = ww; + if (h) *h = hh; } -static Eina_Bool -_zoom_anim(void *data) +static void +_grid_unload(Grid *g) { - ELM_CHECK_WIDTYPE(data, widtype) ECORE_CALLBACK_CANCEL; - Evas_Object *obj = data; - Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN(g); + Eina_Iterator *it; + Eina_Matrixsparse_Cell *cell; + Grid_Item *gi; - if (!wd) return ECORE_CALLBACK_CANCEL; - if (wd->zoom_method == ZOOM_METHOD_IN) wd->t += 0.1 ; - else if (wd->zoom_method == ZOOM_METHOD_OUT) wd->t -= 0.05; - else + it = eina_matrixsparse_iterator_new(g->grid); + EINA_ITERATOR_FOREACH(it, cell) { - wd->zoom_animator = NULL; - zoom_do(obj); - evas_object_smart_callback_call(data, SIG_ZOOM_STOP, NULL); - return ECORE_CALLBACK_CANCEL; + gi = eina_matrixsparse_cell_data_get(cell); + _grid_item_unload(gi); } + eina_iterator_free(it); +} - if (wd->t >= 2.0) +static void +_grid_load(Grid *g) +{ + EINA_SAFETY_ON_NULL_RETURN(g); + int x, y, xx, yy, ww, hh; + Eina_Iterator *it; + Eina_Matrixsparse_Cell *cell; + Grid_Item *gi; + + it = eina_matrixsparse_iterator_new(g->grid); + EINA_ITERATOR_FOREACH(it, cell) { - wd->zoom_animator = NULL; - wd->pinch.level = 2.0; - if (wd->zoom_timer) ecore_timer_del(wd->zoom_timer); - wd->zoom_timer = ecore_timer_add(0.35, _zoom_timeout, obj); - return ECORE_CALLBACK_CANCEL; + gi = eina_matrixsparse_cell_data_get(cell); + if (!_grid_item_intersect(gi)) _grid_item_unload(gi); } - else if (wd->t <= 0.5) + eina_iterator_free(it); + + _grid_viewport_get(g, &xx, &yy, &ww, &hh); + for (y = yy; y < yy + hh; y++) { - wd->zoom_animator = NULL; - wd->pinch.level = 0.5; - if (wd->zoom_timer) ecore_timer_del(wd->zoom_timer); - wd->zoom_timer = ecore_timer_add(1.35, _zoom_timeout, obj); - return ECORE_CALLBACK_CANCEL; + for (x = xx; x < xx + ww; x++) + { + gi = eina_matrixsparse_data_idx_get(g->grid, y, x); + if (!gi) gi = _grid_item_create(g, x, y); + _grid_item_load(gi); + } } - else if (wd->t != 1.0) +} + +static void +_grid_place(Widget_Data *wd) +{ + EINA_SAFETY_ON_NULL_RETURN(wd); + Eina_List *l; + Grid *g; + + EINA_LIST_FOREACH(wd->grids, l, g) { - Evas_Coord x, y, w, h; - float half_w, half_h; - evas_object_geometry_get(data, &x, &y, &w, &h); - half_w = (float)w * 0.5; - half_h = (float)h * 0.5; - wd->pinch.cx = x + half_w; - wd->pinch.cy = y + half_h; - wd->pinch.level = wd->t; - if (wd->calc_job) ecore_job_del(wd->calc_job); - wd->calc_job = ecore_job_add(_calc_job, wd); + if (wd->zoom == g->zoom) _grid_load(g); + else _grid_unload(g); } - return ECORE_CALLBACK_RENEW; + if (!wd->download_idler) wd->download_idler = ecore_idler_add(_download_job, wd); } -static Eina_Bool -_long_press(void *data) +static void +_grid_all_create(Widget_Data *wd) { - ELM_CHECK_WIDTYPE(data, widtype) ECORE_CALLBACK_CANCEL; - Widget_Data *wd = elm_widget_data_get(data); + EINA_SAFETY_ON_NULL_RETURN(wd); + EINA_SAFETY_ON_NULL_RETURN(wd->src); - if (!wd) return ECORE_CALLBACK_CANCEL; - wd->long_timer = NULL; - evas_object_smart_callback_call(data, SIG_LONGPRESSED, &wd->ev); - return ECORE_CALLBACK_CANCEL; + int zoom; + for (zoom = wd->src->zoom_min; zoom <= wd->src->zoom_max; zoom++) + { + Grid *g; + int tnum; + g = ELM_NEW(Grid); + g->wd = wd; + g->zoom = zoom; + tnum = pow(2.0, g->zoom); + g->tw = tnum; + g->th = tnum; + g->grid = eina_matrixsparse_new(g->th, g->tw, NULL, NULL); + wd->grids = eina_list_append(wd->grids, g); + } } static void -_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) +_grid_all_clear(Widget_Data *wd) { - ELM_CHECK_WIDTYPE(data, widtype); - Widget_Data *wd = elm_widget_data_get(data); - Evas_Event_Mouse_Down *ev = event_info; + EINA_SAFETY_ON_NULL_RETURN(wd); - 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, ev); - else - evas_object_smart_callback_call(data, SIG_PRESS, ev); - if (wd->long_timer) ecore_timer_del(wd->long_timer); - wd->ev = *ev; - wd->long_timer = ecore_timer_add(_elm_config->longpress_timeout, _long_press, data); + Grid *g; + EINA_LIST_FREE(wd->grids, g) + { + Grid_Item *gi; + Eina_Iterator *it = eina_matrixsparse_iterator_new(g->grid); + Eina_Matrixsparse_Cell *cell; + EINA_ITERATOR_FOREACH(it, cell) + { + gi = eina_matrixsparse_cell_data_get(cell); + if (gi) _grid_item_free(gi); + } + eina_iterator_free(it); + + eina_matrixsparse_free(g->grid); + free(g); + } + if (!ecore_file_recursive_rm(CACHE_ROOT_PATH)) + ERR("Deletion of %s failed", CACHE_ROOT_PATH); } static void -_mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) +_track_place(Widget_Data *wd) { - ELM_CHECK_WIDTYPE(data, widtype); - Widget_Data *wd = elm_widget_data_get(data); +#ifdef ELM_EMAP EINA_SAFETY_ON_NULL_RETURN(wd); - Evas_Event_Mouse_Up *ev = event_info; - EINA_SAFETY_ON_NULL_RETURN(ev); + Eina_List *l; + Evas_Object *route; + int xmin, xmax, ymin, ymax; + Evas_Coord px, py, ow, oh; + px = wd->pan_x; + py = wd->pan_y; + _viewport_size_get(wd, &ow, &oh); - 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 (wd->long_timer) + Evas_Coord size = wd->size.w; + + EINA_LIST_FOREACH(wd->track, l, route) { - ecore_timer_del(wd->long_timer); - wd->long_timer = NULL; + elm_map_utils_convert_geo_into_coord(wd->obj, elm_route_lon_min_get(route), elm_route_lat_max_get(route), size, &xmin, &ymin); + elm_map_utils_convert_geo_into_coord(wd->obj, elm_route_lon_max_get(route), elm_route_lat_min_get(route), size, &xmax, &ymax); + + if( !(xmin < px && xmax < px) && !(xmin > px+ow && xmax > px+ow)) + { + if( !(ymin < py && ymax < py) && !(ymin > py+oh && ymax > py+oh)) + { + //display the route + evas_object_move(route, xmin - px + ox, ymin - py + oy); + evas_object_resize(route, xmax - xmin, ymax - ymin); + + evas_object_raise(route); + _obj_rotate(wd->obj, route); + evas_object_show(route); + + continue; + } + } + //the route is not display + evas_object_hide(route); } - if (!wd->on_hold) evas_object_smart_callback_call(data, SIG_CLICKED, ev); - wd->on_hold = EINA_FALSE; +#else + (void) wd; +#endif } - static void -_mouse_wheel_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) +_route_place(Widget_Data *wd) { - ELM_CHECK_WIDTYPE(data, widtype); - Widget_Data *wd = elm_widget_data_get(data); EINA_SAFETY_ON_NULL_RETURN(wd); + Eina_List *lr, *lp, *ln; + Path_Node *n; + Evas_Object *p; + Elm_Map_Route *r; + int nodes; + int x, y; + double a; + Evas_Coord ow, oh; + Evas_Coord px, py; - if (!wd->paused) - { - int zoom_diff = 0; - Evas_Event_Mouse_Wheel *ev = (Evas_Event_Mouse_Wheel*) event_info; - Evas_Coord x, y, w, h; + px = wd->pan_x; + py = wd->pan_y; + _viewport_size_get(wd, &ow, &oh); - evas_object_geometry_get(data, &x, &y, &w, &h); + Evas_Coord size = wd->size.w; - if (wd->calc_job) ecore_job_del(wd->calc_job); - wd->calc_job = ecore_job_add(_calc_job, wd); + EINA_LIST_FOREACH(wd->route, lr, r) + { + EINA_LIST_FOREACH(r->path, lp, p) + { + evas_object_polygon_points_clear(p); + } - wd->wheel_diff -= ev->z; - wd->pinch.level = wd->pinch.diff * pow(2.0, (double)wd->wheel_diff/10); - wd->pinch.cx = x + ((double)w * 0.5); - wd->pinch.cy = y + ((double)h * 0.5); + nodes = eina_list_count(r->nodes); - if (wd->pinch.level > 1.99 || wd->pinch.level < 1.01) + EINA_LIST_FOREACH(r->nodes, ln, n) { - wd->wheel_diff = 0; - if (wd->pinch.level > 1.99) + if ((!wd->zoom) || ((n->idx) && + ((n->idx % (int)ceil((double)nodes/(double)size*100.0))))) continue; + if (r->inbound) { - zoom_diff = 1; - wd->pinch.diff = wd->pinch.level / 2.0; - wd->pinch.level = wd->pinch.level / 2.0; + elm_map_utils_convert_geo_into_coord(wd->obj, n->pos.lon, n->pos.lat, size, &x, &y); + if ((x >= px - ow) && (x <= (px + ow*2)) && + (y >= py - oh) && (y <= (py + oh*2))) + { + x = x - px; + y = y - py; + + p = eina_list_nth(r->path, n->idx); + a = (double)(y - r->y) / (double)(x - r->x); + if ((abs(a) >= 1) || (r->x == x)) + { + evas_object_polygon_point_add(p, r->x - 3, r->y); + evas_object_polygon_point_add(p, r->x + 3, r->y); + evas_object_polygon_point_add(p, x + 3, y); + evas_object_polygon_point_add(p, x - 3, y); + } + else + { + evas_object_polygon_point_add(p, r->x, r->y - 3); + evas_object_polygon_point_add(p, r->x, r->y + 3); + evas_object_polygon_point_add(p, x, y + 3); + evas_object_polygon_point_add(p, x, y - 3); + } + + evas_object_color_set(p, r->color.r, r->color.g, r->color.b, r->color.a); + evas_object_raise(p); + _obj_rotate(wd, p); + evas_object_show(p); + r->x = x; + r->y = y; + } + else r->inbound = EINA_FALSE; } - else if (wd->pinch.level < 1.01) + else { - zoom_diff = -1; - wd->pinch.diff = wd->pinch.level * 2.0; - wd->pinch.level = wd->pinch.level * 2.0; + elm_map_utils_convert_geo_into_coord(wd->obj, n->pos.lon, n->pos.lat, size, &x, &y); + if ((x >= px - ow) && (x <= (px + ow*2)) && + (y >= py - oh) && (y <= (py + oh*2))) + { + r->x = x - px; + r->y = y - py; + r->inbound = EINA_TRUE; + } + else r->inbound = EINA_FALSE; } - - Elm_Map_Zoom_Mode temp; - temp = wd->mode; - wd->mode = ELM_MAP_ZOOM_MODE_MANUAL; - wd->paused = EINA_TRUE; - elm_map_zoom_set(data, wd->zoom + zoom_diff); - wd->paused = EINA_FALSE; - wd->mode = temp; - } - else - { - if (wd->calc_job) ecore_job_del(wd->calc_job); - wd->calc_job = ecore_job_add(_calc_job, wd); } + r->inbound = EINA_FALSE; } } static void -_rect_resize_cb(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +_delayed_do(Widget_Data *wd) { - ELM_CHECK_WIDTYPE(data, widtype); - 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); + Delayed_Data *dd; + dd = eina_list_nth(wd->delayed_jobs, 0); + if (dd && !dd->wd->zoom_animator) + { + dd->func(dd); + wd->delayed_jobs = eina_list_remove(wd->delayed_jobs, dd); + free(dd); + } } static void -_del_hook(Evas_Object *obj) +_smooth_update(Widget_Data *wd) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - Elm_Map_Group_Class *group_clas; - Elm_Map_Marker_Class *marker_clas; + EINA_SAFETY_ON_NULL_RETURN(wd); Eina_List *l; - Evas_Object *p; - Path_Node *n; - Path_Waypoint *w; - Ecore_Event_Handler *h; - Elm_Map_Route *r; - Elm_Map_Name *na; - Evas_Object *route; - - if (!wd) return; - EINA_LIST_FREE(wd->groups_clas, group_clas) - { - if (group_clas->style) - eina_stringshare_del(group_clas->style); - free(group_clas); - } + Grid *g; - EINA_LIST_FREE(wd->markers_clas, marker_clas) + EINA_LIST_FOREACH(wd->grids, l, g) { - if (marker_clas->style) - eina_stringshare_del(marker_clas->style); - free(marker_clas); - } + Eina_Iterator *it = eina_matrixsparse_iterator_new(g->grid); + Eina_Matrixsparse_Cell *cell; - EINA_LIST_FOREACH(wd->route, l, r) - { - EINA_LIST_FREE(r->path, p) + EINA_ITERATOR_FOREACH(it, cell) { - evas_object_del(p); + Grid_Item *gi = eina_matrixsparse_cell_data_get(cell); + if (_grid_item_intersect(gi)) + evas_object_image_smooth_scale_set(gi->img, EINA_TRUE); } + eina_iterator_free(it); + } +} - EINA_LIST_FREE(r->waypoint, w) - { - if (w->point) eina_stringshare_del(w->point); - free(w); - } +static Eina_Bool +_zoom_timeout(void *data) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(data, ECORE_CALLBACK_CANCEL); + Widget_Data *wd = data; + _smooth_update(wd); + wd->zoom_timer = NULL; + evas_object_smart_callback_call(wd->obj, SIG_ZOOM_STOP, NULL); + return ECORE_CALLBACK_CANCEL; +} - EINA_LIST_FREE(r->nodes, n) - { - if (n->pos.address) eina_stringshare_del(n->pos.address); - free(n); - } +static void +zoom_do(Widget_Data *wd, double zoom) +{ + EINA_SAFETY_ON_NULL_RETURN(wd); + if (zoom > wd->zoom_max) zoom = wd->zoom_max; + else if (zoom < wd->zoom_min) zoom = wd->zoom_min; - EINA_LIST_FREE(r->handlers, h) - { - ecore_event_handler_del(h); - } + Evas_Coord px, py, vw, vh; + Evas_Coord ow, oh; - if (r->con_url) ecore_con_url_free(r->con_url); - if (r->info.nodes) eina_stringshare_del(r->info.nodes); - if (r->info.waypoints) eina_stringshare_del(r->info.waypoints); - } + wd->zoom = ROUND(zoom); + wd->zoom_detail = zoom; + ow = wd->size.w; + oh = wd->size.h; + wd->size.tile = pow(2.0, (zoom - wd->zoom)) * wd->tsize; + wd->size.w = pow(2.0, wd->zoom) * wd->size.tile; + wd->size.h = wd->size.w;; + + // Fix to zooming with (viewport center px, py) as the center to prevent + // from zooming with (0,0) as the cetner. (scroller default behavior) + _pan_geometry_get(wd, &px, &py); + _viewport_size_get(wd, &vw, &vh); + if ((vw > 0) && (vh > 0) && (ow > 0) && (oh > 0)) + { + Evas_Coord xx, yy; + double sx, sy; + if (vw > ow) sx = 0.5; + else sx = (double)(-px + (vw / 2)) / ow; + if (vh > oh) sy = 0.5; + else sy = (double)(-py + (vh / 2)) / oh; + + if (sx > 1.0) sx = 1.0; + if (sy > 1.0) sy = 1.0; + + xx = (sx * wd->size.w) - (vw / 2); + yy = (sy * wd->size.h) - (vh / 2); + if (xx < 0) xx = 0; + else if (xx > (wd->size.w - vw)) xx = wd->size.w - vw; + if (yy < 0) yy = 0; + else if (yy > (wd->size.h - vh)) yy = wd->size.h - vh; + elm_smart_scroller_child_region_show(wd->scr, xx, yy, vw, vh); + } + + if (wd->zoom_timer) ecore_timer_del(wd->zoom_timer); + else evas_object_smart_callback_call(wd->obj, SIG_ZOOM_START, NULL); + wd->zoom_timer = ecore_timer_add(0.25, _zoom_timeout, wd); + evas_object_smart_callback_call(wd->obj, SIG_ZOOM_CHANGE, NULL); + + evas_object_smart_callback_call(wd->pan_smart, SIG_CHANGED, NULL); + evas_object_smart_changed(wd->pan_smart); +} - EINA_LIST_FREE(wd->names, na) +static Eina_Bool +_zoom_anim(void *data) +{ + Widget_Data *wd = data; + EINA_SAFETY_ON_NULL_RETURN_VAL(wd, ECORE_CALLBACK_CANCEL); + + if (wd->ani.cnt <= 0) { - 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; - } + wd->zoom_animator = NULL; + evas_object_smart_changed(wd->pan_smart); + return ECORE_CALLBACK_CANCEL; } - - EINA_LIST_FREE(wd->track, route) + else { - evas_object_del(route); + wd->ani.zoom += wd->ani.diff; + wd->ani.cnt--; + zoom_do(wd, wd->ani.zoom); + return ECORE_CALLBACK_RENEW; } +} - if (wd->map) evas_map_free(wd->map); - if (wd->source_names) free(wd->source_names); - 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->long_timer) ecore_timer_del(wd->long_timer); - if (wd->user_agent) eina_stringshare_del(wd->user_agent); - if (wd->ua) eina_hash_free(wd->ua); - if (wd->markers) free(wd->markers); +static void +zoom_with_animation(Widget_Data *wd, double zoom, int cnt) +{ + EINA_SAFETY_ON_NULL_RETURN(wd); + if (cnt == 0) return; - free(wd); + wd->ani.cnt = cnt; + wd->ani.zoom = wd->zoom; + wd->ani.diff = (double)(zoom - wd->zoom) / cnt; + if (wd->zoom_animator) ecore_animator_del(wd->zoom_animator); + wd->zoom_animator = ecore_animator_add(_zoom_anim, wd); } static void -_del_pre_hook(Evas_Object *obj) +_sizing_eval(Widget_Data *wd) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - Marker_Group *group; - Elm_Map_Marker *marker; - int i; - Eina_Bool free_marker = EINA_TRUE; - Eina_List *l; + EINA_SAFETY_ON_NULL_RETURN(wd); - if (!wd) return; - grid_clear_all(obj); - for (i = 0; i <= wd->zoom_max; i++) - { - if (!wd->markers[i]) continue; - Eina_Iterator *it = eina_matrixsparse_iterator_new(wd->markers[i]); - Eina_Matrixsparse_Cell *cell; + Evas_Coord maxw = -1, maxh = -1; - EINA_ITERATOR_FOREACH(it, cell) - { - l = eina_matrixsparse_cell_data_get(cell); - EINA_LIST_FREE(l, group) - { - EINA_LIST_FREE(group->markers, marker) - { - evas_object_event_callback_del_full(group->sc, EVAS_CALLBACK_CHANGED_SIZE_HINTS, - _bubble_sc_hints_changed_cb, group); - if (free_marker) free(marker); - } - free(group); - } - free_marker = EINA_FALSE; - } - eina_iterator_free(it); - eina_matrixsparse_free(wd->markers[i]); - } + evas_object_size_hint_max_get(wd->scr, &maxw, &maxh); + evas_object_size_hint_max_set(wd->obj, maxw, maxh); +} + +static void +_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + _sizing_eval(data); +} - evas_object_del(wd->sep_maps_markers); - evas_object_del(wd->pan_smart); - wd->pan_smart = NULL; +static Eina_Bool +_scr_timeout(void *data) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(data, ECORE_CALLBACK_CANCEL); + Widget_Data *wd = data; + _smooth_update(wd); + wd->scr_timer = NULL; + evas_object_smart_callback_call(wd->obj, SIG_SCROLL_DRAG_STOP, NULL); + return ECORE_CALLBACK_CANCEL; } static void -_on_focus_hook(void *data __UNUSED__, Evas_Object *obj) +_scr(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN(data); + Widget_Data *wd = data; - if (!wd) return; - if (elm_widget_focus_get(obj)) - { - edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), "elm,action,focus", "elm"); - evas_object_focus_set(wd->obj, EINA_TRUE); - } - else - { - edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), "elm,action,unfocus", "elm"); - evas_object_focus_set(wd->obj, EINA_FALSE); - } + if (wd->scr_timer) ecore_timer_del(wd->scr_timer); + else evas_object_smart_callback_call(wd->obj, SIG_SCROLL_DRAG_START, NULL); + wd->scr_timer = ecore_timer_add(0.25, _scr_timeout, wd); + evas_object_smart_callback_call(wd->obj, SIG_SCROLL, NULL); } static void -_theme_hook(Evas_Object *obj) +_scr_anim_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN(data); + Widget_Data *wd = data; + evas_object_smart_callback_call(wd->obj, "scroll,anim,start", NULL); +} - if (!wd) return; - elm_smart_scroller_object_theme_set(obj, wd->scr, "map", "base", elm_widget_style_get(obj)); - // edje_object_scale_set(wd->scr, elm_widget_scale_get(obj) * _elm_config->scale); - _sizing_eval(obj); +static void +_scr_anim_stop(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + EINA_SAFETY_ON_NULL_RETURN(data); + Widget_Data *wd = data; + evas_object_smart_callback_call(wd->obj, "scroll,anim,stop", NULL); +} + +static Eina_Bool +_long_press(void *data) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(data, ECORE_CALLBACK_CANCEL); + Widget_Data *wd = data; + + wd->long_timer = NULL; + evas_object_smart_callback_call(wd->obj, SIG_LONGPRESSED, &wd->ev); + return ECORE_CALLBACK_CANCEL; } static void -_sizing_eval(Evas_Object *obj) +_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1; + EINA_SAFETY_ON_NULL_RETURN(data); + Widget_Data *wd = data; + Evas_Event_Mouse_Down *ev = event_info; - if (!wd) return; - evas_object_size_hint_max_get(wd->scr, &maxw, &maxh); - evas_object_size_hint_min_set(obj, minw, minh); - evas_object_size_hint_max_set(obj, maxw, maxh); + 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(wd->obj, SIG_CLICKED_DOUBLE, ev); + else evas_object_smart_callback_call(wd->obj, SIG_PRESS, ev); + + if (wd->long_timer) ecore_timer_del(wd->long_timer); + wd->ev = *ev; + wd->long_timer = ecore_timer_add(_elm_config->longpress_timeout, _long_press, wd); } static void -_calc_job(void *data) +_mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) { + EINA_SAFETY_ON_NULL_RETURN(data); Widget_Data *wd = data; - Evas_Coord minw, minh; - if (!wd) return; - minw = wd->size.w; - minh = wd->size.h; - if (wd->resized) + Evas_Event_Mouse_Up *ev = event_info; + EINA_SAFETY_ON_NULL_RETURN(ev); + + 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 (wd->long_timer) { - wd->resized = EINA_FALSE; - if (wd->mode != ELM_MAP_ZOOM_MODE_MANUAL) - { - double tz = wd->zoom; - wd->zoom = 0.0; - elm_map_zoom_set(wd->obj, tz); - } + ecore_timer_del(wd->long_timer); + wd->long_timer = NULL; } - if ((minw != wd->minw) || (minh != wd->minh)) + if (!wd->on_hold) evas_object_smart_callback_call(wd->obj, SIG_CLICKED, ev); + wd->on_hold = EINA_FALSE; +} + +static void +_mouse_wheel_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) +{ + EINA_SAFETY_ON_NULL_RETURN(data); + Widget_Data *wd = data; + + if (!wd->paused) { - wd->minw = minw; - wd->minh = minh; - evas_object_smart_callback_call(wd->pan_smart, SIG_CHANGED, NULL); - _sizing_eval(wd->obj); - } - wd->calc_job = NULL; - evas_object_smart_changed(wd->pan_smart); + Evas_Event_Mouse_Wheel *ev = (Evas_Event_Mouse_Wheel*) event_info; + zoom_do(wd, wd->zoom_detail - ((double)ev->z / 10)); + } } static void _pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y) { Pan *sd = evas_object_smart_data_get(obj); - if (!sd) return; + EINA_SAFETY_ON_NULL_RETURN(sd); if ((x == sd->wd->pan_x) && (y == sd->wd->pan_y)) return; + sd->wd->pan_x = x; sd->wd->pan_y = y; evas_object_smart_changed(obj); @@ -1941,7 +1842,7 @@ static void _pan_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y) { Pan *sd = evas_object_smart_data_get(obj); - if (!sd) return; + EINA_SAFETY_ON_NULL_RETURN(sd); if (x) *x = sd->wd->pan_x; if (y) *y = sd->wd->pan_y; } @@ -1950,12 +1851,12 @@ static void _pan_max_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y) { Pan *sd = evas_object_smart_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN(sd); Evas_Coord ow, oh; - if (!sd) return; evas_object_geometry_get(obj, NULL, NULL, &ow, &oh); - ow = sd->wd->minw - ow; + ow = sd->wd->size.w - ow; + oh = sd->wd->size.h - oh; if (ow < 0) ow = 0; - oh = sd->wd->minh - oh; if (oh < 0) oh = 0; if (x) *x = ow; if (y) *y = oh; @@ -1972,9 +1873,9 @@ static void _pan_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h) { Pan *sd = evas_object_smart_data_get(obj); - if (!sd) return; - if (w) *w = sd->wd->minw; - if (h) *h = sd->wd->minh; + EINA_SAFETY_ON_NULL_RETURN(sd); + if (w) *w = sd->wd->size.w; + if (h) *h = sd->wd->size.h; } static void @@ -1982,431 +1883,229 @@ _pan_add(Evas_Object *obj) { Pan *sd; Evas_Object_Smart_Clipped_Data *cd; - _pan_sc.add(obj); + parent_sc.add(obj); cd = evas_object_smart_data_get(obj); - if (!cd) return; - sd = calloc(1, sizeof(Pan)); - if (!sd) return; + EINA_SAFETY_ON_NULL_RETURN(cd); + sd = ELM_NEW(Pan); sd->__clipped_data = *cd; free(cd); evas_object_smart_data_set(obj, sd); } static void -_pan_del(Evas_Object *obj) +_pan_resize(Evas_Object *obj, Evas_Coord w __UNUSED__, Evas_Coord h __UNUSED__) { Pan *sd = evas_object_smart_data_get(obj); - if (!sd) return; - _pan_sc.del(obj); -} + EINA_SAFETY_ON_NULL_RETURN(sd); -static void -_pan_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h) -{ - Pan *sd = evas_object_smart_data_get(obj); - Evas_Coord ow, oh; - if (!sd) return; - evas_object_geometry_get(obj, NULL, NULL, &ow, &oh); - if ((ow == w) && (oh == h)) return; - sd->wd->resized = EINA_TRUE; - if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job); - sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd); + _sizing_eval(sd->wd); + elm_map_zoom_mode_set(sd->wd->obj, sd->wd->mode); + evas_object_smart_changed(obj); } static void _pan_calculate(Evas_Object *obj) { Pan *sd = evas_object_smart_data_get(obj); - Evas_Coord ox, oy, ow, oh; - Eina_List *l; - Grid *g; - EINA_SAFETY_ON_NULL_RETURN(sd); - EINA_SAFETY_ON_NULL_RETURN(sd->wd); - - evas_object_geometry_get(obj, &ox, &oy, &ow, &oh); - rect_place(sd->wd->obj, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh); - EINA_LIST_FOREACH(sd->wd->grids, l, g) - { - if (sd->wd->zoom == g->zoom) grid_load(sd->wd->obj, g); - else if (sd->wd->zoom-1 != g->zoom && sd->wd->zoom+1 != g->zoom) grid_unload(sd->wd->obj, g); // remain only adjacent grids - grid_place(sd->wd->obj, g, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh); - if (sd->wd->zoom == g->zoom) marker_place(sd->wd->obj, g, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh); - if (!sd->wd->zoom_animator) route_place(sd->wd->obj, g, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh); - if (!sd->wd->zoom_animator) track_place(sd->wd->obj, g, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh); - } -} - -static void -_pan_move(Evas_Object *obj, Evas_Coord x __UNUSED__, Evas_Coord y __UNUSED__) -{ - Pan *sd = evas_object_smart_data_get(obj); - if (!sd) return; - if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job); - sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd); -} - -static void -_hold_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) -{ - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return; - elm_smart_scroller_hold_set(wd->scr, 1); -} - -static void -_hold_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) -{ - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); + Evas_Coord w, h; + evas_object_geometry_get(sd->wd->pan_smart, NULL, NULL, &w, &h); + if (w <= 0 || h <= 0) return; - if (!wd) return; - elm_smart_scroller_hold_set(wd->scr, 0); + _grid_place(sd->wd); + _marker_place(sd->wd); + _route_place(sd->wd); + _track_place(sd->wd); + _delayed_do(sd->wd); } static void -_freeze_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) +_pan_move(Evas_Object *obj, Evas_Coord x __UNUSED__, Evas_Coord y __UNUSED__) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - - if (!wd) return; - elm_smart_scroller_freeze_set(wd->scr, 1); + EINA_SAFETY_ON_NULL_RETURN(obj); + evas_object_smart_changed(obj); } static void -_freeze_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) +_hold_on(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - - if (!wd) return; - elm_smart_scroller_freeze_set(wd->scr, 0); + EINA_SAFETY_ON_NULL_RETURN(data); + Widget_Data *wd = data; + elm_smart_scroller_hold_set(wd->scr, 1); } static void -_scr_anim_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +_hold_off(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) { - evas_object_smart_callback_call(data, "scroll,anim,start", NULL); + EINA_SAFETY_ON_NULL_RETURN(data); + Widget_Data *wd = data; + elm_smart_scroller_hold_set(wd->scr, 0); } static void -_scr_anim_stop(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +_freeze_on(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) { - evas_object_smart_callback_call(data, "scroll,anim,stop", NULL); + EINA_SAFETY_ON_NULL_RETURN(data); + Widget_Data *wd = data; + elm_smart_scroller_freeze_set(wd->scr, 1); } static void -_scr_drag_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +_freeze_off(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) { - Widget_Data *wd = elm_widget_data_get(data); - EINA_SAFETY_ON_NULL_RETURN(wd); - wd->center_on.enabled = EINA_FALSE; - - // FIXME: els_scoller sometimes give start event again & again... it confuses app. (els_scr bug?) - if (!wd->scr_started) - { - wd->scr_started = EINA_TRUE; - evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_START, NULL); - } + EINA_SAFETY_ON_NULL_RETURN(data); + Widget_Data *wd = data; + elm_smart_scroller_freeze_set(wd->scr, 0); } static void -_scr_drag_stop(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +_on_focus_hook(void *data __UNUSED__, Evas_Object *obj) { - Widget_Data *wd = elm_widget_data_get(data); + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); EINA_SAFETY_ON_NULL_RETURN(wd); - wd->center_on.enabled = EINA_FALSE; - // FIXME: els_scoller sometimes give start event again & again... it confuses app. (els_scr bug?) - if (wd->scr_started) + if (elm_widget_focus_get(obj)) + { + edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), "elm,action,focus", "elm"); + evas_object_focus_set(wd->obj, EINA_TRUE); + } + else { - wd->scr_started = EINA_FALSE; - evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_STOP, NULL); + edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), "elm,action,unfocus", "elm"); + evas_object_focus_set(wd->obj, EINA_FALSE); } } static void -_scr_scroll(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +_del_hook(Evas_Object *obj) { - evas_object_smart_callback_call(data, SIG_SCROLL, NULL); -} - + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN(wd); -static void -_group_object_create(Marker_Group *group) -{ - const char *style = "radio"; - Evas_Object *icon = NULL; + Eina_List *l, *ll; + Evas_Object *p; + Path_Node *n; + Path_Waypoint *w; + Ecore_Event_Handler *h; + Elm_Map_Route *r; + Elm_Map_Name *na; + Evas_Object *route; + Elm_Map_Marker *marker; + Elm_Map_Group_Class *group_clas; + Elm_Map_Marker_Class *clas; + Delayed_Data *dd; + int idx = 0; + Map_Sources_Tab *s; - if (group->obj) return; - if ((!group->clas->priv.objs_notused) || (eina_list_count(group->markers) == 1)) + EINA_LIST_FOREACH(wd->route, l, r) { - //set icon and style - if (eina_list_count(group->markers) == 1) + EINA_LIST_FREE(r->path, p) { - Elm_Map_Marker *m = eina_list_data_get(group->markers); - if (m->clas->style) - style = m->clas->style; - - if (m->clas->func.icon_get) - icon = m->clas->func.icon_get(group->wd->obj, m, m->data); - - group->delete_object = EINA_TRUE; + evas_object_del(p); } - else - { - if (group->clas->style) - style = group->clas->style; - - if (group->clas->func.icon_get) - icon = group->clas->func.icon_get(group->wd->obj, group->clas->data); - group->delete_object = EINA_FALSE; + EINA_LIST_FREE(r->waypoint, w) + { + if (w->point) eina_stringshare_del(w->point); + free(w); } - group->obj = elm_layout_add(group->wd->obj); - elm_layout_theme_set(group->obj, "map/marker", style, elm_widget_style_get(group->wd->obj)); - - if (icon) elm_object_part_content_set(group->obj, "elm.icon", icon); - - evas_object_smart_member_add(group->obj, group->wd->pan_smart); - elm_widget_sub_object_add(group->wd->obj, group->obj); - evas_object_stack_above(group->obj, group->wd->sep_maps_markers); + EINA_LIST_FREE(r->nodes, n) + { + if (n->pos.address) eina_stringshare_del(n->pos.address); + free(n); + } - if (!group->delete_object) - group->clas->priv.objs_used = eina_list_append(group->clas->priv.objs_used, group->obj); - } - else - { - group->delete_object = EINA_FALSE; + EINA_LIST_FREE(r->handlers, h) + { + ecore_event_handler_del(h); + } - group->obj = eina_list_data_get(group->clas->priv.objs_notused); - group->clas->priv.objs_used = eina_list_append(group->clas->priv.objs_used, group->obj); - group->clas->priv.objs_notused = eina_list_remove(group->clas->priv.objs_notused, group->obj); - evas_object_show(group->obj); + if (r->con_url) ecore_con_url_free(r->con_url); + if (r->info.nodes) eina_stringshare_del(r->info.nodes); + if (r->info.waypoints) eina_stringshare_del(r->info.waypoints); } - edje_object_signal_callback_add(elm_layout_edje_get(group->obj), "open", "elm", _group_open_cb, group); - edje_object_signal_callback_add(elm_layout_edje_get(group->obj), "bringin", "elm", _group_bringin_cb, group); - - group->update_nbelems = EINA_TRUE; - group->update_resize = EINA_TRUE; - group->update_raise = EINA_TRUE; - - if (group->open) _group_bubble_create(group); -} - -static void -_group_object_free(Marker_Group *group) -{ - if (!group->obj) return; - if (!group->delete_object) + EINA_LIST_FREE(wd->names, na) { - group->clas->priv.objs_notused = eina_list_append(group->clas->priv.objs_notused, group->obj); - group->clas->priv.objs_used = eina_list_remove(group->clas->priv.objs_used, group->obj); - evas_object_hide(group->obj); - - edje_object_signal_callback_del(elm_layout_edje_get(group->obj), "open", "elm", _group_open_cb); - edje_object_signal_callback_del(elm_layout_edje_get(group->obj), "bringin", "elm", _group_bringin_cb); + 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; + } } - else - evas_object_del(group->obj); - - group->obj = NULL; - _group_bubble_free(group); -} - -static void -_group_bubble_mouse_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) -{ - Marker_Group *group = data; - - if (!evas_object_above_get(group->rect)) return; - evas_object_raise(group->bubble); - evas_object_raise(group->sc); - evas_object_raise(group->rect); -} - -static void -_group_bubble_create(Marker_Group *group) -{ - if (group->bubble) return; - - group->wd->opened_bubbles = eina_list_append(group->wd->opened_bubbles, group); - group->bubble = edje_object_add(evas_object_evas_get(group->obj)); - _elm_theme_object_set(group->wd->obj, group->bubble, "map", "marker_bubble", - elm_widget_style_get(group->wd->obj)); - evas_object_smart_member_add(group->bubble, - group->wd->obj); - elm_widget_sub_object_add(group->wd->obj, group->bubble); - _group_bubble_content_free(group); - if (!_group_bubble_content_update(group)) + EINA_LIST_FREE(wd->track, route) { - //no content, we can delete the bubble - _group_bubble_free(group); - return; + evas_object_del(route); } - group->rect = evas_object_rectangle_add(evas_object_evas_get(group->obj)); - evas_object_color_set(group->rect, 0, 0, 0, 0); - evas_object_repeat_events_set(group->rect, EINA_TRUE); - evas_object_smart_member_add(group->rect, group->wd->obj); - elm_widget_sub_object_add(group->wd->obj, group->rect); - - evas_object_event_callback_add(group->rect, EVAS_CALLBACK_MOUSE_UP, _group_bubble_mouse_up_cb, group); - - _group_bubble_place(group); -} - -static void _bubble_sc_hints_changed_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) -{ - _group_bubble_place(data); -} - -static int -_group_bubble_content_update(Marker_Group *group) -{ - Eina_List *l; - Elm_Map_Marker *marker; - int i = 0; - if (!group->bubble) return 1; + EINA_LIST_FOREACH_SAFE(wd->markers, l, ll, marker) + elm_map_marker_remove(marker); + eina_list_free(wd->markers); - if (!group->sc) + EINA_LIST_FREE(wd->group_classes, group_clas) { - group->sc = elm_scroller_add(group->bubble); - elm_widget_style_set(group->sc, "map_bubble"); - elm_scroller_content_min_limit(group->sc, EINA_FALSE, EINA_TRUE); - elm_scroller_policy_set(group->sc, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF); - elm_scroller_bounce_set(group->sc, _elm_config->thumbscroll_bounce_enable, EINA_FALSE); - edje_object_part_swallow(group->bubble, "elm.swallow.content", group->sc); - evas_object_show(group->sc); - evas_object_smart_member_add(group->sc, - group->wd->obj); - elm_widget_sub_object_add(group->wd->obj, group->sc); - - group->bx = elm_box_add(group->bubble); - evas_object_size_hint_align_set(group->bx, EVAS_HINT_FILL, EVAS_HINT_FILL); - evas_object_size_hint_weight_set(group->bx, 0.5, 0.5); - elm_box_horizontal_set(group->bx, EINA_TRUE); - evas_object_show(group->bx); - - elm_object_content_set(group->sc, group->bx); - - evas_object_event_callback_add(group->sc, EVAS_CALLBACK_CHANGED_SIZE_HINTS, - _bubble_sc_hints_changed_cb, group); + eina_list_free(group_clas->markers); + if (group_clas->style) eina_stringshare_del(group_clas->style); + free(group_clas); } - EINA_LIST_FOREACH(group->markers, l, marker) + EINA_LIST_FREE(wd->marker_classes, clas) { - if (i >= group->wd->markers_max_num) break; - if ((!marker->content) && (marker->clas->func.get)) - marker->content = marker->clas->func.get(group->wd->obj, marker, marker->data); - else if (marker->content) - elm_box_unpack(group->bx, marker->content); - if (marker->content) - { - elm_box_pack_end(group->bx, marker->content); - i++; - } + if (clas->style) eina_stringshare_del(clas->style); + free(clas); } - return i; -} -static void -_group_bubble_content_free(Marker_Group *group) -{ - Eina_List *l; - Elm_Map_Marker *marker; + if (wd->scr_timer) ecore_timer_del(wd->scr_timer); + if (wd->long_timer) ecore_timer_del(wd->long_timer); - if (!group->sc) return; - EINA_LIST_FOREACH(group->markers, l, marker) - { - if ((marker->content) && (marker->clas->func.del)) - marker->clas->func.del(group->wd->obj, marker, marker->data, marker->content); - else if (marker->content) - evas_object_del(marker->content); - marker->content = NULL; - } - evas_object_del(group->sc); - group->sc = NULL; -} + if (wd->delayed_jobs) EINA_LIST_FREE(wd->delayed_jobs, dd) free(dd); -static void -_group_bubble_free(Marker_Group *group) -{ - if (!group->bubble) return; - group->wd->opened_bubbles = eina_list_remove(group->wd->opened_bubbles, group); - evas_object_event_callback_del_full(group->sc, EVAS_CALLBACK_CHANGED_SIZE_HINTS, - _bubble_sc_hints_changed_cb, group); - evas_object_del(group->bubble); - evas_object_del(group->rect); - group->bubble = NULL; - _group_bubble_content_free(group); -} + if (wd->user_agent) eina_stringshare_del(wd->user_agent); + if (wd->ua) eina_hash_free(wd->ua); + if (wd->download_idler) ecore_idler_del(wd->download_idler); + eina_list_free(wd->download_list); -static void -_group_bubble_place(Marker_Group *group) -{ - Evas_Coord x, y, w; - Evas_Coord xx, yy, ww, hh; - const char *s; + if (wd->zoom_timer) ecore_timer_del(wd->zoom_timer); + if (wd->zoom_animator) ecore_animator_del(wd->zoom_animator); - if ((!group->bubble) || (!group->obj)) return; + _grid_all_clear(wd); - evas_object_geometry_get(group->obj, &x, &y, &w, NULL); - edje_object_size_min_calc(group->bubble, NULL, &hh); + for (idx = 0; wd->src_names[idx]; idx++) + eina_stringshare_del(wd->src_names[idx]); - s = edje_object_data_get(group->bubble, "size_w"); - if (s) ww = atoi(s); - else ww = 0; - xx = x + w / 2 - ww / 2; - yy = y-hh; + EINA_LIST_FREE(wd->srcs, s) free(s); - evas_object_move(group->bubble, xx, yy); - evas_object_resize(group->bubble, ww, hh); - obj_rotate_zoom(group->wd->obj, group->bubble); - evas_object_show(group->bubble); + if (wd->map) evas_map_free(wd->map); - evas_object_move(group->rect, xx, yy); - evas_object_resize(group->rect, ww, hh); - obj_rotate_zoom(group->wd->obj, group->rect); - evas_object_show(group->rect); + free(wd); } static void -_group_bringin_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *soure __UNUSED__) +_del_pre_hook(Evas_Object *obj) { - Marker_Group *group = data; - Elm_Map_Marker *marker = eina_list_data_get(group->markers); - if (!marker) return; - group->bringin = EINA_TRUE; - elm_map_geo_region_bring_in(group->wd->obj, marker->longitude, marker->latitude); + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN(wd); } static void -_group_open_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *soure __UNUSED__) +_theme_hook(Evas_Object *obj) { - Marker_Group *group = data; - - if (group->bringin) - { - group->bringin = EINA_FALSE; - return; - } + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN(wd); - if (group->bubble) - { - group->open = EINA_FALSE; - _group_bubble_free(group); - return; - } - group->open = EINA_TRUE; - _group_bubble_create(group); + elm_smart_scroller_object_theme_set(obj, wd->scr, "map", "base", elm_widget_style_get(obj)); + _sizing_eval(wd); } static Eina_Bool @@ -2414,17 +2113,12 @@ _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type ty { ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; Widget_Data *wd = elm_widget_data_get(obj); - int zoom; - Evas_Coord x = 0; - Evas_Coord y = 0; - Evas_Coord step_x = 0; - Evas_Coord step_y = 0; - Evas_Coord v_w = 0; - Evas_Coord v_h = 0; - Evas_Coord page_x = 0; - Evas_Coord page_y = 0; - - if (!wd) return EINA_FALSE; + EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EINA_FALSE); + + Evas_Coord x, y; + Evas_Coord vh; + Evas_Coord step_x, step_y, page_x, page_y; + if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE; Evas_Event_Key_Down *ev = event_info; if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE; @@ -2432,7 +2126,7 @@ _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type ty elm_smart_scroller_child_pos_get(wd->scr, &x, &y); elm_smart_scroller_step_size_get(wd->scr, &step_x, &step_y); elm_smart_scroller_page_size_get(wd->scr, &page_x, &page_y); - elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h); + _viewport_size_get(wd, NULL, &vh); if ((!strcmp(ev->keyname, "Left")) || (!strcmp(ev->keyname, "KP_Left"))) { @@ -2453,29 +2147,25 @@ _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type ty else if ((!strcmp(ev->keyname, "Prior")) || (!strcmp(ev->keyname, "KP_Prior"))) { if (page_y < 0) - y -= -(page_y * v_h) / 100; + y -= -(page_y * vh) / 100; else y -= page_y; } else if ((!strcmp(ev->keyname, "Next")) || (!strcmp(ev->keyname, "KP_Next"))) { if (page_y < 0) - y += -(page_y * v_h) / 100; + y += -(page_y * vh) / 100; else y += page_y; } else if (!strcmp(ev->keyname, "KP_Add")) { - zoom = elm_map_zoom_get(obj) + 1; - elm_map_zoom_mode_set(obj, ELM_MAP_ZOOM_MODE_MANUAL); - elm_map_zoom_set(obj, zoom); + zoom_with_animation(wd, wd->zoom + 1, 10); return EINA_TRUE; } else if (!strcmp(ev->keyname, "KP_Subtract")) { - zoom = elm_map_zoom_get(obj) - 1; - elm_map_zoom_mode_set(obj, ELM_MAP_ZOOM_MODE_MANUAL); - elm_map_zoom_set(obj, zoom); + zoom_with_animation(wd, wd->zoom - 1, 10); return EINA_TRUE; } else return EINA_FALSE; @@ -2498,7 +2188,6 @@ cb_dump_name_attrs(void *data, const char *key, const char *value) return EINA_TRUE; } - static Eina_Bool cb_route_dump(void *data, Eina_Simple_XML_Type type, const char *value, unsigned offset __UNUSED__, unsigned length) { @@ -2623,7 +2312,7 @@ _parse_kml(void *data) eina_stringshare_replace(&r->info.waypoints, dump.description); str = eina_str_split_full(dump.description, "\n", 0, &ele); r->info.waypoint_count = ele; - for (idx = 0 ; idx < ele ; idx++) + for (idx = 0; idx < ele; idx++) { Path_Waypoint *wp = ELM_NEW(Path_Waypoint); if (wp) @@ -2647,7 +2336,7 @@ _parse_kml(void *data) eina_stringshare_replace(&r->info.nodes, dump.coordinates); str = eina_str_split_full(dump.coordinates, "\n", 0, &ele); r->info.node_count = ele; - for (idx = 0 ; idx < ele ; idx++) + for (idx = 0; idx < ele; idx++) { sscanf(str[idx], "%lf,%lf", &lon, &lat); Path_Node *n = ELM_NEW(Path_Node); @@ -2750,14 +2439,8 @@ _route_complete_cb(void *data, int ev_type __UNUSED__, void *event) if (r->ud.fd) fclose(r->ud.fd); _parse_kml(r); - if (wd->grids) - { - Grid *g; - Evas_Coord ox, oy, ow, oh; - evas_object_geometry_get(wd->obj, &ox, &oy, &ow, &oh); - g = _get_current_grid(wd); - route_place(wd->obj, g, wd->pan_x, wd->pan_y, ox, oy, ow, oh); - } + _route_place(wd); + 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_ROUTE_LOADED, NULL); @@ -2796,7 +2479,6 @@ _utils_convert_name(const Evas_Object *obj, int method, char *address, double lo if ((!wd) || (!wd->src)) return NULL; Elm_Map_Name *name = ELM_NEW(Elm_Map_Name); - if (!name) return NULL; snprintf(buf, sizeof(buf), DEST_NAME_XML_FILE); fd = mkstemp(buf); @@ -2845,189 +2527,338 @@ _utils_convert_name(const Evas_Object *obj, int method, char *address, double lo } static Evas_Event_Flags -zoom_start_cb(void *data, void *event_info __UNUSED__) +_pinch_zoom_start_cb(void *data, void *event_info __UNUSED__) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(data, EVAS_EVENT_FLAG_NONE); + Widget_Data *wd = data; + + wd->pinch_zoom = wd->zoom_detail; + return EVAS_EVENT_FLAG_NONE; +} + +static Evas_Event_Flags +_pinch_zoom_cb(void *data, void *event_info) { Widget_Data *wd = data; EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EVAS_EVENT_FLAG_NONE); - // FIXME: scroller can be jumping strangely when resizing & scrolling at the sametime (els_scr bug?) - elm_smart_scroller_hold_set(wd->scr, 1); - elm_smart_scroller_freeze_set(wd->scr, 1); - _scr_drag_start(wd->obj, NULL, NULL); + if (!wd->paused) + { + Elm_Gesture_Zoom_Info *ei = event_info; + zoom_do(wd, wd->pinch_zoom + ei->zoom - 1); + } + return EVAS_EVENT_FLAG_NONE; +} + +static Evas_Event_Flags +_pinch_rotate_cb(void *data, void *event_info) +{ + Widget_Data *wd = data; + EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EVAS_EVENT_FLAG_NONE); + + if (!wd->paused) + { + int x, y, w, h; + Elm_Gesture_Rotate_Info *ei = event_info; + evas_object_geometry_get(wd->obj, &x, &y, &w, &h); - wd->pinch.diff += 0.001; + wd->rotate.d = wd->rotate.a + ((ei->base_angle-ei->angle) * 50); + wd->rotate.cx = x + ((double)w * 0.5); + wd->rotate.cy = y + ((double)h * 0.5); + evas_object_smart_changed(wd->pan_smart); + } return EVAS_EVENT_FLAG_NONE; } static Evas_Event_Flags -zoom_end_cb(void *data, void *event_info __UNUSED__) +_pinch_rotate_end_cb(void *data, void *event_info __UNUSED__) { Widget_Data *wd = data; EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EVAS_EVENT_FLAG_NONE); - // FIXME: scroller can be jumping strangely when resizing & scrolling at the sametime (els_scr bug?) - elm_smart_scroller_hold_set(wd->scr, 0); - elm_smart_scroller_freeze_set(wd->scr, 0); - _scr_drag_stop(wd->obj, NULL, NULL); + wd->rotate.a = wd->rotate.d; + + return EVAS_EVENT_FLAG_NONE; +} + +static void +_zoom_mode_set(void *data) +{ + EINA_SAFETY_ON_NULL_RETURN(data); + Delayed_Data *dd = data; + + dd->wd->mode = dd->mode; + if (dd->mode != ELM_MAP_ZOOM_MODE_MANUAL) + { + Evas_Coord w, h; + Evas_Coord vw, vh; + + double zoom; + double diff; + + w = dd->wd->size.w; + h = dd->wd->size.h; + zoom = dd->wd->zoom_detail; + _viewport_size_get(dd->wd, &vw, &vh); - wd->pinch.diff = wd->pinch.level; + if (dd->mode == ELM_MAP_ZOOM_MODE_AUTO_FIT) + { + if ((w < vw) && (h < vh)) + { + diff = 0.01; + while ((w < vw) && (h < vh)) + { + zoom += diff; + w = pow(2.0, zoom) * dd->wd->tsize; + h = pow(2.0, zoom) * dd->wd->tsize; + } + } + else + { + diff = -0.01; + while ((w > vw) || (h > vh)) + { + zoom += diff; + w = pow(2.0, zoom) * dd->wd->tsize; + h = pow(2.0, zoom) * dd->wd->tsize; + } + } + + } + else if (dd->mode == ELM_MAP_ZOOM_MODE_AUTO_FILL) + { + if ((w < vw) || (h < vh)) + { + diff = 0.01; + while ((w < vw) || (h < vh)) + { + zoom += diff; + w = pow(2.0, zoom) * dd->wd->tsize; + h = pow(2.0, zoom) * dd->wd->tsize; + } + } + else + { + diff = -0.01; + while ((w > vw) && (h > vh)) + { + zoom += diff; + w = pow(2.0, zoom) * dd->wd->tsize; + h = pow(2.0, zoom) * dd->wd->tsize; + } + } + } + zoom_with_animation(dd->wd, zoom, 10); + } +} + +static void +_zoom_set(void *data) +{ + EINA_SAFETY_ON_NULL_RETURN(data); + Delayed_Data *dd = data; + + if (dd->wd->paused) zoom_do(dd->wd, dd->zoom); + else zoom_with_animation(dd->wd, dd->zoom, 10); + evas_object_smart_changed(dd->wd->pan_smart); +} + +static void +_region_bring_in(void *data) +{ + EINA_SAFETY_ON_NULL_RETURN(data); + Delayed_Data *dd = data; + int x, y, w, h; + + elm_map_utils_convert_geo_into_coord(dd->wd->obj, dd->lon, dd->lat, + dd->wd->size.w, &x, &y); + _viewport_size_get(dd->wd, &w, &h); + x = x - (w / 2); + y = y - (h / 2); + elm_smart_scroller_region_bring_in(dd->wd->scr, x, y, w, h); + evas_object_smart_changed(dd->wd->pan_smart); +} + +static void +_region_show(void *data) +{ + EINA_SAFETY_ON_NULL_RETURN(data); + Delayed_Data *dd = data; + int x, y, w, h; - return EVAS_EVENT_FLAG_NONE; + elm_map_utils_convert_geo_into_coord(dd->wd->obj, dd->lon, dd->lat, + dd->wd->size.w, &x, &y); + _viewport_size_get(dd->wd, &w, &h); + x = x - (w / 2); + y = y - (h / 2); + elm_smart_scroller_child_region_show(dd->wd->scr, x, y, w, h); + evas_object_smart_changed(dd->wd->pan_smart); } -static Evas_Event_Flags -zoom_cb(void *data, void *event_info) +static void +_marker_list_show(void *data) { - Widget_Data *wd = data; - EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EVAS_EVENT_FLAG_NONE); + EINA_SAFETY_ON_NULL_RETURN(data); + Delayed_Data *dd = data; + int zoom; + double max_lon = -180, min_lon = 180; + double max_lat = -90, min_lat = 90; + Evas_Coord vw, vh; + Elm_Map_Marker *marker; - if (!wd->paused) + EINA_LIST_FREE(dd->markers, marker) { - int zoom_diff = 0; - int x, y, w, h; - Elm_Gesture_Zoom_Info *ei = event_info; - evas_object_geometry_get(wd->obj, &x, &y, &w, &h); - - wd->pinch.level = wd->pinch.diff * ei->zoom; - wd->pinch.cx = x + ((double)w * 0.5); - wd->pinch.cy = y + ((double)h * 0.5); - - if (wd->pinch.level > 1.999 || wd->pinch.level < 1.001) - { - if (wd->pinch.level > 1.999) - { - zoom_diff = 1; - wd->pinch.diff = wd->pinch.level / 2.0; - wd->pinch.level = wd->pinch.level / 2.0; - } - else if (wd->pinch.level < 1.001) - { - zoom_diff = -1; - wd->pinch.diff = wd->pinch.level * 2.0; - wd->pinch.level = wd->pinch.level * 2.0; - } - Elm_Map_Zoom_Mode temp; - elm_gesture_layer_cb_set(wd->ges, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_MOVE, NULL, wd); // ei->zoom is refreshed - temp = wd->mode; - wd->mode = ELM_MAP_ZOOM_MODE_MANUAL; - wd->paused = EINA_TRUE; - elm_map_zoom_set(wd->obj, wd->zoom + zoom_diff); - wd->paused = EINA_FALSE; - wd->mode = temp; - elm_gesture_layer_cb_set(wd->ges, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_MOVE, zoom_cb, wd); // ei->zoom is refreshed - } - else - { - if (wd->calc_job) ecore_job_del(wd->calc_job); - wd->calc_job = ecore_job_add(_calc_job, wd); - } - evas_object_smart_callback_call(wd->obj, SIG_ZOOM_CHANGE, NULL); + if (marker->longitude > max_lon) max_lon = marker->longitude; + if (marker->longitude < min_lon) min_lon = marker->longitude; + if (marker->latitude > max_lat) max_lat = marker->latitude; + if (marker->latitude < min_lat) min_lat = marker->latitude; } + dd->lon = (max_lon + min_lon) / 2; + dd->lat = (max_lat + min_lat) / 2; - // FIXME: scroller can be jumping strangely when resizing & scrolling at the sametime (els_scr bug?) - _scr_scroll(wd->obj, NULL, NULL); + zoom = dd->wd->src->zoom_min; + _viewport_size_get(dd->wd, &vw, &vh); + while (zoom <= dd->wd->src->zoom_max) + { + Evas_Coord size, max_x, max_y, min_x, min_y; + size = pow(2.0, zoom) * dd->wd->tsize; + elm_map_utils_convert_geo_into_coord(dd->wd->obj, min_lon, max_lat, size, &min_x, &max_y); + elm_map_utils_convert_geo_into_coord(dd->wd->obj, max_lon, min_lat, size, &max_x, &min_y); + if ((max_x - min_x) > vw || (max_y - min_y) > vh) break; + zoom++; + } + zoom--; - return EVAS_EVENT_FLAG_NONE; + zoom_do(dd->wd, zoom); + _region_show(dd); + evas_object_smart_changed(dd->wd->pan_smart); } -static Evas_Event_Flags -rotate_cb(void *data, void *event_info) +static char * +_mapnik_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom) { - Widget_Data *wd = data; - EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EVAS_EVENT_FLAG_NONE); + char buf[PATH_MAX]; + // ((x+y+zoom)%3)+'a' is requesting map images from distributed tile servers (eg., a, b, c) + snprintf(buf, sizeof(buf), "http://%c.tile.openstreetmap.org/%d/%d/%d.png", + ((x + y + zoom) % 3) + 'a', zoom, x, y); + return strdup(buf); +} - if (!wd->paused) - { - int x, y, w, h; - Elm_Gesture_Rotate_Info *ei = event_info; - evas_object_geometry_get(wd->obj, &x, &y, &w, &h); +static char * +_osmarender_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom) +{ + char buf[PATH_MAX]; + snprintf(buf, sizeof(buf), + "http://%c.tah.openstreetmap.org/Tiles/tile/%d/%d/%d.png", + ((x + y + zoom) % 3) + 'a', zoom, x, y); + return strdup(buf); +} - wd->rotate.d = wd->rotate.a + (ei->base_angle-ei->angle)*50; - wd->rotate.cx = x + ((double)w * 0.5); - wd->rotate.cy = y + ((double)h * 0.5); +static char * +_cyclemap_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom) +{ + char buf[PATH_MAX]; + snprintf(buf, sizeof(buf), + "http://%c.tile.opencyclemap.org/cycle/%d/%d/%d.png", + (( x + y + zoom) % 3) + 'a', zoom, x, y); + return strdup(buf); +} - if (wd->calc_job) ecore_job_del(wd->calc_job); - wd->calc_job = ecore_job_add(_calc_job, wd); - } - return EVAS_EVENT_FLAG_NONE; +static char * +_mapquest_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom) +{ + char buf[PATH_MAX]; + snprintf(buf, sizeof(buf), + "http://otile%d.mqcdn.com/tiles/1.0.0/osm/%d/%d/%d.png", + ((x + y + zoom) % 4) + 1, zoom, x, y); + return strdup(buf); } -static Evas_Event_Flags -rotate_end_cb(void *data, void *event_info __UNUSED__) +static char * +_mapquest_aerial_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom) { - Widget_Data *wd = data; - EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EVAS_EVENT_FLAG_NONE); + char buf[PATH_MAX]; + snprintf(buf, sizeof(buf), "http://oatile%d.mqcdn.com/naip/%d/%d/%d.png", + ((x + y + zoom) % 4) + 1, zoom, x, y); + return strdup(buf); +} - wd->rotate.a = wd->rotate.d; +static char *_yours_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat) +{ + char buf[PATH_MAX]; + snprintf(buf, sizeof(buf), + "%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 EVAS_EVENT_FLAG_NONE; + return strdup(buf); } -static void -_region_get(Widget_Data *wd, Evas_Coord *x, Evas_Coord *y, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *w, Evas_Coord *h) +// TODO: fix monav api +/* +static char *_monav_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat) { - EINA_SAFETY_ON_NULL_RETURN(wd); - Evas_Coord sx, sy, tx, ty, tcx, tcy, sw, sh, tw, th, rw, rh; - - elm_smart_scroller_child_pos_get(wd->scr, &sx, &sy); - elm_smart_scroller_child_viewport_size_get(wd->scr, &sw, &sh); - rw = wd->size.w * wd->pinch.level; - rh = wd->size.h * wd->pinch.level; + char buf[PATH_MAX]; + snprintf(buf, sizeof(buf), + "%s?flat=%f&flon=%f&tlat=%f&tlon=%f&v=%s&fast=%d&instructions=1", + ROUTE_MONAV_URL, flat, flon, tlat, tlon, type_name, method); - if (wd->size.w < sw) - { - tw = rw; - tcx = sx + tw/2; - tx = sx + (sw - tw)/2; - } - else - { - tw = sw; - tcx = (sx + tw/2) * wd->pinch.level; - tx = tcx - tw/2; + return strdup(buf); +} +*/ - } - if (wd->size.h < sh) - { - th = rh; - ty = sy + (sh - th)/2; - tcy = sy + th/2; - } - else - { - th = sw; - tcy = (sy + th/2) * wd->pinch.level; - ty = tcy - th/2; - } +// TODO: fix ors api +/* +static char *_ors_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat) +{ + char buf[PATH_MAX]; + snprintf(buf, sizeof(buf), + "%s?flat=%f&flon=%f&tlat=%f&tlon=%f&v=%s&fast=%d&instructions=1", + ROUTE_ORS_URL, flat, flon, tlat, tlon, type_name, method); - if (x) *x = tx; - if (y) *y = ty; - if (cx) *cx= tcx; - if (cy) *cy = tcy; - if (w) *w = tw; - if (h) *h = th; + return strdup(buf); } +*/ -static void -_coord_rotate(const Evas_Coord x, const Evas_Coord y, const Evas_Coord cx, const Evas_Coord cy, const double degree, Evas_Coord *xx, Evas_Coord *yy) +static char * +_nominatim_url_cb(Evas_Object *obj, int method, char *name, double lon, double lat) { - EINA_SAFETY_ON_NULL_RETURN(xx); - EINA_SAFETY_ON_NULL_RETURN(yy); + ELM_CHECK_WIDTYPE(obj, widtype) strdup(""); + Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN_VAL(wd, strdup("")); - double r = (degree * M_PI) / 180.0; - double tx, ty, ttx, tty; + char **str; + unsigned int ele, idx; + char search_url[PATH_MAX]; + char buf[PATH_MAX]; - tx = x - cx; - ty = y - cy; + 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); - ttx = tx * cos(r); - tty = tx * sin(r); - tx = ttx + (ty * cos(r + M_PI_2)); - ty = tty + (ty * sin(r + M_PI_2)); + if (str && str[0]) + { + free(str[0]); + free(str); + } + } + 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, (int)wd->zoom); + else strcpy(buf, ""); - *xx = tx + cx; - *yy = ty + cy; + return strdup(buf); } #endif @@ -3038,68 +2869,55 @@ elm_map_add(Evas_Object *parent) #ifdef HAVE_ELEMENTARY_ECORE_CON Evas *e; Widget_Data *wd; - Evas_Coord minw, minh; Evas_Object *obj; - static Evas_Smart *smart = NULL; - Eina_Bool bounce = _elm_config->thumbscroll_bounce_enable; + Evas_Coord minw, minh; ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL); - ELM_SET_WIDTYPE(widtype, "map"); elm_widget_type_set(obj, "map"); elm_widget_sub_object_add(parent, obj); - elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL); elm_widget_data_set(obj, wd); + elm_widget_can_focus_set(obj, EINA_TRUE); + elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL); elm_widget_del_hook_set(obj, _del_hook); elm_widget_del_pre_hook_set(obj, _del_pre_hook); elm_widget_theme_hook_set(obj, _theme_hook); - elm_widget_can_focus_set(obj, EINA_TRUE); elm_widget_event_hook_set(obj, _event_hook); + evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, wd); + evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, wd); + evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, wd); + evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, wd); + evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN, + _mouse_down, wd); + evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP, + _mouse_up, wd); + evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_WHEEL, + _mouse_wheel_cb,wd); + wd->obj = obj; wd->scr = elm_smart_scroller_add(e); + elm_widget_sub_object_add(obj, wd->scr); elm_smart_scroller_widget_set(wd->scr, obj); elm_smart_scroller_object_theme_set(obj, wd->scr, "map", "base", "default"); - evas_object_smart_callback_add(wd->scr, "scroll", _scr, obj); - evas_object_smart_callback_add(wd->scr, "drag", _scr, obj); elm_widget_resize_object_set(obj, wd->scr); elm_smart_scroller_wheel_disabled_set(wd->scr, EINA_TRUE); - - evas_object_smart_callback_add(wd->scr, "animate,start", _scr_anim_start, obj); - evas_object_smart_callback_add(wd->scr, "animate,stop", _scr_anim_stop, obj); - evas_object_smart_callback_add(wd->scr, "drag,start", _scr_drag_start, obj); - evas_object_smart_callback_add(wd->scr, "drag,stop", _scr_drag_stop, obj); - evas_object_smart_callback_add(wd->scr, "scroll", _scr_scroll, obj); - - elm_smart_scroller_bounce_allow_set(wd->scr, bounce, bounce); - - wd->zoom_min = 0xFF; - wd->zoom_max = 0X00; - source_init(obj); - - wd->obj = obj; - wd->map = evas_map_new(4); - if (!wd->map) return NULL; - - wd->markers_max_num = 30; - wd->pinch.level = 1.0; - wd->pinch.diff = 1.0; - wd->markers = calloc(wd->zoom_max + 1, sizeof(void*)); - - evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj); - evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj); - evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj); - evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj); + elm_smart_scroller_bounce_allow_set(wd->scr, + _elm_config->thumbscroll_bounce_enable, + _elm_config->thumbscroll_bounce_enable); + evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_CHANGED_SIZE_HINTS, + _changed_size_hints, wd); + evas_object_smart_callback_add(wd->scr, "scroll", _scr, wd); + evas_object_smart_callback_add(wd->scr, "drag", _scr, wd); + evas_object_smart_callback_add(wd->scr, "animate,start", _scr_anim_start, wd); + evas_object_smart_callback_add(wd->scr, "animate,stop", _scr_anim_stop, wd); if (!smart) { - static Evas_Smart_Class sc; - - evas_object_smart_clipped_smart_set(&_pan_sc); - sc = _pan_sc; + evas_object_smart_clipped_smart_set(&parent_sc); + sc = parent_sc; sc.name = "elm_map_pan"; sc.version = EVAS_SMART_CLASS_VERSION; sc.add = _pan_add; - sc.del = _pan_del; sc.resize = _pan_resize; sc.move = _pan_move; sc.calculate = _pan_calculate; @@ -3107,75 +2925,58 @@ elm_map_add(Evas_Object *parent) } if (smart) { + Pan *pan; wd->pan_smart = evas_object_smart_add(e, smart); - wd->pan = evas_object_smart_data_get(wd->pan_smart); - wd->pan->wd = wd; + pan = evas_object_smart_data_get(wd->pan_smart); + pan->wd = wd; } + elm_widget_sub_object_add(obj, wd->pan_smart); elm_smart_scroller_extern_pan_set(wd->scr, wd->pan_smart, _pan_set, _pan_get, _pan_max_get, _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_UP, - _mouse_up, obj); - evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MOUSE_WHEEL, - _mouse_wheel_cb, obj); - - evas_object_smart_member_add(wd->rect, wd->pan_smart); - elm_widget_sub_object_add(obj, wd->rect); - evas_object_show(wd->rect); - evas_object_color_set(wd->rect, 0, 0, 0, 0); + edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr), + &minw, &minh); + evas_object_size_hint_min_set(obj, minw, minh); wd->ges = elm_gesture_layer_add(obj); if (!wd->ges) ERR("elm_gesture_layer_add() failed"); - elm_gesture_layer_attach(wd->ges, wd->rect); + elm_gesture_layer_attach(wd->ges, obj); elm_gesture_layer_cb_set(wd->ges, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_START, - zoom_start_cb, wd); + _pinch_zoom_start_cb, wd); elm_gesture_layer_cb_set(wd->ges, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_MOVE, - zoom_cb, wd); - elm_gesture_layer_cb_set(wd->ges, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_END, - zoom_end_cb, wd); - elm_gesture_layer_cb_set(wd->ges, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_ABORT, - zoom_end_cb, wd); + _pinch_zoom_cb, wd); elm_gesture_layer_cb_set(wd->ges, ELM_GESTURE_ROTATE, ELM_GESTURE_STATE_MOVE, - rotate_cb, wd); + _pinch_rotate_cb, wd); elm_gesture_layer_cb_set(wd->ges, ELM_GESTURE_ROTATE, ELM_GESTURE_STATE_END, - rotate_end_cb, wd); + _pinch_rotate_end_cb, wd); elm_gesture_layer_cb_set(wd->ges, ELM_GESTURE_ROTATE, ELM_GESTURE_STATE_ABORT, - rotate_end_cb, wd); - - wd->mode = ELM_MAP_ZOOM_MODE_MANUAL; - wd->id = ((int)getpid() << 16) | idnum; - idnum++; - - wd->tsize = 256; - edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr), - &minw, &minh); - evas_object_size_hint_min_set(obj, minw, minh); + _pinch_rotate_end_cb, wd); wd->sep_maps_markers = evas_object_rectangle_add(evas_object_evas_get(obj)); + elm_widget_sub_object_add(obj, wd->sep_maps_markers); evas_object_smart_member_add(wd->sep_maps_markers, wd->pan_smart); - grid_create_all(obj); + wd->map = evas_map_new(EVAS_MAP_POINT); + + source_init(wd); + wd->tsize = DEFAULT_TILE_SIZE; // FIXME: It should be hard-coded ? or can get from provider? + + wd->id = ((int)getpid() << 16) | idnum; + idnum++; + _grid_all_create(wd); - wd->paused = EINA_TRUE; - elm_map_zoom_set(obj, 0); - wd->paused = EINA_FALSE; - _sizing_eval(obj); + zoom_do(wd, 0); + + wd->mode = ELM_MAP_ZOOM_MODE_MANUAL; + wd->markers_max_num = MARER_MAX_NUMBER; // TODO: convert Elementary to subclassing of Evas_Smart_Class // TODO: and save some bytes, making descriptions per-class and not instance! evas_object_smart_callbacks_descriptions_set(obj, _signals); if (!ecore_file_download_protocol_available("http://")) - { - ERR("Ecore must be built with curl support for the map widget!"); - } + ERR("Ecore must be built with curl support for the map widget!"); return obj; #else @@ -3190,119 +2991,21 @@ elm_map_zoom_set(Evas_Object *obj, int zoom) #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype); Widget_Data *wd = elm_widget_data_get(obj); - Eina_List *l; - Evas_Coord rx, ry, rw, rh; - Evas_Object *p; - Elm_Map_Route *r; - Evas_Object *route; - int z = 0; - EINA_SAFETY_ON_NULL_RETURN(wd); EINA_SAFETY_ON_NULL_RETURN(wd->src); - if (wd->zoom_animator) return; + if (wd->mode != ELM_MAP_ZOOM_MODE_MANUAL) return; if (zoom < 0) zoom = 0; + if (wd->zoom == zoom) return; if (zoom > wd->src->zoom_max) zoom = wd->src->zoom_max; if (zoom < wd->src->zoom_min) zoom = wd->src->zoom_min; - if ((wd->zoom - zoom) > 0) wd->zoom_method = ZOOM_METHOD_OUT; - else if ((wd->zoom - zoom) < 0) wd->zoom_method = ZOOM_METHOD_IN; - else wd->zoom_method = ZOOM_METHOD_NONE; - - wd->zoom = 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); - - EINA_LIST_FOREACH(wd->route, l, r) - { - if (r) - { - EINA_LIST_FOREACH(r->path, l, p) - { - evas_object_polygon_points_clear(p); - } - } - } - - EINA_LIST_FOREACH(wd->track, l, route) - { - evas_object_hide(route); - } - - if (wd->mode != ELM_MAP_ZOOM_MODE_MANUAL) - { - int p2w, p2h; - int cumulw, cumulh; - - cumulw = wd->tsize; - p2w = 0; - while (cumulw <= rw) - { - p2w++; - cumulw *= 2; - } - p2w--; - - cumulh = wd->tsize; - p2h = 0; - while (cumulh <= rh) - { - p2h++; - cumulh *= 2; - } - p2h--; - - if (wd->mode == ELM_MAP_ZOOM_MODE_AUTO_FIT) - { - if (p2w < p2h) z = p2w; - else z = p2h; - } - else if (wd->mode == ELM_MAP_ZOOM_MODE_AUTO_FILL) - { - if (p2w > p2h) z = p2w; - else z = p2h; - } - wd->zoom = z; - } - - wd->size.nw = pow(2.0, wd->zoom) * wd->tsize; - wd->size.nh = pow(2.0, wd->zoom) * wd->tsize; - wd->t = 1.0; - - if ((wd->size.w > 0) && (wd->size.h > 0)) - { - wd->size.spos.x = (double)(rx + (rw / 2)) / (double)wd->size.ow; - wd->size.spos.y = (double)(ry + (rh / 2)) / (double)wd->size.oh; - } - else - { - wd->size.spos.x = 0.5; - wd->size.spos.y = 0.5; - } - - if (rw > wd->size.ow) wd->size.spos.x = 0.5; - if (rh > wd->size.oh) wd->size.spos.y = 0.5; - if (wd->size.spos.x > 1.0) wd->size.spos.x = 1.0; - if (wd->size.spos.y > 1.0) wd->size.spos.y = 1.0; - - if (wd->paused) - { - zoom_do(obj); - } - else - { - if (!wd->zoom_animator) - { - wd->zoom_animator = ecore_animator_add(_zoom_anim, obj); - wd->nosmooth++; - if (wd->nosmooth == 1) _smooth_update(obj); - evas_object_smart_callback_call(obj, SIG_ZOOM_START, NULL); - } - } - - if (wd->zoom_method != ZOOM_METHOD_NONE) evas_object_smart_callback_call(obj, SIG_ZOOM_CHANGE, NULL); + Delayed_Data *data = ELM_NEW(Delayed_Data); + data->func = _zoom_set; + data->wd = wd; + data->zoom = zoom; + data->wd->delayed_jobs = eina_list_append(data->wd->delayed_jobs, data); + evas_object_smart_changed(data->wd->pan_smart); #else (void) obj; (void) zoom; @@ -3316,7 +3019,7 @@ elm_map_zoom_get(const Evas_Object *obj) ELM_CHECK_WIDTYPE(obj, widtype) 0; Widget_Data *wd = elm_widget_data_get(obj); - if (!wd) return 0; + EINA_SAFETY_ON_NULL_RETURN_VAL(wd, 0); return wd->zoom; #else (void) obj; @@ -3330,17 +3033,14 @@ elm_map_zoom_mode_set(Evas_Object *obj, Elm_Map_Zoom_Mode mode) #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype); Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN(wd); - if (!wd) return; - if (wd->mode == mode) return; - wd->mode = mode; - - if (wd->mode != ELM_MAP_ZOOM_MODE_MANUAL) - { - int tz = wd->zoom; - wd->zoom = 0; - elm_map_zoom_set(wd->obj, tz); - } + Delayed_Data *data = ELM_NEW(Delayed_Data); + data->mode = mode; + data->func = _zoom_mode_set; + data->wd = wd; + data->wd->delayed_jobs = eina_list_append(data->wd->delayed_jobs, data); + evas_object_smart_changed(data->wd->pan_smart); #else (void) obj; (void) mode; @@ -3353,8 +3053,8 @@ elm_map_zoom_mode_get(const Evas_Object *obj) #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype) ELM_MAP_ZOOM_MODE_MANUAL; Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN_VAL(wd, ELM_MAP_ZOOM_MODE_MANUAL); - if (!wd) return ELM_MAP_ZOOM_MODE_MANUAL; return wd->mode; #else (void) obj; @@ -3368,29 +3068,14 @@ elm_map_geo_region_bring_in(Evas_Object *obj, double lon, double lat) #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype); Widget_Data *wd = elm_widget_data_get(obj); - int rx, ry, rw, rh; - if (!wd) return; - elm_map_utils_convert_geo_into_coord(obj, lon, lat, wd->size.w, &rx, &ry); - elm_smart_scroller_child_viewport_size_get(wd->scr, &rw, &rh); - - rx = rx - rw / 2; - ry = ry - rh / 2; - - if (wd->zoom_animator) - { - wd->nosmooth--; - if (!wd->nosmooth) _smooth_update(obj); - ecore_animator_del(wd->zoom_animator); - wd->zoom_animator = NULL; - zoom_do(obj); - evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL); - } - elm_smart_scroller_region_bring_in(wd->scr, rx, ry, rw, rh); - - wd->center_on.enabled = EINA_TRUE; - wd->center_on.lon = lon; - wd->center_on.lat = lat; + Delayed_Data *data = ELM_NEW(Delayed_Data); + data->func = _region_bring_in; + data->wd = wd; + data->lon = lon; + data->lat = lat; + data->wd->delayed_jobs = eina_list_append(data->wd->delayed_jobs, data); + evas_object_smart_changed(data->wd->pan_smart); #else (void) obj; (void) lon; @@ -3400,32 +3085,18 @@ elm_map_geo_region_bring_in(Evas_Object *obj, double lon, double lat) EAPI void elm_map_geo_region_show(Evas_Object *obj, double lon, double lat) -{ -#ifdef HAVE_ELEMENTARY_ECORE_CON - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); - int rx, ry, rw, rh; - - if (!wd) return; - elm_map_utils_convert_geo_into_coord(obj, lon, lat, wd->size.w, &rx, &ry); - elm_smart_scroller_child_viewport_size_get(wd->scr, &rw, &rh); - - rx = rx - rw / 2; - ry = ry - rh / 2; - - if (wd->zoom_animator) - { - wd->nosmooth--; - ecore_animator_del(wd->zoom_animator); - wd->zoom_animator = NULL; - zoom_do(obj); - evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL); - } - elm_smart_scroller_child_region_show(wd->scr, rx, ry, rw, rh); +{ +#ifdef HAVE_ELEMENTARY_ECORE_CON + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); - wd->center_on.enabled = EINA_TRUE; - wd->center_on.lon = lon; - wd->center_on.lat = lat; + Delayed_Data *data = ELM_NEW(Delayed_Data); + data->func = _region_show; + data->wd = wd; + data->lon = lon; + data->lat = lat; + data->wd->delayed_jobs = eina_list_append(data->wd->delayed_jobs, data); + evas_object_smart_changed(data->wd->pan_smart); #else (void) obj; (void) lon; @@ -3439,14 +3110,15 @@ elm_map_geo_region_get(const Evas_Object *obj, double *lon, double *lat) #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype); Widget_Data *wd = elm_widget_data_get(obj); - Evas_Coord cx, cy; - int rw; - double tlon, tlat; EINA_SAFETY_ON_NULL_RETURN(wd); - _region_get(wd, NULL, NULL, &cx, &cy, NULL, NULL); - rw = wd->size.w * wd->pinch.level; - elm_map_utils_convert_coord_into_geo(obj, cx, cy, rw, &tlon, &tlat); + double tlon, tlat; + Evas_Coord px, py, vw, vh; + + _pan_geometry_get(wd, &px, &py); + _viewport_size_get(wd, &vw, &vh); + elm_map_utils_convert_coord_into_geo(obj, vw/2 - px, vh/2 -py, wd->size.w, + &tlon, &tlat); if (lon) *lon = tlon; if (lat) *lat = tlat; #else @@ -3462,8 +3134,8 @@ elm_map_paused_set(Evas_Object *obj, Eina_Bool paused) #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype); Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN(wd); - if (!wd) return; if (wd->paused == !!paused) return; wd->paused = !!paused; if (wd->paused) @@ -3472,8 +3144,7 @@ elm_map_paused_set(Evas_Object *obj, Eina_Bool paused) { if (wd->zoom_animator) ecore_animator_del(wd->zoom_animator); wd->zoom_animator = NULL; - zoom_do(obj); - evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL); + zoom_do(wd, wd->zoom); } edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), "elm,state,busy,stop", "elm"); @@ -3496,8 +3167,8 @@ elm_map_paused_markers_set(Evas_Object *obj, Eina_Bool paused) #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype); Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN(wd); - if (!wd) return; if (wd->paused_markers == !!paused) return; wd->paused_markers = paused; #else @@ -3512,8 +3183,8 @@ elm_map_paused_get(const Evas_Object *obj) #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EINA_FALSE); - if (!wd) return EINA_FALSE; return wd->paused; #else (void) obj; @@ -3527,8 +3198,8 @@ elm_map_paused_markers_get(const Evas_Object *obj) #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EINA_FALSE); - if (!wd) return EINA_FALSE; return wd->paused_markers; #else (void) obj; @@ -3542,17 +3213,10 @@ elm_map_utils_downloading_status_get(const Evas_Object *obj, int *try_num, int * #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype); Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN(wd); - if (!wd) return; - if (try_num) - { - *try_num = wd->try_num; - } - - if (finish_num) - { - *finish_num = wd->finish_num; - } + if (try_num) *try_num = wd->try_num; + if (finish_num) *finish_num = wd->finish_num; #else (void) obj; (void) try_num; @@ -3566,21 +3230,18 @@ elm_map_utils_convert_coord_into_geo(const Evas_Object *obj, int x, int y, int s #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype); Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN(wd); - if (!wd) return; int zoom = floor(log(size / 256) / log(2)); if ((wd->src) && (wd->src->coord_into_geo)) { if (wd->src->coord_into_geo(obj, zoom, x, y, size, lon, lat)) return; } - if (lon) - { - *lon = x / (double)size * 360.0 - 180; - } + if (lon) *lon = (x / (double)size * 360.0) - 180; if (lat) { - double n = ELM_PI - 2.0 * ELM_PI * y / size; + double n = ELM_PI - (2.0 * ELM_PI * y / size); *lat = 180.0 / ELM_PI * atan(0.5 * (exp(n) - exp(-n))); } #else @@ -3599,18 +3260,18 @@ elm_map_utils_convert_geo_into_coord(const Evas_Object *obj, double lon, double #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype); Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN(wd); - if (!wd) return; int zoom = floor(log(size / 256) / log(2)); if ((wd->src) && (wd->src->geo_into_coord)) { if (wd->src->geo_into_coord(obj, zoom, lon, lat, size, x, y)) return; } - if (x) - *x = floor((lon + 180.0) / 360.0 * size); + if (x) *x = floor((lon + 180.0) / 360.0 * size); if (y) - *y = floor((1.0 - log( tan(lat * ELM_PI / 180.0) + 1.0 / cos(lat * ELM_PI / 180.0)) / ELM_PI) / 2.0 * size); + *y = floor((1.0 - log(tan(lat * ELM_PI / 180.0) + (1.0 / cos(lat * ELM_PI / 180.0))) + / ELM_PI) / 2.0 * size); #else (void) obj; (void) lon; @@ -3667,7 +3328,7 @@ elm_map_utils_rotate_coord(const Evas_Object *obj, const Evas_Coord x, const Eva } EAPI void -elm_map_canvas_to_geo_convert(const Evas_Object *obj, const Evas_Coord x, const Evas_Coord y, double *lon, double *lat) +elm_map_canvas_to_geo_convert(const Evas_Object *obj, Evas_Coord x, Evas_Coord y, double *lon, double *lat) { #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype); @@ -3676,25 +3337,12 @@ elm_map_canvas_to_geo_convert(const Evas_Object *obj, const Evas_Coord x, const EINA_SAFETY_ON_NULL_RETURN(lat); EINA_SAFETY_ON_NULL_RETURN(wd); - Evas_Coord xx, yy, w, h, mw, tx, ty, cx, cy; - double d; - - _region_get(wd, &xx, &yy, &cx, &cy, &w, &h); - mw = wd->size.w * wd->pinch.level; - if (w < mw) - { - xx += x; - yy += y; - } - else - { - xx = x - xx; - yy = y - yy; - } - - elm_map_rotate_get(obj, &d, NULL, NULL); - _coord_rotate(xx, yy, cx, cy, -d, &tx, &ty); - elm_map_utils_convert_coord_into_geo(obj, tx, ty, mw, lon, lat); + Evas_Coord px, py, vw, vh; + _pan_geometry_get(wd, &px, &py); + _viewport_size_get(wd, &vw, &vh); + _coord_rotate(x - px, y - py, (vw / 2) - px, (vh / 2) - py, -wd->rotate.d, + &x, &y); + elm_map_utils_convert_coord_into_geo(obj, x, y, wd->size.w, lon, lat); #else (void) obj; (void) x; @@ -3705,196 +3353,48 @@ elm_map_canvas_to_geo_convert(const Evas_Object *obj, const Evas_Coord x, const } 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) +elm_map_marker_add(Evas_Object *obj, double lon, double lat, Elm_Map_Marker_Class *clas, Elm_Map_Group_Class *group_clas, void *data) { #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype) NULL; Widget_Data *wd = elm_widget_data_get(obj); - int i, j; - Eina_List *l; - Marker_Group *group; - int mpi, mpj; - int tabi[9]; - int tabj[9]; - const char *s; - const char *style; - Evas_Object *o; - if (!wd) return NULL; - EINA_SAFETY_ON_NULL_RETURN_VAL(clas_group, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL); EINA_SAFETY_ON_NULL_RETURN_VAL(clas, NULL); Elm_Map_Marker *marker = ELM_NEW(Elm_Map_Marker); - marker->wd = wd; marker->clas = clas; - marker->clas_group = clas_group; + marker->group_clas = group_clas; marker->longitude = lon; marker->latitude = lat; marker->data = data; - marker->x = calloc(wd->zoom_max + 1, sizeof(Evas_Coord)); - marker->y = calloc(wd->zoom_max + 1, sizeof(Evas_Coord)); - marker->groups = calloc(wd->zoom_max + 1, sizeof(Marker_Group*)); - - tabi[1] = tabi[4] = tabi[6] = -1; - tabi[2] = tabi[0] = tabi[7] = 0; - tabi[3] = tabi[5] = tabi[8] = 1; - - tabj[1] = tabj[2] = tabj[3] = -1; - tabj[4] = tabj[0] = tabj[5] = 0; - tabj[6] = tabj[7] = tabj[8] = 1; - - if (!clas_group->priv.set) - { - style = "radio"; - if (marker->clas_group && marker->clas_group->style) - style = marker->clas_group->style; - - o = edje_object_add(evas_object_evas_get(obj)); - _elm_theme_object_set(obj, o, "map/marker", style, elm_widget_style_get(obj)); - s = edje_object_data_get(o, "size_w"); - if (s) clas_group->priv.edje_w = atoi(s); - else clas_group->priv.edje_w = 0; - s = edje_object_data_get(o, "size_h"); - if (s) clas_group->priv.edje_h = atoi(s); - else clas_group->priv.edje_h = 0; - s = edje_object_data_get(o, "size_max_w"); - if (s) clas_group->priv.edje_max_w = atoi(s); - else clas_group->priv.edje_max_w = 0; - s = edje_object_data_get(o, "size_max_h"); - if (s) clas_group->priv.edje_max_h = atoi(s); - else clas_group->priv.edje_max_h = 0; - evas_object_del(o); - - clas_group->priv.set = EINA_TRUE; - } - - if (!clas->priv.set) - { - style = "radio"; - if (marker->clas && marker->clas->style) - style = marker->clas->style; - - o = edje_object_add(evas_object_evas_get(obj)); - _elm_theme_object_set(obj, o, "map/marker", style, elm_widget_style_get(obj)); - s = edje_object_data_get(o, "size_w"); - if (s) clas->priv.edje_w = atoi(s); - else clas->priv.edje_w = 0; - s = edje_object_data_get(o, "size_h"); - if (s) clas->priv.edje_h = atoi(s); - else clas->priv.edje_h = 0; - evas_object_del(o); - - clas->priv.set = EINA_TRUE; - } - - for (i = clas_group->zoom_displayed; i <= wd->zoom_max; i++) - { - elm_map_utils_convert_geo_into_coord(obj, lon, lat, pow(2.0, i)*wd->tsize, - &(marker->x[i]), &(marker->y[i])); - - //search in the matrixsparse the region where the marker will be - mpi = marker->x[i] / wd->tsize; - mpj = marker->y[i] / wd->tsize; - - if (!wd->markers[i]) - { - int size = pow(2.0, i); - wd->markers[i] = eina_matrixsparse_new(size, size, NULL, NULL); - } - - group = NULL; - if (i <= clas_group->zoom_grouped) - { - for (j = 0, group = NULL; j < 9 && !group; j++) - { - EINA_LIST_FOREACH(eina_matrixsparse_data_idx_get(wd->markers[i], mpj + tabj[j], mpi + tabi[j]), - l, group) - { - if (group->clas == marker->clas_group - && ELM_RECTS_INTERSECT(marker->x[i]-clas->priv.edje_w/4, - marker->y[i]-clas->priv.edje_h/4, clas->priv.edje_w, clas->priv.edje_h, - group->x-group->w/4, group->y-group->h/4, group->w, group->h)) - { - group->markers = eina_list_append(group->markers, marker); - group->update_nbelems = EINA_TRUE; - group->update_resize = EINA_TRUE; - - group->sum_x += marker->x[i]; - group->sum_y += marker->y[i]; - group->x = group->sum_x / eina_list_count(group->markers); - group->y = group->sum_y / eina_list_count(group->markers); - - group->w = group->clas->priv.edje_w + group->clas->priv.edje_w/8. - * eina_list_count(group->markers); - group->h = group->clas->priv.edje_h + group->clas->priv.edje_h/8. - * eina_list_count(group->markers); - if (group->w > group->clas->priv.edje_max_w) group->w = group->clas->priv.edje_max_w; - if (group->h > group->clas->priv.edje_max_h) group->h = group->clas->priv.edje_max_h; - - if (group->obj && eina_list_count(group->markers) == 2) - { - _group_object_free(group); - _group_object_create(group); - } - if (group->bubble) - _group_bubble_content_update(group); - - break; - } - } - } - } - if (!group) - { - group = calloc(1, sizeof(Marker_Group)); - group->wd = wd; - group->sum_x = marker->x[i]; - group->sum_y = marker->y[i]; - group->x = marker->x[i]; - group->y = marker->y[i]; - group->w = clas_group->priv.edje_w; - group->h = clas_group->priv.edje_h; - group->clas = clas_group; - - group->markers = eina_list_append(group->markers, marker); - group->update_nbelems = EINA_TRUE; - group->update_resize = EINA_TRUE; - - eina_matrixsparse_cell_idx_get(wd->markers[i], mpj, mpi, &(group->cell)); - - if (!group->cell) - { - l = eina_list_append(NULL, group); - eina_matrixsparse_data_idx_set(wd->markers[i], mpj, mpi, l); - eina_matrixsparse_cell_idx_get(wd->markers[i], mpj, mpi, &(group->cell)); - } - else - { - l = eina_matrixsparse_cell_data_get(group->cell); - l = eina_list_append(l, group); - eina_matrixsparse_cell_data_set(group->cell, l); - } - } - marker->groups[i] = group; - } - - if (wd->grids) - { - Grid *g; - Evas_Coord ox, oy, ow, oh; - evas_object_geometry_get(obj, &ox, &oy, &ow, &oh); - g = _get_current_grid(wd); - marker_place(obj, g, wd->pan_x, wd->pan_y, ox, oy, ow, oh); - } - + marker->x = 0; + marker->y = 0; + _edj_marker_size_get(wd, &marker->w, &marker->h); + + marker->obj = elm_layout_add(wd->obj); + evas_object_smart_member_add(marker->obj, wd->pan_smart); + evas_object_stack_above(marker->obj, wd->sep_maps_markers); + + edje_object_signal_callback_add(elm_layout_edje_get(marker->obj), + "open", "elm", _marker_bubble_open_cb, + marker); + edje_object_signal_callback_add(elm_layout_edje_get(marker->obj), + "bringin", "elm", _marker_bringin_cb, + marker); + + wd->markers = eina_list_append(wd->markers, marker); + if (marker->group_clas) group_clas->markers = eina_list_append(group_clas->markers, + marker); + evas_object_smart_changed(wd->pan_smart); return marker; #else (void) obj; (void) lon; (void) lat; (void) clas; - (void) clas_group; + (void) group_clas; (void) data; return NULL; #endif @@ -3904,70 +3404,24 @@ EAPI void elm_map_marker_remove(Elm_Map_Marker *marker) { #ifdef HAVE_ELEMENTARY_ECORE_CON - int i; - Eina_List *groups; - Widget_Data *wd; - EINA_SAFETY_ON_NULL_RETURN(marker); - wd = marker->wd; - if (!wd) return; - for (i = marker->clas_group->zoom_displayed; i <= wd->zoom_max; i++) - { - marker->groups[i]->markers = eina_list_remove(marker->groups[i]->markers, marker); - if (!eina_list_count(marker->groups[i]->markers)) - { - groups = eina_matrixsparse_cell_data_get(marker->groups[i]->cell); - groups = eina_list_remove(groups, marker->groups[i]); - eina_matrixsparse_cell_data_set(marker->groups[i]->cell, groups); - - _group_object_free(marker->groups[i]); - _group_bubble_free(marker->groups[i]); - free(marker->groups[i]); - } - else - { - marker->groups[i]->sum_x -= marker->x[i]; - marker->groups[i]->sum_y -= marker->y[i]; - - marker->groups[i]->x = marker->groups[i]->sum_x / eina_list_count(marker->groups[i]->markers); - marker->groups[i]->y = marker->groups[i]->sum_y / eina_list_count(marker->groups[i]->markers); - - marker->groups[i]->w = marker->groups[i]->clas->priv.edje_w - + marker->groups[i]->clas->priv.edje_w/8. * eina_list_count(marker->groups[i]->markers); - marker->groups[i]->h = marker->groups[i]->clas->priv.edje_h - + marker->groups[i]->clas->priv.edje_h/8. * eina_list_count(marker->groups[i]->markers); - if (marker->groups[i]->w > marker->groups[i]->clas->priv.edje_max_w) - marker->groups[i]->w = marker->groups[i]->clas->priv.edje_max_w; - if (marker->groups[i]->h > marker->groups[i]->clas->priv.edje_max_h) - marker->groups[i]->h = marker->groups[i]->clas->priv.edje_max_h; - - if ((marker->groups[i]->obj) && (eina_list_count(marker->groups[i]->markers) == 1)) - { - _group_object_free(marker->groups[i]); - _group_object_create(marker->groups[i]); - } - } - } + Widget_Data *wd = marker->wd; + EINA_SAFETY_ON_NULL_RETURN(wd); if ((marker->content) && (marker->clas->func.del)) - marker->clas->func.del(marker->wd->obj, marker, marker->data, marker->content); - else if (marker->content) - evas_object_del(marker->content); + marker->clas->func.del(wd->obj, marker, marker->data, marker->content); - if (marker->x) free(marker->x); - if (marker->y) free(marker->y); - if (marker->groups) free(marker->groups); + if (marker->bubble) _bubble_free(marker->bubble); + if (marker->group) _marker_group_free(marker->group); + if (marker->group_clas) + marker->group_clas->markers = eina_list_remove(marker->group_clas->markers, marker); + wd->markers = eina_list_remove(wd->markers, marker); + + evas_object_del(marker->obj); free(marker); - if (wd->grids) - { - Grid *g; - Evas_Coord ox, oy, ow, oh; - evas_object_geometry_get(wd->obj, &ox, &oy, &ow, &oh); - g = _get_current_grid(wd); - marker_place(wd->obj, g, wd->pan_x, wd->pan_y, ox, oy, ow, oh); - } + evas_object_smart_changed(wd->pan_smart); #else (void) marker; #endif @@ -4013,49 +3467,18 @@ EAPI void elm_map_markers_list_show(Eina_List *markers) { #ifdef HAVE_ELEMENTARY_ECORE_CON - int zoom; - double lon, lat; - Eina_List *l; - Elm_Map_Marker *marker, *m_max_lon = NULL, *m_max_lat = NULL, *m_min_lon = NULL, *m_min_lat = NULL; - Evas_Coord rw, rh, xc, yc; - Widget_Data *wd; - EINA_SAFETY_ON_NULL_RETURN(markers); - EINA_LIST_FOREACH(markers, l, marker) - { - wd = marker->wd; - - if ((!m_min_lon) || (marker->longitude < m_min_lon->longitude)) - m_min_lon = marker; - - if ((!m_max_lon) || (marker->longitude > m_max_lon->longitude)) - m_max_lon = marker; + EINA_SAFETY_ON_TRUE_RETURN(!eina_list_count(markers)); - if ((!m_min_lat) || (marker->latitude > m_min_lat->latitude)) - m_min_lat = marker; - - if ((!m_max_lat) || (marker->latitude < m_max_lat->latitude)) - m_max_lat = marker; - } - - lon = (m_max_lon->longitude - m_min_lon->longitude) / 2. + m_min_lon->longitude; - lat = (m_max_lat->latitude - m_min_lat->latitude) / 2. + m_min_lat->latitude; - - elm_smart_scroller_child_viewport_size_get(wd->scr, &rw, &rh); - for (zoom = wd->src->zoom_max; zoom > wd->src->zoom_min; zoom--) - { - Evas_Coord size = pow(2.0, zoom)*wd->tsize; - elm_map_utils_convert_geo_into_coord(wd->obj, lon, lat, size, &xc, &yc); - - if ((m_min_lon->x[zoom] - wd->marker_max_w >= xc-rw/2) - && (m_min_lat->y[zoom] - wd->marker_max_h >= yc-rh/2) - && (m_max_lon->x[zoom] + wd->marker_max_w <= xc+rw/2) - && (m_max_lat->y[zoom] + wd->marker_max_h <= yc+rh/2)) - break; - } - - elm_map_geo_region_show(wd->obj, lon, lat); - elm_map_zoom_set(wd->obj, zoom); + Elm_Map_Marker *marker; + marker = eina_list_data_get(markers); + + Delayed_Data *data = ELM_NEW(Delayed_Data); + data->func = _marker_list_show; + data->wd = marker->wd; + data->markers = eina_list_clone(markers); + data->wd->delayed_jobs = eina_list_append(data->wd->delayed_jobs, data); + evas_object_smart_changed(data->wd->pan_smart); #else (void) markers; #endif @@ -4067,8 +3490,8 @@ elm_map_max_marker_per_group_set(Evas_Object *obj, int max) #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype); Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN(wd); - if (!wd) return; wd->markers_max_num = max; #else (void) obj; @@ -4093,15 +3516,10 @@ elm_map_marker_update(Elm_Map_Marker *marker) { #ifdef HAVE_ELEMENTARY_ECORE_CON EINA_SAFETY_ON_NULL_RETURN(marker); - if (marker->content) - { - if (marker->clas->func.del) - marker->clas->func.del(marker->wd->obj, marker, marker->data, marker->content); - else - evas_object_del(marker->content); - marker->content = NULL; - _group_bubble_content_update(marker->groups[marker->wd->zoom]); - } + Widget_Data *wd = marker->wd; + EINA_SAFETY_ON_NULL_RETURN(wd); + + _marker_update(marker); #else (void) marker; #endif @@ -4113,12 +3531,21 @@ elm_map_bubbles_close(Evas_Object *obj) #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype); Widget_Data *wd = elm_widget_data_get(obj); - Marker_Group *group; - Eina_List *l, *l_next; + EINA_SAFETY_ON_NULL_RETURN(wd); - if (!wd) return; - EINA_LIST_FOREACH_SAFE(wd->opened_bubbles, l, l_next, group) - _group_bubble_free(group); + Eina_List *l; + Elm_Map_Marker *marker; + EINA_LIST_FOREACH(wd->markers, l, marker) + { + if (marker->bubble) _bubble_free(marker->bubble); + marker->bubble = NULL; + + if (marker->group) + { + if (marker->group->bubble) _bubble_free(marker->group->bubble); + marker->group->bubble = NULL; + } + } #else (void) obj; #endif @@ -4130,11 +3557,16 @@ elm_map_group_class_new(Evas_Object *obj) #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype) NULL; Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL); + + Elm_Map_Group_Class *clas = ELM_NEW(Elm_Map_Group_Class); + clas->wd = wd; + clas->zoom_displayed = 0; + clas->zoom_grouped = 255; + eina_stringshare_replace(&clas->style, "radio"); + + wd->group_classes = eina_list_append(wd->group_classes, clas); - if (!wd) return NULL; - Elm_Map_Group_Class *clas = calloc(1, sizeof(Elm_Map_Group_Class)); - clas->zoom_grouped = wd->zoom_max; - wd->groups_clas = eina_list_append(wd->groups_clas, clas); return clas; #else (void) obj; @@ -4208,19 +3640,11 @@ elm_map_group_class_hide_set(Evas_Object *obj, Elm_Map_Group_Class *clas, Eina_B #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype); Widget_Data *wd = elm_widget_data_get(obj); - - if (!wd) return; + EINA_SAFETY_ON_NULL_RETURN(wd); EINA_SAFETY_ON_NULL_RETURN(clas); - if (clas->hide == hide) return; + clas->hide = hide; - if (wd->grids) - { - Grid *g; - Evas_Coord ox, oy, ow, oh; - evas_object_geometry_get(obj, &ox, &oy, &ow, &oh); - g = _get_current_grid(wd); - marker_place(obj, g, wd->pan_x, wd->pan_y, ox, oy, ow, oh); - } + evas_object_smart_changed(wd->pan_smart); #else (void) obj; (void) clas; @@ -4234,10 +3658,12 @@ elm_map_marker_class_new(Evas_Object *obj) #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype) NULL; Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL); - if (!wd) return NULL; - Elm_Map_Marker_Class *clas = calloc(1, sizeof(Elm_Map_Marker_Class)); - wd->markers_clas = eina_list_append(wd->markers_clas, clas); + Elm_Map_Marker_Class *clas = ELM_NEW(Elm_Map_Marker_Class); + eina_stringshare_replace(&clas->style, "radio"); + + wd->marker_classes = eina_list_append(wd->marker_classes, clas); return clas; #else (void) obj; @@ -4299,9 +3725,9 @@ elm_map_source_names_get(const Evas_Object *obj) #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype) NULL; Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL); - if (!wd) return NULL; - return wd->source_names; + return wd->src_names; #else (void) obj; return NULL; @@ -4314,19 +3740,20 @@ elm_map_source_name_set(Evas_Object *obj, const char *source_name) #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype); Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN(wd); + Map_Sources_Tab *s; Eina_List *l; int zoom; - if (!wd) return; if (wd->src) { if (!strcmp(wd->src->name, source_name)) return; if (!wd->src->url_cb) return; } - grid_clear_all(obj); - EINA_LIST_FOREACH(wd->map_sources_tab, l, s) + _grid_all_clear(wd); + EINA_LIST_FOREACH(wd->srcs, l, s) { if (!strcmp(s->name, source_name)) { @@ -4343,9 +3770,11 @@ elm_map_source_name_set(Evas_Object *obj, const char *source_name) zoom = wd->src->zoom_max; if (wd->src->zoom_min > zoom) zoom = wd->src->zoom_min; + if (wd->src->zoom_max < wd->zoom_max) wd->zoom_max = wd->src->zoom_max; + if (wd->src->zoom_min > wd->zoom_min) wd->zoom_min = wd->src->zoom_min; } - grid_create_all(obj); - elm_map_zoom_set(obj, zoom); + _grid_all_create(wd); + zoom_do(wd, zoom); #else (void) obj; (void) source_name; @@ -4373,8 +3802,8 @@ elm_map_route_source_set(Evas_Object *obj, Elm_Map_Route_Sources source) #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype); Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN(wd); - if (!wd) return; wd->route_source = source; #else (void) obj; @@ -4388,8 +3817,8 @@ elm_map_route_source_get(const Evas_Object *obj) #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype) ELM_MAP_ROUTE_SOURCE_YOURS; Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN_VAL(wd, ELM_MAP_ROUTE_SOURCE_YOURS); - if (!wd) return ELM_MAP_ROUTE_SOURCE_YOURS; return wd->route_source; #else (void) obj; @@ -4403,10 +3832,11 @@ elm_map_source_zoom_max_set(Evas_Object *obj, int zoom) #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype); Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN(wd); + EINA_SAFETY_ON_NULL_RETURN(wd->src); - if ((!wd) || (!wd->src)) return; - if ((zoom > wd->zoom_max) || (zoom < wd->zoom_min)) return; - wd->src->zoom_max = zoom; + if ((zoom > wd->src->zoom_max) || (zoom < wd->src->zoom_min)) return; + wd->zoom_max = zoom; #else (void) obj; (void) zoom; @@ -4419,9 +3849,10 @@ elm_map_source_zoom_max_get(const Evas_Object *obj) #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype) 18; Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN_VAL(wd, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(wd->src, -1); - if ((!wd) || (!wd->src)) return 18; - return wd->src->zoom_max; + return wd->zoom_max; #else (void) obj; return 18; @@ -4434,10 +3865,11 @@ elm_map_source_zoom_min_set(Evas_Object *obj, int zoom) #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype); Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN(wd); + EINA_SAFETY_ON_NULL_RETURN(wd->src); - if ((!wd) || (!wd->src)) return; - if ((zoom > wd->zoom_max) || (zoom < wd->zoom_min)) return; - wd->src->zoom_min = zoom; + if ((zoom > wd->src->zoom_max) || (zoom < wd->src->zoom_min)) return; + wd->zoom_min = zoom; #else (void) obj; (void) zoom; @@ -4450,9 +3882,10 @@ elm_map_source_zoom_min_get(const Evas_Object *obj) #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype) 0; Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN_VAL(wd, -1); + EINA_SAFETY_ON_NULL_RETURN_VAL(wd->src, -1); - if ((!wd) || (!wd->src)) return 0; - return wd->src->zoom_min; + return wd->zoom_min; #else (void) obj; return 0; @@ -4465,10 +3898,10 @@ elm_map_user_agent_set(Evas_Object *obj, const char *user_agent) #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype); Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN(wd); + EINA_SAFETY_ON_NULL_RETURN(user_agent); - if (!wd) return; - if (!wd->user_agent) wd->user_agent = eina_stringshare_add(user_agent); - else eina_stringshare_replace(&wd->user_agent, user_agent); + eina_stringshare_replace(&wd->user_agent, user_agent); if (!wd->ua) wd->ua = eina_hash_string_small_new(NULL); eina_hash_set(wd->ua, "User-Agent", wd->user_agent); @@ -4484,8 +3917,8 @@ elm_map_user_agent_get(const Evas_Object *obj) #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype) NULL; Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL); - if (!wd) return NULL; return wd->user_agent; #else (void) obj; @@ -4494,13 +3927,7 @@ elm_map_user_agent_get(const Evas_Object *obj) } EAPI Elm_Map_Route * -elm_map_route_add(Evas_Object *obj, - Elm_Map_Route_Type type, - Elm_Map_Route_Method method, - double flon, - double flat, - double tlon, - double tlat) +elm_map_route_add(Evas_Object *obj, Elm_Map_Route_Type type, Elm_Map_Route_Method method, double flon, double flat, double tlon, double tlat) { #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype) NULL; @@ -4510,10 +3937,10 @@ elm_map_route_add(Evas_Object *obj, char *type_name = NULL; int fd; - if ((!wd) || (!wd->src)) return NULL; + EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(wd->src, NULL); Elm_Map_Route *route = ELM_NEW(Elm_Map_Route); - if (!route) return NULL; snprintf(buf, sizeof(buf), DEST_ROUTE_XML_FILE); fd = mkstemp(buf); @@ -4769,12 +4196,13 @@ elm_map_rotate_set(Evas_Object *obj, double degree, Evas_Coord cx, Evas_Coord cy #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype); Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN(wd); - if (!wd) return; wd->rotate.d = degree; wd->rotate.cx = cx; wd->rotate.cy = cy; - wd->calc_job = ecore_job_add(_calc_job, wd); + + evas_object_smart_changed(wd->pan_smart); #else (void) obj; (void) degree; @@ -4789,8 +4217,8 @@ elm_map_rotate_get(const Evas_Object *obj, double *degree, Evas_Coord *cx, Evas_ #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype); Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN(wd); - if (!wd) return; if (degree) *degree = wd->rotate.d; if (cx) *cx = wd->rotate.cx; if (cy) *cy = wd->rotate.cy; @@ -4808,12 +4236,12 @@ elm_map_wheel_disabled_set(Evas_Object *obj, Eina_Bool disabled) #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype); Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN(wd); - if (!wd) return; if ((!wd->wheel_disabled) && (disabled)) - evas_object_event_callback_del_full(wd->rect, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel_cb, obj); + evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel_cb, obj); else if ((wd->wheel_disabled) && (!disabled)) - evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel_cb, obj); + evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel_cb, obj); wd->wheel_disabled = !!disabled; #else (void) obj; @@ -4827,8 +4255,8 @@ elm_map_wheel_disabled_get(const Evas_Object *obj) #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; Widget_Data *wd = elm_widget_data_get(obj); + EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EINA_FALSE); - if (!wd) return EINA_FALSE; return wd->wheel_disabled; #else (void) obj; @@ -4843,8 +4271,7 @@ elm_map_track_add(Evas_Object *obj, EMap_Route *emap) #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype) NULL; Widget_Data *wd = elm_widget_data_get(obj); - - if (!wd) return EINA_FALSE; + EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EINA_FALSE); Evas_Object *route = elm_route_add(obj); elm_route_emap_set(route, emap); @@ -4865,8 +4292,7 @@ elm_map_track_remove(Evas_Object *obj, Evas_Object *route) #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype) ; Widget_Data *wd = elm_widget_data_get(obj); - - if (!wd) return ; + EINA_SAFETY_ON_NULL_RETURN(wd); wd->track = eina_list_remove(wd->track, route); evas_object_del(route); @@ -4875,118 +4301,3 @@ elm_map_track_remove(Evas_Object *obj, Evas_Object *route) (void) route; #endif } - -#ifdef HAVE_ELEMENTARY_ECORE_CON - -static char * -_mapnik_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom) -{ - char buf[PATH_MAX]; - // ((x+y+zoom)%3)+'a' is requesting map images from distributed tile servers (eg., a, b, c) - snprintf(buf, sizeof(buf), "http://%c.tile.openstreetmap.org/%d/%d/%d.png", ((x+y+zoom)%3)+'a', zoom, x, y); - return strdup(buf); -} - -static char * -_osmarender_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom) -{ - char buf[PATH_MAX]; - snprintf(buf, sizeof(buf), "http://%c.tah.openstreetmap.org/Tiles/tile/%d/%d/%d.png", ((x+y+zoom)%3)+'a', zoom, x, y); - return strdup(buf); -} - -static char * -_cyclemap_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom) -{ - char buf[PATH_MAX]; - snprintf(buf, sizeof(buf), "http://%c.tile.opencyclemap.org/cycle/%d/%d/%d.png", ((x+y+zoom)%3)+'a', zoom, x, y); - return strdup(buf); -} - -static char * -_mapquest_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom) -{ - char buf[PATH_MAX]; - snprintf(buf, sizeof(buf), "http://otile%d.mqcdn.com/tiles/1.0.0/osm/%d/%d/%d.png", ((x+y+zoom)%4)+1, zoom, x, y); - return strdup(buf); -} - -static char * -_mapquest_aerial_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom) -{ - char buf[PATH_MAX]; - snprintf(buf, sizeof(buf), "http://oatile%d.mqcdn.com/naip/%d/%d/%d.png", ((x+y+zoom)%4)+1, zoom, x, y); - return strdup(buf); -} - -static char *_yours_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat) -{ - char buf[PATH_MAX]; - snprintf(buf, sizeof(buf), - "%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); -} - -// TODO: fix monav api -/* -static char *_monav_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat) -{ - char buf[PATH_MAX]; - snprintf(buf, sizeof(buf), - "%s?flat=%f&flon=%f&tlat=%f&tlon=%f&v=%s&fast=%d&instructions=1", - ROUTE_MONAV_URL, flat, flon, tlat, tlon, type_name, method); - - return strdup(buf); -} -*/ - -// TODO: fix ors api -/* -static char *_ors_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat) -{ - char buf[PATH_MAX]; - snprintf(buf, sizeof(buf), - "%s?flat=%f&flon=%f&tlat=%f&tlon=%f&v=%s&fast=%d&instructions=1", - ROUTE_ORS_URL, flat, flon, tlat, tlon, type_name, method); - - return strdup(buf); -} -*/ - -static char * -_nominatim_url_cb(Evas_Object *obj, int method, char *name, double lon, double lat) -{ - ELM_CHECK_WIDTYPE(obj, widtype) strdup(""); - Widget_Data *wd = elm_widget_data_get(obj); - char **str; - unsigned int ele, idx; - char search_url[PATH_MAX]; - char buf[PATH_MAX]; - - if (!wd) return strdup(""); - 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); - - if (str && str[0]) - { - free(str[0]); - free(str); - } - } - 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); -} - -#endif -- 2.7.4