1 #include <Elementary.h>
10 * This is a widget specifically for displaying the map. It uses basically
11 * OpenStreetMap provider. but it can be added custom providers.
13 * Signals that you can add callbacks for are:
15 * "clicked" - This is called when a user has clicked the map without dragging
17 * "press" - This is called when a user has pressed down on the map.
18 * "longpressed" - This is called when a user has pressed down on the map for
19 * a long time without dragging around.
20 * "clicked,double" - This is called when a user has double-clicked the photo.
21 * "load,detail" - Map detailed data load begins.
22 * "loaded,detail" - This is called when all parts of the map are loaded.
23 * "zoom,start" - Zoom animation started.
24 * "zoom,stop" - Zoom animation stopped.
25 * "zoom,change" - Zoom changed when using an auto zoom mode.
26 * "scroll" - the content has been scrolled (moved)
27 * "scroll,anim,start" - scrolling animation has started
28 * "scroll,anim,stop" - scrolling animation has stopped
29 * "scroll,drag,start" - dragging the contents around has started
30 * "scroll,drag,stop" - dragging the contents around has stopped
31 * "downloaded" - This is called when map images are downloaded
32 * "route,load" - This is called when route request begins
33 * "route,loaded" - This is called when route request ends
39 typedef struct _Widget_Data Widget_Data;
40 typedef struct _Pan Pan;
41 typedef struct _Grid Grid;
42 typedef struct _Grid_Item Grid_Item;
43 typedef struct _Marker_Group Marker_Group;
44 typedef struct _Mod_Api Mod_Api;
45 typedef struct _Event Event;
46 typedef struct _Route_Node Route_Node;
47 typedef struct _Route_Waypoint Route_Waypoint;
48 typedef struct _Url_Data Url_Data;
49 typedef struct _Route_Dump Route_Dump;
51 #define DEST_DIR_ZOOM_PATH "/tmp/elm_map/%d/%d/"
52 #define DEST_DIR_PATH DEST_DIR_ZOOM_PATH"%d/"
53 #define DEST_FILE_PATH "%s%d.png"
54 #define MOD_AS "map/api"
55 #define DEST_XML_FILE "/tmp/elm_map-XXXXXX.xml"
57 #define ROUTE_YOURS_URL "http://www.yournavigation.org/api/dev/route.php"
58 #define ROUTE_TYPE_MOTORCAR "motocar"
59 #define ROUTE_TYPE_BICYCLE "bicycle"
60 #define ROUTE_TYPE_FOOT "foot"
61 #define YOURS_DISTANCE "distance"
62 #define YOURS_DESCRIPTION "description"
63 #define YOURS_COORDINATES "coordinates"
65 // TODO: fix monav & ors url
66 #define ROUTE_MONAV_URL "http://"
67 #define ROUTE_ORS_URL "http:///"
70 // Currently the size of a tile must be 256*256
71 // and the size of the map must be pow(2.0, z)*tile_size
72 typedef struct _Map_Sources_Tab
74 Elm_Map_Sources source;
78 ElmMapSourceURLFunc url_cb;
79 Elm_Map_Route_Sources route_source;
80 ElmMapRouteSourceURLFunc route_url_cb;
85 //Zemm min is supposed to be 0
86 static char *_mapnik_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom);
87 static char *_osmarender_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom);
88 static char *_cyclemap_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom);
89 static char *_maplint_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom);
90 static char *_module_url_cb(Evas_Object *obj, int x, int y, int zoom);
91 static char * _custom1_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom);
92 static char * _custom2_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom);
93 static char * _custom3_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom);
94 static char * _custom4_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom);
95 static char * _custom5_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom);
96 static char * _custom6_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom);
98 static char *_yours_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat);
100 static char *_monav_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat)
101 static char *_ors_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat);
103 static char *_route_custom1_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat);
104 static char *_route_custom2_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat);
105 static char *_route_custom3_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat);
106 static char *_route_custom4_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat);
107 static char *_route_custom5_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat);
108 static char *_route_custom6_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat);
110 static char *_route_module_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat);
113 static Map_Sources_Tab map_sources_tab[] =
115 {ELM_MAP_SOURCE_MAPNIK, "Mapnik", 0, 18, _mapnik_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb},
116 {ELM_MAP_SOURCE_OSMARENDER, "Osmarender", 0, 17, _osmarender_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb},
117 {ELM_MAP_SOURCE_CYCLEMAP, "Cycle Map", 0, 17, _cyclemap_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb},
118 {ELM_MAP_SOURCE_MAPLINT, "Maplint", 12, 16, _maplint_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb},
119 {ELM_MAP_SOURCE_CUSTOM_1, "Custom 1", 0, 18, _custom1_url_cb, ELM_MAP_ROUTE_SOURCE_CUSTOM_1, _route_custom1_url_cb},
120 {ELM_MAP_SOURCE_CUSTOM_2, "Custom 2", 0, 18, _custom2_url_cb, ELM_MAP_ROUTE_SOURCE_CUSTOM_2, _route_custom2_url_cb},
121 {ELM_MAP_SOURCE_CUSTOM_3, "Custom 3", 0, 18, _custom3_url_cb, ELM_MAP_ROUTE_SOURCE_CUSTOM_3, _route_custom3_url_cb},
122 {ELM_MAP_SOURCE_CUSTOM_4, "Custom 4", 0, 18, _custom4_url_cb, ELM_MAP_ROUTE_SOURCE_CUSTOM_4, _route_custom4_url_cb},
123 {ELM_MAP_SOURCE_CUSTOM_5, "Custom 5", 0, 18, _custom5_url_cb, ELM_MAP_ROUTE_SOURCE_CUSTOM_5, _route_custom5_url_cb},
124 {ELM_MAP_SOURCE_CUSTOM_6, "Custom 6", 0, 18, _custom6_url_cb, ELM_MAP_ROUTE_SOURCE_CUSTOM_6, _route_custom6_url_cb},
125 {ELM_MAP_SOURCE_MODULE, "Module", 0, 18, _module_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb}
130 Ecore_Con_Url *con_url;
136 struct _Elm_Map_Marker_Class
141 struct _Elm_Map_Marker_Class_Func {
142 ElmMapMarkerGetFunc get;
143 ElmMapMarkerDelFunc del; //if NULL the object will be destroyed with evas_object_del()
144 ElmMapMarkerIconGetFunc icon_get;
147 struct { //this part is private, do not modify these values
149 Evas_Coord edje_w, edje_h;
153 struct _Elm_Map_Marker
156 Elm_Map_Marker_Class *clas;
157 Elm_Map_Group_Class *clas_group;
158 double longitude, latitude;
161 Evas_Coord x[ZOOM_MAX+1], y[ZOOM_MAX+1];
164 Marker_Group *groups[ZOOM_MAX+1];
166 Evas_Object *content;
169 struct _Elm_Map_Group_Class
173 int zoom_displayed; // display the group if the zoom is >= to zoom_display
174 int zoom_grouped; // group the markers only if the zoom is <= to zoom_groups
178 ElmMapGroupIconGetFunc icon_get;
181 struct { //this part is private, do not modify these values
183 Evas_Coord edje_w, edje_h;
184 Evas_Coord edje_max_w, edje_max_h;
186 Eina_List *objs_used;
187 Eina_List *objs_notused;
194 Eina_Matrixsparse_Cell *cell;
195 Elm_Map_Group_Class *clas;
198 long long sum_x, sum_y;
202 Evas_Object *obj, *bubble, *sc, *bx, *rect;
204 Eina_Bool bringin : 1;
205 Eina_Bool update_nbelems : 1;
206 Eina_Bool update_resize : 1;
207 Eina_Bool update_raise : 1;
208 Eina_Bool delete_object : 1;
211 struct _Elm_Map_Route
217 Ecore_Con_Url *con_url;
222 double flon, flat, tlon, tlat;
224 Eina_List *nodes, *path;
231 const char *waypoints;
232 double distance; /* unit : km */
245 Eina_Bool inbound : 1;
259 struct _Route_Waypoint
276 Eina_Bool download : 1;
278 Ecore_File_Download_Job *job;
285 int tsize; // size of tile (tsize x tsize pixels)
286 int zoom; // zoom level tiles want for optimal display (1, 2, 4, 8)
287 int iw, ih; // size of image in pixels
288 int w, h; // size of grid image in pixels (represented by grid)
289 int gw, gh; // size of grid in tiles
290 Eina_Matrixsparse *grid;
297 Evas_Object *pan_smart;
299 Evas_Object *sep_maps_markers; //map objects are below this object and marker objects are on top
301 Evas_Coord pan_x, pan_y, minw, minh;
306 Elm_Map_Zoom_Mode mode;
309 Ecore_Timer *scr_timer;
310 Ecore_Timer *long_timer;
311 Ecore_Animator *zoom_animator;
312 double t_start, t_end;
322 Evas_Coord x, y ,w ,h;
328 Eina_Bool resized : 1;
329 Eina_Bool longpressed : 1;
330 Eina_Bool on_hold : 1;
331 Eina_Bool paused : 1;
332 Eina_Bool paused_markers : 1;
333 Eina_Bool pinch_zoom : 1;
340 Ecore_Job *markers_place_job;
341 Eina_Matrixsparse *markers[ZOOM_MAX+1];
342 Eina_List *cells_displayed; // list of Eina_Matrixsparse_Cell
343 Evas_Coord markers_max_num;
344 int marker_max_w, marker_max_h;
346 Eina_List *opened_bubbles; //opened bubbles, list of Map_Group *
348 Eina_List *groups_clas; // list of Elm_Map_Group_Class*
349 Eina_List *markers_clas; // list of Elm_Map_Markers_Class*
351 Elm_Map_Sources source;
352 Elm_Map_Route_Sources route_source;
354 Eina_List *s_event_list;
359 const char *user_agent;
365 Eina_Bool (*obj_hook) (Evas_Object *obj);
366 Eina_Bool (*obj_unhook) (Evas_Object *obj);
367 char * (*obj_url_request) (Evas_Object *obj, int x, int y, int zoom);
368 Eina_Bool (*obj_convert_coord_into_geo) (const Evas_Object *obj, int zoom, int x, int y, int size, double *lon, double *lat);
369 Eina_Bool (*obj_convert_geo_into_coord) (const Evas_Object *obj, int zoom, double lon, double lat, int size, int *x, int *y);
373 Evas_Object_Smart_Clipped_Data __clipped_data;
385 Evas_Coord x, y, w, h;
388 Ecore_Timer *hold_timer;
402 enum _Route_Xml_Attribute
406 ROUTE_XML_DESCRIPTION,
407 ROUTE_XML_COORDINATES,
409 } Route_Xml_Attibute;
411 static int dis_old = 0;
412 static const char *widtype = NULL;
414 static const char SIG_CHANGED[] = "changed";
415 static const char SIG_CLICKED[] = "clicked";
416 static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
417 static const char SIG_LOADED_DETAIL[] = "loaded,detail";
418 static const char SIG_LOAD_DETAIL[] = "load,detail";
419 static const char SIG_LONGPRESSED[] = "longpressed";
420 static const char SIG_PRESS[] = "press";
421 static const char SIG_SCROLL[] = "scroll";
422 static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start";
423 static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop";
424 static const char SIG_ZOOM_CHANGE[] = "zoom,change";
425 static const char SIG_ZOOM_START[] = "zoom,start";
426 static const char SIG_ZOOM_STOP[] = "zoom,stop";
427 static const char SIG_DOWNLOADED[] = "downloaded";
428 static const char SIG_ROUTE_LOAD[] = "route,load";
429 static const char SIG_ROUTE_LOADED[] = "route,loaded";
430 static const Evas_Smart_Cb_Description _signals[] = {
433 {SIG_CLICKED_DOUBLE, ""},
434 {SIG_LOADED_DETAIL, ""},
435 {SIG_LOAD_DETAIL, ""},
436 {SIG_LONGPRESSED, ""},
439 {SIG_SCROLL_DRAG_START, ""},
440 {SIG_SCROLL_DRAG_STOP, ""},
441 {SIG_ZOOM_CHANGE, ""},
442 {SIG_ZOOM_START, ""},
444 {SIG_DOWNLOADED, ""},
445 {SIG_ROUTE_LOAD, ""},
446 {SIG_ROUTE_LOADED, ""},
450 static void _pan_calculate(Evas_Object *obj);
452 static Eina_Bool _hold_timer_cb(void *data);
453 static void _rect_resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
454 static void _del_hook(Evas_Object *obj);
455 static void _theme_hook(Evas_Object *obj);
456 static void _on_focus_hook(void *data, Evas_Object *obj);
457 static void _sizing_eval(Evas_Object *obj);
458 static void _calc_job(void *data);
459 static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
460 Evas_Callback_Type type, void *event_info);
461 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);
462 static void grid_clear(Evas_Object *obj, Grid *g);
463 static Grid *grid_create(Evas_Object *obj);
464 static void grid_load(Evas_Object *obj, Grid *g);
467 static void _group_object_create(Marker_Group *group);
468 static void _group_object_free(Marker_Group *group);
469 static void _group_open_cb(void *data, Evas_Object *obj, const char *emission, const char *soure);
470 static void _group_bringin_cb(void *data, Evas_Object *obj, const char *emission, const char *soure);
471 static void _group_bubble_create(Marker_Group *group);
472 static void _group_bubble_free(Marker_Group *group);
473 static void _group_bubble_place(Marker_Group *group);
475 static int _group_bubble_content_update(Marker_Group *group);
476 static void _group_bubble_content_free(Marker_Group *group);
477 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);
478 static void _bubble_sc_hits_changed_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
480 static void _mouse_down(void *data, Evas *evas, Evas_Object *obj, void *event_info);
481 static void _mouse_up(void *data, Evas *evas, Evas_Object *obj, void *event_info);
482 static void _mouse_move(void *data, Evas *evas, Evas_Object *obj, void *event_info);
484 static void _mouse_multi_down(void *data, Evas *evas, Evas_Object *obj, void *event_info);
485 static void _mouse_multi_up(void *data, Evas *evas, Evas_Object *obj, void *event_info);
486 static void _mouse_multi_move(void *data, Evas *evas, Evas_Object *obj, void *event_info);
488 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);
491 get_multi_device(Evas_Object *obj)
493 Widget_Data *wd = elm_widget_data_get(obj);
497 EINA_LIST_FOREACH(wd->s_event_list, l, ev)
499 if (ev->device) return ev->device;
505 get_distance(Evas_Coord x1, Evas_Coord y1, Evas_Coord x2, Evas_Coord y2)
509 return sqrt((dx * dx) + (dy * dy));
513 create_event_object(void *data, Evas_Object *obj, int device)
515 Widget_Data *wd = elm_widget_data_get(data);
516 Event *ev = calloc(1, sizeof(Event));
518 EINA_SAFETY_ON_NULL_RETURN_VAL(ev, NULL);
522 evas_object_geometry_get(obj, &ev->x, &ev->y, &ev->w, &ev->h);
523 wd->s_event_list = eina_list_append(wd->s_event_list, ev);
528 get_event_object(void *data, int device)
530 Widget_Data *wd = elm_widget_data_get(data);
534 EINA_LIST_FOREACH(wd->s_event_list, l, ev)
536 if (ev->device == device) break;
543 destroy_event_object(void *data, Event *ev)
545 Widget_Data *wd = elm_widget_data_get(data);
546 EINA_SAFETY_ON_NULL_RETURN(ev);
548 wd->s_event_list = eina_list_remove(wd->s_event_list, ev);
551 ecore_timer_del(ev->hold_timer);
552 ev->hold_timer = NULL;
558 module(Evas_Object *obj)
560 Widget_Data *wd = elm_widget_data_get(obj);
565 Mod_Api *api = wd->m->api;
566 if ((api) && (api->obj_unhook)) api->obj_unhook(obj);
567 _elm_module_del(wd->m);
571 p = _elm_config->modules;
575 if ((*pe == ':') || (!*pe))
579 char *n = malloc(pe - p + 1);
584 strncpy(n, p, pe - p);
591 if (!strcmp(nn, MOD_AS))
593 wd->m = _elm_module_add(n, nn);
594 _elm_module_load(wd->m);
609 if (!wd->m->api) wd->m->api = malloc(sizeof(Mod_Api));
610 ((Mod_Api *)(wd->m->api) )->obj_hook =
611 _elm_module_symbol_get(wd->m, "obj_hook");
612 ((Mod_Api *)(wd->m->api) )->obj_unhook =
613 _elm_module_symbol_get(wd->m, "obj_unhook");
614 ((Mod_Api *)(wd->m->api) )->obj_url_request =
615 _elm_module_symbol_get(wd->m, "obj_url_request");
616 ((Mod_Api *)(wd->m->api) )->obj_convert_coord_into_geo =
617 _elm_module_symbol_get(wd->m, "obj_convert_coord_into_geo");
618 ((Mod_Api *)(wd->m->api) )->obj_convert_geo_into_coord =
619 _elm_module_symbol_get(wd->m, "obj_convert_geo_into_coord");
623 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)
625 ELM_CHECK_WIDTYPE(obj, widtype);
626 Widget_Data *wd = elm_widget_data_get(obj);
629 Eina_List *lr, *lp, *ln;
635 Evas_Coord size = pow(2.0, wd->zoom)*wd->tsize;
637 EINA_LIST_FOREACH(wd->route, lr, r)
639 EINA_LIST_FOREACH(r->path, lp, p)
644 evas_object_geometry_get(wd->rect, &rx, &ry, NULL, NULL);
645 nodes = eina_list_count(r->nodes);
647 EINA_LIST_FOREACH(r->nodes, ln, n)
649 if ((!wd->zoom) || ((n->idx) &&
650 ((n->idx % (int)ceil((double)nodes/(double)size*100.0))))) continue;
653 elm_map_utils_convert_geo_into_coord(wd->obj, n->pos.lon, n->pos.lat, size, &x, &y);
654 if ((x >= px - ow) && (x <= (px + ow*2)) &&
655 (y >= py - oh) && (y <= (py + oh*2)))
660 p = eina_list_nth(r->path, n->idx);
661 evas_object_line_xy_set(p, r->x, r->y, x, y);
662 evas_object_color_set(p, r->color.r, r->color.g, r->color.b, r->color.a);
663 evas_object_raise(p);
668 else r->inbound = EINA_FALSE;
672 elm_map_utils_convert_geo_into_coord(wd->obj, n->pos.lon, n->pos.lat, size, &x, &y);
673 if ((x >= px - ow) && (x <= (px + ow*2)) &&
674 (y >= py - oh) && (y <= (py + oh*2)))
678 r->inbound = EINA_TRUE;
680 else r->inbound = EINA_FALSE;
683 r->inbound = EINA_FALSE;
688 rect_place(Evas_Object *obj, Evas_Coord px, Evas_Coord py, Evas_Coord ox, Evas_Coord oy, Evas_Coord ow, Evas_Coord oh)
690 Widget_Data *wd = elm_widget_data_get(obj);
691 Evas_Coord ax, ay, gw, gh, hh, ww;
693 evas_object_geometry_get(wd->rect, NULL, NULL, &ww, &hh);
700 if ((ww == gw) && (hh == gh)) return;
702 if (ow > gw) ax = (ow - gw) / 2;
703 if (oh > gh) ay = (oh - gh) / 2;
704 evas_object_move(wd->rect,
707 evas_object_resize(wd->rect, gw, gh);
711 wd->show.show = EINA_FALSE;
712 elm_smart_scroller_child_region_show(wd->scr, wd->show.x, wd->show.y, wd->show.w, wd->show.h);
717 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)
719 Widget_Data *wd = elm_widget_data_get(obj);
720 Evas_Coord ax, ay, gw, gh, tx, ty;
721 Eina_List *l, *markers;
722 Eina_Matrixsparse_Cell *cell;
727 int g_xx, g_yy, g_hh, g_ww;
730 if (g != eina_list_data_get(wd->grids)) return;
736 if (ow > gw) ax = (ow - gw) / 2;
737 if (oh > gh) ay = (oh - gh) / 2;
739 if (wd->zoom != wd->marker_zoom)
741 EINA_LIST_FREE(wd->cells_displayed, cell)
743 EINA_LIST_FOREACH(eina_matrixsparse_cell_data_get(cell), l, group)
745 if (group->obj) _group_object_free(group);
749 wd->marker_zoom = wd->zoom;
751 if ((wd->paused_markers)
752 && ((wd->size.nw != wd->size.w) || (wd->size.nh != wd->size.h)) )
755 g_xx = wd->pan_x / wd->tsize;
756 if (g_xx < 0) g_xx = 0;
757 g_yy = wd->pan_y / wd->tsize;
758 if (g_yy < 0) g_yy = 0;
759 g_ww = ow / wd->tsize + 1;
760 if (g_xx + g_ww >= g->gw) g_ww = g->gw - g_xx - 1;
761 g_hh = oh / wd->tsize + 1;
762 if (g_yy + g_hh >= g->gh) g_hh = g->gh - g_yy - 1;
764 //hide groups no more displayed
765 EINA_LIST_FREE(wd->cells_displayed, cell)
767 eina_matrixsparse_cell_position_get(cell, (unsigned long *)&y, (unsigned long *)&x);
768 if ((y < g_yy) || (y > g_yy + g_hh) || (x < g_xx) || (x > g_xx + g_ww))
770 EINA_LIST_FOREACH(eina_matrixsparse_cell_data_get(cell), l, group)
772 if (group->obj) _group_object_free(group);
777 for (y = g_yy; y <= g_yy + g_hh; y++)
779 for (x = g_xx; x <= g_xx + g_ww; x++)
781 if (!wd->markers[wd->zoom]) continue;
782 eina_matrixsparse_cell_idx_get(wd->markers[wd->zoom], y, x, &cell);
784 wd->cells_displayed = eina_list_append(wd->cells_displayed, cell);
785 markers = eina_matrixsparse_cell_data_get(cell);
786 EINA_LIST_FOREACH(markers, l, group)
788 if (!group->markers) continue;
789 if (group->clas->zoom_displayed > wd->zoom) continue;
796 if (eina_list_count(group->markers) == 1)
798 Elm_Map_Marker *m = eina_list_data_get(group->markers);
799 ww = m->clas->priv.edje_w;
800 hh = m->clas->priv.edje_h;
806 if ((gw != g->w) && (g->w > 0))
809 xx = ((long long )gw * xx) / g->w;
810 ww = (((long long)gw * (tx + ww)) / g->w) - xx;
812 if ((gh != g->h) && (g->h > 0))
815 yy = ((long long)gh * yy) / g->h;
816 hh = (((long long)gh * (ty + hh)) / g->h) - yy;
819 if ((!group->clas->hide)
820 && (xx-px+ax+ox >= ox) && (xx-px+ax+ox<= ox+ow)
821 && (yy-py+ay+oy >= oy) && (yy-py+ay+oy<= oy+oh))
823 if (!group->obj) _group_object_create(group);
825 if (group->update_nbelems)
827 group->update_nbelems = EINA_FALSE;
828 if (eina_list_count(group->markers) > 1)
830 snprintf(buf, sizeof(buf), "%d", eina_list_count(group->markers));
831 edje_object_part_text_set(elm_layout_edje_get(group->obj), "elm.text", buf);
834 edje_object_part_text_set(elm_layout_edje_get(group->obj), "elm.text", "");
836 evas_object_move(group->obj,
837 xx - px + ax + ox - ww/2,
838 yy - py + ay + oy - hh/2);
839 if ((!wd->paused_markers) || (group->update_resize))
841 group->update_resize = EINA_FALSE;
842 evas_object_resize(group->obj, ww, hh);
844 if (group->update_raise)
846 group->update_raise = EINA_FALSE;
847 evas_object_raise(group->obj);
848 evas_object_show(group->obj);
850 if (group->bubble) _group_bubble_place(group);
854 _group_object_free(group);
862 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)
864 Widget_Data *wd = elm_widget_data_get(obj);
865 Evas_Coord ax, ay, gw, gh, tx, ty;
874 if (ow > gw) ax = (ow - gw) / 2;
875 if (oh > gh) ay = (oh - gh) / 2;
877 Eina_Iterator *it = eina_matrixsparse_iterator_new(g->grid);
878 Eina_Matrixsparse_Cell *cell;
880 EINA_ITERATOR_FOREACH(it, cell)
882 Grid_Item *gi = eina_matrixsparse_cell_data_get(cell);
888 if ((gw != g->w) && (g->w > 0))
891 xx = ((long long )gw * xx) / g->w;
892 ww = (((long long)gw * (tx + ww)) / g->w) - xx;
894 if ((gh != g->h) && (g->h > 0))
897 yy = ((long long)gh * yy) / g->h;
898 hh = (((long long)gh * (ty + hh)) / g->h) - yy;
900 evas_object_move(gi->img,
904 evas_object_resize(gi->img, ww, hh);
906 /*evas_object_move(gi->txt,
910 evas_object_resize(gi->txt, ww, hh);
913 eina_iterator_free(it);
917 grid_clear(Evas_Object *obj, Grid *g)
919 Widget_Data *wd = elm_widget_data_get(obj);
923 if (!g->grid) return;
925 Eina_Iterator *it = eina_matrixsparse_iterator_new(g->grid);
926 Eina_Matrixsparse_Cell *cell;
928 snprintf(buf, sizeof(buf), DEST_DIR_ZOOM_PATH, wd->id, g->zoom);
929 ecore_file_recursive_rm(buf);
931 EINA_ITERATOR_FOREACH(it, cell)
933 Grid_Item *gi = eina_matrixsparse_cell_data_get(cell);
934 evas_object_del(gi->img);
935 //evas_object_del(gi->txt);
939 gi->want = EINA_FALSE;
941 if (!wd->preload_num)
943 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
944 "elm,state,busy,stop", "elm");
945 evas_object_smart_callback_call(obj, SIG_LOADED_DETAIL, NULL);
951 DBG("DOWNLOAD abort %s", gi->file);
952 ecore_file_download_abort(gi->job);
953 ecore_file_remove(gi->file);
958 eina_stringshare_del(gi->file);
962 eina_matrixsparse_free(g->grid);
963 eina_iterator_free(it);
970 _tile_update(Grid_Item *gi)
972 gi->want = EINA_FALSE;
973 gi->download = EINA_FALSE;
974 evas_object_image_file_set(gi->img, gi->file, NULL);
975 if (evas_object_image_load_error_get(gi->img) != EVAS_LOAD_ERROR_NONE)
976 ecore_file_remove(gi->file);
978 evas_object_show(gi->img);
980 //evas_object_text_text_set(gi->txt, gi->file);
981 //evas_object_show(gi->txt);
983 gi->have = EINA_TRUE;
984 gi->wd->preload_num--;
985 if (!gi->wd->preload_num)
987 edje_object_signal_emit(elm_smart_scroller_edje_object_get(gi->wd->scr),
988 "elm,state,busy,stop", "elm");
989 evas_object_smart_callback_call(gi->wd->obj, SIG_LOADED_DETAIL, NULL);
995 _tile_downloaded(void *data, const char *file __UNUSED__, int status)
997 Grid_Item *gi = data;
999 gi->download = EINA_FALSE;
1002 DBG("DOWNLOAD done %s", gi->file);
1003 if ((gi->want) && (!status)) _tile_update(gi);
1007 DBG("Download failed %s (%d) ", gi->file, status);
1008 ecore_file_remove(gi->file);
1011 gi->wd->finish_num++;
1013 evas_object_smart_callback_call(gi->wd->obj, SIG_DOWNLOADED, NULL);
1017 grid_create(Evas_Object *obj)
1019 Widget_Data *wd = elm_widget_data_get(obj);
1022 g = calloc(1, sizeof(Grid));
1025 g->tsize = wd->tsize;
1028 if (g->zoom > map_sources_tab[wd->source].zoom_max) return NULL;
1029 if (g->zoom < map_sources_tab[wd->source].zoom_min) return NULL;
1031 int size = pow(2.0, wd->zoom);
1035 g->w = g->tsize * g->gw;
1036 g->h = g->tsize * g->gh;
1038 g->grid = eina_matrixsparse_new(g->gh, g->gw, NULL, NULL);
1044 grid_load(Evas_Object *obj, Grid *g)
1046 Widget_Data *wd = elm_widget_data_get(obj);
1049 Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh, tx, ty, gw, gh, xx, yy, ww, hh;
1051 Eina_Matrixsparse_Cell *cell;
1055 evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
1056 evas_output_viewport_get(evas_object_evas_get(wd->obj), &cvx, &cvy, &cvw, &cvh);
1061 if ((gw <= 0) || (gh <= 0)) return;
1064 if ((gw != g->w) && (g->w > 0))
1065 size = ((long long)gw * size) / g->w;
1066 if (size < (g->tsize / 2)) return; // else we will load to much tiles
1068 it = eina_matrixsparse_iterator_new(g->grid);
1070 EINA_ITERATOR_FOREACH(it, cell)
1072 gi = eina_matrixsparse_cell_data_get(cell);
1079 if ((gw != g->w) && (g->w > 0))
1082 xx = ((long long )gw * xx) / g->w;
1083 ww = (((long long)gw * (tx + ww)) / g->w) - xx;
1085 if ((gh != g->h) && (g->h > 0))
1088 yy = ((long long)gh * yy) / g->h;
1089 hh = (((long long)gh * (ty + hh)) / g->h) - yy;
1092 if (!ELM_RECTS_INTERSECT(xx - wd->pan_x + ox,
1093 yy - wd->pan_y + oy,
1095 cvx, cvy, cvw, cvh))
1099 evas_object_hide(gi->img);
1100 //evas_object_hide(gi->txt);
1101 evas_object_image_file_set(gi->img, NULL, NULL);
1102 gi->want = EINA_FALSE;
1103 gi->have = EINA_FALSE;
1107 DBG("DOWNLOAD abort %s", gi->file);
1108 ecore_file_download_abort(gi->job);
1109 ecore_file_remove(gi->file);
1113 gi->download = EINA_FALSE;
1115 if (!wd->preload_num)
1117 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
1118 "elm,state,busy,stop", "elm");
1119 evas_object_smart_callback_call(obj, SIG_LOADED_DETAIL,
1126 evas_object_hide(gi->img);
1127 //evas_object_hide(gi->txt);
1128 evas_object_image_preload(gi->img, 1);
1129 evas_object_image_file_set(gi->img, NULL, NULL);
1130 gi->have = EINA_FALSE;
1131 gi->want = EINA_FALSE;
1135 eina_iterator_free(it);
1137 xx = wd->pan_x / size;
1140 yy = wd->pan_y / size;
1144 if (xx + ww >= g->gw) ww = g->gw - xx - 1;
1147 if (yy + hh >= g->gh) hh = g->gh - yy - 1;
1149 for (y = yy; y <= yy + hh; y++)
1151 for (x = xx; x <= xx + ww; x++)
1153 gi = eina_matrixsparse_data_idx_get(g->grid, y, x);
1155 if ((!gi) && (g != eina_list_data_get(wd->grids)))
1160 gi = calloc(1, sizeof(Grid_Item));
1161 gi->src.x = x * g->tsize;
1162 gi->src.y = y * g->tsize;
1163 gi->src.w = g->tsize;
1164 gi->src.h = g->tsize;
1166 gi->out.x = gi->src.x;
1167 gi->out.y = gi->src.y;
1168 gi->out.w = gi->src.w;
1169 gi->out.h = gi->src.h;
1173 gi->img = evas_object_image_add(evas_object_evas_get(obj));
1174 evas_object_image_scale_hint_set
1175 (gi->img, EVAS_IMAGE_SCALE_HINT_DYNAMIC);
1176 evas_object_image_filled_set(gi->img, 1);
1178 evas_object_smart_member_add(gi->img, wd->pan_smart);
1179 elm_widget_sub_object_add(obj, gi->img);
1180 evas_object_pass_events_set(gi->img, EINA_TRUE);
1181 evas_object_stack_below(gi->img, wd->sep_maps_markers);
1183 /* gi->txt = evas_object_text_add(evas_object_evas_get(obj));
1184 evas_object_text_font_set(gi->txt, "Vera", 12);
1185 evas_object_color_set(gi->txt, 100, 100, 100, 255);
1186 evas_object_smart_member_add(gi->txt,
1188 elm_widget_sub_object_add(obj, gi->txt);
1189 evas_object_pass_events_set(gi->txt, EINA_TRUE);
1191 eina_matrixsparse_data_idx_set(g->grid, y, x, gi);
1194 if ((!gi->have) && (!gi->download))
1196 char buf[PATH_MAX], buf2[PATH_MAX];
1199 gi->want = EINA_TRUE;
1201 snprintf(buf, sizeof(buf), DEST_DIR_PATH, wd->id, g->zoom, x);
1202 if (!ecore_file_exists(buf))
1203 ecore_file_mkpath(buf);
1205 snprintf(buf2, sizeof(buf2), DEST_FILE_PATH, buf, y);
1207 source = map_sources_tab[wd->source].url_cb(obj, x, y, g->zoom);
1208 if ((!source) || (strlen(source)==0)) continue;
1210 eina_stringshare_replace(&gi->file, buf2);
1212 if ((ecore_file_exists(buf2)) || (g == eina_list_data_get(wd->grids)))
1214 gi->download = EINA_TRUE;
1216 if (wd->preload_num == 1)
1218 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
1219 "elm,state,busy,start", "elm");
1220 evas_object_smart_callback_call(obj,
1225 if (ecore_file_exists(buf2))
1229 DBG("DOWNLOAD %s \t in %s", source, buf2);
1230 ecore_file_download_full(source, buf2, _tile_downloaded, NULL, gi, &(gi->job), wd->ua);
1232 DBG("Can't start to download %s", buf);
1237 if (source) free(source);
1240 evas_object_show(gi->img);
1246 grid_clearall(Evas_Object *obj)
1248 Widget_Data *wd = elm_widget_data_get(obj);
1252 EINA_LIST_FREE(wd->grids, g)
1260 _smooth_update(Evas_Object *obj)
1262 Widget_Data *wd = elm_widget_data_get(obj);
1267 EINA_LIST_FOREACH(wd->grids, l, g)
1269 Eina_Iterator *it = eina_matrixsparse_iterator_new(g->grid);
1270 Eina_Matrixsparse_Cell *cell;
1272 EINA_ITERATOR_FOREACH(it, cell)
1274 Grid_Item *gi = eina_matrixsparse_cell_data_get(cell);
1275 evas_object_image_smooth_scale_set(gi->img, (!wd->nosmooth));
1277 eina_iterator_free(it);
1282 _grid_raise(Grid *g)
1284 Eina_Iterator *it = eina_matrixsparse_iterator_new(g->grid);
1285 Eina_Matrixsparse_Cell *cell;
1287 g->wd->size.w = g->w;
1288 g->wd->size.h = g->h;
1290 EINA_ITERATOR_FOREACH(it, cell)
1292 Grid_Item *gi = eina_matrixsparse_cell_data_get(cell);
1293 evas_object_raise(gi->img);
1294 //evas_object_raise(gi->txt);
1296 eina_iterator_free(it);
1300 _scr_timeout(void *data)
1302 Widget_Data *wd = elm_widget_data_get(data);
1303 if (!wd) return ECORE_CALLBACK_CANCEL;
1305 if (!wd->nosmooth) _smooth_update(data);
1306 wd->scr_timer = NULL;
1307 return ECORE_CALLBACK_CANCEL;
1311 _scr(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1313 Widget_Data *wd = elm_widget_data_get(data);
1318 if (wd->nosmooth == 1) _smooth_update(data);
1320 if (wd->scr_timer) ecore_timer_del(wd->scr_timer);
1321 wd->scr_timer = ecore_timer_add(0.5, _scr_timeout, data);
1325 zoom_do(Evas_Object *obj, double t)
1327 Widget_Data *wd = elm_widget_data_get(obj);
1328 Evas_Coord xx, yy, ow, oh;
1331 if (t > 1.0) t = 1.0;
1333 wd->size.w = (wd->size.ow * (1.0 - t)) + (wd->size.nw * t);
1334 wd->size.h = (wd->size.oh * (1.0 - t)) + (wd->size.nh * t);
1336 elm_smart_scroller_child_viewport_size_get(wd->scr, &ow, &oh);
1338 if (wd->center_on.enabled)
1340 elm_map_utils_convert_geo_into_coord(obj, wd->center_on.lon, wd->center_on.lat, wd->size.w, &xx, &yy);
1346 xx = (wd->size.spos.x * wd->size.w) - (ow / 2);
1347 yy = (wd->size.spos.y * wd->size.h) - (oh / 2);
1351 else if (xx > (wd->size.w - ow)) xx = wd->size.w - ow;
1353 else if (yy > (wd->size.h - oh)) yy = wd->size.h - oh;
1355 wd->show.show = EINA_TRUE;
1361 if (wd->calc_job) ecore_job_del(wd->calc_job);
1362 wd->calc_job = ecore_job_add(_calc_job, wd);
1365 return ECORE_CALLBACK_CANCEL;
1367 return ECORE_CALLBACK_RENEW;
1371 _zoom_anim(void *data)
1373 Evas_Object *obj = data;
1374 Widget_Data *wd = elm_widget_data_get(obj);
1378 if (!wd) return ECORE_CALLBACK_CANCEL;
1379 t = ecore_loop_time_get();
1382 else if (wd->t_end > wd->t_start)
1383 t = (t - wd->t_start) / (wd->t_end - wd->t_start);
1388 go = zoom_do(obj, t);
1392 if (!wd->nosmooth) _smooth_update(data);
1393 wd->zoom_animator = NULL;
1394 evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL);
1400 _long_press(void *data)
1402 Widget_Data *wd = elm_widget_data_get(data);
1403 if (!wd) return ECORE_CALLBACK_CANCEL;
1404 wd->long_timer = NULL;
1405 wd->longpressed = EINA_TRUE;
1406 evas_object_smart_callback_call(data, SIG_LONGPRESSED, NULL);
1407 return ECORE_CALLBACK_CANCEL;
1411 _mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info)
1413 Widget_Data *wd = elm_widget_data_get(data);
1414 Evas_Event_Mouse_Down *ev = event_info;
1417 ev0 = get_event_object(data, 0);
1419 ev0 = create_event_object(data, obj, 0);
1422 ev0->hold_timer = NULL;
1423 ev0->prev.x = ev->output.x;
1424 ev0->prev.y = ev->output.y;
1427 if (ev->button != 1) return;
1428 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) wd->on_hold = EINA_TRUE;
1429 else wd->on_hold = EINA_FALSE;
1430 if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
1431 evas_object_smart_callback_call(data, SIG_CLICKED_DOUBLE, ev);
1433 evas_object_smart_callback_call(data, SIG_PRESS, ev);
1434 wd->longpressed = EINA_FALSE;
1435 if (wd->long_timer) ecore_timer_del(wd->long_timer);
1436 wd->long_timer = ecore_timer_add(_elm_config->longpress_timeout, _long_press, data);
1440 _mouse_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1442 Evas_Event_Mouse_Move *move = event_info;
1445 ev0 = get_event_object(data, 0);
1447 ev0->prev.x = move->cur.output.x;
1448 ev0->prev.y = move->cur.output.y;
1452 _mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1454 Widget_Data *wd = elm_widget_data_get(data);
1455 Evas_Event_Mouse_Up *ev = event_info;
1460 ev0 = get_event_object(data, 0);
1463 mdevice = get_multi_device(data);
1466 if (ev0->hold_timer)
1468 ecore_timer_del(ev0->hold_timer);
1469 ev0->hold_timer = NULL;
1471 elm_smart_scroller_hold_set(wd->scr, 0);
1472 elm_smart_scroller_freeze_set(wd->scr, 0);
1473 wd->pinch_zoom = EINA_FALSE;
1477 ev1 = get_event_object(data, mdevice);
1479 ev1->hold_timer = ecore_timer_add(0.35, _hold_timer_cb, ev1);
1481 destroy_event_object(data, ev0);
1485 if (ev->button != 1) return;
1486 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) wd->on_hold = EINA_TRUE;
1487 else wd->on_hold = EINA_FALSE;
1490 ecore_timer_del(wd->long_timer);
1491 wd->long_timer = NULL;
1493 if (!wd->on_hold) evas_object_smart_callback_call(data, SIG_CLICKED, ev);
1494 wd->on_hold = EINA_FALSE;
1498 _mouse_multi_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info)
1500 Widget_Data *wd = elm_widget_data_get(data);
1502 Evas_Event_Multi_Down *down = event_info;
1504 elm_smart_scroller_hold_set(wd->scr, 1);
1505 elm_smart_scroller_freeze_set(wd->scr, 1);
1507 ev = get_event_object(data, down->device);
1510 ev = create_event_object(data, obj, down->device);
1513 DBG("Failed : create_event_object");
1517 wd->pinch_zoom = EINA_FALSE;
1519 ev->hold_timer = NULL;
1520 ev->prev.x = down->output.x;
1521 ev->prev.y = down->output.y;
1528 _mouse_multi_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1530 Widget_Data *wd = elm_widget_data_get(data);
1531 Evas_Event_Multi_Move *move = event_info;
1536 ev = get_event_object(data, move->device);
1539 ev->prev.x = move->cur.output.x;
1540 ev->prev.y = move->cur.output.y;
1542 ev0 = get_event_object(data, 0);
1545 dis_new = get_distance(ev0->prev.x, ev0->prev.y, ev->prev.x, ev->prev.y);
1550 if (((dis_old - dis_new) > 0) &&
1551 (ev->pinch_dis > elm_finger_size_get()*5))
1553 wd->pinch_zoom = EINA_TRUE;
1555 elm_map_zoom_set(data, zoom);
1558 else if (((dis_old - dis_new) < 0) &&
1559 (ev->pinch_dis < -elm_finger_size_get()*5))
1561 wd->pinch_zoom = EINA_TRUE;
1563 elm_map_zoom_set(data, zoom);
1566 ev->pinch_dis += (dis_old - dis_new);
1572 _mouse_multi_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1574 Evas_Event_Multi_Up *up = event_info;
1578 ev = get_event_object(data, up->device);
1581 DBG("Cannot get multi device");
1586 ev0 = get_event_object(data, 0);
1588 ev0->hold_timer = ecore_timer_add(0.35, _hold_timer_cb, ev0);
1593 ecore_timer_del(ev->hold_timer);
1594 ev->hold_timer = NULL;
1597 destroy_event_object(data, ev);
1600 static Evas_Smart_Class _pan_sc = EVAS_SMART_CLASS_INIT_NULL;
1603 _hold_timer_cb(void *data)
1607 ev0->hold_timer = NULL;
1608 return ECORE_CALLBACK_CANCEL;
1612 _rect_resize_cb(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1614 Widget_Data *wd = elm_widget_data_get(data);
1617 evas_object_geometry_get(wd->rect, &x, &y, &w, &h);
1618 evas_object_geometry_get(wd->pan_smart, &x, &y, &w, &h);
1619 evas_object_resize(wd->rect, w, h);
1620 evas_object_move(wd->rect, x, y);
1624 _del_hook(Evas_Object *obj)
1626 Elm_Map_Group_Class *group_clas;
1627 Elm_Map_Marker_Class *marker_clas;
1628 Widget_Data *wd = elm_widget_data_get(obj);
1634 Ecore_Event_Handler *h;
1639 EINA_LIST_FREE(wd->groups_clas, group_clas)
1641 if (group_clas->style)
1642 eina_stringshare_del(group_clas->style);
1646 EINA_LIST_FREE(wd->markers_clas, marker_clas)
1648 if (marker_clas->style)
1649 eina_stringshare_del(marker_clas->style);
1653 EINA_LIST_FOREACH(wd->s_event_list, l, ev)
1655 destroy_event_object(obj, ev);
1658 EINA_LIST_FOREACH(wd->route, l, r)
1660 EINA_LIST_FREE(r->path, p)
1665 EINA_LIST_FREE(r->waypoint, w)
1667 if (w->point) eina_stringshare_del(w->point);
1671 EINA_LIST_FREE(r->nodes, n)
1673 if (n->pos.address) eina_stringshare_del(n->pos.address);
1677 EINA_LIST_FREE(r->handlers, h)
1679 ecore_event_handler_del(h);
1682 if (r->con_url) ecore_con_url_free(r->con_url);
1683 if (r->info.nodes) eina_stringshare_del(r->info.nodes);
1684 if (r->info.waypoints) eina_stringshare_del(r->info.waypoints);
1686 if (wd->calc_job) ecore_job_del(wd->calc_job);
1687 if (wd->scr_timer) ecore_timer_del(wd->scr_timer);
1688 if (wd->zoom_animator) ecore_animator_del(wd->zoom_animator);
1689 if (wd->long_timer) ecore_timer_del(wd->long_timer);
1690 if ((wd->m) && (wd->m->api))
1692 Mod_Api *api = wd->m->api;
1693 if (api->obj_unhook) api->obj_unhook(obj);
1695 if (wd->user_agent) eina_stringshare_del(wd->user_agent);
1696 if (wd->ua) eina_hash_free(wd->ua);
1702 _del_pre_hook(Evas_Object *obj)
1704 Marker_Group *group;
1705 Elm_Map_Marker *marker;
1707 Eina_Bool free_marker = EINA_TRUE;
1709 Widget_Data *wd = elm_widget_data_get(obj);
1713 for (i = 0; i < ZOOM_MAX + 1; i++)
1715 if (!wd->markers[i]) continue;
1716 Eina_Iterator *it = eina_matrixsparse_iterator_new(wd->markers[i]);
1717 Eina_Matrixsparse_Cell *cell;
1719 EINA_ITERATOR_FOREACH(it, cell)
1721 l = eina_matrixsparse_cell_data_get(cell);
1722 EINA_LIST_FREE(l, group)
1724 EINA_LIST_FREE(group->markers, marker)
1726 evas_object_event_callback_del_full(group->sc, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1727 _bubble_sc_hits_changed_cb, group);
1728 if (free_marker) free(marker);
1732 free_marker = EINA_FALSE;
1734 eina_iterator_free(it);
1735 eina_matrixsparse_free(wd->markers[i]);
1738 evas_object_del(wd->sep_maps_markers);
1739 evas_object_del(wd->pan_smart);
1740 wd->pan_smart = NULL;
1744 _on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
1746 Widget_Data *wd = elm_widget_data_get(obj);
1748 if (elm_widget_focus_get(obj))
1750 edje_object_signal_emit(wd->obj, "elm,action,focus", "elm");
1751 evas_object_focus_set(wd->obj, EINA_TRUE);
1755 edje_object_signal_emit(wd->obj, "elm,action,unfocus", "elm");
1756 evas_object_focus_set(wd->obj, EINA_FALSE);
1761 _theme_hook(Evas_Object *obj)
1763 Widget_Data *wd = elm_widget_data_get(obj);
1765 elm_smart_scroller_object_theme_set(obj, wd->scr, "map", "base", elm_widget_style_get(obj));
1766 // edje_object_scale_set(wd->scr, elm_widget_scale_get(obj) * _elm_config->scale);
1771 _sizing_eval(Evas_Object *obj)
1773 Widget_Data *wd = elm_widget_data_get(obj);
1774 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
1776 evas_object_size_hint_max_get(wd->scr, &maxw, &maxh);
1777 evas_object_size_hint_min_set(obj, minw, minh);
1778 evas_object_size_hint_max_set(obj, maxw, maxh);
1782 _calc_job(void *data)
1784 Widget_Data *wd = data;
1785 Evas_Coord minw, minh;
1792 if (wd->mode != ELM_MAP_ZOOM_MODE_MANUAL)
1794 double tz = wd->zoom;
1796 elm_map_zoom_set(wd->obj, tz);
1799 if ((minw != wd->minw) || (minh != wd->minh))
1803 evas_object_smart_callback_call(wd->pan_smart, SIG_CHANGED, NULL);
1804 _sizing_eval(wd->obj);
1806 wd->calc_job = NULL;
1807 evas_object_smart_changed(wd->pan_smart);
1811 _pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
1813 Pan *sd = evas_object_smart_data_get(obj);
1815 if ((x == sd->wd->pan_x) && (y == sd->wd->pan_y)) return;
1818 evas_object_smart_changed(obj);
1822 _pan_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
1824 Pan *sd = evas_object_smart_data_get(obj);
1826 if (x) *x = sd->wd->pan_x;
1827 if (y) *y = sd->wd->pan_y;
1831 _pan_max_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
1833 Pan *sd = evas_object_smart_data_get(obj);
1836 evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
1837 ow = sd->wd->minw - ow;
1839 oh = sd->wd->minh - oh;
1846 _pan_min_get(Evas_Object *obj __UNUSED__, Evas_Coord *x, Evas_Coord *y)
1853 _pan_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
1855 Pan *sd = evas_object_smart_data_get(obj);
1857 if (w) *w = sd->wd->minw;
1858 if (h) *h = sd->wd->minh;
1862 _pan_add(Evas_Object *obj)
1865 Evas_Object_Smart_Clipped_Data *cd;
1867 cd = evas_object_smart_data_get(obj);
1869 sd = calloc(1, sizeof(Pan));
1871 sd->__clipped_data = *cd;
1873 evas_object_smart_data_set(obj, sd);
1877 _pan_del(Evas_Object *obj)
1879 Pan *sd = evas_object_smart_data_get(obj);
1885 _pan_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
1887 Pan *sd = evas_object_smart_data_get(obj);
1890 evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
1891 if ((ow == w) && (oh == h)) return;
1892 sd->wd->resized = 1;
1893 if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
1894 sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd);
1898 _pan_calculate(Evas_Object *obj)
1900 Pan *sd = evas_object_smart_data_get(obj);
1901 Evas_Coord ox, oy, ow, oh;
1905 evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
1906 rect_place(sd->wd->obj, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh);
1907 EINA_LIST_FOREACH(sd->wd->grids, l, g)
1909 grid_load(sd->wd->obj, g);
1910 grid_place(sd->wd->obj, g, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh);
1911 marker_place(sd->wd->obj, g, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh);
1912 if (!sd->wd->zoom_animator) route_place(sd->wd->obj, g, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh);
1917 _pan_move(Evas_Object *obj, Evas_Coord x __UNUSED__, Evas_Coord y __UNUSED__)
1919 Pan *sd = evas_object_smart_data_get(obj);
1921 if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
1922 sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd);
1926 _hold_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1928 Widget_Data *wd = elm_widget_data_get(obj);
1930 elm_smart_scroller_hold_set(wd->scr, 1);
1934 _hold_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1936 Widget_Data *wd = elm_widget_data_get(obj);
1938 elm_smart_scroller_hold_set(wd->scr, 0);
1942 _freeze_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1944 Widget_Data *wd = elm_widget_data_get(obj);
1946 elm_smart_scroller_freeze_set(wd->scr, 1);
1950 _freeze_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1952 Widget_Data *wd = elm_widget_data_get(obj);
1954 elm_smart_scroller_freeze_set(wd->scr, 0);
1958 _scr_anim_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1960 evas_object_smart_callback_call(data, "scroll,anim,start", NULL);
1964 _scr_anim_stop(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1966 evas_object_smart_callback_call(data, "scroll,anim,stop", NULL);
1970 _scr_drag_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1972 Widget_Data *wd = elm_widget_data_get(data);
1973 wd->center_on.enabled = EINA_FALSE;
1974 evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_START, NULL);
1978 _scr_drag_stop(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1980 evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_STOP, NULL);
1984 _scr_scroll(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1986 evas_object_smart_callback_call(data, SIG_SCROLL, NULL);
1991 _group_object_create(Marker_Group *group)
1993 const char *style = "radio";
1994 Evas_Object *icon = NULL;
1996 if (group->obj) return;
1997 if ((!group->clas->priv.objs_notused) || (eina_list_count(group->markers) == 1))
1999 //set icon and style
2000 if (eina_list_count(group->markers) == 1)
2002 Elm_Map_Marker *m = eina_list_data_get(group->markers);
2004 style = m->clas->style;
2006 if (m->clas->func.icon_get)
2007 icon = m->clas->func.icon_get(group->wd->obj, m, m->data);
2009 group->delete_object = EINA_TRUE;
2013 if (group->clas->style)
2014 style = group->clas->style;
2016 if (group->clas->func.icon_get)
2017 icon = group->clas->func.icon_get(group->wd->obj, group->clas->data);
2019 group->delete_object = EINA_FALSE;
2022 group->obj = elm_layout_add(group->wd->obj);
2023 elm_layout_theme_set(group->obj, "map/marker", style, elm_widget_style_get(group->wd->obj));
2025 if (icon) elm_layout_content_set(group->obj, "elm.icon", icon);
2027 evas_object_smart_member_add(group->obj, group->wd->pan_smart);
2028 elm_widget_sub_object_add(group->wd->obj, group->obj);
2029 evas_object_stack_above(group->obj, group->wd->sep_maps_markers);
2031 if (!group->delete_object)
2032 group->clas->priv.objs_used = eina_list_append(group->clas->priv.objs_used, group->obj);
2036 group->delete_object = EINA_FALSE;
2038 group->obj = eina_list_data_get(group->clas->priv.objs_notused);
2039 group->clas->priv.objs_used = eina_list_append(group->clas->priv.objs_used, group->obj);
2040 group->clas->priv.objs_notused = eina_list_remove(group->clas->priv.objs_notused, group->obj);
2041 evas_object_show(group->obj);
2044 edje_object_signal_callback_add(elm_layout_edje_get(group->obj), "open", "elm", _group_open_cb, group);
2045 edje_object_signal_callback_add(elm_layout_edje_get(group->obj), "bringin", "elm", _group_bringin_cb, group);
2047 group->update_nbelems = EINA_TRUE;
2048 group->update_resize = EINA_TRUE;
2049 group->update_raise = EINA_TRUE;
2051 if (group->open) _group_bubble_create(group);
2055 _group_object_free(Marker_Group *group)
2057 if (!group->obj) return;
2058 if (!group->delete_object)
2060 group->clas->priv.objs_notused = eina_list_append(group->clas->priv.objs_notused, group->obj);
2061 group->clas->priv.objs_used = eina_list_remove(group->clas->priv.objs_used, group->obj);
2062 evas_object_hide(group->obj);
2064 edje_object_signal_callback_del(elm_layout_edje_get(group->obj), "open", "elm", _group_open_cb);
2065 edje_object_signal_callback_del(elm_layout_edje_get(group->obj), "bringin", "elm", _group_bringin_cb);
2068 evas_object_del(group->obj);
2071 _group_bubble_free(group);
2075 _group_bubble_mouse_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2077 Marker_Group *group = data;
2079 if (!evas_object_above_get(group->rect)) return;
2080 evas_object_raise(group->bubble);
2081 evas_object_raise(group->sc);
2082 evas_object_raise(group->rect);
2086 _group_bubble_create(Marker_Group *group)
2088 if (group->bubble) return;
2090 group->wd->opened_bubbles = eina_list_append(group->wd->opened_bubbles, group);
2091 group->bubble = edje_object_add(evas_object_evas_get(group->obj));
2092 _elm_theme_object_set(group->wd->obj, group->bubble, "map", "marker_bubble",
2093 elm_widget_style_get(group->wd->obj));
2094 evas_object_smart_member_add(group->bubble,
2096 elm_widget_sub_object_add(group->wd->obj, group->bubble);
2098 _group_bubble_content_free(group);
2099 if (!_group_bubble_content_update(group))
2101 //no content, we can delete the bubble
2102 _group_bubble_free(group);
2106 group->rect = evas_object_rectangle_add(evas_object_evas_get(group->obj));
2107 evas_object_color_set(group->rect, 0, 0, 0, 0);
2108 evas_object_repeat_events_set(group->rect, EINA_TRUE);
2109 evas_object_smart_member_add(group->rect, group->wd->obj);
2110 elm_widget_sub_object_add(group->wd->obj, group->rect);
2112 evas_object_event_callback_add(group->rect, EVAS_CALLBACK_MOUSE_UP, _group_bubble_mouse_up_cb, group);
2114 _group_bubble_place(group);
2117 static void _bubble_sc_hits_changed_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2119 _group_bubble_place(data);
2123 _group_bubble_content_update(Marker_Group *group)
2126 Elm_Map_Marker *marker;
2129 if (!group->bubble) return 1;
2133 group->sc = elm_scroller_add(group->bubble);
2134 elm_widget_style_set(group->sc, "map_bubble");
2135 elm_scroller_content_min_limit(group->sc, EINA_FALSE, EINA_TRUE);
2136 elm_scroller_policy_set(group->sc, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
2137 elm_scroller_bounce_set(group->sc, _elm_config->thumbscroll_bounce_enable, EINA_FALSE);
2138 edje_object_part_swallow(group->bubble, "elm.swallow.content", group->sc);
2139 evas_object_show(group->sc);
2140 evas_object_smart_member_add(group->sc,
2142 elm_widget_sub_object_add(group->wd->obj, group->sc);
2144 group->bx = elm_box_add(group->bubble);
2145 evas_object_size_hint_align_set(group->bx, EVAS_HINT_FILL, EVAS_HINT_FILL);
2146 evas_object_size_hint_weight_set(group->bx, 0.5, 0.5);
2147 elm_box_horizontal_set(group->bx, EINA_TRUE);
2148 evas_object_show(group->bx);
2150 elm_scroller_content_set(group->sc, group->bx);
2152 evas_object_event_callback_add(group->sc, EVAS_CALLBACK_RESIZE,
2153 _bubble_sc_hits_changed_cb, group);
2156 EINA_LIST_FOREACH(group->markers, l, marker)
2158 if (i >= group->wd->markers_max_num) break;
2159 if ((!marker->content) && (marker->clas->func.get))
2160 marker->content = marker->clas->func.get(group->wd->obj, marker, marker->data);
2161 else if (marker->content)
2162 elm_box_unpack(group->bx, marker->content);
2163 if (marker->content)
2165 elm_box_pack_end(group->bx, marker->content);
2173 _group_bubble_content_free(Marker_Group *group)
2176 Elm_Map_Marker *marker;
2178 if (!group->sc) return;
2179 EINA_LIST_FOREACH(group->markers, l, marker)
2181 if ((marker->content) && (marker->clas->func.del))
2182 marker->clas->func.del(group->wd->obj, marker, marker->data, marker->content);
2183 else if (marker->content)
2184 evas_object_del(marker->content);
2185 marker->content = NULL;
2187 evas_object_del(group->sc);
2192 _group_bubble_free(Marker_Group *group)
2194 if (!group->bubble) return;
2195 group->wd->opened_bubbles = eina_list_remove(group->wd->opened_bubbles, group);
2196 evas_object_event_callback_del_full(group->sc, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
2197 _bubble_sc_hits_changed_cb, group);
2198 evas_object_del(group->bubble);
2199 evas_object_del(group->rect);
2200 group->bubble = NULL;
2201 _group_bubble_content_free(group);
2205 _group_bubble_place(Marker_Group *group)
2208 Evas_Coord xx, yy, ww, hh;
2211 if ((!group->bubble) || (!group->obj)) return;
2213 evas_object_geometry_get(group->obj, &x, &y, &w, NULL);
2214 edje_object_size_min_calc(group->bubble, NULL, &hh);
2216 s = edje_object_data_get(group->bubble, "size_w");
2217 if (s) ww = atoi(s);
2219 xx = x + w / 2 - ww / 2;
2222 evas_object_move(group->bubble, xx, yy);
2223 evas_object_resize(group->bubble, ww, hh);
2224 evas_object_show(group->bubble);
2226 evas_object_move(group->rect, xx, yy);
2227 evas_object_resize(group->rect, ww, hh);
2228 evas_object_show(group->rect);
2232 _group_bringin_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *soure __UNUSED__)
2234 Marker_Group *group = data;
2235 Elm_Map_Marker *marker = eina_list_data_get(group->markers);
2236 if (!marker) return;
2237 group->bringin = EINA_TRUE;
2238 elm_map_geo_region_bring_in(group->wd->obj, marker->longitude, marker->latitude);
2242 _group_open_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *soure __UNUSED__)
2244 Marker_Group *group = data;
2248 group->bringin = EINA_FALSE;
2254 group->open = EINA_FALSE;
2255 _group_bubble_free(group);
2258 group->open = EINA_TRUE;
2259 _group_bubble_create(group);
2263 _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
2268 Evas_Coord step_x = 0;
2269 Evas_Coord step_y = 0;
2272 Evas_Coord page_x = 0;
2273 Evas_Coord page_y = 0;
2275 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
2276 Evas_Event_Key_Down *ev = event_info;
2277 Widget_Data *wd = elm_widget_data_get(obj);
2278 if (!wd) return EINA_FALSE;
2279 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
2281 elm_smart_scroller_child_pos_get(wd->scr, &x, &y);
2282 elm_smart_scroller_step_size_get(wd->scr, &step_x, &step_y);
2283 elm_smart_scroller_page_size_get(wd->scr, &page_x, &page_y);
2284 elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h);
2286 if ((!strcmp(ev->keyname, "Left")) || (!strcmp(ev->keyname, "KP_Left")))
2290 else if ((!strcmp(ev->keyname, "Right")) || (!strcmp(ev->keyname, "KP_Right")))
2294 else if ((!strcmp(ev->keyname, "Up")) || (!strcmp(ev->keyname, "KP_Up")))
2298 else if ((!strcmp(ev->keyname, "Down")) || (!strcmp(ev->keyname, "KP_Down")))
2302 else if ((!strcmp(ev->keyname, "Prior")) || (!strcmp(ev->keyname, "KP_Prior")))
2305 y -= -(page_y * v_h) / 100;
2309 else if ((!strcmp(ev->keyname, "Next")) || (!strcmp(ev->keyname, "KP_Next")))
2312 y += -(page_y * v_h) / 100;
2316 else if (!strcmp(ev->keyname, "KP_Add"))
2318 zoom = elm_map_zoom_get(obj);
2320 elm_map_zoom_mode_set(obj, ELM_MAP_ZOOM_MODE_MANUAL);
2321 elm_map_zoom_set(obj, zoom);
2324 else if (!strcmp(ev->keyname, "KP_Subtract"))
2326 zoom = elm_map_zoom_get(obj);
2328 elm_map_zoom_mode_set(obj, ELM_MAP_ZOOM_MODE_MANUAL);
2329 elm_map_zoom_set(obj, zoom);
2332 else return EINA_FALSE;
2334 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2335 elm_smart_scroller_child_pos_set(wd->scr, x, y);
2341 cb_dump_attrs(void *data __UNUSED__, const char *key __UNUSED__, const char *value __UNUSED__)
2348 cb_dump(void *data, Eina_Simple_XML_Type type, const char *value, unsigned offset __UNUSED__, unsigned length)
2350 Route_Dump *dump = data;
2354 case EINA_SIMPLE_XML_OPEN:
2355 case EINA_SIMPLE_XML_OPEN_EMPTY:
2359 attrs = eina_simple_xml_tag_attributes_find(value, length);
2362 if (!strncmp(value, YOURS_DISTANCE, length)) dump->id = ROUTE_XML_DISTANCE;
2363 else if (!strncmp(value, YOURS_DESCRIPTION, length)) dump->id = ROUTE_XML_DESCRIPTION;
2364 else if (!strncmp(value, YOURS_COORDINATES, length)) dump->id = ROUTE_XML_COORDINATES;
2365 else dump->id = ROUTE_XML_NONE;
2369 eina_simple_xml_attributes_parse
2370 (attrs, length - (attrs - value), cb_dump_attrs, dump);
2375 case EINA_SIMPLE_XML_DATA:
2377 char *buf = malloc(length);
2378 if (!buf) return EINA_FALSE;
2379 snprintf(buf, length, "%s", value);
2380 if (dump->id == ROUTE_XML_DISTANCE) dump->distance = atof(buf);
2381 else if (!(dump->description) && (dump->id == ROUTE_XML_DESCRIPTION)) dump->description = strdup(buf);
2382 else if (dump->id == ROUTE_XML_COORDINATES) dump->coordinates = strdup(buf);
2387 case EINA_SIMPLE_XML_CLOSE:
2389 case EINA_SIMPLE_XML_CDATA:
2391 case EINA_SIMPLE_XML_ERROR:
2393 case EINA_SIMPLE_XML_PROCESSING:
2395 case EINA_SIMPLE_XML_DOCTYPE:
2397 case EINA_SIMPLE_XML_COMMENT:
2399 case EINA_SIMPLE_XML_IGNORED:
2407 _parse_kml(void *data)
2409 Elm_Map_Route *r = (Elm_Map_Route*)data;
2410 if (!r && !r->ud.fname) return;
2414 unsigned int ele, idx;
2418 Route_Dump dump = {0, r->ud.fname, 0.0, NULL, NULL};
2420 f = fopen(r->ud.fname, "rb");
2425 fseek(f, 0, SEEK_END);
2431 fseek(f, 0, SEEK_SET);
2435 if (fread(buf, 1, sz, f))
2437 eina_simple_xml_parse(buf, sz, EINA_TRUE, cb_dump, &dump);
2444 if (dump.distance) r->info.distance = dump.distance;
2445 if (dump.description)
2447 eina_stringshare_replace(&r->info.waypoints, dump.description);
2448 str = eina_str_split_full(dump.description, "\n", 0, &ele);
2449 r->info.waypoint_count = ele;
2450 for (idx = 0 ; idx < ele ; idx++)
2452 Route_Waypoint *wp = ELM_NEW(Route_Waypoint);
2456 wp->point = eina_stringshare_add(str[idx]);
2457 DBG("%s", str[idx]);
2458 r->waypoint = eina_list_append(r->waypoint, wp);
2467 else WRN("description is not found !");
2469 if (dump.coordinates)
2471 eina_stringshare_replace(&r->info.nodes, dump.coordinates);
2472 str = eina_str_split_full(dump.coordinates, "\n", 0, &ele);
2473 r->info.node_count = ele;
2474 for (idx = 0 ; idx < ele ; idx++)
2476 sscanf(str[idx], "%lf,%lf", &lon, &lat);
2477 Route_Node *n = ELM_NEW(Route_Node);
2484 DBG("%lf:%lf", lon, lat);
2485 n->pos.address = NULL;
2486 r->nodes = eina_list_append(r->nodes, n);
2488 path = evas_object_line_add(evas_object_evas_get(r->wd->obj));
2489 evas_object_smart_member_add(path, r->wd->pan_smart);
2490 r->path = eina_list_append(r->path, path);
2503 _common_complete_cb(void *data, int ev_type __UNUSED__, void *event)
2505 Ecore_Con_Event_Url_Complete *ev = event;
2506 Elm_Map_Route *r = (Elm_Map_Route*)data;
2507 Widget_Data *wd = r->wd;
2509 if ((!r) || (!ev)) return EINA_TRUE;
2510 Elm_Map_Route *rr = ecore_con_url_data_get(r->con_url);
2511 ecore_con_url_data_set(r->con_url, NULL);
2512 if (r!=rr) return EINA_TRUE;
2514 if (r->ud.fd) fclose(r->ud.fd);
2519 Evas_Coord ox, oy, ow, oh;
2520 evas_object_geometry_get(wd->obj, &ox, &oy, &ow, &oh);
2521 route_place(wd->obj, eina_list_data_get(wd->grids), wd->pan_x, wd->pan_y, ox, oy, ow, oh);
2523 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
2524 "elm,state,busy,stop", "elm");
2525 evas_object_smart_callback_call(wd->obj, SIG_ROUTE_LOADED, NULL);
2529 static int idnum = 1;
2532 * Add a new Map object
2534 * @param parent The parent object
2535 * @return The new object or NULL if it cannot be created
2540 elm_map_add(Evas_Object *parent)
2544 Evas_Coord minw, minh;
2546 static Evas_Smart *smart = NULL;
2547 Eina_Bool bounce = _elm_config->thumbscroll_bounce_enable;
2549 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
2551 ELM_SET_WIDTYPE(widtype, "map");
2552 elm_widget_type_set(obj, "map");
2553 elm_widget_sub_object_add(parent, obj);
2554 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
2555 elm_widget_data_set(obj, wd);
2556 elm_widget_del_hook_set(obj, _del_hook);
2557 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
2558 elm_widget_theme_hook_set(obj, _theme_hook);
2559 elm_widget_can_focus_set(obj, EINA_TRUE);
2560 elm_widget_event_hook_set(obj, _event_hook);
2562 wd->scr = elm_smart_scroller_add(e);
2563 elm_smart_scroller_widget_set(wd->scr, obj);
2564 elm_smart_scroller_object_theme_set(obj, wd->scr, "map", "base", "default");
2565 evas_object_smart_callback_add(wd->scr, "scroll", _scr, obj);
2566 evas_object_smart_callback_add(wd->scr, "drag", _scr, obj);
2567 elm_widget_resize_object_set(obj, wd->scr);
2569 evas_object_smart_callback_add(wd->scr, "animate,start", _scr_anim_start, obj);
2570 evas_object_smart_callback_add(wd->scr, "animate,stop", _scr_anim_stop, obj);
2571 evas_object_smart_callback_add(wd->scr, "drag,start", _scr_drag_start, obj);
2572 evas_object_smart_callback_add(wd->scr, "drag,stop", _scr_drag_stop, obj);
2573 evas_object_smart_callback_add(wd->scr, "scroll", _scr_scroll, obj);
2575 elm_smart_scroller_bounce_allow_set(wd->scr, bounce, bounce);
2579 wd->markers_max_num = 30;
2580 wd->source = ELM_MAP_SOURCE_MAPNIK;
2582 evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
2583 evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
2584 evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
2585 evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
2589 static Evas_Smart_Class sc;
2591 evas_object_smart_clipped_smart_set(&_pan_sc);
2593 sc.name = "elm_map_pan";
2594 sc.version = EVAS_SMART_CLASS_VERSION;
2597 sc.resize = _pan_resize;
2598 sc.move = _pan_move;
2599 sc.calculate = _pan_calculate;
2600 smart = evas_smart_class_new(&sc);
2604 wd->pan_smart = evas_object_smart_add(e, smart);
2605 wd->pan = evas_object_smart_data_get(wd->pan_smart);
2609 elm_smart_scroller_extern_pan_set(wd->scr, wd->pan_smart,
2610 _pan_set, _pan_get, _pan_max_get,
2611 _pan_min_get, _pan_child_size_get);
2613 wd->rect = evas_object_rectangle_add(e);
2614 evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_RESIZE,
2615 _rect_resize_cb, obj);
2616 evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MOUSE_DOWN,
2618 evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MOUSE_MOVE,
2620 evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MOUSE_UP,
2622 evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MULTI_DOWN,
2623 _mouse_multi_down, obj);
2624 evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MULTI_MOVE,
2625 _mouse_multi_move, obj);
2626 evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MULTI_UP,
2627 _mouse_multi_up, obj);
2629 evas_object_smart_member_add(wd->rect, wd->pan_smart);
2630 elm_widget_sub_object_add(obj, wd->rect);
2631 evas_object_show(wd->rect);
2632 evas_object_color_set(wd->rect, 0, 0, 0, 0);
2635 wd->mode = ELM_MAP_ZOOM_MODE_MANUAL;
2637 wd->id = ((int)getpid() << 16) | idnum;
2642 edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
2644 evas_object_size_hint_min_set(obj, minw, minh);
2646 wd->paused = EINA_TRUE;
2647 elm_map_zoom_set(obj, 0);
2648 wd->paused = EINA_FALSE;
2652 wd->calc_job = ecore_job_add(_calc_job, wd);
2654 wd->sep_maps_markers = evas_object_rectangle_add(evas_object_evas_get(obj));
2655 evas_object_smart_member_add(wd->sep_maps_markers, wd->pan_smart);
2657 // TODO: convert Elementary to subclassing of Evas_Smart_Class
2658 // TODO: and save some bytes, making descriptions per-class and not instance!
2659 evas_object_smart_callbacks_descriptions_set(obj, _signals);
2661 if (!ecore_file_download_protocol_available("http://"))
2663 ERR("Ecore must be built with curl support for the map widget!");
2669 * Set the zoom level of the map
2671 * This sets the zoom level. 0 is the world map and 18 is the maximum zoom.
2673 * @param obj The map object
2674 * @param zoom The zoom level to set
2679 elm_map_zoom_set(Evas_Object *obj, int zoom)
2681 ELM_CHECK_WIDTYPE(obj, widtype);
2682 Widget_Data *wd = elm_widget_data_get(obj);
2684 Grid *g, *g_zoom = NULL;
2685 Evas_Coord rx, ry, rw, rh;
2689 int zoom_changed = 0, started = 0;
2692 if (zoom < 0 ) zoom = 0;
2693 if (zoom > map_sources_tab[wd->source].zoom_max)
2694 zoom = map_sources_tab[wd->source].zoom_max;
2695 if (zoom < map_sources_tab[wd->source].zoom_min)
2696 zoom = map_sources_tab[wd->source].zoom_min;
2697 if (zoom == wd->zoom) return;
2700 wd->size.ow = wd->size.w;
2701 wd->size.oh = wd->size.h;
2702 elm_smart_scroller_child_pos_get(wd->scr, &rx, &ry);
2703 elm_smart_scroller_child_viewport_size_get(wd->scr, &rw, &rh);
2705 EINA_LIST_FOREACH(wd->route, lr, r)
2709 EINA_LIST_FOREACH(r->path, l, p)
2711 evas_object_hide(p);
2716 if (wd->mode == ELM_MAP_ZOOM_MODE_MANUAL)
2718 wd->size.nw = pow(2.0, wd->zoom) * wd->tsize;
2719 wd->size.nh = pow(2.0, wd->zoom) * wd->tsize;
2721 else if (wd->mode == ELM_MAP_ZOOM_MODE_AUTO_FIT)
2728 while (cumulw <= rw)
2737 while (cumulh <= rh)
2750 wd->size.nw = pow(2.0, wd->zoom) * wd->tsize;
2751 wd->size.nh = pow(2.0, wd->zoom) * wd->tsize;
2753 else if (wd->mode == ELM_MAP_ZOOM_MODE_AUTO_FILL)
2760 while (cumulw <= rw)
2769 while (cumulh <= rh)
2782 wd->size.nw = pow(2.0, wd->zoom) * wd->tsize;
2783 wd->size.nh = pow(2.0, wd->zoom) * wd->tsize;
2786 EINA_LIST_FOREACH(wd->grids, l, g)
2788 if (g->zoom == wd->zoom)
2790 wd->grids = eina_list_remove(wd->grids, g);
2791 wd->grids = eina_list_prepend(wd->grids, g);
2796 g = grid_create(obj);
2799 if (eina_list_count(wd->grids) > 1)
2801 g_zoom = eina_list_last(wd->grids)->data;
2802 wd->grids = eina_list_remove(wd->grids, g_zoom);
2803 grid_clear(obj, g_zoom);
2806 wd->grids = eina_list_prepend(wd->grids, g);
2810 EINA_LIST_FREE(wd->grids, g)
2818 wd->t_start = ecore_loop_time_get();
2819 wd->t_end = wd->t_start + _elm_config->zoom_friction;
2820 if ((wd->size.w > 0) && (wd->size.h > 0))
2822 wd->size.spos.x = (double)(rx + (rw / 2)) / (double)wd->size.ow;
2823 wd->size.spos.y = (double)(ry + (rh / 2)) / (double)wd->size.oh;
2827 wd->size.spos.x = 0.5;
2828 wd->size.spos.y = 0.5;
2830 if (rw > wd->size.ow) wd->size.spos.x = 0.5;
2831 if (rh > wd->size.oh) wd->size.spos.y = 0.5;
2832 if (wd->size.spos.x > 1.0) wd->size.spos.x = 1.0;
2833 if (wd->size.spos.y > 1.0) wd->size.spos.y = 1.0;
2840 if (!wd->zoom_animator)
2842 wd->zoom_animator = ecore_animator_add(_zoom_anim, obj);
2844 if (wd->nosmooth == 1) _smooth_update(obj);
2848 if (wd->zoom_animator)
2850 if (!_zoom_anim(obj))
2852 ecore_animator_del(wd->zoom_animator);
2853 wd->zoom_animator = NULL;
2856 if (wd->calc_job) ecore_job_del(wd->calc_job);
2857 wd->calc_job = ecore_job_add(_calc_job, wd);
2861 evas_object_smart_callback_call(obj, SIG_ZOOM_START, NULL);
2862 if (!wd->zoom_animator)
2863 evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL);
2867 evas_object_smart_callback_call(obj, SIG_ZOOM_CHANGE, NULL);
2871 * Get the zoom level of the photo
2873 * This returns the current zoom level of the map object. Note that if
2874 * you set the fill mode to other than ELM_MAP_ZOOM_MODE_MANUAL
2875 * (which is the default), the zoom level may be changed at any time by the
2876 * map object itself to account for map size and map viewpoer size
2878 * @param obj The map object
2879 * @return The current zoom level
2884 elm_map_zoom_get(const Evas_Object *obj)
2886 ELM_CHECK_WIDTYPE(obj, widtype) 1.0;
2887 Widget_Data *wd = elm_widget_data_get(obj);
2888 if (!wd) return 1.0;
2895 * This sets the zoom mode to manual or one of several automatic levels.
2896 * Manual (ELM_MAP_ZOOM_MODE_MANUAL) means that zoom is set manually by
2897 * elm_map_zoom_set() and will stay at that level until changed by code
2898 * or until zoom mode is changed. This is the default mode.
2899 * The Automatic modes will allow the map object to automatically
2900 * adjust zoom mode based on properties. ELM_MAP_ZOOM_MODE_AUTO_FIT) will
2901 * adjust zoom so the photo fits inside the scroll frame with no pixels
2902 * outside this area. ELM_MAP_ZOOM_MODE_AUTO_FILL will be similar but
2903 * ensure no pixels within the frame are left unfilled. Do not forget that the valid sizes are 2^zoom, consequently the map may be smaller than the scroller view.
2905 * @param obj The map object
2906 * @param mode The desired mode
2911 elm_map_zoom_mode_set(Evas_Object *obj, Elm_Map_Zoom_Mode mode)
2913 ELM_CHECK_WIDTYPE(obj, widtype);
2914 Widget_Data *wd = elm_widget_data_get(obj);
2916 if (wd->mode == mode) return;
2919 double tz = wd->zoom;
2921 elm_map_zoom_set(wd->obj, tz);
2928 * This gets the current zoom mode of the map object
2930 * @param obj The map object
2931 * @return The current zoom mode
2935 EAPI Elm_Map_Zoom_Mode
2936 elm_map_zoom_mode_get(const Evas_Object *obj)
2938 ELM_CHECK_WIDTYPE(obj, widtype) ELM_MAP_ZOOM_MODE_MANUAL;
2939 Widget_Data *wd = elm_widget_data_get(obj);
2940 if (!wd) return ELM_MAP_ZOOM_MODE_MANUAL;
2945 * Centers the map at @p lon @p lat using an animation to scroll.
2947 * @param obj The map object
2948 * @param lon Longitude to center at
2949 * @param lon Latitude to center at
2954 elm_map_geo_region_bring_in(Evas_Object *obj, double lon, double lat)
2956 ELM_CHECK_WIDTYPE(obj, widtype);
2957 Widget_Data *wd = elm_widget_data_get(obj);
2961 elm_map_utils_convert_geo_into_coord(obj, lon, lat, wd->size.w, &rx, &ry);
2962 elm_smart_scroller_child_viewport_size_get(wd->scr, &rw, &rh);
2967 if (wd->zoom_animator)
2970 if (!wd->nosmooth) _smooth_update(obj);
2971 ecore_animator_del(wd->zoom_animator);
2972 wd->zoom_animator = NULL;
2974 evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL);
2976 elm_smart_scroller_region_bring_in(wd->scr, rx, ry, rw, rh);
2978 wd->center_on.enabled = EINA_TRUE;
2979 wd->center_on.lon = lon;
2980 wd->center_on.lat = lat;
2984 * Move the map to the current coordinates.
2986 * This move the map to the current coordinates. The map will be centered on these coordinates.
2988 * @param obj The map object
2989 * @param lat The latitude.
2990 * @param lon The longitude.
2995 elm_map_geo_region_show(Evas_Object *obj, double lon, double lat)
2997 ELM_CHECK_WIDTYPE(obj, widtype);
2998 Widget_Data *wd = elm_widget_data_get(obj);
3002 elm_map_utils_convert_geo_into_coord(obj, lon, lat, wd->size.w, &rx, &ry);
3003 elm_smart_scroller_child_viewport_size_get(wd->scr, &rw, &rh);
3008 if (wd->zoom_animator)
3011 ecore_animator_del(wd->zoom_animator);
3012 wd->zoom_animator = NULL;
3014 evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL);
3016 elm_smart_scroller_child_region_show(wd->scr, rx, ry, rw, rh);
3018 wd->center_on.enabled = EINA_TRUE;
3019 wd->center_on.lon = lon;
3020 wd->center_on.lat = lat;
3024 * Get the current coordinates of the map.
3026 * This gets the current coordinates of the map object.
3028 * @param obj The map object
3029 * @param lat The latitude.
3030 * @param lon The longitude.
3035 elm_map_geo_region_get(const Evas_Object *obj, double *lon, double *lat)
3037 ELM_CHECK_WIDTYPE(obj, widtype);
3038 Widget_Data *wd = elm_widget_data_get(obj);
3039 Evas_Coord sx, sy, sw, sh;
3042 elm_smart_scroller_child_pos_get(wd->scr, &sx, &sy);
3043 elm_smart_scroller_child_viewport_size_get(wd->scr, &sw, &sh);
3047 elm_map_utils_convert_coord_into_geo(obj, sx, sy, wd->size.w, lon, lat);
3051 * Set the paused state for map
3053 * This sets the paused state to on (1) or off (0) for map. The default
3054 * is off. This will stop zooming using animation change zoom levels and
3055 * change instantly. This will stop any existing animations that are running.
3057 * @param obj The map object
3058 * @param paused The pause state to set
3063 elm_map_paused_set(Evas_Object *obj, Eina_Bool paused)
3065 ELM_CHECK_WIDTYPE(obj, widtype);
3066 Widget_Data *wd = elm_widget_data_get(obj);
3068 if (wd->paused == !!paused) return;
3069 wd->paused = paused;
3072 if (wd->zoom_animator)
3074 ecore_animator_del(wd->zoom_animator);
3075 wd->zoom_animator = NULL;
3077 evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL);
3083 * Set the paused state for the markers
3085 * This sets the paused state to on (1) or off (0) for the markers. The default
3086 * is off. This will stop displaying the markers during change zoom levels. Set
3087 * to on if you have a large number of markers.
3089 * @param obj The map object
3090 * @param paused The pause state to set
3095 elm_map_paused_markers_set(Evas_Object *obj, Eina_Bool paused)
3097 ELM_CHECK_WIDTYPE(obj, widtype);
3098 Widget_Data *wd = elm_widget_data_get(obj);
3100 if (wd->paused_markers == !!paused) return;
3101 wd->paused_markers = paused;
3105 * Get the paused state for map
3107 * This gets the current paused state for the map object.
3109 * @param obj The map object
3110 * @return The current paused state
3115 elm_map_paused_get(const Evas_Object *obj)
3117 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3118 Widget_Data *wd = elm_widget_data_get(obj);
3119 if (!wd) return EINA_FALSE;
3124 * Get the paused state for the markers
3126 * This gets the current paused state for the markers object.
3128 * @param obj The map object
3129 * @return The current paused state
3134 elm_map_paused_markers_get(const Evas_Object *obj)
3136 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3137 Widget_Data *wd = elm_widget_data_get(obj);
3138 if (!wd) return EINA_FALSE;
3139 return wd->paused_markers;
3143 * Get the information of downloading status
3145 * This gets the current downloading status for the map object.
3147 * @param obj The map object
3148 * @param try_num the number of download trying map
3149 * @param finish_num the number of downloaded map
3155 elm_map_utils_downloading_status_get(const Evas_Object *obj, int *try_num, int *finish_num)
3157 ELM_CHECK_WIDTYPE(obj, widtype);
3158 Widget_Data *wd = elm_widget_data_get(obj);
3163 *try_num = wd->try_num;
3168 *finish_num = wd->finish_num;
3172 * Convert a pixel coordinate (x,y) into a geographic coordinate (longitude, latitude).
3174 * @param obj The map object
3175 * @param x the coordinate
3176 * @param y the coordinate
3177 * @param size the size in pixels of the map. The map is a square and generally his size is : pow(2.0, zoom)*256.
3178 * @param lon the longitude correspond to x
3179 * @param lat the latitude correspond to y
3184 elm_map_utils_convert_coord_into_geo(const Evas_Object *obj, int x, int y, int size, double *lon, double *lat)
3186 Widget_Data *wd = elm_widget_data_get(obj);
3187 int zoom = floor(log(size/256) / log(2));
3189 if (elm_map_source_get(obj) == ELM_MAP_SOURCE_MODULE)
3190 if ((wd->m) && (wd->m->api))
3192 Mod_Api *api = wd->m->api;
3193 if ((api) && (api->obj_convert_coord_into_geo))
3194 if (api->obj_convert_coord_into_geo(obj, zoom, x, y, size, lon, lat)) return;
3199 *lon = x / (double)size * 360.0 - 180;
3203 double n = ELM_PI - 2.0 * ELM_PI * y / size;
3204 *lat = 180.0 / ELM_PI * atan(0.5 * (exp(n) - exp(-n)));
3209 * Convert a geographic coordinate (longitude, latitude) into a pixel coordinate (x, y).
3211 * @param obj The map object
3212 * @param lon the longitude
3213 * @param lat the latitude
3214 * @param size the size in pixels of the map. The map is a square and generally his size is : pow(2.0, zoom)*256.
3215 * @param x the coordinate correspond to the longitude
3216 * @param y the coordinate correspond to the latitude
3221 elm_map_utils_convert_geo_into_coord(const Evas_Object *obj, double lon, double lat, int size, int *x, int *y)
3223 Widget_Data *wd = elm_widget_data_get(obj);
3224 int zoom = floor(log(size/256) / log(2));
3226 if (elm_map_source_get(obj) == ELM_MAP_SOURCE_MODULE)
3227 if ((wd->m) && (wd->m->api))
3229 Mod_Api *api = wd->m->api;
3230 if ((api) && (api->obj_convert_geo_into_coord))
3231 if (api->obj_convert_geo_into_coord(obj, zoom, lon, lat, size, x, y)) return;
3235 *x = floor((lon + 180.0) / 360.0 * size);
3237 *y = floor((1.0 - log( tan(lat * ELM_PI/180.0) + 1.0 / cos(lat * ELM_PI/180.0)) / ELM_PI) / 2.0 * size);
3243 * Add a marker on the map
3245 * @param obj The map object
3246 * @param lon the longitude
3247 * @param lat the latitude
3248 * @param clas the class to use
3249 * @param data the data passed to the callbacks
3251 * @return The marker object
3255 EAPI Elm_Map_Marker *
3256 elm_map_marker_add(Evas_Object *obj, double lon, double lat, Elm_Map_Marker_Class *clas, Elm_Map_Group_Class *clas_group, void *data)
3260 Marker_Group *group;
3261 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3262 Widget_Data *wd = elm_widget_data_get(obj);
3270 if (!wd) return NULL;
3271 EINA_SAFETY_ON_NULL_RETURN_VAL(clas_group, NULL);
3272 EINA_SAFETY_ON_NULL_RETURN_VAL(clas, NULL);
3274 Elm_Map_Marker *marker = ELM_NEW(Elm_Map_Marker);
3277 marker->clas = clas;
3278 marker->clas_group = clas_group;
3279 marker->longitude = lon;
3280 marker->latitude = lat;
3281 marker->data = data;
3283 tabi[1] = tabi[4] = tabi[6] = -1;
3284 tabi[2] = tabi[0] = tabi[7] = 0;
3285 tabi[3] = tabi[5] = tabi[8] = 1;
3287 tabj[1] = tabj[2] = tabj[3] = -1;
3288 tabj[4] = tabj[0] = tabj[5] = 0;
3289 tabj[6] = tabj[7] = tabj[8] = 1;
3291 if (!clas_group->priv.set)
3294 if (marker->clas_group && marker->clas_group->style)
3295 style = marker->clas_group->style;
3297 o = edje_object_add(evas_object_evas_get(obj));
3298 _elm_theme_object_set(obj, o, "map/marker", style, elm_widget_style_get(obj));
3299 s = edje_object_data_get(o, "size_w");
3300 if (s) clas_group->priv.edje_w = atoi(s);
3301 else clas_group->priv.edje_w = 0;
3302 s = edje_object_data_get(o, "size_h");
3303 if (s) clas_group->priv.edje_h = atoi(s);
3304 else clas_group->priv.edje_h = 0;
3305 s = edje_object_data_get(o, "size_max_w");
3306 if (s) clas_group->priv.edje_max_w = atoi(s);
3307 else clas_group->priv.edje_max_w = 0;
3308 s = edje_object_data_get(o, "size_max_h");
3309 if (s) clas_group->priv.edje_max_h = atoi(s);
3310 else clas_group->priv.edje_max_h = 0;
3313 clas_group->priv.set = EINA_TRUE;
3316 if (!clas->priv.set)
3319 if (marker->clas && marker->clas->style)
3320 style = marker->clas->style;
3322 o = edje_object_add(evas_object_evas_get(obj));
3323 _elm_theme_object_set(obj, o, "map/marker", style, elm_widget_style_get(obj));
3324 s = edje_object_data_get(o, "size_w");
3325 if (s) clas->priv.edje_w = atoi(s);
3326 else clas->priv.edje_w = 0;
3327 s = edje_object_data_get(o, "size_h");
3328 if (s) clas->priv.edje_h = atoi(s);
3329 else clas->priv.edje_h = 0;
3332 clas->priv.set = EINA_TRUE;
3335 for (i = clas_group->zoom_displayed; i <= ZOOM_MAX; i++)
3337 elm_map_utils_convert_geo_into_coord(obj, lon, lat, pow(2.0, i)*wd->tsize,
3338 &(marker->x[i]), &(marker->y[i]));
3340 //search in the matrixsparse the region where the marker will be
3341 mpi = marker->x[i] / wd->tsize;
3342 mpj = marker->y[i] / wd->tsize;
3344 if (!wd->markers[i])
3346 int size = pow(2.0, i);
3347 wd->markers[i] = eina_matrixsparse_new(size, size, NULL, NULL);
3351 if (i <= clas_group->zoom_grouped)
3353 for (j = 0, group = NULL; j < 9 && !group; j++)
3355 EINA_LIST_FOREACH(eina_matrixsparse_data_idx_get(wd->markers[i], mpj + tabj[j], mpi + tabi[j]),
3358 if (group->clas == marker->clas_group
3359 && ELM_RECTS_INTERSECT(marker->x[i]-clas->priv.edje_w/4,
3360 marker->y[i]-clas->priv.edje_h/4, clas->priv.edje_w, clas->priv.edje_h,
3361 group->x-group->w/4, group->y-group->h/4, group->w, group->h))
3363 group->markers = eina_list_append(group->markers, marker);
3364 group->update_nbelems = EINA_TRUE;
3365 group->update_resize = EINA_TRUE;
3367 group->sum_x += marker->x[i];
3368 group->sum_y += marker->y[i];
3369 group->x = group->sum_x / eina_list_count(group->markers);
3370 group->y = group->sum_y / eina_list_count(group->markers);
3372 group->w = group->clas->priv.edje_w + group->clas->priv.edje_w/8.
3373 * eina_list_count(group->markers);
3374 group->h = group->clas->priv.edje_h + group->clas->priv.edje_h/8.
3375 * eina_list_count(group->markers);
3376 if (group->w > group->clas->priv.edje_max_w) group->w = group->clas->priv.edje_max_w;
3377 if (group->h > group->clas->priv.edje_max_h) group->h = group->clas->priv.edje_max_h;
3379 if (group->obj && eina_list_count(group->markers) == 2)
3381 _group_object_free(group);
3382 _group_object_create(group);
3385 _group_bubble_content_update(group);
3394 group = calloc(1, sizeof(Marker_Group));
3396 group->sum_x = marker->x[i];
3397 group->sum_y = marker->y[i];
3398 group->x = marker->x[i];
3399 group->y = marker->y[i];
3400 group->w = clas_group->priv.edje_w;
3401 group->h = clas_group->priv.edje_h;
3402 group->clas = clas_group;
3404 group->markers = eina_list_append(group->markers, marker);
3405 group->update_nbelems = EINA_TRUE;
3406 group->update_resize = EINA_TRUE;
3408 eina_matrixsparse_cell_idx_get(wd->markers[i], mpj, mpi, &(group->cell));
3412 l = eina_list_append(NULL, group);
3413 eina_matrixsparse_data_idx_set(wd->markers[i], mpj, mpi, l);
3414 eina_matrixsparse_cell_idx_get(wd->markers[i], mpj, mpi, &(group->cell));
3418 l = eina_matrixsparse_cell_data_get(group->cell);
3419 l = eina_list_append(l, group);
3420 eina_matrixsparse_cell_data_set(group->cell, l);
3423 marker->groups[i] = group;
3428 Evas_Coord ox, oy, ow, oh;
3429 evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
3430 marker_place(obj, eina_list_data_get(wd->grids), wd->pan_x, wd->pan_y, ox, oy, ow, oh);
3437 * Remove a marker from the map
3439 * @param marker The marker to remove
3444 elm_map_marker_remove(Elm_Map_Marker *marker)
3450 EINA_SAFETY_ON_NULL_RETURN(marker);
3453 for (i = marker->clas_group->zoom_displayed; i <= ZOOM_MAX; i++)
3455 marker->groups[i]->markers = eina_list_remove(marker->groups[i]->markers, marker);
3456 if (!eina_list_count(marker->groups[i]->markers))
3458 groups = eina_matrixsparse_cell_data_get(marker->groups[i]->cell);
3459 groups = eina_list_remove(groups, marker->groups[i]);
3460 eina_matrixsparse_cell_data_set(marker->groups[i]->cell, groups);
3462 _group_object_free(marker->groups[i]);
3463 _group_bubble_free(marker->groups[i]);
3464 free(marker->groups[i]);
3468 marker->groups[i]->sum_x -= marker->x[i];
3469 marker->groups[i]->sum_y -= marker->y[i];
3471 marker->groups[i]->x = marker->groups[i]->sum_x / eina_list_count(marker->groups[i]->markers);
3472 marker->groups[i]->y = marker->groups[i]->sum_y / eina_list_count(marker->groups[i]->markers);
3474 marker->groups[i]->w = marker->groups[i]->clas->priv.edje_w
3475 + marker->groups[i]->clas->priv.edje_w/8. * eina_list_count(marker->groups[i]->markers);
3476 marker->groups[i]->h = marker->groups[i]->clas->priv.edje_h
3477 + marker->groups[i]->clas->priv.edje_h/8. * eina_list_count(marker->groups[i]->markers);
3478 if (marker->groups[i]->w > marker->groups[i]->clas->priv.edje_max_w)
3479 marker->groups[i]->w = marker->groups[i]->clas->priv.edje_max_w;
3480 if (marker->groups[i]->h > marker->groups[i]->clas->priv.edje_max_h)
3481 marker->groups[i]->h = marker->groups[i]->clas->priv.edje_max_h;
3483 if ((marker->groups[i]->obj) && (eina_list_count(marker->groups[i]->markers) == 1))
3485 _group_object_free(marker->groups[i]);
3486 _group_object_create(marker->groups[i]);
3491 if ((marker->content) && (marker->clas->func.del))
3492 marker->clas->func.del(marker->wd->obj, marker, marker->data, marker->content);
3493 else if (marker->content)
3494 evas_object_del(marker->content);
3500 Evas_Coord ox, oy, ow, oh;
3501 evas_object_geometry_get(wd->obj, &ox, &oy, &ow, &oh);
3502 marker_place(wd->obj, eina_list_data_get(wd->grids), wd->pan_x, wd->pan_y, ox, oy, ow, oh);
3507 * Get the current coordinates of the marker.
3509 * @param marker marker.
3510 * @param lat The latitude.
3511 * @param lon The longitude.
3516 elm_map_marker_region_get(const Elm_Map_Marker *marker, double *lon, double *lat)
3518 EINA_SAFETY_ON_NULL_RETURN(marker);
3519 if (lon) *lon = marker->longitude;
3520 if (lat) *lat = marker->latitude;
3524 * Move the map to the coordinate of the marker.
3526 * @param marker The marker where the map will be center.
3531 elm_map_marker_bring_in(Elm_Map_Marker *marker)
3533 EINA_SAFETY_ON_NULL_RETURN(marker);
3534 elm_map_geo_region_bring_in(marker->wd->obj, marker->longitude, marker->latitude);
3538 * Move the map to the coordinate of the marker.
3540 * @param marker The marker where the map will be center.
3545 elm_map_marker_show(Elm_Map_Marker *marker)
3547 EINA_SAFETY_ON_NULL_RETURN(marker);
3548 elm_map_geo_region_show(marker->wd->obj, marker->longitude, marker->latitude);
3552 * Move and zoom the map to display a list of markers.
3554 * The map will be centered on the center point of the markers in the list. Then
3555 * the map will be zoomed in order to fit the markers using the maximum zoom which
3556 * allows display of all the markers.
3558 * @param markers The list of markers (list of Elm_Map_Marker *)
3563 elm_map_markers_list_show(Eina_List *markers)
3568 Elm_Map_Marker *marker, *m_max_lon = NULL, *m_max_lat = NULL, *m_min_lon = NULL, *m_min_lat = NULL;
3569 Evas_Coord rw, rh, xc, yc;
3572 EINA_SAFETY_ON_NULL_RETURN(markers);
3574 EINA_LIST_FOREACH(markers, l, marker)
3578 if ((!m_min_lon) || (marker->longitude < m_min_lon->longitude))
3581 if ((!m_max_lon) || (marker->longitude > m_max_lon->longitude))
3584 if ((!m_min_lat) || (marker->latitude > m_min_lat->latitude))
3587 if ((!m_max_lat) || (marker->latitude < m_max_lat->latitude))
3591 lon = (m_max_lon->longitude - m_min_lon->longitude) / 2. + m_min_lon->longitude;
3592 lat = (m_max_lat->latitude - m_min_lat->latitude) / 2. + m_min_lat->latitude;
3594 elm_smart_scroller_child_viewport_size_get(wd->scr, &rw, &rh);
3595 for (zoom = map_sources_tab[wd->source].zoom_max; zoom>map_sources_tab[wd->source].zoom_min; zoom--)
3597 Evas_Coord size = pow(2.0, zoom)*wd->tsize;
3598 elm_map_utils_convert_geo_into_coord(wd->obj, lon, lat, size, &xc, &yc);
3600 if ((m_min_lon->x[zoom] - wd->marker_max_w >= xc-rw/2)
3601 && (m_min_lat->y[zoom] - wd->marker_max_h >= yc-rh/2)
3602 && (m_max_lon->x[zoom] + wd->marker_max_w <= xc+rw/2)
3603 && (m_max_lat->y[zoom] + wd->marker_max_h <= yc+rh/2))
3607 elm_map_geo_region_show(wd->obj, lon, lat);
3608 elm_map_zoom_set(wd->obj, zoom);
3612 * Set the maximum numbers of markers display in a group.
3614 * A group can have a long list of markers, consequently the creation of the content
3615 * of the bubble can be very slow. In order to avoid this, a maximum number of items
3616 * is displayed in a bubble. By default this number is 30.
3618 * @param obj The map object.
3619 * @param max The maximum numbers of items displayed in a bubble.
3624 elm_map_max_marker_per_group_set(Evas_Object *obj, int max)
3626 ELM_CHECK_WIDTYPE(obj, widtype);
3627 Widget_Data *wd = elm_widget_data_get(obj);
3629 wd->markers_max_num = max;
3633 * Return the evas object getting from the ElmMapMarkerGetFunc callback
3635 * @param marker The marker.
3636 * @return Return the evas object if it exists, else NULL.
3641 elm_map_marker_object_get(const Elm_Map_Marker *marker)
3643 EINA_SAFETY_ON_NULL_RETURN_VAL(marker, NULL);
3644 return marker->content;
3650 * @param marker The marker.
3655 elm_map_marker_update(Elm_Map_Marker *marker)
3657 EINA_SAFETY_ON_NULL_RETURN(marker);
3658 if (marker->content)
3660 if (marker->clas->func.del)
3661 marker->clas->func.del(marker->wd->obj, marker, marker->data, marker->content);
3663 evas_object_del(marker->content);
3664 marker->content = NULL;
3665 _group_bubble_content_update(marker->groups[marker->wd->zoom]);
3670 * Close all opened bubbles
3672 * @param obj The map object
3677 elm_map_bubbles_close(Evas_Object *obj)
3679 ELM_CHECK_WIDTYPE(obj, widtype);
3680 Widget_Data *wd = elm_widget_data_get(obj);
3681 Marker_Group *group;
3682 Eina_List *l, *l_next;
3684 EINA_LIST_FOREACH_SAFE(wd->opened_bubbles, l, l_next, group)
3685 _group_bubble_free(group);
3690 * Create a group class.
3692 * Each marker must be associated to a group class. Marker with the same group are grouped if they are close.
3693 * The group class defines the style of the marker when a marker is grouped to others markers.
3695 * @param obj The map object
3696 * @return Returns the new group class
3700 EAPI Elm_Map_Group_Class *
3701 elm_map_group_class_new(Evas_Object *obj)
3703 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3704 Widget_Data *wd = elm_widget_data_get(obj);
3705 if (!wd) return NULL;
3706 Elm_Map_Group_Class *clas = calloc(1, sizeof(Elm_Map_Group_Class));
3707 clas->zoom_grouped = ZOOM_MAX;
3708 wd->groups_clas = eina_list_append(wd->groups_clas, clas);
3713 * Set the style of a group class (radio, radio2 or empty)
3715 * @param clas the group class
3716 * @param style the new style
3721 elm_map_group_class_style_set(Elm_Map_Group_Class *clas, const char *style)
3723 EINA_SAFETY_ON_NULL_RETURN(clas);
3724 eina_stringshare_replace(&clas->style, style);
3728 * Set the icon callback of a group class.
3730 * A custom icon can be displayed in a marker. The function @ref icon_get must return this icon.
3732 * @param clas the group class
3733 * @param icon_get the callback to create the icon
3738 elm_map_group_class_icon_cb_set(Elm_Map_Group_Class *clas, ElmMapGroupIconGetFunc icon_get)
3740 EINA_SAFETY_ON_NULL_RETURN(clas);
3741 clas->func.icon_get = icon_get;
3745 * Set the data associated to the group class (radio, radio2 or empty)
3747 * @param clas the group class
3748 * @param data the new user data
3753 elm_map_group_class_data_set(Elm_Map_Group_Class *clas, void *data)
3755 EINA_SAFETY_ON_NULL_RETURN(clas);
3760 * Set the zoom from where the markers are displayed.
3762 * Markers will not be displayed for a zoom less than @ref zoom
3764 * @param clas the group class
3765 * @param zoom the zoom
3770 elm_map_group_class_zoom_displayed_set(Elm_Map_Group_Class *clas, int zoom)
3772 EINA_SAFETY_ON_NULL_RETURN(clas);
3773 clas->zoom_displayed = zoom;
3777 * Set the zoom from where the markers are no more grouped.
3779 * @param clas the group class
3780 * @param zoom the zoom
3785 elm_map_group_class_zoom_grouped_set(Elm_Map_Group_Class *clas, int zoom)
3787 EINA_SAFETY_ON_NULL_RETURN(clas);
3788 clas->zoom_grouped = zoom;
3792 * Set if the markers associated to the group class @clas are hidden or not.
3793 * If @ref hide is true the markers will be hidden.
3795 * @param clas the group class
3796 * @param hide if true the markers will be hidden, else they will be displayed.
3801 elm_map_group_class_hide_set(Evas_Object *obj, Elm_Map_Group_Class *clas, Eina_Bool hide)
3803 ELM_CHECK_WIDTYPE(obj, widtype);
3804 Widget_Data *wd = elm_widget_data_get(obj);
3806 EINA_SAFETY_ON_NULL_RETURN(clas);
3807 if (clas->hide == hide) return;
3811 Evas_Coord ox, oy, ow, oh;
3812 evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
3813 marker_place(obj, eina_list_data_get(wd->grids), wd->pan_x, wd->pan_y, ox, oy, ow, oh);
3819 * Create a marker class.
3821 * Each marker must be associated to a class.
3822 * The class defines the style of the marker when a marker is displayed alone (not grouped).
3824 * @param obj The map object
3825 * @return Returns the new class
3829 EAPI Elm_Map_Marker_Class *
3830 elm_map_marker_class_new(Evas_Object *obj)
3832 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3833 Widget_Data *wd = elm_widget_data_get(obj);
3834 if (!wd) return NULL;
3835 Elm_Map_Marker_Class *clas = calloc(1, sizeof(Elm_Map_Marker_Class));
3836 wd->markers_clas = eina_list_append(wd->markers_clas, clas);
3841 * Set the style of a class (radio, radio2 or empty)
3843 * @param clas the group class
3844 * @param style the new style
3849 elm_map_marker_class_style_set(Elm_Map_Marker_Class *clas, const char *style)
3851 EINA_SAFETY_ON_NULL_RETURN(clas);
3852 eina_stringshare_replace(&clas->style, style);
3856 * Set the icon callback of a class.
3858 * A custom icon can be displayed in a marker. The function @ref icon_get must return this icon.
3860 * @param clas the group class
3861 * @param icon_get the callback to create the icon
3866 elm_map_marker_class_icon_cb_set(Elm_Map_Marker_Class *clas, ElmMapMarkerIconGetFunc icon_get)
3868 EINA_SAFETY_ON_NULL_RETURN(clas);
3869 clas->func.icon_get = icon_get;
3874 * Set the callback of the content of the bubble.
3876 * When the user click on a marker, a bubble is displayed with a content.
3877 * The callback @ref get musst return this content. It can be NULL.
3879 * @param clas the group class
3880 * @param get the callback to create the content
3885 elm_map_marker_class_get_cb_set(Elm_Map_Marker_Class *clas, ElmMapMarkerGetFunc get)
3887 EINA_SAFETY_ON_NULL_RETURN(clas);
3888 clas->func.get = get;
3892 * Set the callback of the content of delete the object created by the callback "get".
3894 * If this callback is defined the user will have to delete (or not) the object inside.
3895 * If the callback is not defined the object will be destroyed with evas_object_del()
3897 * @param clas the group class
3898 * @param del the callback to delete the content
3903 elm_map_marker_class_del_cb_set(Elm_Map_Marker_Class *clas, ElmMapMarkerDelFunc del)
3905 EINA_SAFETY_ON_NULL_RETURN(clas);
3906 clas->func.del = del;
3910 * Set the source of the map.
3912 * Elm_Map retrieves the image which composed the map from a web service. This web service can
3913 * be set with this method. A different service can return a different maps with different
3914 * information and it can use different zoom value.
3916 * @param clas the group class
3917 * @param source the new source
3922 elm_map_source_set(Evas_Object *obj, Elm_Map_Sources source)
3924 ELM_CHECK_WIDTYPE(obj, widtype);
3925 Widget_Data *wd = elm_widget_data_get(obj);
3928 Mod_Api *api = NULL;
3930 if (source == ELM_MAP_SOURCE_MODULE)
3934 if ((api) && (api->obj_hook)) api->obj_hook(obj);
3937 if (wd->source == source ) return;
3938 if (!map_sources_tab[source].url_cb) return;
3940 EINA_LIST_FREE(wd->grids, grid) grid_clear(obj, grid);
3942 wd->source = source;
3946 if (map_sources_tab[wd->source].zoom_max < zoom)
3947 zoom = map_sources_tab[wd->source].zoom_max;
3948 if (map_sources_tab[wd->source].zoom_min > zoom)
3949 zoom = map_sources_tab[wd->source].zoom_min;
3951 elm_map_zoom_set(obj, zoom);
3955 * Set the source of the route.
3957 * @param clas the group class
3958 * @param source the new source
3963 elm_map_route_source_set(Evas_Object *obj, Elm_Map_Route_Sources source __UNUSED__)
3965 ELM_CHECK_WIDTYPE(obj, widtype);
3966 Widget_Data *wd = elm_widget_data_get(obj);
3968 wd->source = source;
3972 * Get the current source
3974 * @param obj the map object
3975 * @return Returns the maximum zoom of the source
3979 EAPI Elm_Map_Sources
3980 elm_map_source_get(const Evas_Object *obj)
3982 ELM_CHECK_WIDTYPE(obj, widtype) ELM_MAP_SOURCE_MAPNIK;
3983 Widget_Data *wd = elm_widget_data_get(obj);
3984 if (!wd) return ELM_MAP_SOURCE_MAPNIK;
3989 * Get the current route source
3991 * @param obj the map object
3992 * @return Returns the source of the route
3996 EAPI Elm_Map_Route_Sources
3997 elm_map_route_source_get(const Evas_Object *obj)
3999 ELM_CHECK_WIDTYPE(obj, widtype) ELM_MAP_ROUTE_SOURCE_YOURS;
4000 Widget_Data *wd = elm_widget_data_get(obj);
4001 if (!wd) return ELM_MAP_ROUTE_SOURCE_YOURS;
4002 return wd->route_source;
4006 * Set the API of a custom source.
4008 * A custom web service can be associated to the source ELM_MAP_SOURCE_CUSTOM_(1..7).
4010 * @param source the source ID (ELM_MAP_SOURCE_CUSTOM_(1..7))
4011 * @param name the name of the source
4012 * @param zoom_min the minimum zoom of the source, must be >= 0
4013 * @param zoom_max the maximum zoom of the source, must be <= ZOOM_MAX
4014 * @param url_cb the callback used to create the url from where a tile (png or jpeg file) is downloaded.
4019 elm_map_source_custom_api_set(Elm_Map_Sources source, const char *name, int zoom_min, int zoom_max, ElmMapSourceURLFunc url_cb, ElmMapRouteSourceURLFunc route_url_cb)
4021 EINA_SAFETY_ON_NULL_RETURN(name);
4022 EINA_SAFETY_ON_NULL_RETURN(url_cb);
4023 map_sources_tab[source].name = name;
4024 map_sources_tab[source].zoom_min = zoom_min;
4025 map_sources_tab[source].zoom_max = zoom_max;
4026 map_sources_tab[source].url_cb = url_cb;
4027 map_sources_tab[source].route_url_cb = route_url_cb;
4031 * Get the maximum zoom of the source.
4033 * @param source the source
4034 * @return Returns the maximum zoom of the source
4039 elm_map_source_zoom_max_get(Elm_Map_Sources source)
4041 return map_sources_tab[source].zoom_max;
4045 * Get the minimum zoom of the source.
4047 * @param source the source
4048 * @return Returns the minimum zoom of the source
4053 elm_map_source_zoom_min_get(Elm_Map_Sources source)
4055 return map_sources_tab[source].zoom_min;
4059 * Get the name of a source.
4061 * @param source the source
4062 * @return Returns the name of the source
4067 elm_map_source_name_get(Elm_Map_Sources source)
4069 return map_sources_tab[source].name;
4073 * Set the user agent of the widget map.
4075 * @param obj The map object
4076 * @param user_agent the user agent of the widget map
4081 elm_map_user_agent_set(Evas_Object *obj, const char *user_agent)
4083 ELM_CHECK_WIDTYPE(obj, widtype);
4084 Widget_Data *wd = elm_widget_data_get(obj);
4087 if (!wd->user_agent) wd->user_agent = eina_stringshare_add(user_agent);
4088 else eina_stringshare_replace(&wd->user_agent, user_agent);
4090 if (!wd->ua) wd->ua = eina_hash_string_small_new(NULL);
4091 eina_hash_set(wd->ua, "User-Agent", wd->user_agent);
4095 * Get the user agent of the widget map.
4097 * @param obj The map object
4098 * @return The user agent of the widget map
4103 elm_map_user_agent_get(Evas_Object *obj)
4105 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4106 Widget_Data *wd = elm_widget_data_get(obj);
4108 if (!wd) return NULL;
4109 return wd->user_agent;
4113 * Add a route on the map
4115 * @param obj The map object
4116 * @param type the type if transport
4117 * @param method the routing method
4118 * @param flon the start longitude
4119 * @param flat the start latitude
4120 * @param tlon the destination longitude
4121 * @param tlat the destination latitude
4123 * @return The Route object
4127 EAPI Elm_Map_Route *
4128 elm_map_route_add(Evas_Object *obj,
4129 Elm_Map_Route_Type type,
4130 Elm_Map_Route_Method method,
4136 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4137 Widget_Data *wd = elm_widget_data_get(obj);
4138 if (!wd) return EINA_FALSE;
4141 char *type_name = NULL;
4143 Elm_Map_Route *route = ELM_NEW(Elm_Map_Route);
4144 if (!route) return NULL;
4146 snprintf(buf, sizeof(buf), DEST_XML_FILE);
4154 route->con_url = ecore_con_url_new(NULL);
4155 route->ud.fname = strdup(buf);
4156 INF("xml file : %s", route->ud.fname);
4159 route->ud.fd = fdopen(fd, "w+");
4160 if ((!route->con_url) || (!route->ud.fd))
4162 ecore_con_url_free(route->con_url);
4168 route->color.r = 255;
4171 route->color.a = 255;
4172 route->handlers = eina_list_append
4173 (route->handlers, (void *)ecore_event_handler_add
4174 (ECORE_CON_EVENT_URL_COMPLETE, _common_complete_cb, route));
4176 route->inbound = EINA_FALSE;
4178 route->method = method;
4186 case ELM_MAP_ROUTE_TYPE_MOTOCAR:
4187 type_name = strdup(ROUTE_TYPE_MOTORCAR);
4189 case ELM_MAP_ROUTE_TYPE_BICYCLE:
4190 type_name = strdup(ROUTE_TYPE_BICYCLE);
4192 case ELM_MAP_ROUTE_TYPE_FOOT:
4193 type_name = strdup(ROUTE_TYPE_FOOT);
4199 source = map_sources_tab[wd->source].route_url_cb(obj, type_name, method, flon, flat, tlon, tlat);
4200 INF("route url = %s", source);
4202 wd->route = eina_list_append(wd->route, route);
4204 ecore_con_url_url_set(route->con_url, source);
4205 ecore_con_url_fd_set(route->con_url, fileno(route->ud.fd));
4206 ecore_con_url_data_set(route->con_url, route);
4207 ecore_con_url_get(route->con_url);
4208 if (type_name) free(type_name);
4209 if (source) free(source);
4211 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
4212 "elm,state,busy,start", "elm");
4213 evas_object_smart_callback_call(wd->obj, SIG_ROUTE_LOAD, NULL);
4218 * Remove a route from the map
4220 * @param route The route to remove
4226 elm_map_route_remove(Elm_Map_Route *route)
4228 EINA_SAFETY_ON_NULL_RETURN(route);
4233 Ecore_Event_Handler *h;
4235 EINA_LIST_FREE(route->path, p)
4240 EINA_LIST_FREE(route->waypoint, w)
4242 if (w->point) eina_stringshare_del(w->point);
4246 EINA_LIST_FREE(route->nodes, n)
4248 if (n->pos.address) eina_stringshare_del(n->pos.address);
4252 EINA_LIST_FREE(route->handlers, h)
4254 ecore_event_handler_del(h);
4257 if (route->ud.fname)
4259 ecore_file_remove(route->ud.fname);
4260 free(route->ud.fname);
4261 route->ud.fname = NULL;
4266 * Set the option used for the background color
4268 * @param route The route object
4274 * This sets the color used for the route
4279 elm_map_route_color_set(Elm_Map_Route *route, int r, int g , int b, int a)
4288 * Get the option used for the background color
4290 * @param route The route object
4299 elm_map_route_color_get(Elm_Map_Route *route, int *r, int *g , int *b, int *a)
4301 if (*r) *r = route->color.r;
4302 if (*g) *g = route->color.g;
4303 if (*b) *b = route->color.b;
4304 if (*a) *a = route->color.a;
4308 * Get the information of route distance
4310 * @param route the route object
4311 * @return Returns the distance of route (unit : km)
4316 elm_map_route_distance_get(Elm_Map_Route *route)
4318 return route->info.distance;
4322 * Get the information of route nodes
4324 * @param route the route object
4325 * @return Returns the nodes of route
4331 elm_map_route_node_get(Elm_Map_Route *route)
4333 return route->info.nodes;
4337 * Get the information of route waypoint
4339 * @param route the route object
4340 * @return Returns the waypoint of route
4346 elm_map_route_waypoint_get(Elm_Map_Route *route)
4348 return route->info.waypoints;
4352 _mapnik_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom)
4355 snprintf(buf, sizeof(buf), "http://tile.openstreetmap.org/%d/%d/%d.png",
4361 _osmarender_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom)
4364 snprintf(buf, sizeof(buf),
4365 "http://tah.openstreetmap.org/Tiles/tile/%d/%d/%d.png",
4371 _cyclemap_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom)
4374 snprintf(buf, sizeof(buf),
4375 "http://andy.sandbox.cloudmade.com/tiles/cycle/%d/%d/%d.png",
4381 _maplint_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom)
4384 snprintf(buf, sizeof(buf),
4385 "http://tah.openstreetmap.org/Tiles/maplint/%d/%d/%d.png",
4391 _custom1_url_cb(Evas_Object *obj __UNUSED__, int x __UNUSED__, int y __UNUSED__, int zoom __UNUSED__)
4397 _custom2_url_cb(Evas_Object *obj __UNUSED__, int x __UNUSED__, int y __UNUSED__, int zoom __UNUSED__)
4403 _custom3_url_cb(Evas_Object *obj __UNUSED__, int x __UNUSED__, int y __UNUSED__, int zoom __UNUSED__)
4409 _custom4_url_cb(Evas_Object *obj __UNUSED__, int x __UNUSED__, int y __UNUSED__, int zoom __UNUSED__)
4415 _custom5_url_cb(Evas_Object *obj __UNUSED__, int x __UNUSED__, int y __UNUSED__, int zoom __UNUSED__)
4421 _custom6_url_cb(Evas_Object *obj __UNUSED__, int x __UNUSED__, int y __UNUSED__, int zoom __UNUSED__)
4427 _module_url_cb(Evas_Object *obj, int x, int y, int zoom)
4430 Widget_Data *wd = elm_widget_data_get(obj);
4431 if (elm_map_source_get(obj) == ELM_MAP_SOURCE_MODULE)
4432 if ((wd->m) && (wd->m->api))
4434 Mod_Api *api = wd->m->api;
4435 if ((api) && (api->obj_url_request)) buf = api->obj_url_request(obj, x, y, zoom);
4438 if (!buf) buf = strdup("");
4443 static char *_yours_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat)
4446 snprintf(buf, sizeof(buf),
4447 "%s?flat=%f&flon=%f&tlat=%f&tlon=%f&v=%s&fast=%d&instructions=1",
4448 ROUTE_YOURS_URL, flat, flon, tlat, tlon, type_name, method);
4453 // TODO: fix monav api
4455 static char *_monav_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat)
4458 snprintf(buf, sizeof(buf),
4459 "%s?flat=%f&flon=%f&tlat=%f&tlon=%f&v=%s&fast=%d&instructions=1",
4460 ROUTE_MONAV_URL, flat, flon, tlat, tlon, type_name, method);
4466 // TODO: fix ors api
4468 static char *_ors_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat)
4471 snprintf(buf, sizeof(buf),
4472 "%s?flat=%f&flon=%f&tlat=%f&tlon=%f&v=%s&fast=%d&instructions=1",
4473 ROUTE_ORS_URL, flat, flon, tlat, tlon, type_name, method);
4479 static char *_route_custom1_url_cb(Evas_Object *obj __UNUSED__, char *type_name __UNUSED__, int method __UNUSED__, double flon __UNUSED__, double flat __UNUSED__, double tlon __UNUSED__, double tlat __UNUSED__)
4484 static char *_route_custom2_url_cb(Evas_Object *obj __UNUSED__, char *type_name __UNUSED__, int method __UNUSED__, double flon __UNUSED__, double flat __UNUSED__, double tlon __UNUSED__, double tlat __UNUSED__)
4489 static char *_route_custom3_url_cb(Evas_Object *obj __UNUSED__, char *type_name __UNUSED__, int method __UNUSED__, double flon __UNUSED__, double flat __UNUSED__, double tlon __UNUSED__, double tlat __UNUSED__)
4494 static char *_route_custom4_url_cb(Evas_Object *obj __UNUSED__, char *type_name __UNUSED__, int method __UNUSED__, double flon __UNUSED__, double flat __UNUSED__, double tlon __UNUSED__, double tlat __UNUSED__)
4499 static char *_route_custom5_url_cb(Evas_Object *obj __UNUSED__, char *type_name __UNUSED__, int method __UNUSED__, double flon __UNUSED__, double flat __UNUSED__, double tlon __UNUSED__, double tlat __UNUSED__)
4504 static char *_route_custom6_url_cb(Evas_Object *obj __UNUSED__, char *type_name __UNUSED__, int method __UNUSED__, double flon __UNUSED__, double flat __UNUSED__, double tlon __UNUSED__, double tlat __UNUSED__)
4509 static char *_route_module_url_cb(Evas_Object *obj __UNUSED__, char *type_name __UNUSED__, int method __UNUSED__, double flon __UNUSED__, double flat __UNUSED__, double tlon __UNUSED__, double tlat __UNUSED__)
4511 // TODO: make example route module