From: raster Date: Tue, 21 Feb 2012 07:59:19 +0000 (+0000) Subject: aah we'll take bluz' patch then instead of my fixing X-Git-Tag: REL_F_I9500_20120323_1~17^2~615 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0b0f6f79093ee82c98bb4fd164842190a7bba69d;p=framework%2Fuifw%2Felementary.git aah we'll take bluz' patch then instead of my fixing git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/elementary@68206 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- diff --git a/src/bin/test_map.c b/src/bin/test_map.c index 8600469..7f2da19 100644 --- a/src/bin/test_map.c +++ b/src/bin/test_map.c @@ -20,9 +20,10 @@ 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, *route_group; +static Elm_Map_Group_Class *itc_group1, *itc_group2, *itc_group_parking; -static Evas_Object *menu, *fs_win; +static Evas_Object *rect, *menu, *fs_win; +static int nb_elts; /*static Elm_Map_Marker *markers[MARKER_MAX];*/ static Elm_Map_Marker *route_from, *route_to; static Elm_Map_Route *route; @@ -87,14 +88,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) { - if (!event_info) return; + printf("longpressed\n"); double lon, lat; Evas_Event_Mouse_Down *down = (Evas_Event_Mouse_Down *)event_info; - elm_map_canvas_to_geo_convert(obj, 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 (!down) return; if (elm_map_zoom_get(obj) < 5) return; - if (name) elm_map_name_remove(name); + + 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); name = elm_map_utils_convert_coord_into_name(obj, lon, lat); } @@ -110,18 +111,15 @@ 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); - if (!itc1) itc1 = elm_map_marker_class_new(obj); + itc1 = elm_map_marker_class_new(obj); elm_map_marker_class_del_cb_set(itc1, NULL); - 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); - } + 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_from && route_to) { @@ -132,8 +130,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, route_group, NULL); - else route_to = elm_map_marker_add(obj, lon, lat, itc1, route_group, NULL); + 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_to) { @@ -203,9 +201,10 @@ 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 @@ -583,6 +582,16 @@ _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; @@ -720,6 +729,7 @@ 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); @@ -734,7 +744,9 @@ 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"); @@ -747,7 +759,18 @@ 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, @@ -770,6 +793,8 @@ 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 0a8a8c0..7557f20 100644 --- a/src/examples/map_example_02.c +++ b/src/examples/map_example_02.c @@ -94,6 +94,13 @@ _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; @@ -234,6 +241,7 @@ 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 f9015a4..d9adef9 100644 --- a/src/lib/elm_map.c +++ b/src/lib/elm_map.c @@ -13,100 +13,86 @@ typedef struct _Pan Pan; typedef struct _Grid Grid; typedef struct _Grid_Item Grid_Item; typedef struct _Marker_Group Marker_Group; -typedef struct _Marker_Bubble Marker_Bubble; +typedef struct _Event Event; 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" + +#define CACHE_ROOT_PATH "/tmp/elm_map" +#define CACHE_PATH CACHE_ROOT_PATH"/%d/%d/%d" +#define CACHE_FILE_PATH "%s/%d.png" #define DEST_ROUTE_XML_FILE "/tmp/elm_map-route-XXXXXX" -#define DEST_NAME_XML_FILE "/tmp/elm_map-name-XXXXXX" +#define DEST_NAME_XML_FILE "/tmp/elm_map-name-XXXXXX" -#define ROUTE_YOURS_URL "http://www.yournavigation.org/api/dev/route.php" +#define ROUTE_YOURS_URL "http://www.yournavigation.org/api/dev/route.php" #define ROUTE_TYPE_MOTORCAR "motocar" -#define ROUTE_TYPE_BICYCLE "bicycle" -#define ROUTE_TYPE_FOOT "foot" -#define YOURS_DISTANCE "distance" -#define YOURS_DESCRIPTION "description" -#define YOURS_COORDINATES "coordinates" - -#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 ROUTE_TYPE_BICYCLE "bicycle" +#define ROUTE_TYPE_FOOT "foot" +#define YOURS_DISTANCE "distance" +#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 -struct _Map_Sources_Tab +typedef struct _Map_Sources_Tab { const char *name; int zoom_min; int zoom_max; - Elm_Map_Module_Url_Func url_cb; + ElmMapModuleUrlFunc url_cb; Elm_Map_Route_Sources route_source; - Elm_Map_Module_Route_Url_Func route_url_cb; - Elm_Map_Module_Name_Url_Func name_url_cb; - Elm_Map_Module_Geo_Into_Coord_Func geo_into_coord; - Elm_Map_Module_Coord_Into_Geo_Func coord_into_geo; + ElmMapModuleRouteUrlFunc route_url_cb; + 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 @@ -120,68 +106,78 @@ struct _Url_Data struct _Elm_Map_Marker_Class { const char *style; + int zoom_displayed; + struct _Elm_Map_Marker_Class_Func { - Elm_Map_Marker_Get_Func get; - Elm_Map_Marker_Del_Func del; //if NULL the object will be destroyed with evas_object_del() - Elm_Map_Marker_Icon_Get_Func icon_get; + ElmMapMarkerGetFunc get; + ElmMapMarkerDelFunc del; //if NULL the object will be destroyed with evas_object_del() + ElmMapMarkerIconGetFunc icon_get; } func; -}; - -struct _Elm_Map_Group_Class -{ - Widget_Data *wd; - 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; struct - { - Elm_Map_Group_Icon_Get_Func icon_get; - } func; - - Eina_Bool hide : 1; -}; - -struct _Marker_Bubble -{ - Widget_Data *wd; - Evas_Object *pobj; - Evas_Object *obj, *sc, *bx; + { //this part is private, do not modify these values + Eina_Bool set : 1; + Evas_Coord edje_w, edje_h; + } priv; }; struct _Elm_Map_Marker { Widget_Data *wd; Elm_Map_Marker_Class *clas; - Elm_Map_Group_Class *group_clas; + Elm_Map_Group_Class *clas_group; 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_Coord map_size; + Evas_Coord *x, *y; + void *data; + Marker_Group **groups; Evas_Object *content; +}; + +struct _Elm_Map_Group_Class +{ + 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; }; struct _Marker_Group { Widget_Data *wd; + Eina_Matrixsparse_Cell *cell; Elm_Map_Group_Class *clas; - Evas_Coord w, h; - Evas_Object *obj; - Evas_Coord x, y; Eina_List *markers; + long long sum_x, sum_y; + Evas_Coord x, y; + Evas_Coord w, h; - Marker_Bubble *bubble; + 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; }; struct _Elm_Map_Route @@ -254,170 +250,236 @@ 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 { - Grid *g; - Widget_Data *wd; + Grid *g; + int zoom; Evas_Object *img; + //Evas_Object *txt; const char *file; const char *source; - int x, y; // Tile coordinate - Eina_Bool file_have : 1; + struct + { + int x, y, w, h; + } src, out; + 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 tw, th; // size of grid in tiles + 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 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 *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; + 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; int id; - Eina_List *grids; - int zoom; - double zoom_detail; - double prev_lon, prev_lat; - Evas_Coord ox, oy; + int zoom_method; + Elm_Map_Zoom_Mode mode; + + Ecore_Job *calc_job; + Ecore_Timer *scr_timer; + Ecore_Timer *long_timer; + Ecore_Animator *zoom_animator; + double t; struct { - int w, h; // Current pixel width, heigth of a grid - int tile; // Current pixel size of a grid item + int w, h; + int ow, oh, nw, nh; + struct + { + double x, y; + } spos; } size; - Elm_Map_Zoom_Mode mode; struct { - double zoom; - double diff; - int cnt; - } ani; - Ecore_Timer *zoom_timer; - Ecore_Animator *zoom_animator; + 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* + 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; - - Evas_Coord pan_x, pan_y; - Eina_List *delayed_jobs; - - Ecore_Timer *scr_timer; - Ecore_Timer *long_timer; + Eina_List *route; + Eina_List *track; Evas_Event_Mouse_Down ev; - Eina_Bool on_hold : 1; - Eina_Bool paused : 1; + Eina_List *names; + int multi_count; + + struct + { + Evas_Coord cx, cy; + double level, diff; + } pinch; - 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; - unsigned int markers_max_num; - Eina_Bool paused_markers : 1; - Eina_List *group_classes; - Eina_List *marker_classes; - Eina_List *markers; + 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; +}; - Elm_Map_Route_Sources route_source; - Eina_List *route; - Eina_List *track; - Eina_List *names; +struct _Pan +{ + Evas_Object_Smart_Clipped_Data __clipped_data; + Widget_Data *wd; }; -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 _Event +{ + int device; -static Map_Sources_Tab default_map_sources_tab[] = + 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; +}; + +struct _Route_Dump { - {"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}, + int id; + char *fname; + double distance; + char *description; + char *coordinates; }; -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; +enum _Route_Xml_Attribute +{ + ROUTE_XML_NONE, + ROUTE_XML_DISTANCE, + ROUTE_XML_DESCRIPTION, + ROUTE_XML_COORDINATES, + ROUTE_XML_LAST +} Route_Xml_Attibute; -static const char SIG_CHANGED[] = "changed"; -static const char SIG_CLICKED[] = "clicked"; -static const char SIG_CLICKED_DOUBLE[] = "clicked,double"; -static const char SIG_LOADED_DETAIL[] = "loaded,detail"; -static const char SIG_LOAD_DETAIL[] = "load,detail"; -static const char SIG_LONGPRESSED[] = "longpressed"; -static const char SIG_PRESS[] = "press"; -static const char SIG_SCROLL[] = "scroll"; -static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start"; -static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop"; -static const char SIG_ZOOM_CHANGE[] = "zoom,change"; -static const char SIG_ZOOM_START[] = "zoom,start"; -static const char SIG_ZOOM_STOP[] = "zoom,stop"; -static const char SIG_DOWNLOADED[] = "downloaded"; -static const char SIG_ROUTE_LOAD[] = "route,load"; -static const char SIG_ROUTE_LOADED[] = "route,loaded"; -static const char SIG_NAME_LOAD[] = "name,load"; +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 SIG_CHANGED[] = "changed"; +static const char SIG_CLICKED[] = "clicked"; +static const char SIG_CLICKED_DOUBLE[] = "clicked,double"; +static const char SIG_LOADED_DETAIL[] = "loaded,detail"; +static const char SIG_LOAD_DETAIL[] = "load,detail"; +static const char SIG_LONGPRESSED[] = "longpressed"; +static const char SIG_PRESS[] = "press"; +static const char SIG_SCROLL[] = "scroll"; +static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start"; +static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop"; +static const char SIG_ZOOM_CHANGE[] = "zoom,change"; +static const char SIG_ZOOM_START[] = "zoom,start"; +static const char SIG_ZOOM_STOP[] = "zoom,stop"; +static const char SIG_DOWNLOADED[] = "downloaded"; +static const char SIG_ROUTE_LOAD[] = "route,load"; +static const char SIG_ROUTE_LOADED[] = "route,loaded"; +static const char SIG_NAME_LOAD[] = "name,load"; static const char SIG_NAME_LOADED[] = "name,loaded"; static const Evas_Smart_Cb_Description _signals[] = { {SIG_CHANGED, ""}, @@ -441,24 +503,60 @@ 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) { - EINA_SAFETY_ON_NULL_RETURN_VAL(data,EINA_FALSE); - Widget_Data *wd = data; - + ELM_CHECK_WIDTYPE(data, widtype) EINA_FALSE; + Widget_Data *wd = elm_widget_data_get(data); Map_Sources_Tab *s; - Elm_Map_Module_Source_Func source; - Elm_Map_Module_Zoom_Min_Func zoom_min; - Elm_Map_Module_Zoom_Max_Func zoom_max; - Elm_Map_Module_Url_Func url; - Elm_Map_Module_Route_Source_Func route_source; - Elm_Map_Module_Route_Url_Func route_url; - Elm_Map_Module_Name_Url_Func name_url; - Elm_Map_Module_Geo_Into_Coord_Func geo_into_coord; - Elm_Map_Module_Coord_Into_Geo_Func coord_into_geo; + ElmMapModuleSourceFunc source; + ElmMapModuleZoomMinFunc zoom_min; + ElmMapModuleZoomMaxFunc zoom_max; + ElmMapModuleUrlFunc url; + ElmMapModuleRouteSourceFunc route_source; + ElmMapModuleRouteUrlFunc route_url; + ElmMapModuleNameUrlFunc name_url; + ElmMapModuleGeoIntoCoordFunc geo_into_coord; + ElmMapModuleCoordIntoGeoFunc coord_into_geo; const char *file; + if (!wd) return EINA_FALSE; + file = eina_module_file_get(m); if (!eina_module_load(m)) { @@ -475,15 +573,14 @@ 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 = ELM_NEW(Map_Sources_Tab); + s = calloc(1, sizeof(Map_Sources_Tab)); + EINA_SAFETY_ON_NULL_RETURN_VAL(s, EINA_FALSE); s->name = source(); s->zoom_min = zoom_min(); s->zoom_max = zoom_max(); @@ -493,25 +590,35 @@ 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->srcs = eina_list_append(wd->srcs, s); + wd->map_sources_tab = eina_list_append(wd->map_sources_tab, s); - eina_module_unload(m); return EINA_TRUE; } static void -source_init(Widget_Data *wd) +module_init(void *data) { - EINA_SAFETY_ON_NULL_RETURN(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); +} +static void +source_init(void *data) +{ + ELM_CHECK_WIDTYPE(data, widtype); + Widget_Data *wd = elm_widget_data_get(data); Map_Sources_Tab *s; - unsigned int idx; - Eina_Array *modules = NULL; Eina_List *l; + unsigned int idx; + if (!wd) return; for (idx = 0; idx < sizeof(default_map_sources_tab)/sizeof(Map_Sources_Tab); idx++) { - s = ELM_NEW(Map_Sources_Tab); + s = calloc(1, sizeof(Map_Sources_Tab)); + EINA_SAFETY_ON_NULL_RETURN(s); 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; @@ -521,604 +628,427 @@ source_init(Widget_Data *wd) 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->srcs = eina_list_append(wd->srcs, s); - if (!idx) - { - wd->src = s; - wd->zoom_min = s->zoom_min; - wd->zoom_max = s->zoom_max; - } + wd->map_sources_tab = eina_list_append(wd->map_sources_tab, s); + if (!idx) wd->src = s; } - modules = eina_module_list_get(modules, MODULES_PATH, 1, &module_list_cb, wd); - eina_array_free(modules); + module_init(data); - wd->src_names = calloc(eina_list_count(wd->srcs) +1, sizeof(char *)); + 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; + } idx = 0; - EINA_LIST_FOREACH(wd->srcs, l, s) + EINA_LIST_FOREACH(wd->map_sources_tab, l, s) { - eina_stringshare_replace(&wd->src_names[idx], s->name); - INF("source : %s", wd->src_names[idx]); + 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; idx++; } + wd->source_names[idx] = NULL; } static void -_edj_marker_size_get(Widget_Data *wd, Evas_Coord *w, Evas_Coord *h) -{ - EINA_SAFETY_ON_NULL_RETURN(wd); - EINA_SAFETY_ON_NULL_RETURN(w); - EINA_SAFETY_ON_NULL_RETURN(h); - - 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 -_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) -{ - EINA_SAFETY_ON_NULL_RETURN(xx); - EINA_SAFETY_ON_NULL_RETURN(yy); - - double r = (degree * M_PI) / 180.0; - double tx, ty, ttx, tty; - - tx = x - cx; - ty = y - cy; - - ttx = tx * cos(r); - tty = tx * sin(r); - tx = ttx + (ty * cos(r + M_PI_2)); - ty = tty + (ty * sin(r + M_PI_2)); - - *xx = tx + cx; - *yy = ty + cy; -} - -static void -_viewport_size_get(Widget_Data *wd, Evas_Coord *vw, Evas_Coord *vh) -{ - EINA_SAFETY_ON_NULL_RETURN(wd); - - 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 -_pan_geometry_get(Widget_Data *wd, Evas_Coord *px, Evas_Coord *py) -{ - EINA_SAFETY_ON_NULL_RETURN(wd); - - 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; - } - -static void -_obj_rotate(Widget_Data *wd, Evas_Object *obj) +obj_rotate_zoom(void *data, Evas_Object *obj) { - Evas_Coord w, h, ow, oh; - evas_map_util_points_populate_from_object(wd->map, obj); + 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; + } + 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); - evas_object_image_size_get(obj, &w, &h); - if ((w > ow) || (h > oh)) + if ((ow < iw) || (oh < ih)) { - 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); + 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_set(obj, wd->map); evas_object_map_enable_set(obj, EINA_TRUE); + evas_object_map_set(obj, wd->map); } static void -_obj_place(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h) +#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 { - EINA_SAFETY_ON_NULL_RETURN(obj); +#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; - evas_object_move(obj, x, y); - evas_object_resize(obj, w, h); - evas_object_show(obj); -} + if (!wd) return; + Evas_Coord size = pow(2.0, wd->zoom)*wd->tsize; -static void -_bubble_update(Marker_Bubble *bubble, Eina_List *contents) -{ - EINA_SAFETY_ON_NULL_RETURN(bubble); - EINA_SAFETY_ON_NULL_RETURN(contents); + 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); - Eina_List *l; - Evas_Object *c; + 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); - elm_box_clear(bubble->bx); - EINA_LIST_FOREACH(contents, l, c) elm_box_pack_end(bubble->bx, c); -} + evas_object_raise(route); + obj_rotate_zoom(obj, route); + evas_object_show(route); + continue; + } + } + //the route is not display + evas_object_hide(route); + } +#endif +} static void -_bubble_place(Marker_Bubble *bubble) +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) { - EINA_SAFETY_ON_NULL_RETURN(bubble); - - Evas_Coord x, y, w, h; - Evas_Coord xx, yy, ww, hh; - const char *s; - - if ((!bubble->obj) || (!bubble->pobj)) return; - evas_object_geometry_get(bubble->pobj, &x, &y, &w, NULL); - - s = edje_object_data_get(bubble->obj, "size_w"); - if (s) ww = atoi(s); - else ww = 0; + 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; - 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 (!wd) return; + Evas_Coord size = pow(2.0, wd->zoom)*wd->tsize; - xx = x + w/2 - ww/2; - yy = y - hh; + EINA_LIST_FOREACH(wd->route, lr, r) + { + EINA_LIST_FOREACH(r->path, lp, p) + { + evas_object_polygon_points_clear(p); + } - _obj_place(bubble->obj, xx, yy, ww, hh); - evas_object_raise(bubble->obj); -} + evas_object_geometry_get(wd->rect, &rx, &ry, NULL, NULL); + nodes = eina_list_count(r->nodes); -static void -_bubble_sc_hints_changed_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(data); -} + 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; -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); -} + 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); + } -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); + 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; + } } static void -_bubble_show_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +rect_place(Evas_Object *obj, Evas_Coord px, Evas_Coord py, Evas_Coord ox, Evas_Coord oy, Evas_Coord ow, Evas_Coord oh) { - Marker_Bubble *bubble = data; - EINA_SAFETY_ON_NULL_RETURN(bubble); - _bubble_place(bubble); -} + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); + Evas_Coord ax, ay, gw, gh, hh, ww; -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); -} + if (!wd) return; + evas_object_geometry_get(wd->rect, NULL, NULL, &ww, &hh); -static void -_bubble_free(Marker_Bubble* bubble) -{ - EINA_SAFETY_ON_NULL_RETURN(bubble); + ax = 0; + ay = 0; + gw = wd->size.w; + gh = wd->size.h; - evas_object_del(bubble->bx); - evas_object_del(bubble->sc); - evas_object_del(bubble->obj); - free(bubble); -} + if ((ww == gw) && (hh == gh)) return; -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); + 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); - 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; + if (wd->show.show) + { + 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); + } } static void -_marker_group_update(Marker_Group* group, Elm_Map_Group_Class *clas, Eina_List *markers) +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) { - 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); - + 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]; - Eina_List *l; - Elm_Map_Marker *marker; - int cnt = 0; - int sum_x = 0, sum_y = 0; + int y, x; + int g_xx, g_yy, g_hh, g_ww; - EINA_LIST_FOREACH(markers, l, marker) - { - sum_x += marker->x; - sum_y += marker->y; - cnt++; - } - - 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; + if (!wd) return; - 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)); + 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; - - if (clas->func.icon_get) + if (wd->zoom != wd->marker_zoom) { - 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); - } - 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 -_marker_group_bubble_open_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *soure __UNUSED__) -{ - EINA_SAFETY_ON_NULL_RETURN(data); - Marker_Group *group = data; - Eina_List *l; - Elm_Map_Marker *marker; - Eina_List *contents = NULL; - - if (!group->bubble) group->bubble = _bubble_create(group->obj, group->wd); - - EINA_LIST_FOREACH(group->markers, l, marker) + 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) { - 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); + 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); + } + } } - _bubble_update(group->bubble, contents); - _bubble_place(group->bubble); -} - -static void -_marker_group_bringin_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *soure __UNUSED__) -{ - EINA_SAFETY_ON_NULL_RETURN(data); - - 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 -_marker_group_free(Marker_Group* group) -{ - EINA_SAFETY_ON_NULL_RETURN(group); - - if (group->bubble) _bubble_free(group->bubble); - - eina_list_free(group->markers); - evas_object_del(group->obj); - - free(group); -} -static Marker_Group* -_marker_group_create(Widget_Data *wd) -{ - EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL); - - Marker_Group *group = ELM_NEW(Marker_Group); - - 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; -} - -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); -} - -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); -} + if (!wd->marker_zoom) + { + g_ww = 0; + g_hh = 0; + } -static void -_marker_update(Elm_Map_Marker *marker) -{ - EINA_SAFETY_ON_NULL_RETURN(marker); - Elm_Map_Marker_Class *clas = marker->clas; - EINA_SAFETY_ON_NULL_RETURN(clas); + 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; - 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)); + xx = group->x; + yy = group->y; + ww = group->w; + hh = group->h; - if (clas->func.icon_get) - { - Evas_Object *icon = NULL; + 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; + } - icon = elm_object_part_content_get(marker->obj, "elm.icon"); - if (icon) evas_object_del(icon); + if (ww <= 0) ww = 1; + if (hh <= 0) hh = 1; - icon = clas->func.icon_get(marker->wd->obj, marker, marker->data); - elm_object_part_content_set(marker->obj, "elm.icon", icon); - } + 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; + } - elm_map_utils_convert_geo_into_coord(marker->wd->obj, marker->longitude, - marker->latitude, marker->wd->size.w, - &(marker->x), &(marker->y)); + 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); - 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) - { - Eina_List *contents = NULL; - contents = eina_list_append(contents, marker->content); - _bubble_update(marker->bubble, contents); + 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); + } + } } - } + } } - - static void -_marker_place(Widget_Data *wd) +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) { - EINA_SAFETY_ON_NULL_RETURN(wd); - - Eina_List *l; - - Elm_Map_Marker *marker; - Elm_Map_Group_Class *group_clas; - - Evas_Coord gw, gh; - Evas_Coord px, py; - - if (wd->paused_markers || eina_list_count(wd->markers) == 0) return; + 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; - _pan_geometry_get(wd, &px, &py); + 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; - _edj_marker_size_get(wd, &gw, &gh); - gw *= 2; - gh *= 2; + Eina_Iterator *it = eina_matrixsparse_iterator_new(g->grid); + Eina_Matrixsparse_Cell *cell; - EINA_LIST_FOREACH(wd->markers, l, marker) + EINA_ITERATOR_FOREACH(it, cell) { - _marker_update(marker); - marker->grouped = EINA_FALSE; - marker->leader = EINA_FALSE; - } + Grid_Item *gi = eina_matrixsparse_cell_data_get(cell); - EINA_LIST_FOREACH(wd->group_classes, l, group_clas) - { - Eina_List *ll; - EINA_LIST_FOREACH(group_clas->markers, ll, marker) + xx = gi->out.x; + yy = gi->out.y; + ww = gi->out.w; + hh = gi->out.h; + if ((gw != g->w) && (g->w > 0)) { - Eina_List *lll; - Elm_Map_Marker *mm; - Eina_List *markers = NULL; - - if (marker->grouped) continue; - if (group_clas->zoom_grouped < wd->zoom) - { - marker->grouped = EINA_FALSE; - continue; - } - - EINA_LIST_FOREACH(group_clas->markers, lll, mm) - { - 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); - } + tx = xx; + xx = ((long long )gw * xx) / g->w; + ww = (((long long)gw * (tx + ww)) / g->w) - xx; } - } - - EINA_LIST_FOREACH(wd->markers, l, marker) - { - - if (marker->grouped || - (marker->group_clas && - (marker->group_clas->hide || - marker->group_clas->zoom_displayed > wd->zoom))) - evas_object_hide(marker->obj); - else + if ((gh != g->h) && (g->h > 0)) { - 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); + 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); - EINA_LIST_FOREACH(wd->markers, l, marker) - { - 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 - { - 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); - } - } -} + evas_object_resize(gi->img, ww, hh); + obj_rotate_zoom(obj, gi->img); + /*evas_object_move(gi->txt, + xx - px + ax + ox, + yy - py + ay + oy); -static void -_grid_item_coord_get(Grid_Item *gi, int *x, int *y, int *w, int *h) -{ - EINA_SAFETY_ON_NULL_RETURN(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; -} - -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); + evas_object_resize(gi->txt, ww, hh); + */ + } + eina_iterator_free(it); } static void -_grid_item_update(Grid_Item *gi) +_tile_update(Grid_Item *gi) { 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); - Evas_Load_Error err = evas_object_image_load_error_get(gi->img); if (err != EVAS_LOAD_ERROR_NONE) { @@ -1128,117 +1058,25 @@ _grid_item_update(Grid_Item *gi) } else { - Evas_Coord px, py; - Evas_Coord x, y, w, h; - - _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); + 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); } } static void -_grid_item_load(Grid_Item *gi) +_tile_downloaded(void *data, const char *file __UNUSED__, int status) { - 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 -_grid_item_unload(Grid_Item *gi) -{ - 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; + Grid_Item *gi = data; - 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); - - 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)==0)) - { - eina_stringshare_replace(&gi->source, NULL); - ERR("Getting source url failed: %s", gi->file); - } - 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 -_grid_item_free(Grid_Item *gi) -{ - EINA_SAFETY_ON_NULL_RETURN(gi); - - _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); -} - -static void -_downloaded_cb(void *data, const char *file __UNUSED__, int status) -{ - Grid_Item *gi = data; - if (status == 200) { DBG("Download success from %s to %s", gi->source, gi->file); - _grid_item_update(gi); + _tile_update(gi); gi->wd->finish_num++; } else @@ -1248,589 +1086,852 @@ _downloaded_cb(void *data, const char *file __UNUSED__, int status) gi->file_have = EINA_FALSE; } - gi->job = NULL; gi->wd->download_num--; evas_object_smart_callback_call(gi->wd->obj, SIG_DOWNLOADED, NULL); - if (!gi->wd->download_num) { - edje_object_signal_emit(elm_smart_scroller_edje_object_get(gi->wd->scr), - "elm,state,busy,stop", "elm"); + 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); } + _process_download_list(gi->wd->obj); } -static Eina_Bool -_download_job(void *data) +static void +_process_download_list(Evas_Object *obj) { - EINA_SAFETY_ON_NULL_RETURN_VAL(data, ECORE_CALLBACK_CANCEL); - Widget_Data *wd = data; - + 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; - if (eina_list_count(wd->download_list) == 0) - { - wd->download_idler = NULL; - return ECORE_CALLBACK_CANCEL; - } + 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); + + gw = wd->size.w; + gh = wd->size.h; EINA_LIST_REVERSE_FOREACH_SAFE(wd->download_list, l, ll, gi) { - if (gi->g->zoom != wd->zoom || !_grid_item_intersect(gi)) + 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 (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); + + 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 { - wd->download_list = eina_list_remove(wd->download_list, gi); - + gi->wd->download_num++; wd->try_num++; - wd->download_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"); + edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), "elm,state,busy,start", "elm"); } } - return ECORE_CALLBACK_RENEW; } static void -_grid_viewport_get(Grid *g, int *x, int *y, int *w, int *h) +_add_download_list(Evas_Object *obj, Grid_Item *gi) { - EINA_SAFETY_ON_NULL_RETURN(g); - int xx, yy, ww, hh; - Evas_Coord px, py, vw, vh; + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); - _pan_geometry_get(g->wd, &px, &py); - _viewport_size_get(g->wd, &vw, &vh); - if (px > 0) px = 0; - if (py > 0) py = 0; + wd->download_list = eina_list_remove(wd->download_list, gi); + wd->download_list = eina_list_append(wd->download_list, gi); + _process_download_list(obj); +} - xx = -px / g->wd->size.tile - 1; - if (xx < 0) xx = 0; +static void +grid_create_all(Evas_Object *obj) +{ + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); + Grid *g; + int zoom = 0; - yy = -py / g->wd->size.tile - 1; - if (yy < 0) yy = 0; + EINA_SAFETY_ON_NULL_RETURN(wd); + EINA_SAFETY_ON_NULL_RETURN(wd->src); - ww = vw / g->wd->size.tile + 3; - if (xx + ww >= g->tw) ww = g->tw - xx; + 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; + + g->grid = eina_matrixsparse_new(g->gh, g->gw, NULL, NULL); + wd->grids = eina_list_append(wd->grids, g); + } +} + +static void +grid_clear_all(Evas_Object *obj) +{ + 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_LIST_FREE(wd->grids, g) + { + 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); + evas_object_del(gi->img); + //evas_object_del(gi->txt); + + 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); + } - hh = vh / g->wd->size.tile + 3; - if (yy + hh >= g->th) hh = g->th - yy; + EINA_LIST_FREE(wd->download_list, gi); + if (!ecore_file_recursive_rm("/tmp/elm_map/")) WRN("Deletion of /tmp/elm_map/ failed"); - if (x) *x = xx; - if (y) *y = yy; - if (w) *w = ww; - if (h) *h = hh; } static void -_grid_unload(Grid *g) +grid_unload(Evas_Object *obj, Grid *g) { - EINA_SAFETY_ON_NULL_RETURN(g); + 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(wd); + it = eina_matrixsparse_iterator_new(g->grid); EINA_ITERATOR_FOREACH(it, cell) { gi = eina_matrixsparse_cell_data_get(cell); - _grid_item_unload(gi); + + 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) + { + DBG("DOWNLOAD abort %s", gi->file); + ecore_file_download_abort(gi->job); + ecore_file_remove(gi->file); + gi->job = NULL; + wd->try_num--; + } } eina_iterator_free(it); } + static void -_grid_load(Grid *g) +grid_load(Evas_Object *obj, Grid *g) { - EINA_SAFETY_ON_NULL_RETURN(g); - int x, y, xx, yy, ww, hh; + 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); + + gw = wd->size.w; + gh = wd->size.h; + + if ((gw <= 0) || (gh <= 0)) return; + + 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 + it = eina_matrixsparse_iterator_new(g->grid); + EINA_ITERATOR_FOREACH(it, cell) { gi = eina_matrixsparse_cell_data_get(cell); - if (!_grid_item_intersect(gi)) _grid_item_unload(gi); + + 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; + } + + if (!ELM_RECTS_INTERSECT(xx - wd->pan_x + ox, + yy - wd->pan_y + oy, + ww, hh, + cvx, cvy, cvw, cvh)) + { + 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) + { + DBG("Download abort %s", gi->file); + ecore_file_download_abort(gi->job); + ecore_file_remove(gi->file); + gi->job = NULL; + wd->try_num--; + } + } } eina_iterator_free(it); - _grid_viewport_get(g, &xx, &yy, &ww, &hh); - for (y = yy; y < yy + hh; y++) + 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; + + hh = oh / size + 2; + if (yy + hh >= g->gh) hh = g->gh - yy - 1; + + for (y = yy; y <= yy + hh; y++) { - for (x = xx; x < xx + ww; x++) + 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); + + 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); + + eina_matrixsparse_data_idx_set(g->grid, y, x, gi); + } + + 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 void -_grid_place(Widget_Data *wd) +_smooth_update(Evas_Object *obj) { - EINA_SAFETY_ON_NULL_RETURN(wd); + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); Eina_List *l; Grid *g; + if (!wd) return; EINA_LIST_FOREACH(wd->grids, l, g) { - if (wd->zoom == g->zoom) _grid_load(g); - else _grid_unload(g); + Eina_Iterator *it = eina_matrixsparse_iterator_new(g->grid); + Eina_Matrixsparse_Cell *cell; + + 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); } - if (!wd->download_idler) wd->download_idler = ecore_idler_add(_download_job, wd); +} + +static Eina_Bool +_scr_timeout(void *data) +{ + 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; } static void -_grid_all_create(Widget_Data *wd) +_scr(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) { - EINA_SAFETY_ON_NULL_RETURN(wd); - EINA_SAFETY_ON_NULL_RETURN(wd->src); + ELM_CHECK_WIDTYPE(data, widtype); + Widget_Data *wd = elm_widget_data_get(data); - int zoom; - for (zoom = wd->src->zoom_min; zoom <= wd->src->zoom_max; zoom++) + if (!wd) return; + if (!wd->scr_timer) { - 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); + wd->nosmooth++; + if (wd->nosmooth == 1) _smooth_update(data); } + if (wd->scr_timer) ecore_timer_del(wd->scr_timer); + wd->scr_timer = ecore_timer_add(0.5, _scr_timeout, data); } static void -_grid_all_clear(Widget_Data *wd) +zoom_do(Evas_Object *obj) { - EINA_SAFETY_ON_NULL_RETURN(wd); + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); + Evas_Coord xx, yy, ow, oh; - 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); + if (!wd) return; + wd->size.w = wd->size.nw; + wd->size.h = wd->size.nh; - eina_matrixsparse_free(g->grid); - free(g); + elm_smart_scroller_child_viewport_size_get(wd->scr, &ow, &oh); + + if (wd->center_on.enabled) + { + 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; + } + else + { + xx = (wd->size.spos.x * wd->size.w) - (ow / 2); + yy = (wd->size.spos.y * wd->size.h) - (oh / 2); } - if (!ecore_file_recursive_rm(CACHE_ROOT_PATH)) - ERR("Deletion of %s failed", CACHE_ROOT_PATH); + + + 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; + + wd->show.show = EINA_TRUE; + wd->show.x = xx; + wd->show.y = yy; + wd->show.w = ow; + wd->show.h = oh; + + if (wd->calc_job) ecore_job_del(wd->calc_job); + wd->calc_job = ecore_job_add(_calc_job, wd); } -static void -_track_place(Widget_Data *wd) +static Eina_Bool +_zoom_timeout(void *data) { -#ifdef ELM_EMAP - EINA_SAFETY_ON_NULL_RETURN(wd); + ELM_CHECK_WIDTYPE(data, widtype) ECORE_CALLBACK_CANCEL; + Widget_Data *wd = elm_widget_data_get(data); - 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 (!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; +} - Evas_Coord size = wd->size.w; +static Eina_Bool +_zoom_anim(void *data) +{ + ELM_CHECK_WIDTYPE(data, widtype) ECORE_CALLBACK_CANCEL; + Evas_Object *obj = data; + Widget_Data *wd = elm_widget_data_get(obj); - EINA_LIST_FOREACH(wd->track, l, route) + 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 { - 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); + wd->zoom_animator = NULL; + zoom_do(obj); + evas_object_smart_callback_call(data, SIG_ZOOM_STOP, NULL); + return ECORE_CALLBACK_CANCEL; + } - 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); + if (wd->t >= 2.0) + { + 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; + } + else if (wd->t <= 0.5) + { + 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; + } + else if (wd->t != 1.0) + { + 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); + } + return ECORE_CALLBACK_RENEW; +} - evas_object_raise(route); - _obj_rotate(obj, route); - evas_object_show(route); +static Eina_Bool +_long_press(void *data) +{ + ELM_CHECK_WIDTYPE(data, widtype) ECORE_CALLBACK_CANCEL; + Widget_Data *wd = elm_widget_data_get(data); - continue; - } - } - //the route is not display - evas_object_hide(route); - } -#else - (void) wd; -#endif + if (!wd) return ECORE_CALLBACK_CANCEL; + wd->long_timer = NULL; + evas_object_smart_callback_call(data, SIG_LONGPRESSED, &wd->ev); + return ECORE_CALLBACK_CANCEL; +} + +static void +_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) +{ + ELM_CHECK_WIDTYPE(data, widtype); + Widget_Data *wd = elm_widget_data_get(data); + Evas_Event_Mouse_Down *ev = event_info; + + 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); } + static void -_route_place(Widget_Data *wd) +_mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) { + 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; - px = wd->pan_x; - py = wd->pan_y; - _viewport_size_get(wd, &ow, &oh); + Evas_Event_Mouse_Up *ev = event_info; + EINA_SAFETY_ON_NULL_RETURN(ev); - Evas_Coord size = wd->size.w; + 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) + { + ecore_timer_del(wd->long_timer); + wd->long_timer = NULL; + } + if (!wd->on_hold) evas_object_smart_callback_call(data, SIG_CLICKED, ev); + wd->on_hold = EINA_FALSE; +} - EINA_LIST_FOREACH(wd->route, lr, r) +static void +_mouse_wheel_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) +{ + ELM_CHECK_WIDTYPE(data, widtype); + Widget_Data *wd = elm_widget_data_get(data); + EINA_SAFETY_ON_NULL_RETURN(wd); + + if (!wd->paused) { - EINA_LIST_FOREACH(r->path, lp, p) - { - evas_object_polygon_points_clear(p); - } + int zoom_diff = 0; + Evas_Event_Mouse_Wheel *ev = (Evas_Event_Mouse_Wheel*) event_info; + Evas_Coord x, y, w, h; - nodes = eina_list_count(r->nodes); + evas_object_geometry_get(data, &x, &y, &w, &h); - 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; - y = y - py; + if (wd->calc_job) ecore_job_del(wd->calc_job); + wd->calc_job = ecore_job_add(_calc_job, wd); - 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); - } + 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); - 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; + if (wd->pinch.level > 1.99 || wd->pinch.level < 1.01) + { + wd->wheel_diff = 0; + if (wd->pinch.level > 1.99) + { + zoom_diff = 1; + wd->pinch.diff = wd->pinch.level / 2.0; + wd->pinch.level = wd->pinch.level / 2.0; } - else + else if (wd->pinch.level < 1.01) { - 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; + zoom_diff = -1; + wd->pinch.diff = wd->pinch.level * 2.0; + wd->pinch.level = wd->pinch.level * 2.0; } + + 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 -_delayed_do(Widget_Data *wd) +_rect_resize_cb(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) { - 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); - } + 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); } static void -_smooth_update(Widget_Data *wd) +_del_hook(Evas_Object *obj) { - EINA_SAFETY_ON_NULL_RETURN(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_List *l; - Grid *g; + Evas_Object *p; + Path_Node *n; + Path_Waypoint *w; + Ecore_Event_Handler *h; + Elm_Map_Route *r; + Elm_Map_Name *na; + Evas_Object *route; - EINA_LIST_FOREACH(wd->grids, l, g) + if (!wd) return; + EINA_LIST_FREE(wd->groups_clas, group_clas) { - Eina_Iterator *it = eina_matrixsparse_iterator_new(g->grid); - Eina_Matrixsparse_Cell *cell; + if (group_clas->style) + eina_stringshare_del(group_clas->style); + free(group_clas); + } - EINA_ITERATOR_FOREACH(it, cell) - { - 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(wd->markers_clas, marker_clas) + { + if (marker_clas->style) + eina_stringshare_del(marker_clas->style); + free(marker_clas); } -} -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_FOREACH(wd->route, l, r) + { + EINA_LIST_FREE(r->path, p) + { + evas_object_del(p); + } -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->waypoint, w) + { + if (w->point) eina_stringshare_del(w->point); + free(w); + } - Evas_Coord px, py, vw, vh; - Evas_Coord ow, oh; + EINA_LIST_FREE(r->nodes, n) + { + if (n->pos.address) eina_stringshare_del(n->pos.address); + free(n); + } - 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(r->handlers, h) + { + ecore_event_handler_del(h); + } -static Eina_Bool -_zoom_anim(void *data) -{ - Widget_Data *wd = data; - EINA_SAFETY_ON_NULL_RETURN_VAL(wd, ECORE_CALLBACK_CANCEL); + 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); + } - if (wd->ani.cnt <= 0) + EINA_LIST_FREE(wd->names, na) { - wd->zoom_animator = NULL; - evas_object_smart_changed(wd->pan_smart); - return ECORE_CALLBACK_CANCEL; + 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 + + EINA_LIST_FREE(wd->track, route) { - wd->ani.zoom += wd->ani.diff; - wd->ani.cnt--; - zoom_do(wd, wd->ani.zoom); - return ECORE_CALLBACK_RENEW; + evas_object_del(route); } -} - -static void -zoom_with_animation(Widget_Data *wd, double zoom, int cnt) -{ - EINA_SAFETY_ON_NULL_RETURN(wd); - if (cnt == 0) return; - wd->ani.cnt = cnt; - wd->ani.zoom = wd->zoom; - wd->ani.diff = (double)(zoom - wd->zoom)/cnt; + 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); - wd->zoom_animator = ecore_animator_add(_zoom_anim, wd); -} - -static void -_sizing_eval(Widget_Data *wd) -{ - EINA_SAFETY_ON_NULL_RETURN(wd); - - Evas_Coord maxw = -1, maxh = -1; + 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); - evas_object_size_hint_max_get(wd->scr, &maxw, &maxh); - evas_object_size_hint_max_set(wd->obj, maxw, maxh); + free(wd); } static void -_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +_del_pre_hook(Evas_Object *obj) { - _sizing_eval(data); -} + 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; -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; -} + 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; -static void -_scr(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) -{ - EINA_SAFETY_ON_NULL_RETURN(data); - Widget_Data *wd = data; + 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]); + } - 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); + evas_object_del(wd->sep_maps_markers); + evas_object_del(wd->pan_smart); + wd->pan_smart = NULL; } static void -_scr_anim_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +_on_focus_hook(void *data __UNUSED__, Evas_Object *obj) { - EINA_SAFETY_ON_NULL_RETURN(data); - Widget_Data *wd = data; - evas_object_smart_callback_call(wd->obj, "scroll,anim,start", NULL); -} + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(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); + 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); + } } -static Eina_Bool -_long_press(void *data) +static void +_theme_hook(Evas_Object *obj) { - EINA_SAFETY_ON_NULL_RETURN_VAL(data, ECORE_CALLBACK_CANCEL); - Widget_Data *wd = data; + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); - wd->long_timer = NULL; - evas_object_smart_callback_call(wd->obj, SIG_LONGPRESSED, &wd->ev); - return ECORE_CALLBACK_CANCEL; + 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 -_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) +_sizing_eval(Evas_Object *obj) { - EINA_SAFETY_ON_NULL_RETURN(data); - Widget_Data *wd = data; - Evas_Event_Mouse_Down *ev = event_info; - - 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); + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); + Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1; - 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); + 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); } static void -_mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) +_calc_job(void *data) { - EINA_SAFETY_ON_NULL_RETURN(data); Widget_Data *wd = data; + Evas_Coord minw, minh; - 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) + if (!wd) return; + minw = wd->size.w; + minh = wd->size.h; + if (wd->resized) { - ecore_timer_del(wd->long_timer); - wd->long_timer = NULL; + 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); + } } - 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) + if ((minw != wd->minw) || (minh != wd->minh)) { - Evas_Event_Mouse_Wheel *ev = (Evas_Event_Mouse_Wheel*) event_info; - zoom_do(wd, wd->zoom_detail - ((double)ev->z / 10)); - } + 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); } static void _pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y) { Pan *sd = evas_object_smart_data_get(obj); - EINA_SAFETY_ON_NULL_RETURN(sd); + if (!sd) return; 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); @@ -1840,7 +1941,7 @@ static void _pan_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y) { Pan *sd = evas_object_smart_data_get(obj); - EINA_SAFETY_ON_NULL_RETURN(sd); + if (!sd) return; if (x) *x = sd->wd->pan_x; if (y) *y = sd->wd->pan_y; } @@ -1849,12 +1950,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->size.w - ow; - oh = sd->wd->size.h - oh; + ow = sd->wd->minw - ow; if (ow < 0) ow = 0; + oh = sd->wd->minh - oh; if (oh < 0) oh = 0; if (x) *x = ow; if (y) *y = oh; @@ -1871,9 +1972,9 @@ static void _pan_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h) { Pan *sd = evas_object_smart_data_get(obj); - EINA_SAFETY_ON_NULL_RETURN(sd); - if (w) *w = sd->wd->size.w; - if (h) *h = sd->wd->size.h; + if (!sd) return; + if (w) *w = sd->wd->minw; + if (h) *h = sd->wd->minh; } static void @@ -1881,229 +1982,431 @@ _pan_add(Evas_Object *obj) { Pan *sd; Evas_Object_Smart_Clipped_Data *cd; - parent_sc.add(obj); + _pan_sc.add(obj); cd = evas_object_smart_data_get(obj); - EINA_SAFETY_ON_NULL_RETURN(cd); - sd = ELM_NEW(Pan); + if (!cd) return; + sd = calloc(1, sizeof(Pan)); + if (!sd) return; sd->__clipped_data = *cd; free(cd); evas_object_smart_data_set(obj, sd); } static void -_pan_resize(Evas_Object *obj, Evas_Coord w __UNUSED__, Evas_Coord h __UNUSED__) +_pan_del(Evas_Object *obj) { Pan *sd = evas_object_smart_data_get(obj); - EINA_SAFETY_ON_NULL_RETURN(sd); + if (!sd) return; + _pan_sc.del(obj); +} - _sizing_eval(sd->wd); - elm_map_zoom_mode_set(sd->wd->obj, sd->wd->mode); - evas_object_smart_changed(obj); +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); } static void _pan_calculate(Evas_Object *obj) { Pan *sd = evas_object_smart_data_get(obj); - EINA_SAFETY_ON_NULL_RETURN(sd); + Evas_Coord ox, oy, ow, oh; + Eina_List *l; + Grid *g; - Evas_Coord w, h; - evas_object_geometry_get(sd->wd->pan_smart, NULL, NULL, &w, &h); - if (w <= 0 || h <= 0) return; + EINA_SAFETY_ON_NULL_RETURN(sd); + EINA_SAFETY_ON_NULL_RETURN(sd->wd); - _grid_place(sd->wd); - _marker_place(sd->wd); - _route_place(sd->wd); - _track_place(sd->wd); - _delayed_do(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__) { - EINA_SAFETY_ON_NULL_RETURN(obj); - evas_object_smart_changed(obj); + 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); + + if (!wd) return; + elm_smart_scroller_hold_set(wd->scr, 0); } static void -_hold_on(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +_freeze_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) { - EINA_SAFETY_ON_NULL_RETURN(data); - Widget_Data *wd = data; - elm_smart_scroller_hold_set(wd->scr, 1); + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); + + if (!wd) return; + elm_smart_scroller_freeze_set(wd->scr, 1); } static void -_hold_off(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +_freeze_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) { - EINA_SAFETY_ON_NULL_RETURN(data); - Widget_Data *wd = data; - elm_smart_scroller_hold_set(wd->scr, 0); + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); + + if (!wd) return; + elm_smart_scroller_freeze_set(wd->scr, 0); } static void -_freeze_on(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +_scr_anim_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) { - EINA_SAFETY_ON_NULL_RETURN(data); - Widget_Data *wd = data; - elm_smart_scroller_freeze_set(wd->scr, 1); + evas_object_smart_callback_call(data, "scroll,anim,start", NULL); } static void -_freeze_off(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +_scr_anim_stop(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) { - EINA_SAFETY_ON_NULL_RETURN(data); - Widget_Data *wd = data; - elm_smart_scroller_freeze_set(wd->scr, 0); + evas_object_smart_callback_call(data, "scroll,anim,stop", NULL); } static void -_on_focus_hook(void *data __UNUSED__, Evas_Object *obj) +_scr_drag_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); + Widget_Data *wd = elm_widget_data_get(data); EINA_SAFETY_ON_NULL_RETURN(wd); + wd->center_on.enabled = EINA_FALSE; - if (elm_widget_focus_get(obj)) + // FIXME: els_scoller sometimes give start event again & again... it confuses app. (els_scr bug?) + if (!wd->scr_started) { - edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), "elm,action,focus", "elm"); - evas_object_focus_set(wd->obj, EINA_TRUE); + wd->scr_started = EINA_TRUE; + evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_START, NULL); } - else +} + +static void +_scr_drag_stop(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) { - edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), "elm,action,unfocus", "elm"); - evas_object_focus_set(wd->obj, EINA_FALSE); + wd->scr_started = EINA_FALSE; + evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_STOP, NULL); } } static void -_del_hook(Evas_Object *obj) +_scr_scroll(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(wd); + evas_object_smart_callback_call(data, SIG_SCROLL, 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; - EINA_LIST_FOREACH(wd->route, l, r) +static void +_group_object_create(Marker_Group *group) +{ + const char *style = "radio"; + Evas_Object *icon = NULL; + + if (group->obj) return; + if ((!group->clas->priv.objs_notused) || (eina_list_count(group->markers) == 1)) { - EINA_LIST_FREE(r->path, p) + //set icon and style + if (eina_list_count(group->markers) == 1) { - evas_object_del(p); - } + Elm_Map_Marker *m = eina_list_data_get(group->markers); + if (m->clas->style) + style = m->clas->style; - EINA_LIST_FREE(r->waypoint, w) - { - if (w->point) eina_stringshare_del(w->point); - free(w); - } + if (m->clas->func.icon_get) + icon = m->clas->func.icon_get(group->wd->obj, m, m->data); - EINA_LIST_FREE(r->nodes, n) - { - if (n->pos.address) eina_stringshare_del(n->pos.address); - free(n); + group->delete_object = EINA_TRUE; } - - EINA_LIST_FREE(r->handlers, h) + else { - ecore_event_handler_del(h); + 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; } - 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); + 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); + + 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; + + 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); } - EINA_LIST_FREE(wd->names, na) + 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) { - 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; - } + 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); } + else + evas_object_del(group->obj); - EINA_LIST_FREE(wd->track, route) + 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)) { - evas_object_del(route); + //no content, we can delete the bubble + _group_bubble_free(group); + return; } + 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; - EINA_LIST_FOREACH_SAFE(wd->markers, l, ll, marker) - elm_map_marker_remove(marker); - eina_list_free(wd->markers); + if (!group->bubble) return 1; - EINA_LIST_FREE(wd->group_classes, group_clas) + if (!group->sc) { - eina_list_free(group_clas->markers); - if (group_clas->style) eina_stringshare_del(group_clas->style); - free(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(wd->marker_classes, clas) + EINA_LIST_FOREACH(group->markers, l, marker) { - if (clas->style) eina_stringshare_del(clas->style); - free(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++; + } } + return i; +} - if (wd->scr_timer) ecore_timer_del(wd->scr_timer); - if (wd->long_timer) ecore_timer_del(wd->long_timer); +static void +_group_bubble_content_free(Marker_Group *group) +{ + Eina_List *l; + Elm_Map_Marker *marker; - if (wd->delayed_jobs) EINA_LIST_FREE(wd->delayed_jobs, dd) free(dd); + 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->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_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->zoom_timer) ecore_timer_del(wd->zoom_timer); - if (wd->zoom_animator) ecore_animator_del(wd->zoom_animator); +static void +_group_bubble_place(Marker_Group *group) +{ + Evas_Coord x, y, w; + Evas_Coord xx, yy, ww, hh; + const char *s; - _grid_all_clear(wd); + if ((!group->bubble) || (!group->obj)) return; - for (idx = 0; wd->src_names[idx]; idx++) - eina_stringshare_del(wd->src_names[idx]); + evas_object_geometry_get(group->obj, &x, &y, &w, NULL); + edje_object_size_min_calc(group->bubble, NULL, &hh); - EINA_LIST_FREE(wd->srcs, s) free(s); + 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; - if (wd->map) evas_map_free(wd->map); + 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); - free(wd); + 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); } static void -_del_pre_hook(Evas_Object *obj) +_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(wd); + 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); } static void -_theme_hook(Evas_Object *obj) +_group_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_SAFETY_ON_NULL_RETURN(wd); + Marker_Group *group = data; - elm_smart_scroller_object_theme_set(obj, wd->scr, "map", "base", elm_widget_style_get(obj)); - _sizing_eval(wd); + if (group->bringin) + { + group->bringin = EINA_FALSE; + return; + } + + if (group->bubble) + { + group->open = EINA_FALSE; + _group_bubble_free(group); + return; + } + group->open = EINA_TRUE; + _group_bubble_create(group); } static Eina_Bool @@ -2111,12 +2414,17 @@ _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); - 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; - + 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; 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; @@ -2124,7 +2432,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); - _viewport_size_get(wd, NULL, &vh); + elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h); if ((!strcmp(ev->keyname, "Left")) || (!strcmp(ev->keyname, "KP_Left"))) { @@ -2145,25 +2453,29 @@ _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 * vh) / 100; + y -= -(page_y * v_h) / 100; else y -= page_y; } else if ((!strcmp(ev->keyname, "Next")) || (!strcmp(ev->keyname, "KP_Next"))) { if (page_y < 0) - y += -(page_y * vh) / 100; + y += -(page_y * v_h) / 100; else y += page_y; } else if (!strcmp(ev->keyname, "KP_Add")) { - zoom_with_animation(wd, wd->zoom + 1, 10); + zoom = elm_map_zoom_get(obj) + 1; + elm_map_zoom_mode_set(obj, ELM_MAP_ZOOM_MODE_MANUAL); + elm_map_zoom_set(obj, zoom); return EINA_TRUE; } else if (!strcmp(ev->keyname, "KP_Subtract")) { - zoom_with_animation(wd, wd->zoom - 1, 10); + zoom = elm_map_zoom_get(obj) - 1; + elm_map_zoom_mode_set(obj, ELM_MAP_ZOOM_MODE_MANUAL); + elm_map_zoom_set(obj, zoom); return EINA_TRUE; } else return EINA_FALSE; @@ -2186,6 +2498,7 @@ 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) { @@ -2437,8 +2750,14 @@ _route_complete_cb(void *data, int ev_type __UNUSED__, void *event) if (r->ud.fd) fclose(r->ud.fd); _parse_kml(r); - _route_place(wd); - + 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); + } 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); @@ -2477,6 +2796,7 @@ _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); @@ -2525,324 +2845,189 @@ _utils_convert_name(const Evas_Object *obj, int method, char *address, double lo } static Evas_Event_Flags -_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); - - 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) +zoom_start_cb(void *data, void *event_info __UNUSED__) { 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); + // 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); - 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); + wd->pinch.diff += 0.001; - evas_object_smart_changed(wd->pan_smart); - } return EVAS_EVENT_FLAG_NONE; } static Evas_Event_Flags -_pinch_rotate_end_cb(void *data, void *event_info __UNUSED__) +zoom_end_cb(void *data, void *event_info __UNUSED__) { Widget_Data *wd = data; EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EVAS_EVENT_FLAG_NONE); - 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); - - 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; + // 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); - 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); + wd->pinch.diff = wd->pinch.level; + + return EVAS_EVENT_FLAG_NONE; } -static void -_marker_list_show(void *data) +static Evas_Event_Flags +zoom_cb(void *data, void *event_info) { - 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; + Widget_Data *wd = data; + EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EVAS_EVENT_FLAG_NONE); - EINA_LIST_FREE(dd->markers, marker) + if (!wd->paused) { - 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; + 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); - 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++; + 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); } - zoom--; - zoom_do(dd->wd, zoom); - _region_show(dd); - evas_object_smart_changed(dd->wd->pan_smart); -} + // FIXME: scroller can be jumping strangely when resizing & scrolling at the sametime (els_scr bug?) + _scr_scroll(wd->obj, NULL, NULL); -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); + return EVAS_EVENT_FLAG_NONE; } -static char * -_osmarender_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom) +static Evas_Event_Flags +rotate_cb(void *data, void *event_info) { - 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); -} + Widget_Data *wd = data; + EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EVAS_EVENT_FLAG_NONE); -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->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 * -_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); -} + 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 * -_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); + 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 *_yours_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat) +static Evas_Event_Flags +rotate_end_cb(void *data, void *event_info __UNUSED__) { - 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); + Widget_Data *wd = data; + EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EVAS_EVENT_FLAG_NONE); - return strdup(buf); + wd->rotate.a = wd->rotate.d; + + return EVAS_EVENT_FLAG_NONE; } -// 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) +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) { - 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); + EINA_SAFETY_ON_NULL_RETURN(wd); + Evas_Coord sx, sy, tx, ty, tcx, tcy, sw, sh, tw, th, rw, rh; - return strdup(buf); -} -*/ + 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; -// 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 (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; + } + + if (x) *x = tx; + if (y) *y = ty; + if (cx) *cx= tcx; + if (cy) *cy = tcy; + if (w) *w = tw; + if (h) *h = th; } -*/ -static char * -_nominatim_url_cb(Evas_Object *obj, int method, char *name, double lon, double lat) +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) { - ELM_CHECK_WIDTYPE(obj, widtype) strdup(""); - Widget_Data *wd = elm_widget_data_get(obj); - EINA_SAFETY_ON_NULL_RETURN_VAL(wd, strdup("")); + EINA_SAFETY_ON_NULL_RETURN(xx); + EINA_SAFETY_ON_NULL_RETURN(yy); - char **str; - unsigned int ele, idx; - char search_url[PATH_MAX]; - char buf[PATH_MAX]; + double r = (degree * M_PI) / 180.0; + double tx, ty, ttx, tty; - 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); + tx = x - cx; + ty = y - cy; - 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, ""); + ttx = tx * cos(r); + tty = tx * sin(r); + tx = ttx + (ty * cos(r + M_PI_2)); + ty = tty + (ty * sin(r + M_PI_2)); - return strdup(buf); + *xx = tx + cx; + *yy = ty + cy; } #endif @@ -2853,55 +3038,68 @@ elm_map_add(Evas_Object *parent) #ifdef HAVE_ELEMENTARY_ECORE_CON Evas *e; Widget_Data *wd; - Evas_Object *obj; Evas_Coord minw, minh; + Evas_Object *obj; + static Evas_Smart *smart = NULL; + Eina_Bool bounce = _elm_config->thumbscroll_bounce_enable; 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_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_data_set(obj, wd); 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); - 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); + + 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); if (!smart) { - evas_object_smart_clipped_smart_set(&parent_sc); - sc = parent_sc; + static Evas_Smart_Class sc; + + evas_object_smart_clipped_smart_set(&_pan_sc); + sc = _pan_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; @@ -2909,58 +3107,75 @@ elm_map_add(Evas_Object *parent) } if (smart) { - Pan *pan; wd->pan_smart = evas_object_smart_add(e, smart); - pan = evas_object_smart_data_get(wd->pan_smart); - pan->wd = wd; + wd->pan = evas_object_smart_data_get(wd->pan_smart); + wd->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); - 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->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); wd->ges = elm_gesture_layer_add(obj); if (!wd->ges) ERR("elm_gesture_layer_add() failed"); - elm_gesture_layer_attach(wd->ges, obj); + elm_gesture_layer_attach(wd->ges, wd->rect); elm_gesture_layer_cb_set(wd->ges, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_START, - _pinch_zoom_start_cb, wd); + zoom_start_cb, wd); elm_gesture_layer_cb_set(wd->ges, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_MOVE, - _pinch_zoom_cb, wd); + 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); elm_gesture_layer_cb_set(wd->ges, ELM_GESTURE_ROTATE, ELM_GESTURE_STATE_MOVE, - _pinch_rotate_cb, wd); + rotate_cb, wd); elm_gesture_layer_cb_set(wd->ges, ELM_GESTURE_ROTATE, ELM_GESTURE_STATE_END, - _pinch_rotate_end_cb, wd); + rotate_end_cb, wd); elm_gesture_layer_cb_set(wd->ges, ELM_GESTURE_ROTATE, ELM_GESTURE_STATE_ABORT, - _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); - - 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? + rotate_end_cb, wd); + wd->mode = ELM_MAP_ZOOM_MODE_MANUAL; wd->id = ((int)getpid() << 16) | idnum; idnum++; - _grid_all_create(wd); - zoom_do(wd, 0); + 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); + + wd->sep_maps_markers = evas_object_rectangle_add(evas_object_evas_get(obj)); + evas_object_smart_member_add(wd->sep_maps_markers, wd->pan_smart); + + grid_create_all(obj); - wd->mode = ELM_MAP_ZOOM_MODE_MANUAL; - wd->markers_max_num = MARER_MAX_NUMBER; + wd->paused = EINA_TRUE; + elm_map_zoom_set(obj, 0); + wd->paused = EINA_FALSE; + _sizing_eval(obj); // 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 @@ -2975,21 +3190,119 @@ 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; - 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); + 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); #else (void) obj; (void) zoom; @@ -3003,7 +3316,7 @@ elm_map_zoom_get(const Evas_Object *obj) ELM_CHECK_WIDTYPE(obj, widtype) 0; Widget_Data *wd = elm_widget_data_get(obj); - EINA_SAFETY_ON_NULL_RETURN_VAL(wd, 0); + if (!wd) return 0; return wd->zoom; #else (void) obj; @@ -3017,14 +3330,17 @@ 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); - 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); + 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); + } #else (void) obj; (void) mode; @@ -3037,8 +3353,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; @@ -3052,14 +3368,29 @@ 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); - 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); + 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; #else (void) obj; (void) lon; @@ -3073,14 +3404,28 @@ 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); - 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); + wd->center_on.enabled = EINA_TRUE; + wd->center_on.lon = lon; + wd->center_on.lat = lat; #else (void) obj; (void) lon; @@ -3094,15 +3439,14 @@ 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); - EINA_SAFETY_ON_NULL_RETURN(wd); - + Evas_Coord cx, cy; + int rw; double tlon, tlat; - Evas_Coord px, py, vw, vh; + EINA_SAFETY_ON_NULL_RETURN(wd); - _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); + _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); if (lon) *lon = tlon; if (lat) *lat = tlat; #else @@ -3118,8 +3462,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) @@ -3128,7 +3472,8 @@ 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(wd, wd->zoom); + zoom_do(obj); + evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL); } edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), "elm,state,busy,stop", "elm"); @@ -3151,8 +3496,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 @@ -3167,8 +3512,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; @@ -3182,8 +3527,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; @@ -3197,8 +3542,8 @@ 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; @@ -3221,8 +3566,8 @@ 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)) { @@ -3254,8 +3599,8 @@ 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)) { @@ -3322,7 +3667,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, Evas_Coord x, Evas_Coord y, double *lon, double *lat) +elm_map_canvas_to_geo_convert(const Evas_Object *obj, const Evas_Coord x, const Evas_Coord y, double *lon, double *lat) { #ifdef HAVE_ELEMENTARY_ECORE_CON ELM_CHECK_WIDTYPE(obj, widtype); @@ -3331,11 +3676,25 @@ elm_map_canvas_to_geo_convert(const Evas_Object *obj, Evas_Coord x, Evas_Coord y EINA_SAFETY_ON_NULL_RETURN(lat); EINA_SAFETY_ON_NULL_RETURN(wd); - 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); + 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); #else (void) obj; (void) x; @@ -3346,48 +3705,196 @@ elm_map_canvas_to_geo_convert(const Evas_Object *obj, Evas_Coord x, Evas_Coord y } EAPI Elm_Map_Marker * -elm_map_marker_add(Evas_Object *obj, double lon, double lat, Elm_Map_Marker_Class *clas, Elm_Map_Group_Class *group_clas, void *data) +elm_map_marker_add(Evas_Object *obj, double lon, double lat, Elm_Map_Marker_Class *clas, Elm_Map_Group_Class *clas_group, 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; - EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL); + if (!wd) return NULL; + EINA_SAFETY_ON_NULL_RETURN_VAL(clas_group, 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->group_clas = group_clas; + marker->clas_group = clas_group; marker->longitude = lon; marker->latitude = lat; marker->data = data; - 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); + 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); + } + return marker; #else (void) obj; (void) lon; (void) lat; (void) clas; - (void) group_clas; + (void) clas_group; (void) data; return NULL; #endif @@ -3397,24 +3904,70 @@ 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); - Widget_Data *wd = marker->wd; - EINA_SAFETY_ON_NULL_RETURN(wd); + 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); - if ((marker->content) && (marker->clas->func.del)) - marker->clas->func.del(wd->obj, marker, marker->data, marker->content); + _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]); + } + } + } - if (marker->bubble) _bubble_free(marker->bubble); - if (marker->group) _marker_group_free(marker->group); + 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); - if (marker->group_clas) - marker->group_clas->markers = eina_list_remove(marker->group_clas->markers, marker); - wd->markers = eina_list_remove(wd->markers, marker); + if (marker->x) free(marker->x); + if (marker->y) free(marker->y); + if (marker->groups) free(marker->groups); - evas_object_del(marker->obj); free(marker); - evas_object_smart_changed(wd->pan_smart); + 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); + } #else (void) marker; #endif @@ -3460,18 +4013,49 @@ 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_SAFETY_ON_TRUE_RETURN(eina_list_count(markers) == 0); + EINA_LIST_FOREACH(markers, l, marker) + { + wd = marker->wd; - 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); + 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; + + 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); #else (void) markers; #endif @@ -3483,8 +4067,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; @@ -3509,10 +4093,15 @@ elm_map_marker_update(Elm_Map_Marker *marker) { #ifdef HAVE_ELEMENTARY_ECORE_CON EINA_SAFETY_ON_NULL_RETURN(marker); - Widget_Data *wd = marker->wd; - EINA_SAFETY_ON_NULL_RETURN(wd); - - _marker_update(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]); + } #else (void) marker; #endif @@ -3524,21 +4113,12 @@ 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); - EINA_SAFETY_ON_NULL_RETURN(wd); - - Eina_List *l; - Elm_Map_Marker *marker; - EINA_LIST_FOREACH(wd->markers, l, marker) - { - if (marker->bubble) _bubble_free(marker->bubble); - marker->bubble = NULL; + Marker_Group *group; + Eina_List *l, *l_next; - if (marker->group) - { - if (marker->group->bubble) _bubble_free(marker->group->bubble); - marker->group->bubble = NULL; - } - } + if (!wd) return; + EINA_LIST_FOREACH_SAFE(wd->opened_bubbles, l, l_next, group) + _group_bubble_free(group); #else (void) obj; #endif @@ -3550,16 +4130,11 @@ 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; @@ -3580,7 +4155,7 @@ elm_map_group_class_style_set(Elm_Map_Group_Class *clas, const char *style) } EAPI void -elm_map_group_class_icon_cb_set(Elm_Map_Group_Class *clas, Elm_Map_Group_Icon_Get_Func icon_get) +elm_map_group_class_icon_cb_set(Elm_Map_Group_Class *clas, ElmMapGroupIconGetFunc icon_get) { #ifdef HAVE_ELEMENTARY_ECORE_CON EINA_SAFETY_ON_NULL_RETURN(clas); @@ -3633,11 +4208,19 @@ 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); - EINA_SAFETY_ON_NULL_RETURN(wd); - EINA_SAFETY_ON_NULL_RETURN(clas); + if (!wd) return; + EINA_SAFETY_ON_NULL_RETURN(clas); + if (clas->hide == hide) return; clas->hide = hide; - evas_object_smart_changed(wd->pan_smart); + 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); + } #else (void) obj; (void) clas; @@ -3651,12 +4234,10 @@ 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); - 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); + 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); return clas; #else (void) obj; @@ -3677,7 +4258,7 @@ elm_map_marker_class_style_set(Elm_Map_Marker_Class *clas, const char *style) } EAPI void -elm_map_marker_class_icon_cb_set(Elm_Map_Marker_Class *clas, Elm_Map_Marker_Icon_Get_Func icon_get) +elm_map_marker_class_icon_cb_set(Elm_Map_Marker_Class *clas, ElmMapMarkerIconGetFunc icon_get) { #ifdef HAVE_ELEMENTARY_ECORE_CON EINA_SAFETY_ON_NULL_RETURN(clas); @@ -3689,7 +4270,7 @@ elm_map_marker_class_icon_cb_set(Elm_Map_Marker_Class *clas, Elm_Map_Marker_Icon } EAPI void -elm_map_marker_class_get_cb_set(Elm_Map_Marker_Class *clas, Elm_Map_Marker_Get_Func get) +elm_map_marker_class_get_cb_set(Elm_Map_Marker_Class *clas, ElmMapMarkerGetFunc get) { #ifdef HAVE_ELEMENTARY_ECORE_CON EINA_SAFETY_ON_NULL_RETURN(clas); @@ -3701,7 +4282,7 @@ elm_map_marker_class_get_cb_set(Elm_Map_Marker_Class *clas, Elm_Map_Marker_Get_F } EAPI void -elm_map_marker_class_del_cb_set(Elm_Map_Marker_Class *clas, Elm_Map_Marker_Del_Func del) +elm_map_marker_class_del_cb_set(Elm_Map_Marker_Class *clas, ElmMapMarkerDelFunc del) { #ifdef HAVE_ELEMENTARY_ECORE_CON EINA_SAFETY_ON_NULL_RETURN(clas); @@ -3718,9 +4299,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); - return wd->src_names; + if (!wd) return NULL; + return wd->source_names; #else (void) obj; return NULL; @@ -3733,20 +4314,19 @@ 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_all_clear(wd); - EINA_LIST_FOREACH(wd->srcs, l, s) + grid_clear_all(obj); + EINA_LIST_FOREACH(wd->map_sources_tab, l, s) { if (!strcmp(s->name, source_name)) { @@ -3763,11 +4343,9 @@ 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_all_create(wd); - zoom_do(wd, zoom); + grid_create_all(obj); + elm_map_zoom_set(obj, zoom); #else (void) obj; (void) source_name; @@ -3795,8 +4373,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; @@ -3810,8 +4388,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; @@ -3825,11 +4403,10 @@ 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 ((zoom > wd->src->zoom_max) || (zoom < wd->src->zoom_min)) return; - wd->zoom_max = zoom; + if ((!wd) || (!wd->src)) return; + if ((zoom > wd->zoom_max) || (zoom < wd->zoom_min)) return; + wd->src->zoom_max = zoom; #else (void) obj; (void) zoom; @@ -3842,10 +4419,9 @@ 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); - return wd->zoom_max; + if ((!wd) || (!wd->src)) return 18; + return wd->src->zoom_max; #else (void) obj; return 18; @@ -3858,11 +4434,10 @@ 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 ((zoom > wd->src->zoom_max) || (zoom < wd->src->zoom_min)) return; - wd->zoom_min = zoom; + if ((!wd) || (!wd->src)) return; + if ((zoom > wd->zoom_max) || (zoom < wd->zoom_min)) return; + wd->src->zoom_min = zoom; #else (void) obj; (void) zoom; @@ -3875,10 +4450,9 @@ 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); - return wd->zoom_min; + if ((!wd) || (!wd->src)) return 0; + return wd->src->zoom_min; #else (void) obj; return 0; @@ -3891,10 +4465,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); - eina_stringshare_replace(&wd->user_agent, 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); if (!wd->ua) wd->ua = eina_hash_string_small_new(NULL); eina_hash_set(wd->ua, "User-Agent", wd->user_agent); @@ -3910,8 +4484,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; @@ -3920,7 +4494,13 @@ 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; @@ -3930,10 +4510,10 @@ elm_map_route_add(Evas_Object *obj, Elm_Map_Route_Type type, Elm_Map_Route_Metho char *type_name = NULL; int fd; - EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL); - EINA_SAFETY_ON_NULL_RETURN_VAL(wd->src, NULL); + if ((!wd) || (!wd->src)) return 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); @@ -4189,13 +4769,12 @@ 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; - - evas_object_smart_changed(wd->pan_smart); + wd->calc_job = ecore_job_add(_calc_job, wd); #else (void) obj; (void) degree; @@ -4210,8 +4789,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; @@ -4229,12 +4808,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(obj, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel_cb, obj); + evas_object_event_callback_del_full(wd->rect, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel_cb, obj); else if ((wd->wheel_disabled) && (!disabled)) - evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel_cb, obj); + evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel_cb, obj); wd->wheel_disabled = !!disabled; #else (void) obj; @@ -4248,8 +4827,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; @@ -4264,7 +4843,8 @@ 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); - EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EINA_FALSE); + + if (!wd) return EINA_FALSE; Evas_Object *route = elm_route_add(obj); elm_route_emap_set(route, emap); @@ -4285,7 +4865,8 @@ 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); - EINA_SAFETY_ON_NULL_RETURN(wd); + + if (!wd) return ; wd->track = eina_list_remove(wd->track, route); evas_object_del(route); @@ -4294,3 +4875,118 @@ 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 diff --git a/src/lib/elm_map.h b/src/lib/elm_map.h index fcc5c12..9a1fde4 100644 --- a/src/lib/elm_map.h +++ b/src/lib/elm_map.h @@ -153,20 +153,20 @@ typedef struct _Elm_Map_Route Elm_Map_Route; /**< A route to be shown in typedef struct _Elm_Map_Name Elm_Map_Name; /**< A handle for specific coordinates. */ typedef struct _Elm_Map_Track Elm_Map_Track; -typedef Evas_Object *(*Elm_Map_Marker_Get_Func)(Evas_Object *obj, Elm_Map_Marker *marker, void *data); /**< Bubble content fetching class function for marker classes. When the user click on a marker, a bubble is displayed with a content. */ -typedef void (*Elm_Map_Marker_Del_Func)(Evas_Object *obj, Elm_Map_Marker *marker, void *data, Evas_Object *o); /**< Function to delete bubble content for marker classes. */ -typedef Evas_Object *(*Elm_Map_Marker_Icon_Get_Func)(Evas_Object *obj, Elm_Map_Marker *marker, void *data); /**< Icon fetching class function for marker classes. */ -typedef Evas_Object *(*Elm_Map_Group_Icon_Get_Func)(Evas_Object *obj, void *data); /**< Icon fetching class function for markers group classes. */ - -typedef char *(*Elm_Map_Module_Source_Func)(void); -typedef int (*Elm_Map_Module_Zoom_Min_Func)(void); -typedef int (*Elm_Map_Module_Zoom_Max_Func)(void); -typedef char *(*Elm_Map_Module_Url_Func)(Evas_Object *obj, int x, int y, int zoom); -typedef int (*Elm_Map_Module_Route_Source_Func)(void); -typedef char *(*Elm_Map_Module_Route_Url_Func)(Evas_Object *obj, char *type_name, int method, double flon, double flat, double tlon, double tlat); -typedef char *(*Elm_Map_Module_Name_Url_Func)(Evas_Object *obj, int method, char *name, double lon, double lat); -typedef Eina_Bool (*Elm_Map_Module_Geo_Into_Coord_Func)(const Evas_Object *obj, int zoom, double lon, double lat, int size, int *x, int *y); -typedef Eina_Bool (*Elm_Map_Module_Coord_Into_Geo_Func)(const Evas_Object *obj, int zoom, int x, int y, int size, double *lon, double *lat); +typedef Evas_Object *(*ElmMapMarkerGetFunc)(Evas_Object *obj, Elm_Map_Marker *marker, void *data); /**< Bubble content fetching class function for marker classes. When the user click on a marker, a bubble is displayed with a content. */ +typedef void (*ElmMapMarkerDelFunc)(Evas_Object *obj, Elm_Map_Marker *marker, void *data, Evas_Object *o); /**< Function to delete bubble content for marker classes. */ +typedef Evas_Object *(*ElmMapMarkerIconGetFunc)(Evas_Object *obj, Elm_Map_Marker *marker, void *data); /**< Icon fetching class function for marker classes. */ +typedef Evas_Object *(*ElmMapGroupIconGetFunc)(Evas_Object *obj, void *data); /**< Icon fetching class function for markers group classes. */ + +typedef char *(*ElmMapModuleSourceFunc)(void); +typedef int (*ElmMapModuleZoomMinFunc)(void); +typedef int (*ElmMapModuleZoomMaxFunc)(void); +typedef char *(*ElmMapModuleUrlFunc)(Evas_Object *obj, int x, int y, int zoom); +typedef int (*ElmMapModuleRouteSourceFunc)(void); +typedef char *(*ElmMapModuleRouteUrlFunc)(Evas_Object *obj, char *type_name, int method, double flon, double flat, double tlon, double tlat); +typedef char *(*ElmMapModuleNameUrlFunc)(Evas_Object *obj, int method, char *name, double lon, double lat); +typedef Eina_Bool (*ElmMapModuleGeoIntoCoordFunc)(const Evas_Object *obj, int zoom, double lon, double lat, int size, int *x, int *y); +typedef Eina_Bool (*ElmMapModuleCoordIntoGeoFunc)(const Evas_Object *obj, int zoom, int x, int y, int size, double *lon, double *lat); /** * Add a new map widget to the given parent Elementary (container) object. @@ -661,12 +661,12 @@ EAPI void elm_map_marker_show(Elm_Map_Marker *marker); EAPI void elm_map_markers_list_show(Eina_List *markers); /** - * Get the Evas object returned by the Elm_Map_Marker_Get_Func callback + * Get the Evas object returned by the ElmMapMarkerGetFunc callback * * @param marker The marker which content should be returned. * @return Return the evas object if it exists, else @c NULL. * - * To set callback function #Elm_Map_Marker_Get_Func for the marker class, + * To set callback function #ElmMapMarkerGetFunc for the marker class, * elm_map_marker_class_get_cb_set() should be used. * * This content is what will be inside the bubble that will be displayed @@ -691,8 +691,8 @@ EAPI Evas_Object *elm_map_marker_object_get(const Elm_Map_Marker *marke * @param marker The marker to be updated. * * If a content is set to this marker, it will call function to delete it, - * #Elm_Map_Marker_Del_Func, and then will fetch the content again with - * #Elm_Map_Marker_Get_Func. + * #ElmMapMarkerDelFunc, and then will fetch the content again with + * #ElmMapMarkerGetFunc. * * These functions are set for the marker class with * elm_map_marker_class_get_cb_set() and elm_map_marker_class_del_cb_set(). @@ -706,7 +706,7 @@ EAPI void elm_map_marker_update(Elm_Map_Marker *marker); * * @param obj The map object. * - * A bubble is displayed with a content fetched with #Elm_Map_Marker_Get_Func + * A bubble is displayed with a content fetched with #ElmMapMarkerGetFunc * when the user clicks on a marker. * * This functions is set for the marker class with @@ -741,7 +741,7 @@ EAPI void elm_map_bubbles_close(Evas_Object *obj); * elm_map_group_class_zoom_grouped_set(). * - visibility - set if markers will be visible or not, set with * elm_map_group_class_hide_set(). - * - #Elm_Map_Group_Icon_Get_Func - used to fetch icon for markers group classes. + * - #ElmMapGroupIconGetFunc - used to fetch icon for markers group classes. * It can be set using elm_map_group_class_icon_cb_set(). * * @see elm_map_marker_add() @@ -791,7 +791,7 @@ EAPI void elm_map_group_class_style_set(Elm_Map_Group_Class *cl * * @ingroup Map */ -EAPI void elm_map_group_class_icon_cb_set(Elm_Map_Group_Class *clas, Elm_Map_Group_Icon_Get_Func icon_get); +EAPI void elm_map_group_class_icon_cb_set(Elm_Map_Group_Class *clas, ElmMapGroupIconGetFunc icon_get); /** * Set the data associated to the group class. @@ -877,11 +877,11 @@ EAPI void elm_map_group_class_hide_set(Evas_Object *obj, Elm_Ma * * Some properties and functions can be set by class, as: * - style, with elm_map_marker_class_style_set() - * - #Elm_Map_Marker_Icon_Get_Func - used to fetch icon for markers classes. + * - #ElmMapMarkerIconGetFunc - used to fetch icon for markers classes. * It can be set using elm_map_marker_class_icon_cb_set(). - * - #Elm_Map_Marker_Get_Func - used to fetch bubble content for marker classes. + * - #ElmMapMarkerGetFunc - used to fetch bubble content for marker classes. * Set using elm_map_marker_class_get_cb_set(). - * - #Elm_Map_Marker_Del_Func - used to delete bubble content for marker classes. + * - #ElmMapMarkerDelFunc - used to delete bubble content for marker classes. * Set using elm_map_marker_class_del_cb_set(). * * @see elm_map_marker_add() @@ -929,7 +929,7 @@ EAPI void elm_map_marker_class_style_set(Elm_Map_Marker_Class * * * @ingroup Map */ -EAPI void elm_map_marker_class_icon_cb_set(Elm_Map_Marker_Class *clas, Elm_Map_Marker_Icon_Get_Func icon_get); +EAPI void elm_map_marker_class_icon_cb_set(Elm_Map_Marker_Class *clas, ElmMapMarkerIconGetFunc icon_get); /** * Set the bubble content callback function of a marker class. @@ -950,7 +950,7 @@ EAPI void elm_map_marker_class_icon_cb_set(Elm_Map_Marker_Class * * @ingroup Map */ -EAPI void elm_map_marker_class_get_cb_set(Elm_Map_Marker_Class *clas, Elm_Map_Marker_Get_Func get); +EAPI void elm_map_marker_class_get_cb_set(Elm_Map_Marker_Class *clas, ElmMapMarkerGetFunc get); /** * Set the callback function used to delete bubble content of a marker class. @@ -976,7 +976,7 @@ EAPI void elm_map_marker_class_get_cb_set(Elm_Map_Marker_Class * * @ingroup Map */ -EAPI void elm_map_marker_class_del_cb_set(Elm_Map_Marker_Class *clas, Elm_Map_Marker_Del_Func del); +EAPI void elm_map_marker_class_del_cb_set(Elm_Map_Marker_Class *clas, ElmMapMarkerDelFunc del); /** * Get the list of available sources.