From: Bluezery <ohpowel@gmail.com>
[framework/uifw/elementary.git] / src / lib / elm_map.c
1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4
5 #include "Elementary.h"
6 #include "elm_priv.h"
7 #include "els_scroller.h"
8
9 typedef struct _Widget_Data Widget_Data;
10 typedef struct _Pan Pan;
11 typedef struct _Grid Grid;
12 typedef struct _Grid_Item Grid_Item;
13 typedef struct _Marker_Group Marker_Group;
14 typedef struct _Event Event;
15 typedef struct _Path_Node Path_Node;
16 typedef struct _Path_Waypoint Path_Waypoint;
17 typedef struct _Url_Data Url_Data;
18 typedef struct _Route_Dump Route_Dump;
19 typedef struct _Name_Dump Name_Dump;
20 typedef struct _Track_Dump Track_Dump;
21
22 #define DEST_DIR_ZOOM_PATH "/tmp/elm_map/%d/%d/"
23 #define DEST_DIR_PATH DEST_DIR_ZOOM_PATH"%d/"
24 #define DEST_FILE_PATH "%s%d.png"
25 #define DEST_ROUTE_XML_FILE "/tmp/elm_map-route-XXXXXX"
26 #define DEST_NAME_XML_FILE "/tmp/elm_map-name-XXXXXX"
27
28 #define ROUTE_YOURS_URL "http://www.yournavigation.org/api/dev/route.php"
29 #define ROUTE_TYPE_MOTORCAR "motocar"
30 #define ROUTE_TYPE_BICYCLE "bicycle"
31 #define ROUTE_TYPE_FOOT "foot"
32 #define YOURS_DISTANCE "distance"
33 #define YOURS_DESCRIPTION "description"
34 #define YOURS_COORDINATES "coordinates"
35
36 // TODO: fix monav & ors url
37 #define ROUTE_MONAV_URL "http://"
38 #define ROUTE_ORS_URL "http:///"
39
40 #define NAME_NOMINATIM_URL "http://nominatim.openstreetmap.org"
41 #define NOMINATIM_RESULT "result"
42 #define NOMINATIM_PLACE "place"
43 #define NOMINATIM_ATTR_LON "lon"
44 #define NOMINATIM_ATTR_LAT "lat"
45
46 #define PINCH_ZOOM_MIN 0.25
47 #define PINCH_ZOOM_MAX 4.0
48
49 #define GPX_NAME "name>"
50 #define GPX_COORDINATES "trkpt "
51 #define GPX_LON "lon"
52 #define GPX_LAT "lat"
53 #define GPX_ELE "ele>"
54 #define GPX_TIME "time>"
55
56 // Map sources
57 // Currently the size of a tile must be 256*256
58 // and the size of the map must be pow(2.0, z)*tile_size
59 typedef struct _Map_Sources_Tab
60 {
61    const char *name;
62    int zoom_min;
63    int zoom_max;
64    ElmMapModuleUrlFunc url_cb;
65    Elm_Map_Route_Sources route_source;
66    ElmMapModuleRouteUrlFunc route_url_cb;
67    ElmMapModuleNameUrlFunc name_url_cb;
68    ElmMapModuleGeoIntoCoordFunc geo_into_coord;
69    ElmMapModuleCoordIntoGeoFunc coord_into_geo;
70 } Map_Sources_Tab;
71
72 //Zemm min is supposed to be 0
73 static char *_mapnik_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom);
74 static char *_osmarender_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom);
75 static char *_cyclemap_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom);
76 static char *_maplint_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom);
77
78 static char *_yours_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat);
79 /*
80 static char *_monav_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat)
81 static char *_ors_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat);
82  */
83 static char *_nominatim_url_cb(Evas_Object *obj, int method, char *name, double lon, double lat);
84
85 static Map_Sources_Tab default_map_sources_tab[] =
86 {
87      {"Mapnik", 0, 18, _mapnik_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb, _nominatim_url_cb, NULL, NULL},
88      {"Osmarender", 0, 17, _osmarender_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb, _nominatim_url_cb, NULL, NULL},
89      {"CycleMap", 0, 17, _cyclemap_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb, _nominatim_url_cb, NULL, NULL},
90      {"Maplint", 12, 16, _maplint_url_cb, ELM_MAP_ROUTE_SOURCE_YOURS, _yours_url_cb, _nominatim_url_cb, NULL, NULL},
91 };
92
93 struct _Url_Data
94 {
95    Ecore_Con_Url *con_url;
96
97    FILE *fd;
98    char *fname;
99 };
100
101 struct _Elm_Map_Marker_Class
102 {
103    const char *style;
104    int zoom_displayed;
105
106    struct _Elm_Map_Marker_Class_Func {
107         ElmMapMarkerGetFunc get;
108         ElmMapMarkerDelFunc del; //if NULL the object will be destroyed with evas_object_del()
109         ElmMapMarkerIconGetFunc icon_get;
110    } func;
111
112    struct { //this part is private, do not modify these values
113         Eina_Bool set : 1;
114         Evas_Coord edje_w, edje_h;
115    } priv;
116 };
117
118 struct _Elm_Map_Marker
119 {
120    Widget_Data *wd;
121    Elm_Map_Marker_Class *clas;
122    Elm_Map_Group_Class *clas_group;
123    double longitude, latitude;
124
125    Evas_Coord map_size;
126    Evas_Coord *x, *y;
127    void *data;
128    Marker_Group **groups;
129    Evas_Object *content;
130 };
131
132 struct _Elm_Map_Group_Class
133 {
134    const char *style;
135    void *data;
136    int zoom_displayed; // display the group if the zoom is >= to zoom_display
137    int zoom_grouped; // group the markers only if the zoom is <= to zoom_groups
138    Eina_Bool hide : 1;
139
140    struct {
141         ElmMapGroupIconGetFunc icon_get;
142    } func;
143
144    struct { //this part is private, do not modify these values
145         Eina_Bool set : 1;
146         Evas_Coord edje_w, edje_h;
147         Evas_Coord edje_max_w, edje_max_h;
148
149         Eina_List *objs_used;
150         Eina_List *objs_notused;
151    } priv;
152 };
153
154 struct _Marker_Group
155 {
156    Widget_Data *wd;
157    Eina_Matrixsparse_Cell *cell;
158    Elm_Map_Group_Class *clas;
159
160    Eina_List *markers;
161    long long sum_x, sum_y;
162    Evas_Coord x, y;
163    Evas_Coord w, h;
164
165    Evas_Object *obj, *bubble, *sc, *bx, *rect;
166    Eina_Bool open : 1;
167    Eina_Bool bringin : 1;
168    Eina_Bool update_nbelems : 1;
169    Eina_Bool update_resize : 1;
170    Eina_Bool update_raise : 1;
171    Eina_Bool delete_object : 1;
172 };
173
174 struct _Elm_Map_Route
175 {
176    Widget_Data *wd;
177
178    Path_Node *n;
179    Path_Waypoint *w;
180    Ecore_Con_Url *con_url;
181
182    int type;
183    int method;
184    int x, y;
185    double flon, flat, tlon, tlat;
186
187    Eina_List *nodes, *path;
188    Eina_List *waypoint;
189
190    struct {
191       int node_count;
192       int waypoint_count;
193       const char *nodes;
194       const char *waypoints;
195       double distance; /* unit : km */
196    } info;
197
198    Eina_List *handlers;
199    Url_Data ud;
200
201    struct {
202       int r;
203       int g;
204       int b;
205       int a;
206    } color;
207
208    Eina_Bool inbound : 1;
209 };
210
211 struct _Path_Node
212 {
213    Widget_Data *wd;
214
215    int idx;
216    struct {
217       double lon, lat;
218       char *address;
219    } pos;
220 };
221
222 struct _Path_Waypoint
223 {
224    Widget_Data *wd;
225
226    const char *point;
227 };
228
229 struct _Elm_Map_Name
230 {
231    Widget_Data *wd;
232
233    Ecore_Con_Url *con_url;
234    int method;
235    char *address;
236    double lon, lat;
237    Url_Data ud;
238    Ecore_Event_Handler *handler;
239 };
240
241 struct _Grid_Item
242 {
243    Widget_Data *wd;
244    Evas_Object *img;
245    //Evas_Object *txt;
246    const char *file;
247    struct {
248         int x, y, w, h;
249    } src, out;
250    Eina_Bool want : 1;
251    Eina_Bool download : 1;
252    Eina_Bool have : 1;
253    Ecore_File_Download_Job *job;
254    int try_num;
255 };
256
257 struct _Grid
258 {
259    Widget_Data *wd;
260    int tsize; // size of tile (tsize x tsize pixels)
261    int zoom; // zoom level tiles want for optimal display (1, 2, 4, 8)
262    int iw, ih; // size of image in pixels
263    int w, h; // size of grid image in pixels (represented by grid)
264    int gw, gh; // size of grid in tiles
265    Eina_Matrixsparse *grid;
266 };
267
268 struct _Widget_Data
269 {
270    Evas_Object *obj;
271    Evas_Object *scr;
272    Evas_Object *pan_smart;
273    Evas_Object *rect;
274    Evas_Object *sep_maps_markers; //map objects are below this object and marker objects are on top
275    Pan *pan;
276    Evas_Coord pan_x, pan_y, minw, minh;
277
278    int id;
279    int zoom;
280    int zoom_method;
281    Elm_Map_Zoom_Mode mode;
282
283    Ecore_Job *calc_job;
284    Ecore_Timer *scr_timer;
285    Ecore_Timer *long_timer;
286    Ecore_Animator *zoom_animator;
287    double t;
288    struct {
289         int w, h;
290         int ow, oh, nw, nh;
291         struct {
292              double x, y;
293         } spos;
294    } size;
295    struct {
296         Eina_Bool show : 1;
297         Evas_Coord x, y ,w ,h;
298    } show;
299    int tsize;
300    int nosmooth;
301    int preload_num;
302    Eina_List *grids;
303    Eina_Bool resized : 1;
304    Eina_Bool on_hold : 1;
305    Eina_Bool paused : 1;
306    Eina_Bool paused_markers : 1;
307
308    struct {
309         Eina_Bool enabled;
310         double lon, lat;
311    } center_on;
312
313    Ecore_Job *markers_place_job;
314    Eina_Matrixsparse **markers;
315    Eina_List *cells_displayed; // list of Eina_Matrixsparse_Cell
316    Evas_Coord markers_max_num;
317    int marker_max_w, marker_max_h;
318    int marker_zoom;
319    Eina_List *opened_bubbles; //opened bubbles, list of Map_Group *
320
321    Eina_List *groups_clas; // list of Elm_Map_Group_Class*
322    Eina_List *markers_clas; // list of Elm_Map_Markers_Class*
323
324    Elm_Map_Route_Sources route_source;
325    Eina_List *s_event_list;
326    int try_num;
327    int finish_num;
328
329    Eina_Hash *ua;
330    const char *user_agent;
331    Eina_List *route;
332    Eina_List *track;
333    Evas_Event_Mouse_Down ev;
334    Eina_List *names;
335    int multi_count;
336
337    struct {
338         Evas_Coord cx, cy;
339         double level, diff;
340         Eina_Bool doing : 1;
341    } pinch;
342
343    struct {
344         Evas_Coord cx, cy;
345         double a, d;
346         Eina_Bool doing : 1;
347    } rotate;
348
349    struct {
350         Evas_Coord cx, cy;
351         double level;
352    } pinch_zoom;
353    double wheel_zoom;
354    Ecore_Timer *wheel_timer;
355    Eina_Bool wheel_disabled : 1;
356
357    Eina_Array *modules;
358    Eina_List *map_sources_tab;
359    const char **source_names;
360    Evas_Map *map;
361    Ecore_Timer *zoom_timer;
362    Map_Sources_Tab *src;
363    const char *gpx_file;
364    int zoom_min, zoom_max;
365 };
366
367 struct _Pan
368 {
369    Evas_Object_Smart_Clipped_Data __clipped_data;
370    Widget_Data *wd;
371 };
372
373 struct _Event
374 {
375    int device;
376
377    struct {
378         Evas_Coord x, y;
379    } start;
380
381    struct {
382         Evas_Coord x, y;
383    } prev;
384
385    Evas_Coord x, y, w, h;
386
387    Evas_Object *object;
388    Ecore_Timer *hold_timer;
389
390    int pinch_start_dis;
391    int pinch_dis;
392 };
393
394 struct _Route_Dump
395 {
396    int id;
397    char *fname;
398    double distance;
399    char *description;
400    char *coordinates;
401 };
402
403 enum _Route_Xml_Attribute
404 {
405    ROUTE_XML_NONE,
406    ROUTE_XML_DISTANCE,
407    ROUTE_XML_DESCRIPTION,
408    ROUTE_XML_COORDINATES,
409    ROUTE_XML_LAST
410 } Route_Xml_Attibute;
411
412 struct _Name_Dump
413 {
414    int id;
415    char *address;
416    double lon;
417    double lat;
418 };
419
420 enum _Name_Xml_Attribute
421 {
422    NAME_XML_NONE,
423    NAME_XML_NAME,
424    NAME_XML_LON,
425    NAME_XML_LAT,
426    NAME_XML_LAST
427 } Name_Xml_Attibute;
428
429 enum _Zoom_Method
430 {
431    ZOOM_METHOD_NONE,
432    ZOOM_METHOD_IN,
433    ZOOM_METHOD_OUT,
434    ZOOM_METHOD_LAST
435 } Zoom_Mode;
436
437 enum _Track_Xml_Attribute
438 {
439    TRACK_XML_NONE,
440    TRACK_XML_COORDINATES,
441    TRACK_XML_LAST
442 } Track_Xml_Attibute;
443
444
445 static const char *widtype = NULL;
446
447 static const char SIG_CHANGED[] = "changed";
448 static const char SIG_CLICKED[] = "clicked";
449 static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
450 static const char SIG_LOADED_DETAIL[] = "loaded,detail";
451 static const char SIG_LOAD_DETAIL[] = "load,detail";
452 static const char SIG_LONGPRESSED[] = "longpressed";
453 static const char SIG_PRESS[] = "press";
454 static const char SIG_SCROLL[] = "scroll";
455 static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start";
456 static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop";
457 static const char SIG_ZOOM_CHANGE[] = "zoom,change";
458 static const char SIG_ZOOM_START[] = "zoom,start";
459 static const char SIG_ZOOM_STOP[] = "zoom,stop";
460 static const char SIG_DOWNLOADED[] = "downloaded";
461 static const char SIG_ROUTE_LOAD[] = "route,load";
462 static const char SIG_ROUTE_LOADED[] = "route,loaded";
463 static const char SIG_NAME_LOAD[] = "name,load";
464 static const char SIG_NAME_LOADED[] = "name,loaded";
465 static const Evas_Smart_Cb_Description _signals[] = {
466        {SIG_CHANGED, ""},
467        {SIG_CLICKED, ""},
468        {SIG_CLICKED_DOUBLE, ""},
469        {SIG_LOADED_DETAIL, ""},
470        {SIG_LOAD_DETAIL, ""},
471        {SIG_LONGPRESSED, ""},
472        {SIG_PRESS, ""},
473        {SIG_SCROLL, ""},
474        {SIG_SCROLL_DRAG_START, ""},
475        {SIG_SCROLL_DRAG_STOP, ""},
476        {SIG_ZOOM_CHANGE, ""},
477        {SIG_ZOOM_START, ""},
478        {SIG_ZOOM_STOP, ""},
479        {SIG_DOWNLOADED, ""},
480        {SIG_ROUTE_LOAD, ""},
481        {SIG_ROUTE_LOADED, ""},
482        {SIG_NAME_LOAD, ""},
483        {SIG_NAME_LOADED, ""},
484        {NULL, NULL}
485 };
486
487 static void _pan_calculate(Evas_Object *obj);
488
489 static Eina_Bool _hold_timer_cb(void *data);
490 static Eina_Bool _wheel_timer_cb(void *data);
491 static void _rect_resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
492 static void _del_hook(Evas_Object *obj);
493 static void _theme_hook(Evas_Object *obj);
494 static void _on_focus_hook(void *data, Evas_Object *obj);
495 static void _sizing_eval(Evas_Object *obj);
496 static void _calc_job(void *data);
497 static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
498                              Evas_Callback_Type type, void *event_info);
499 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);
500 static void grid_clear(Evas_Object *obj, Grid *g);
501 static Grid *grid_create(Evas_Object *obj);
502 static void grid_load(Evas_Object *obj, Grid *g);
503
504
505 static void _group_object_create(Marker_Group *group);
506 static void _group_object_free(Marker_Group *group);
507 static void _group_open_cb(void *data, Evas_Object *obj, const char *emission, const char *soure);
508 static void _group_bringin_cb(void *data, Evas_Object *obj, const char *emission, const char *soure);
509 static void _group_bubble_create(Marker_Group *group);
510 static void _group_bubble_free(Marker_Group *group);
511 static void _group_bubble_place(Marker_Group *group);
512
513 static int _group_bubble_content_update(Marker_Group *group);
514 static void _group_bubble_content_free(Marker_Group *group);
515 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);
516 static void _bubble_sc_hints_changed_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
517
518 static void _mouse_down(void *data, Evas *evas, Evas_Object *obj, void *event_info);
519 static void _mouse_up(void *data, Evas *evas, Evas_Object *obj, void *event_info);
520 static void _mouse_move(void *data, Evas *evas, Evas_Object *obj, void *event_info);
521
522 static void _mouse_multi_down(void *data, Evas *evas, Evas_Object *obj, void *event_info);
523 static void _mouse_multi_up(void *data, Evas *evas, Evas_Object *obj, void *event_info);
524 static void _mouse_multi_move(void *data, Evas *evas, Evas_Object *obj, void *event_info);
525
526 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);
527 static void track_place(Evas_Object *obj, Grid *g, Evas_Coord px, Evas_Coord py, Evas_Coord ox, Evas_Coord oy, Evas_Coord ow, Evas_Coord oh);
528
529 static int
530 get_multi_device(Evas_Object *obj)
531 {
532    Widget_Data *wd = elm_widget_data_get(obj);
533    Eina_List *l;
534    Event *ev;
535
536    EINA_LIST_FOREACH(wd->s_event_list, l, ev)
537      {
538         if (ev->device) return ev->device;
539      }
540    return 0;
541 }
542
543 static Event *
544 create_event_object(void *data, Evas_Object *obj, int device)
545 {
546    Widget_Data *wd = elm_widget_data_get(data);
547    Event *ev = calloc(1, sizeof(Event));
548
549    EINA_SAFETY_ON_NULL_RETURN_VAL(ev, NULL);
550
551    ev->object = obj;
552    ev->device = device;
553    evas_object_geometry_get(obj, &ev->x, &ev->y, &ev->w, &ev->h);
554    wd->s_event_list = eina_list_append(wd->s_event_list, ev);
555    return ev;
556 }
557
558 static Event*
559 get_event_object(void *data, int device)
560 {
561    Widget_Data *wd = elm_widget_data_get(data);
562    Eina_List *l;
563    Event *ev;
564
565    EINA_LIST_FOREACH(wd->s_event_list, l, ev)
566      {
567         if (ev->device == device) break;
568         ev = NULL;
569      }
570    return ev;
571 }
572
573 static void
574 destroy_event_object(void *data, Event *ev)
575 {
576    Widget_Data *wd = elm_widget_data_get(data);
577    EINA_SAFETY_ON_NULL_RETURN(ev);
578    ev->pinch_dis = 0;
579    wd->s_event_list = eina_list_remove(wd->s_event_list, ev);
580    if (ev->hold_timer)
581      {
582         ecore_timer_del(ev->hold_timer);
583         ev->hold_timer = NULL;
584      }
585    free(ev);
586 }
587
588 static Eina_Bool
589 module_list_cb(Eina_Module *m, void *data)
590 {
591    ELM_CHECK_WIDTYPE(data, widtype) EINA_FALSE;
592    Widget_Data *wd = elm_widget_data_get(data);
593    Map_Sources_Tab *s;
594    ElmMapModuleSourceFunc source;
595    ElmMapModuleZoomMinFunc zoom_min;
596    ElmMapModuleZoomMaxFunc zoom_max;
597    ElmMapModuleUrlFunc url;
598    ElmMapModuleRouteSourceFunc route_source;
599    ElmMapModuleRouteUrlFunc route_url;
600    ElmMapModuleNameUrlFunc name_url;
601    ElmMapModuleGeoIntoCoordFunc geo_into_coord;
602    ElmMapModuleCoordIntoGeoFunc coord_into_geo;
603    const char *file;
604
605    if (!wd) return EINA_FALSE;
606
607    file = eina_module_file_get(m);
608    if (!eina_module_load(m))
609      {
610         ERR("could not load module \"%s\": %s", file, eina_error_msg_get(eina_error_get()));
611         return EINA_FALSE;
612      }
613
614    source = eina_module_symbol_get(m, "map_module_source_get");
615    zoom_min = eina_module_symbol_get(m, "map_module_zoom_min_get");
616    zoom_max = eina_module_symbol_get(m, "map_module_zoom_max_get");
617    url = eina_module_symbol_get(m, "map_module_url_get");
618    route_source = eina_module_symbol_get(m, "map_module_route_source_get");
619    route_url = eina_module_symbol_get(m, "map_module_route_url_get");
620    name_url = eina_module_symbol_get(m, "map_module_name_url_get");
621    geo_into_coord = eina_module_symbol_get(m, "map_module_geo_into_coord");
622    coord_into_geo = eina_module_symbol_get(m, "map_module_coord_into_geo");
623    if ((!source) || (!zoom_min) || (!zoom_max) || (!url) || (!route_source) || (!route_url) || (!name_url) || (!geo_into_coord) || (!coord_into_geo))
624      {
625         ERR("could not find map_module_source_get() in module \"%s\": %s", file, eina_error_msg_get(eina_error_get()));
626         eina_module_unload(m);
627         return EINA_FALSE;
628      }
629    s = calloc(1, sizeof(Map_Sources_Tab));
630    EINA_SAFETY_ON_NULL_RETURN_VAL(s, EINA_FALSE);
631    s->name = source();
632    s->zoom_min = zoom_min();
633    s->zoom_max = zoom_max();
634    s->url_cb = url;
635    s->route_source = route_source();
636    s->route_url_cb = route_url;
637    s->name_url_cb = name_url;
638    s->geo_into_coord = geo_into_coord;
639    s->coord_into_geo = coord_into_geo;
640    wd->map_sources_tab = eina_list_append(wd->map_sources_tab, s);
641
642    return EINA_TRUE;
643 }
644
645 static void
646 module_init(void *data)
647 {
648    ELM_CHECK_WIDTYPE(data, widtype);
649    Widget_Data *wd = elm_widget_data_get(data);
650
651    if (!wd) return;
652    wd->modules = eina_module_list_get(wd->modules, MODULES_PATH, 1, &module_list_cb, data);
653 }
654
655 static void
656 source_init(void *data)
657 {
658    ELM_CHECK_WIDTYPE(data, widtype);
659    Widget_Data *wd = elm_widget_data_get(data);
660    Map_Sources_Tab *s;
661    Eina_List *l;
662    int idx;
663
664    if (!wd) return;
665    for (idx = 0; idx < 4; idx++)
666      {
667         s = calloc(1, sizeof(Map_Sources_Tab));
668         EINA_SAFETY_ON_NULL_RETURN(s);
669         s->name = default_map_sources_tab[idx].name;
670         s->zoom_min = default_map_sources_tab[idx].zoom_min;
671         s->zoom_max = default_map_sources_tab[idx].zoom_max;
672         s->url_cb = default_map_sources_tab[idx].url_cb;
673         s->route_source = default_map_sources_tab[idx].route_source;
674         s->route_url_cb = default_map_sources_tab[idx].route_url_cb;
675         s->name_url_cb = default_map_sources_tab[idx].name_url_cb;
676         s->geo_into_coord = default_map_sources_tab[idx].geo_into_coord;
677         s->coord_into_geo = default_map_sources_tab[idx].coord_into_geo;
678         wd->map_sources_tab = eina_list_append(wd->map_sources_tab, s);
679         if (!idx) wd->src = s;
680      }
681    module_init(data);
682
683    int n = eina_list_count(wd->map_sources_tab);
684    wd->source_names = malloc(sizeof(char *) * (n + 1));
685    if (!wd->source_names)
686      {
687         ERR("init source names failed.");
688         return;
689      }
690    idx = 0;
691    EINA_LIST_FOREACH(wd->map_sources_tab, l, s)
692      {
693         wd->source_names[idx] = strdup(s->name);
694         INF("source : %s", wd->source_names[idx]);
695         idx++;
696      }
697    wd->source_names[idx] = NULL;
698 }
699
700 static void
701 zoom_min_get(void *data)
702 {
703    ELM_CHECK_WIDTYPE(data, widtype);
704    Widget_Data *wd = elm_widget_data_get(data);
705    Map_Sources_Tab *s;
706    Eina_List *l;
707    int tz;
708
709    if (!wd) return;
710    EINA_LIST_FOREACH(wd->map_sources_tab, l, s)
711      {
712         tz = s->zoom_min;
713         if (tz < wd->zoom_min) wd->zoom_min = tz;
714      }
715 }
716
717 static void
718 zoom_max_get(void *data)
719 {
720    ELM_CHECK_WIDTYPE(data, widtype);
721    Widget_Data *wd = elm_widget_data_get(data);
722    Map_Sources_Tab *s;
723    Eina_List *l;
724    int tz;
725
726    if (!wd) return;
727    EINA_LIST_FOREACH(wd->map_sources_tab, l, s)
728      {
729         tz = s->zoom_max;
730         if (tz > wd->zoom_max) wd->zoom_max = tz;
731      }
732 }
733
734 static void
735 obj_rotate_zoom(void *data, Evas_Object *obj)
736 {
737    ELM_CHECK_WIDTYPE(data, widtype);
738    Widget_Data *wd = elm_widget_data_get(data);
739    int ow, oh, iw, ih;
740    if ((!wd->pinch.cx) && (!wd->pinch.cy))
741      {
742         wd->pinch.cx = wd->rotate.cx;
743         wd->pinch.cy = wd->rotate.cy;
744      }
745
746    evas_map_util_points_populate_from_object_full(wd->map, obj, 0);
747    evas_object_image_size_get(obj, &iw, &ih);
748    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
749    if ((ow < iw) || (oh < ih))
750      {
751         ow *= (double)iw / ow;
752         oh *= (double)ih / oh;
753         evas_map_point_image_uv_set(wd->map, 1, ow, 0);
754         evas_map_point_image_uv_set(wd->map, 2, ow, oh);
755         evas_map_point_image_uv_set(wd->map, 3, 0, oh);
756      }
757    evas_map_util_zoom(wd->map, wd->pinch.level, wd->pinch.level, wd->pinch.cx, wd->pinch.cy);
758    evas_map_util_rotate(wd->map, wd->rotate.d, wd->rotate.cx, wd->rotate.cy);
759    evas_object_map_enable_set(obj, EINA_TRUE);
760    evas_object_map_set(obj, wd->map);
761 }
762
763 static void
764 #ifdef ELM_EMAP
765 track_place(Evas_Object *obj, Grid *g __UNUSED__, Evas_Coord px, Evas_Coord py, Evas_Coord ox __UNUSED__, Evas_Coord oy __UNUSED__, Evas_Coord ow, Evas_Coord oh)
766 #else
767 track_place(Evas_Object *obj __UNUSED__, Grid *g __UNUSED__, Evas_Coord px __UNUSED__, Evas_Coord py __UNUSED__, Evas_Coord ox __UNUSED__, Evas_Coord oy __UNUSED__, Evas_Coord ow __UNUSED__, Evas_Coord oh __UNUSED__)
768 #endif
769 {
770 #ifdef ELM_EMAP
771    ELM_CHECK_WIDTYPE(obj, widtype);
772    Widget_Data *wd = elm_widget_data_get(obj);
773    Eina_List *l;
774    Evas_Object *route;
775    int xmin, xmax, ymin, ymax;
776
777    if (!wd) return;
778    Evas_Coord size = pow(2.0, wd->zoom)*wd->tsize;
779
780    EINA_LIST_FOREACH(wd->track, l, route)
781      {
782         elm_map_utils_convert_geo_into_coord(wd->obj, elm_route_lon_min_get(route), elm_route_lat_max_get(route), size, &xmin, &ymin);
783         elm_map_utils_convert_geo_into_coord(wd->obj, elm_route_lon_max_get(route), elm_route_lat_min_get(route), size, &xmax, &ymax);
784
785         if( !(xmin < px && xmax < px) && !(xmin > px+ow && xmax > px+ow))
786         {
787            if( !(ymin < py && ymax < py) && !(ymin > py+oh && ymax > py+oh))
788            {
789               //display the route
790               evas_object_move(route, xmin - px + ox, ymin - py + oy);
791               evas_object_resize(route, xmax - xmin, ymax - ymin);
792
793               evas_object_raise(route);
794               obj_rotate_zoom(obj, route);
795               evas_object_show(route);
796
797               continue;
798            }
799         }
800         //the route is not display
801         evas_object_hide(route);
802      }
803 #endif
804 }
805 static void
806 route_place(Evas_Object *obj, Grid *g __UNUSED__, Evas_Coord px, Evas_Coord py, Evas_Coord ox __UNUSED__, Evas_Coord oy __UNUSED__, Evas_Coord ow, Evas_Coord oh)
807 {
808    ELM_CHECK_WIDTYPE(obj, widtype);
809    Widget_Data *wd = elm_widget_data_get(obj);
810    Eina_List *lr, *lp, *ln;
811    Path_Node *n;
812    Evas_Object *p;
813    Elm_Map_Route *r;
814    int nodes;
815    int x, y, rx, ry;
816    double a;
817
818    if (!wd) return;
819    Evas_Coord size = pow(2.0, wd->zoom)*wd->tsize;
820
821    EINA_LIST_FOREACH(wd->route, lr, r)
822      {
823         EINA_LIST_FOREACH(r->path, lp, p)
824           {
825              evas_object_polygon_points_clear(p);
826           }
827
828         evas_object_geometry_get(wd->rect, &rx, &ry, NULL, NULL);
829         nodes = eina_list_count(r->nodes);
830
831         EINA_LIST_FOREACH(r->nodes, ln, n)
832           {
833              if ((!wd->zoom) || ((n->idx) &&
834                  ((n->idx % (int)ceil((double)nodes/(double)size*100.0))))) continue;
835              if (r->inbound)
836                {
837                   elm_map_utils_convert_geo_into_coord(wd->obj, n->pos.lon, n->pos.lat, size, &x, &y);
838                   if ((x >= px - ow) && (x <= (px + ow*2)) &&
839                       (y >= py - oh) && (y <= (py + oh*2)))
840                     {
841                        x = x - px + rx;
842                        y = y - py + ry;
843
844                        p = eina_list_nth(r->path, n->idx);
845                        a = (double)(y - r->y) / (double)(x - r->x);
846                        if ((abs(a) >= 1) || (r->x == x))
847                          {
848                             evas_object_polygon_point_add(p, r->x - 3, r->y);
849                             evas_object_polygon_point_add(p, r->x + 3, r->y);
850                             evas_object_polygon_point_add(p, x + 3, y);
851                             evas_object_polygon_point_add(p, x - 3, y);
852                          }
853                        else
854                          {
855                             evas_object_polygon_point_add(p, r->x, r->y - 3);
856                             evas_object_polygon_point_add(p, r->x, r->y + 3);
857                             evas_object_polygon_point_add(p, x, y + 3);
858                             evas_object_polygon_point_add(p, x, y - 3);
859                          }
860
861                        evas_object_color_set(p, r->color.r, r->color.g, r->color.b, r->color.a);
862                        evas_object_raise(p);
863                        obj_rotate_zoom(obj, p);
864                        evas_object_show(p);
865                        r->x = x;
866                        r->y = y;
867                     }
868                   else r->inbound = EINA_FALSE;
869                }
870              else
871                {
872                   elm_map_utils_convert_geo_into_coord(wd->obj, n->pos.lon, n->pos.lat, size, &x, &y);
873                   if ((x >= px - ow) && (x <= (px + ow*2)) &&
874                       (y >= py - oh) && (y <= (py + oh*2)))
875                     {
876                        r->x = x - px + rx;
877                        r->y = y - py + ry;
878                        r->inbound = EINA_TRUE;
879                     }
880                   else r->inbound = EINA_FALSE;
881                }
882           }
883           r->inbound = EINA_FALSE;
884      }
885 }
886
887 static void
888 rect_place(Evas_Object *obj, Evas_Coord px, Evas_Coord py, Evas_Coord ox, Evas_Coord oy, Evas_Coord ow, Evas_Coord oh)
889 {
890    ELM_CHECK_WIDTYPE(obj, widtype);
891    Widget_Data *wd = elm_widget_data_get(obj);
892    Evas_Coord ax, ay, gw, gh, hh, ww;
893
894    if (!wd) return;
895    evas_object_geometry_get(wd->rect, NULL, NULL, &ww, &hh);
896
897    ax = 0;
898    ay = 0;
899    gw = wd->size.w;
900    gh = wd->size.h;
901
902    if ((ww == gw) && (hh == gh)) return;
903
904    if (ow > gw) ax = (ow - gw) / 2;
905    if (oh > gh) ay = (oh - gh) / 2;
906    evas_object_move(wd->rect,
907                     ox + 0 - px + ax,
908                     oy + 0 - py + ay);
909    evas_object_resize(wd->rect, gw, gh);
910
911    if (wd->show.show)
912      {
913         wd->show.show = EINA_FALSE;
914         elm_smart_scroller_child_region_show(wd->scr, wd->show.x, wd->show.y, wd->show.w, wd->show.h);
915      }
916 }
917
918 static void
919 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)
920 {
921    ELM_CHECK_WIDTYPE(obj, widtype);
922    Widget_Data *wd = elm_widget_data_get(obj);
923    Evas_Coord ax, ay, gw, gh, tx, ty;
924    Eina_List *l, *markers;
925    Eina_Matrixsparse_Cell *cell;
926    Marker_Group *group;
927    int xx, yy, ww, hh;
928    char buf[PATH_MAX];
929    int y, x;
930    int g_xx, g_yy, g_hh, g_ww;
931
932    if (!wd) return;
933    if (g != eina_list_data_get(wd->grids)) return;
934
935    ax = 0;
936    ay = 0;
937    gw = wd->size.w;
938    gh = wd->size.h;
939    if (ow > gw) ax = (ow - gw) / 2;
940    if (oh > gh) ay = (oh - gh) / 2;
941
942    if (wd->zoom != wd->marker_zoom)
943      {
944         EINA_LIST_FREE(wd->cells_displayed, cell)
945           {
946              EINA_LIST_FOREACH(eina_matrixsparse_cell_data_get(cell), l, group)
947                {
948                   if (group->obj) _group_object_free(group);
949                }
950           }
951      }
952    wd->marker_zoom = wd->zoom;
953
954    if ((wd->paused_markers)
955        && ((wd->size.nw != wd->size.w) || (wd->size.nh != wd->size.h)) )
956      return;
957
958    g_xx = wd->pan_x / wd->tsize;
959    if (g_xx < 0) g_xx = 0;
960    g_yy = wd->pan_y / wd->tsize;
961    if (g_yy < 0) g_yy = 0;
962    g_ww = (ow / wd->tsize) + 1;
963    if (g_xx + g_ww >= g->gw) g_ww = g->gw - g_xx - 1;
964    g_hh = (oh / wd->tsize) + 1;
965    if (g_yy + g_hh >= g->gh) g_hh = g->gh - g_yy - 1;
966
967    //hide groups no more displayed
968    EINA_LIST_FREE(wd->cells_displayed, cell)
969      {
970         eina_matrixsparse_cell_position_get(cell, (unsigned long *)&y, (unsigned long *)&x);
971         if ((y < g_yy) || (y > g_yy + g_hh) || (x < g_xx) || (x > g_xx + g_ww))
972           {
973              EINA_LIST_FOREACH(eina_matrixsparse_cell_data_get(cell), l, group)
974                {
975                   if (group->obj) _group_object_free(group);
976                }
977           }
978      }
979
980    if (!wd->marker_zoom)
981      {
982         g_ww = 0;
983         g_hh = 0;
984      }
985
986    for (y = g_yy; y <= g_yy + g_hh; y++)
987      {
988         for (x = g_xx; x <= g_xx + g_ww; x++)
989           {
990              if (!wd->markers[wd->zoom]) continue;
991              eina_matrixsparse_cell_idx_get(wd->markers[wd->zoom], y, x, &cell);
992              if (!cell) continue;
993              wd->cells_displayed = eina_list_append(wd->cells_displayed, cell);
994              markers = eina_matrixsparse_cell_data_get(cell);
995              EINA_LIST_FOREACH(markers, l, group)
996                {
997                   if (!group->markers) continue;
998                   if (group->clas->zoom_displayed > wd->zoom) continue;
999
1000                   xx = group->x;
1001                   yy = group->y;
1002                   ww = group->w;
1003                   hh = group->h;
1004
1005                   if (eina_list_count(group->markers) == 1)
1006                     {
1007                        Elm_Map_Marker *m = eina_list_data_get(group->markers);
1008                        ww = m->clas->priv.edje_w;
1009                        hh = m->clas->priv.edje_h;
1010                     }
1011
1012                   if (ww <= 0) ww = 1;
1013                   if (hh <= 0) hh = 1;
1014
1015                   if ((gw != g->w) && (g->w > 0))
1016                     {
1017                        tx = xx;
1018                        xx = ((long long )gw * xx) / g->w;
1019                        ww = (((long long)gw * (tx + ww)) / g->w) - xx;
1020                     }
1021                   if ((gh != g->h) && (g->h > 0))
1022                     {
1023                        ty = yy;
1024                        yy = ((long long)gh * yy) / g->h;
1025                        hh = (((long long)gh * (ty + hh)) / g->h) - yy;
1026                     }
1027
1028                   if ((!group->clas->hide)
1029                       && (xx-px+ax+ox >= ox) && (xx-px+ax+ox<= ox+ow)
1030                       && (yy-py+ay+oy >= oy) && (yy-py+ay+oy<= oy+oh))
1031                     {
1032                        if (!group->obj) _group_object_create(group);
1033
1034                        if (group->update_nbelems)
1035                          {
1036                             group->update_nbelems = EINA_FALSE;
1037                             if (eina_list_count(group->markers) > 1)
1038                               {
1039                                  snprintf(buf, sizeof(buf), "%d", eina_list_count(group->markers));
1040                                  edje_object_part_text_set(elm_layout_edje_get(group->obj), "elm.text", buf);
1041                               }
1042                             else
1043                               edje_object_part_text_set(elm_layout_edje_get(group->obj), "elm.text", "");
1044                          }
1045                        evas_object_move(group->obj,
1046                                         xx - px + ax + ox - ww/2,
1047                                         yy - py + ay + oy - hh/2);
1048                        if ((!wd->paused_markers) || (group->update_resize))
1049                          {
1050                             group->update_resize = EINA_FALSE;
1051                             evas_object_resize(group->obj, ww, hh);
1052                             obj_rotate_zoom(obj, group->obj);
1053                          }
1054                        if (group->update_raise)
1055                          {
1056                             group->update_raise = EINA_FALSE;
1057                             evas_object_raise(group->obj);
1058                             obj_rotate_zoom(obj, group->obj);
1059                             evas_object_show(group->obj);
1060                          }
1061                        if (group->bubble) _group_bubble_place(group);
1062                     }
1063                   else if (group->obj)
1064                     {
1065                        _group_object_free(group);
1066                     }
1067                }
1068           }
1069      }
1070 }
1071
1072 static void
1073 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)
1074 {
1075    ELM_CHECK_WIDTYPE(obj, widtype);
1076    Widget_Data *wd = elm_widget_data_get(obj);
1077    Evas_Coord ax, ay, gw, gh, tx, ty;
1078    int xx, yy, ww, hh;
1079
1080    if (!wd) return;
1081    ax = 0;
1082    ay = 0;
1083    gw = wd->size.w;
1084    gh = wd->size.h;
1085    if (ow > gw) ax = (ow - gw) / 2;
1086    if (oh > gh) ay = (oh - gh) / 2;
1087
1088    Eina_Iterator *it = eina_matrixsparse_iterator_new(g->grid);
1089    Eina_Matrixsparse_Cell *cell;
1090
1091    EINA_ITERATOR_FOREACH(it, cell)
1092      {
1093         Grid_Item *gi = eina_matrixsparse_cell_data_get(cell);
1094
1095         xx = gi->out.x;
1096         yy = gi->out.y;
1097         ww = gi->out.w;
1098         hh = gi->out.h;
1099         if ((gw != g->w) && (g->w > 0))
1100           {
1101              tx = xx;
1102              xx = ((long long )gw * xx) / g->w;
1103              ww = (((long long)gw * (tx + ww)) / g->w) - xx;
1104           }
1105         if ((gh != g->h) && (g->h > 0))
1106           {
1107              ty = yy;
1108              yy = ((long long)gh * yy) / g->h;
1109              hh = (((long long)gh * (ty + hh)) / g->h) - yy;
1110           }
1111         evas_object_move(gi->img,
1112                          xx - px + ax + ox,
1113                          yy - py + ay + oy);
1114
1115         evas_object_resize(gi->img, ww, hh);
1116
1117         obj_rotate_zoom(obj, gi->img);
1118         /*evas_object_move(gi->txt,
1119                            xx - px + ax + ox,
1120                            yy - py + ay + oy);
1121
1122           evas_object_resize(gi->txt, ww, hh);
1123          */
1124      }
1125    eina_iterator_free(it);
1126 }
1127
1128 static void
1129 grid_clear(Evas_Object *obj, Grid *g)
1130 {
1131    ELM_CHECK_WIDTYPE(obj, widtype);
1132    Widget_Data *wd = elm_widget_data_get(obj);
1133    char buf[PATH_MAX];
1134
1135    if (!wd) return;
1136    if (!g->grid) return;
1137
1138    Eina_Iterator *it = eina_matrixsparse_iterator_new(g->grid);
1139    Eina_Matrixsparse_Cell *cell;
1140
1141    snprintf(buf, sizeof(buf), DEST_DIR_ZOOM_PATH, wd->id, g->zoom);
1142    ecore_file_recursive_rm(buf);
1143
1144    EINA_ITERATOR_FOREACH(it, cell)
1145      {
1146         Grid_Item *gi = eina_matrixsparse_cell_data_get(cell);
1147         evas_object_del(gi->img);
1148         //evas_object_del(gi->txt);
1149
1150         if (gi->want)
1151           {
1152              gi->want = EINA_FALSE;
1153              wd->preload_num--;
1154              if (!wd->preload_num)
1155                {
1156                   edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
1157                                           "elm,state,busy,stop", "elm");
1158                   evas_object_smart_callback_call(obj, SIG_LOADED_DETAIL, NULL);
1159                }
1160           }
1161
1162         if (gi->job)
1163           {
1164              DBG("DOWNLOAD abort %s", gi->file);
1165              ecore_file_download_abort(gi->job);
1166              ecore_file_remove(gi->file);
1167              gi->job = NULL;
1168              wd->try_num--;
1169           }
1170         if (gi->file)
1171           eina_stringshare_del(gi->file);
1172
1173         free(gi);
1174      }
1175    eina_matrixsparse_free(g->grid);
1176    eina_iterator_free(it);
1177    g->grid = NULL;
1178    g->gw = 0;
1179    g->gh = 0;
1180 }
1181
1182 static void
1183 _tile_update(Grid_Item *gi)
1184 {
1185    gi->want = EINA_FALSE;
1186    gi->download = EINA_FALSE;
1187    evas_object_image_file_set(gi->img, gi->file, NULL);
1188    if (evas_object_image_load_error_get(gi->img) != EVAS_LOAD_ERROR_NONE)
1189      {
1190         ERR("Image loading error (%s)", gi->file);
1191         ecore_file_remove(gi->file);
1192         gi->have = EINA_FALSE;
1193         return;
1194      }
1195
1196    obj_rotate_zoom(gi->wd->obj, gi->img);
1197    evas_object_show(gi->img);
1198
1199    //evas_object_text_text_set(gi->txt, gi->file);
1200    //evas_object_show(gi->txt);
1201
1202    gi->have = EINA_TRUE;
1203    gi->wd->preload_num--;
1204    if (!gi->wd->preload_num)
1205      {
1206         edje_object_signal_emit(elm_smart_scroller_edje_object_get(gi->wd->scr),
1207                                 "elm,state,busy,stop", "elm");
1208         evas_object_smart_callback_call(gi->wd->obj, SIG_LOADED_DETAIL, NULL);
1209      }
1210 }
1211
1212 static void
1213 _tile_downloaded(void *data, const char *file __UNUSED__, int status)
1214 {
1215    Grid_Item *gi = data;
1216
1217    gi->download = EINA_FALSE;
1218    gi->job = NULL;
1219
1220    if ((gi->want) && (status == 200)) _tile_update(gi);
1221
1222    if (status != 200)
1223      {
1224         DBG("Download failed %s (%d) ", gi->file, status);
1225         ecore_file_remove(gi->file);
1226      }
1227    else
1228      gi->wd->finish_num++;
1229
1230    evas_object_smart_callback_call(gi->wd->obj, SIG_DOWNLOADED, NULL);
1231    DBG("DOWNLOAD done %s", gi->file);
1232 }
1233
1234 static Grid *
1235 grid_create(Evas_Object *obj)
1236 {
1237    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1238    Widget_Data *wd = elm_widget_data_get(obj);
1239    Grid *g;
1240
1241    if ((!wd) || (!wd->src)) return NULL;
1242    g = calloc(1, sizeof(Grid));
1243
1244    g->zoom = wd->zoom;
1245    g->tsize = wd->tsize;
1246    g->wd = wd;
1247
1248    if (g->zoom > wd->src->zoom_max) return NULL;
1249    if (g->zoom < wd->src->zoom_min) return NULL;
1250
1251    int size =  pow(2.0, wd->zoom);
1252    g->gw = size;
1253    g->gh = size;
1254
1255    g->w = g->tsize * g->gw;
1256    g->h = g->tsize * g->gh;
1257
1258    g->grid = eina_matrixsparse_new(g->gh, g->gw, NULL, NULL);
1259
1260    return g;
1261 }
1262
1263 static void
1264 grid_load(Evas_Object *obj, Grid *g)
1265 {
1266    ELM_CHECK_WIDTYPE(obj, widtype);
1267    Widget_Data *wd = elm_widget_data_get(obj);
1268    int x, y;
1269    int size;
1270    Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh, tx, ty, gw, gh, xx, yy, ww, hh;
1271    Eina_Iterator *it;
1272    Eina_Matrixsparse_Cell *cell;
1273    Grid_Item *gi;
1274
1275    if ((!wd) || (!wd->src)) return;
1276    evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
1277    evas_output_viewport_get(evas_object_evas_get(wd->obj), &cvx, &cvy, &cvw, &cvh);
1278
1279    gw = wd->size.w;
1280    gh = wd->size.h;
1281
1282    if ((gw <= 0) || (gh <= 0)) return;
1283
1284    size = g->tsize;
1285    if ((gw != g->w) && (g->w > 0))
1286      size = ((long long)gw * size) / g->w;
1287    if (size < (g->tsize / 2)) return; // else we will load to much tiles
1288
1289    it = eina_matrixsparse_iterator_new(g->grid);
1290
1291    EINA_ITERATOR_FOREACH(it, cell)
1292      {
1293         gi = eina_matrixsparse_cell_data_get(cell);
1294
1295         xx = gi->out.x;
1296         yy = gi->out.y;
1297         ww = gi->out.w;
1298         hh = gi->out.h;
1299
1300         if ((gw != g->w) && (g->w > 0))
1301           {
1302              tx = xx;
1303              xx = ((long long )gw * xx) / g->w;
1304              ww = (((long long)gw * (tx + ww)) / g->w) - xx;
1305           }
1306         if ((gh != g->h) && (g->h > 0))
1307           {
1308              ty = yy;
1309              yy = ((long long)gh * yy) / g->h;
1310              hh = (((long long)gh * (ty + hh)) / g->h) - yy;
1311           }
1312
1313         if (!ELM_RECTS_INTERSECT(xx - wd->pan_x + ox,
1314                                  yy  - wd->pan_y + oy,
1315                                  ww, hh,
1316                                  cvx, cvy, cvw, cvh))
1317           {
1318              if (gi->want)
1319                {
1320                   evas_object_hide(gi->img);
1321                   //evas_object_hide(gi->txt);
1322                   evas_object_image_file_set(gi->img, NULL, NULL);
1323                   gi->want = EINA_FALSE;
1324                   gi->have = EINA_FALSE;
1325
1326                   if (gi->job)
1327                     {
1328                        DBG("DOWNLOAD abort %s", gi->file);
1329                        ecore_file_download_abort(gi->job);
1330                        ecore_file_remove(gi->file);
1331                        gi->job = NULL;
1332                        wd->try_num--;
1333                     }
1334                   gi->download = EINA_FALSE;
1335                   wd->preload_num--;
1336                   if (!wd->preload_num)
1337                     {
1338                        edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
1339                                                "elm,state,busy,stop", "elm");
1340                        evas_object_smart_callback_call(obj, SIG_LOADED_DETAIL,
1341                                                        NULL);
1342                     }
1343
1344                }
1345              else if (gi->have)
1346                {
1347                   evas_object_hide(gi->img);
1348                   //evas_object_hide(gi->txt);
1349                   evas_object_image_preload(gi->img, 1);
1350                   evas_object_image_file_set(gi->img, NULL, NULL);
1351                   gi->have = EINA_FALSE;
1352                   gi->want = EINA_FALSE;
1353                }
1354           }
1355      }
1356    eina_iterator_free(it);
1357
1358    xx = wd->pan_x / size - 1;
1359    if (xx < 0) xx = 0;
1360
1361    yy = wd->pan_y / size - 1;
1362    if (yy < 0) yy = 0;
1363
1364    ww = ow / size + 2;
1365    if (xx + ww >= g->gw) ww = g->gw - xx - 1;
1366
1367    hh = oh / size + 2;
1368    if (yy + hh >= g->gh) hh = g->gh - yy - 1;
1369
1370    for (y = yy; y <= yy + hh; y++)
1371      {
1372         for (x = xx; x <= xx + ww; x++)
1373           {
1374              gi = eina_matrixsparse_data_idx_get(g->grid, y, x);
1375
1376              if ((!gi) && (g != eina_list_data_get(wd->grids)))
1377                continue;
1378
1379              if (!gi)
1380                {
1381                   gi = calloc(1, sizeof(Grid_Item));
1382                   gi->src.x = x * g->tsize;
1383                   gi->src.y = y * g->tsize;
1384                   gi->src.w = g->tsize;
1385                   gi->src.h = g->tsize;
1386
1387                   gi->out.x = gi->src.x;
1388                   gi->out.y = gi->src.y;
1389                   gi->out.w = gi->src.w;
1390                   gi->out.h = gi->src.h;
1391
1392                   gi->wd = wd;
1393
1394                   gi->img = evas_object_image_add(evas_object_evas_get(obj));
1395                   evas_object_image_scale_hint_set
1396                      (gi->img, EVAS_IMAGE_SCALE_HINT_DYNAMIC);
1397                   evas_object_image_filled_set(gi->img, 1);
1398
1399                   evas_object_smart_member_add(gi->img, wd->pan_smart);
1400                   elm_widget_sub_object_add(obj, gi->img);
1401                   evas_object_pass_events_set(gi->img, EINA_TRUE);
1402                   evas_object_stack_below(gi->img, wd->sep_maps_markers);
1403
1404 /*                gi->txt = evas_object_text_add(evas_object_evas_get(obj));
1405                   evas_object_text_font_set(gi->txt, "Vera", 12);
1406                   evas_object_color_set(gi->txt, 100, 100, 100, 255);
1407                   evas_object_smart_member_add(gi->txt,
1408                                                wd->pan_smart);
1409                   elm_widget_sub_object_add(obj, gi->txt);
1410                   evas_object_pass_events_set(gi->txt, EINA_TRUE);
1411 */
1412                   eina_matrixsparse_data_idx_set(g->grid, y, x, gi);
1413                }
1414
1415              if ((!gi->have) && (!gi->download))
1416                {
1417                   char buf[PATH_MAX], buf2[PATH_MAX];
1418                   char *source;
1419
1420                   gi->want = EINA_TRUE;
1421
1422                   snprintf(buf, sizeof(buf), DEST_DIR_PATH, wd->id, g->zoom, x);
1423                   if (!ecore_file_exists(buf))
1424                     ecore_file_mkpath(buf);
1425
1426                   snprintf(buf2, sizeof(buf2), DEST_FILE_PATH, buf, y);
1427
1428                   source = wd->src->url_cb(obj, x, y, g->zoom);
1429                   if ((!source) || (strlen(source)==0)) continue;
1430
1431                   eina_stringshare_replace(&gi->file, buf2);
1432
1433                   if ((ecore_file_exists(buf2)) || (g == eina_list_data_get(wd->grids)))
1434                     {
1435                        gi->download = EINA_TRUE;
1436                        wd->preload_num++;
1437                        if (wd->preload_num == 1)
1438                          {
1439                             edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
1440                                                     "elm,state,busy,start", "elm");
1441                             evas_object_smart_callback_call(obj,
1442                                                             SIG_LOAD_DETAIL,
1443                                                             NULL);
1444                          }
1445
1446                        if (ecore_file_exists(buf2))
1447                          _tile_update(gi);
1448                        else
1449                          {
1450                             DBG("DOWNLOAD %s \t in %s", source, buf2);
1451                             ecore_file_download_full(source, buf2, _tile_downloaded, NULL, gi, &(gi->job), wd->ua);
1452                             if (!gi->job)
1453                               DBG("Can't start to download %s", buf);
1454                             else
1455                               wd->try_num++;
1456                          }
1457                     }
1458                   if (source) free(source);
1459                }
1460              else if (gi->have)
1461                {
1462                   obj_rotate_zoom(obj, gi->img);
1463                   evas_object_show(gi->img);
1464                }
1465           }
1466      }
1467 }
1468
1469 static void
1470 grid_clearall(Evas_Object *obj)
1471 {
1472    ELM_CHECK_WIDTYPE(obj, widtype);
1473    Widget_Data *wd = elm_widget_data_get(obj);
1474    Grid *g;
1475
1476    if (!wd) return;
1477    EINA_LIST_FREE(wd->grids, g)
1478      {
1479         grid_clear(obj, g);
1480         free(g);
1481      }
1482 }
1483
1484 static void
1485 _smooth_update(Evas_Object *obj)
1486 {
1487    ELM_CHECK_WIDTYPE(obj, widtype);
1488    Widget_Data *wd = elm_widget_data_get(obj);
1489    Eina_List *l;
1490    Grid *g;
1491
1492    if (!wd) return;
1493    EINA_LIST_FOREACH(wd->grids, l, g)
1494      {
1495         Eina_Iterator *it = eina_matrixsparse_iterator_new(g->grid);
1496         Eina_Matrixsparse_Cell *cell;
1497
1498         EINA_ITERATOR_FOREACH(it, cell)
1499           {
1500              Grid_Item *gi = eina_matrixsparse_cell_data_get(cell);
1501              evas_object_image_smooth_scale_set(gi->img, (!wd->nosmooth));
1502           }
1503         eina_iterator_free(it);
1504      }
1505 }
1506
1507 static Eina_Bool
1508 _scr_timeout(void *data)
1509 {
1510    ELM_CHECK_WIDTYPE(data, widtype) ECORE_CALLBACK_CANCEL;
1511    Widget_Data *wd = elm_widget_data_get(data);
1512
1513    if (!wd) return ECORE_CALLBACK_CANCEL;
1514    wd->nosmooth--;
1515    if (!wd->nosmooth) _smooth_update(data);
1516    wd->scr_timer = NULL;
1517    return ECORE_CALLBACK_CANCEL;
1518 }
1519
1520 static void
1521 _scr(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1522 {
1523    ELM_CHECK_WIDTYPE(data, widtype);
1524    Widget_Data *wd = elm_widget_data_get(data);
1525
1526    if (!wd) return;
1527    if (!wd->scr_timer)
1528      {
1529         wd->nosmooth++;
1530         if (wd->nosmooth == 1) _smooth_update(data);
1531      }
1532    if (wd->scr_timer) ecore_timer_del(wd->scr_timer);
1533    wd->scr_timer = ecore_timer_add(0.5, _scr_timeout, data);
1534 }
1535
1536 static void
1537 zoom_do(Evas_Object *obj)
1538 {
1539    ELM_CHECK_WIDTYPE(obj, widtype);
1540    Widget_Data *wd = elm_widget_data_get(obj);
1541    Evas_Coord xx, yy, ow, oh;
1542
1543    if (!wd) return;
1544    wd->size.w = wd->size.nw;
1545    wd->size.h = wd->size.nh;
1546
1547    elm_smart_scroller_child_viewport_size_get(wd->scr, &ow, &oh);
1548
1549    if (wd->center_on.enabled)
1550      {
1551         elm_map_utils_convert_geo_into_coord(obj, wd->center_on.lon, wd->center_on.lat, wd->size.w, &xx, &yy);
1552         xx -= ow / 2;
1553         yy -= oh / 2;
1554      }
1555    else
1556      {
1557         xx = (wd->size.spos.x * wd->size.w) - (ow / 2);
1558         yy = (wd->size.spos.y * wd->size.h) - (oh / 2);
1559      }
1560
1561
1562    if (xx < 0) xx = 0;
1563    else if (xx > (wd->size.w - ow)) xx = wd->size.w - ow;
1564    if (yy < 0) yy = 0;
1565    else if (yy > (wd->size.h - oh)) yy = wd->size.h - oh;
1566
1567    wd->show.show = EINA_TRUE;
1568    wd->show.x = xx;
1569    wd->show.y = yy;
1570    wd->show.w = ow;
1571    wd->show.h = oh;
1572
1573    if (wd->calc_job) ecore_job_del(wd->calc_job);
1574    wd->calc_job = ecore_job_add(_calc_job, wd);
1575 }
1576
1577 static Eina_Bool
1578 _zoom_timeout(void *data)
1579 {
1580    ELM_CHECK_WIDTYPE(data, widtype) ECORE_CALLBACK_CANCEL;
1581    Widget_Data *wd = elm_widget_data_get(data);
1582
1583    if (!wd) return ECORE_CALLBACK_CANCEL;
1584    wd->zoom_timer = NULL;
1585    wd->pinch.level = 1.0;
1586    zoom_do(data);
1587    evas_object_smart_callback_call(data, SIG_ZOOM_STOP, NULL);
1588    return ECORE_CALLBACK_CANCEL;
1589 }
1590
1591 static Eina_Bool
1592 _zoom_anim(void *data)
1593 {
1594    ELM_CHECK_WIDTYPE(data, widtype) ECORE_CALLBACK_CANCEL;
1595    Evas_Object *obj = data;
1596    Widget_Data *wd = elm_widget_data_get(obj);
1597
1598    if (!wd) return ECORE_CALLBACK_CANCEL;
1599    if (wd->zoom_method == ZOOM_METHOD_IN) wd->t += 0.1 ;
1600    else if (wd->zoom_method == ZOOM_METHOD_OUT) wd->t -= 0.05;
1601    else
1602      {
1603         wd->zoom_animator = NULL;
1604         zoom_do(obj);
1605         evas_object_smart_callback_call(data, SIG_ZOOM_STOP, NULL);
1606         return ECORE_CALLBACK_CANCEL;
1607      }
1608
1609    if (wd->t >= 2.0)
1610      {
1611         wd->zoom_animator = NULL;
1612         wd->pinch.level = 2.0;
1613         if (wd->zoom_timer) ecore_timer_del(wd->zoom_timer);
1614         wd->zoom_timer = ecore_timer_add(0.35, _zoom_timeout, obj);
1615         return ECORE_CALLBACK_CANCEL;
1616      }
1617    else if (wd->t <= 0.5)
1618      {
1619         wd->zoom_animator = NULL;
1620         wd->pinch.level = 0.5;
1621         if (wd->zoom_timer) ecore_timer_del(wd->zoom_timer);
1622         wd->zoom_timer = ecore_timer_add(1.35, _zoom_timeout, obj);
1623         return ECORE_CALLBACK_CANCEL;
1624      }
1625    else if (wd->t != 1.0)
1626      {
1627         Evas_Coord x, y, w, h;
1628         float half_w, half_h;
1629         evas_object_geometry_get(data, &x, &y, &w, &h);
1630         half_w = (float)w * 0.5;
1631         half_h = (float)h * 0.5;
1632         wd->pinch.cx = x + half_w;
1633         wd->pinch.cy = y + half_h;
1634         wd->pinch.level = wd->t;
1635         if (wd->calc_job) ecore_job_del(wd->calc_job);
1636         wd->calc_job = ecore_job_add(_calc_job, wd);
1637      }
1638    return ECORE_CALLBACK_RENEW;
1639 }
1640
1641 static Eina_Bool
1642 _long_press(void *data)
1643 {
1644    ELM_CHECK_WIDTYPE(data, widtype) ECORE_CALLBACK_CANCEL;
1645    Widget_Data *wd = elm_widget_data_get(data);
1646
1647    if (!wd) return ECORE_CALLBACK_CANCEL;
1648    wd->long_timer = NULL;
1649    evas_object_smart_callback_call(data, SIG_LONGPRESSED, &wd->ev);
1650    return ECORE_CALLBACK_CANCEL;
1651 }
1652
1653 static void
1654 _mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info)
1655 {
1656    ELM_CHECK_WIDTYPE(data, widtype);
1657    Widget_Data *wd = elm_widget_data_get(data);
1658    Evas_Event_Mouse_Down *ev = event_info;
1659    Event *ev0;
1660
1661    if (!wd) return;
1662    ev0 = get_event_object(data, 0);
1663    if (ev0) return;
1664    ev0 = create_event_object(data, obj, 0);
1665    if (!ev0) return;
1666
1667    ev0->hold_timer = NULL;
1668    ev0->prev.x = ev->canvas.x;
1669    ev0->prev.y = ev->canvas.y;
1670
1671    if (ev->button != 1) return;
1672    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) wd->on_hold = EINA_TRUE;
1673    else wd->on_hold = EINA_FALSE;
1674    if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
1675      evas_object_smart_callback_call(data, SIG_CLICKED_DOUBLE, ev);
1676    else
1677      evas_object_smart_callback_call(data, SIG_PRESS, ev);
1678    if (wd->long_timer) ecore_timer_del(wd->long_timer);
1679    wd->ev.canvas.x = ev->output.x;
1680    wd->ev.canvas.y = ev->output.y;
1681    wd->long_timer = ecore_timer_add(_elm_config->longpress_timeout, _long_press, data);
1682 }
1683
1684 static void
1685 _mouse_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1686 {
1687    Evas_Event_Mouse_Move *move = event_info;
1688    Event *ev0;
1689
1690    ev0 = get_event_object(data, 0);
1691    if (!ev0) return;
1692    ev0->prev.x = move->cur.canvas.x;
1693    ev0->prev.y = move->cur.canvas.y;
1694 }
1695
1696 static void
1697 _mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1698 {
1699    ELM_CHECK_WIDTYPE(data, widtype);
1700    Widget_Data *wd = elm_widget_data_get(data);
1701
1702    if (!wd) return;
1703    Evas_Event_Mouse_Up *ev = event_info;
1704    int mdevice;
1705    Event *ev0;
1706    Event *ev1;
1707
1708    ev0 = get_event_object(data, 0);
1709    if (ev0)
1710      {
1711         mdevice = get_multi_device(data);
1712         if (mdevice == 0)
1713           {
1714              if (ev0->hold_timer)
1715                {
1716                   ecore_timer_del(ev0->hold_timer);
1717                   ev0->hold_timer = NULL;
1718                }
1719              elm_smart_scroller_hold_set(wd->scr, 0);
1720              elm_smart_scroller_freeze_set(wd->scr, 0);
1721           }
1722         else
1723           {
1724              ev1 = get_event_object(data, mdevice);
1725              if (ev1)
1726                ev1->hold_timer = ecore_timer_add(0.35, _hold_timer_cb, ev1);
1727           }
1728         destroy_event_object(data, ev0);
1729      }
1730
1731    if (ev->button != 1) return;
1732    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) wd->on_hold = EINA_TRUE;
1733    else wd->on_hold = EINA_FALSE;
1734    if (wd->long_timer)
1735      {
1736         ecore_timer_del(wd->long_timer);
1737         wd->long_timer = NULL;
1738      }
1739    if (!wd->on_hold) evas_object_smart_callback_call(data, SIG_CLICKED, ev);
1740    wd->on_hold = EINA_FALSE;
1741 }
1742
1743 static void
1744 _mouse_multi_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info)
1745 {
1746    ELM_CHECK_WIDTYPE(data, widtype);
1747    Widget_Data *wd = elm_widget_data_get(data);
1748    Event *ev;
1749    Evas_Event_Multi_Down *down = event_info;
1750
1751    elm_smart_scroller_hold_set(wd->scr, 1);
1752    elm_smart_scroller_freeze_set(wd->scr, 1);
1753
1754    ev = create_event_object(data, obj, down->device);
1755    if (!ev)
1756      {
1757         DBG("Failed : create_event_object");
1758         goto done;
1759      }
1760    wd->multi_count++;
1761
1762    ev->hold_timer = NULL;
1763    ev->start.x = ev->prev.x = down->canvas.x;
1764    ev->start.y = ev->prev.y = down->canvas.y;
1765    ev->pinch_start_dis = 0;
1766    wd->pinch.level = 1.0;
1767    wd->pinch.diff = 1.0;
1768
1769 done:
1770    if (wd->long_timer)
1771      {
1772         ecore_timer_del(wd->long_timer);
1773         wd->long_timer = NULL;
1774      }
1775    return;
1776 }
1777
1778 static void
1779 _mouse_multi_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1780 {
1781    ELM_CHECK_WIDTYPE(data, widtype);
1782    Widget_Data *wd = elm_widget_data_get(data);
1783    Evas_Event_Multi_Move *move = event_info;
1784    int dis_new, dx, dy;
1785    double t, tt, a, a_diff;
1786    Event *ev0;
1787    Event *ev;
1788
1789    if ((!wd) || (!wd->src)) return;
1790    ev = get_event_object(data, move->device);
1791    if (!ev) return;
1792
1793    ev0 = get_event_object(data, 0);
1794    if (!ev0) return;
1795
1796    if (wd->multi_count >= 1)
1797      {
1798         Evas_Coord x, y, w, h;
1799         float half_w, half_h;
1800
1801         evas_object_geometry_get(data, &x, &y, &w, &h);
1802         half_w = (float)w * 0.5;
1803         half_h = (float)h * 0.5;
1804         dx = ev0->prev.x - ev->prev.x;
1805         dy = ev0->prev.y - ev->prev.y;
1806         dis_new = sqrt((dx * dx) + (dy * dy));
1807
1808         if (!ev->pinch_start_dis) ev->pinch_start_dis = dis_new;
1809         else
1810           {
1811              ev->pinch_dis = dis_new;
1812              tt = wd->pinch.diff;
1813              wd->pinch.diff = (double)(ev->pinch_dis - ev->pinch_start_dis);
1814              t = (wd->pinch.diff * 0.01) + 1.0;
1815              if ((t > 1.1) || (wd->rotate.doing))
1816                {
1817                   if (((wd->zoom + (int)t - 1) < wd->src->zoom_min) ||
1818                       ((wd->zoom + (int)t - 1) > wd->src->zoom_max) ||
1819                       (t > PINCH_ZOOM_MAX) || (t < PINCH_ZOOM_MIN))
1820                     {
1821                        wd->pinch.diff = tt;
1822                        goto do_nothing;
1823                     }
1824                   else
1825                     {
1826                        wd->pinch.level = (wd->pinch.diff * 0.01) + 1.0;
1827                        wd->pinch.cx = x + half_w;
1828                        wd->pinch.cy = y + half_h;
1829                        wd->pinch.doing = EINA_TRUE;
1830                        if (!wd->rotate.doing) goto do_zoom_only;
1831                     }
1832                }
1833              else
1834                {
1835                   if (wd->pinch.doing) goto do_nothing;
1836                }
1837
1838              a = (double)(ev->prev.y - ev0->prev.y) / (double)(ev->prev.x - ev0->prev.x);
1839              if (!wd->rotate.a) wd->rotate.a = a;
1840              else
1841                {
1842                   a_diff = wd->rotate.a - a;
1843                   if (a_diff > 0) wd->rotate.d -= 1.0;
1844                   else if (a_diff < 0) wd->rotate.d += 1.0;
1845                   wd->rotate.a = a;
1846                   wd->rotate.cx = x + half_w;
1847                   wd->rotate.cy = y + half_h;
1848                   wd->rotate.doing = EINA_TRUE;
1849                }
1850 do_zoom_only:
1851              if (wd->calc_job) ecore_job_del(wd->calc_job);
1852              wd->calc_job = ecore_job_add(_calc_job, wd);
1853           }
1854      }
1855 do_nothing:
1856    ev->prev.x = move->cur.canvas.x;
1857    ev->prev.y = move->cur.canvas.y;
1858 }
1859
1860 static void
1861 _mouse_multi_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1862 {
1863    ELM_CHECK_WIDTYPE(data, widtype);
1864    Widget_Data *wd = elm_widget_data_get(data);
1865    Evas_Event_Multi_Up *up = event_info;
1866    Event *ev0;
1867    Event *ev;
1868    Eina_Bool tp;
1869    int zoom = 0;
1870
1871    wd->multi_count--;
1872    if (wd->calc_job) ecore_job_del(wd->calc_job);
1873    if (wd->zoom_animator)
1874      {
1875         ecore_animator_del(wd->zoom_animator);
1876         wd->zoom_animator = NULL;
1877      }
1878    tp = wd->paused;
1879    wd->paused = EINA_TRUE;
1880    if (wd->pinch.diff >= 0.0) zoom = (int)ceil((wd->pinch.diff * 0.01) - 1.0);
1881    else if (wd->pinch.diff < 0.0) zoom = (int)floor(-1.0 / ((wd->pinch.diff * 0.005) + 1.0));
1882    elm_map_zoom_set(data, wd->zoom + zoom);
1883    wd->pinch.level = 1.0;
1884    wd->pinch.doing = EINA_FALSE;
1885    wd->paused = tp;
1886    wd->rotate.a = 0.0;
1887    wd->rotate.doing = EINA_FALSE;
1888
1889    ev = get_event_object(data, up->device);
1890    if (!ev)
1891      {
1892         DBG("Cannot get multi device");
1893         return;
1894      }
1895
1896    ev0 = get_event_object(data, 0);
1897    if (ev0)
1898      ev0->hold_timer = ecore_timer_add(0.35, _hold_timer_cb, ev0);
1899    else
1900      {
1901         if (ev->hold_timer)
1902           {
1903              ecore_timer_del(ev->hold_timer);
1904              ev->hold_timer = NULL;
1905           }
1906      }
1907    destroy_event_object(data, ev);
1908 }
1909
1910 static void
1911 _mouse_wheel_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1912 {
1913    ELM_CHECK_WIDTYPE(data, widtype);
1914    Widget_Data *wd = elm_widget_data_get(data);
1915    Evas_Event_Mouse_Wheel *ev = (Evas_Event_Mouse_Wheel*) event_info;
1916    Evas_Coord x, y, w, h;
1917    float half_w, half_h;
1918
1919    if (!wd) return;
1920    evas_object_geometry_get(data, &x, &y, &w, &h);
1921    half_w = (float)w * 0.5;
1922    half_h = (float)h * 0.5;
1923
1924    if (ev->z > 0)
1925      {
1926         wd->zoom_method = ZOOM_METHOD_OUT;
1927         wd->wheel_zoom -= 0.1;
1928         if (wd->wheel_zoom <= -2.0) wd->wheel_zoom = -2.0;
1929      }
1930    else
1931      {
1932         wd->zoom_method = ZOOM_METHOD_IN;
1933         wd->wheel_zoom += 0.1;
1934         if (wd->wheel_zoom >= 2.0) wd->wheel_zoom = 2.0;
1935      }
1936
1937    if (!wd->paused)
1938      {
1939         wd->pinch.level = pow(2.0, wd->wheel_zoom);
1940         wd->pinch.cx = x + half_w;
1941         wd->pinch.cy = y + half_h;
1942         if (wd->calc_job) ecore_job_del(wd->calc_job);
1943         wd->calc_job = ecore_job_add(_calc_job, wd);
1944      }
1945
1946    if (wd->wheel_timer) ecore_timer_del(wd->wheel_timer);
1947    wd->wheel_timer = ecore_timer_add(0.35, _wheel_timer_cb, data);
1948 }
1949
1950
1951 static Evas_Smart_Class _pan_sc = EVAS_SMART_CLASS_INIT_NULL;
1952
1953 static Eina_Bool
1954 _hold_timer_cb(void *data)
1955 {
1956    Event *ev0 = data;
1957
1958    ev0->hold_timer = NULL;
1959    return ECORE_CALLBACK_CANCEL;
1960 }
1961
1962 static Eina_Bool
1963 _wheel_timer_cb(void *data)
1964 {
1965    ELM_CHECK_WIDTYPE(data, widtype) ECORE_CALLBACK_CANCEL;
1966    Widget_Data *wd = elm_widget_data_get(data);
1967    int zoom;
1968
1969    if (!wd) return ECORE_CALLBACK_CANCEL;
1970    if (wd->zoom_method == ZOOM_METHOD_IN) zoom = (int)ceil(wd->wheel_zoom);
1971    else if (wd->zoom_method == ZOOM_METHOD_OUT) zoom = (int)floor(wd->wheel_zoom);
1972    else
1973      {
1974         wd->wheel_timer = NULL;
1975         return ECORE_CALLBACK_CANCEL;
1976      }
1977
1978    wd->mode = ELM_MAP_ZOOM_MODE_MANUAL;
1979    wd->pinch.level = 1.0;
1980    elm_map_zoom_set(data, wd->zoom + zoom);
1981    wd->wheel_zoom = 0.0;
1982    wd->wheel_timer = NULL;
1983    wd->zoom_method = ZOOM_METHOD_NONE;
1984    return ECORE_CALLBACK_CANCEL;
1985 }
1986
1987 static void
1988 _rect_resize_cb(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1989 {
1990    ELM_CHECK_WIDTYPE(data, widtype);
1991    Widget_Data *wd = elm_widget_data_get(data);
1992    int x, y, w, h;
1993
1994    evas_object_geometry_get(wd->rect, &x, &y, &w, &h);
1995    evas_object_geometry_get(wd->pan_smart, &x, &y, &w, &h);
1996    evas_object_resize(wd->rect, w, h);
1997    evas_object_move(wd->rect, x, y);
1998 }
1999
2000 static void
2001 _del_hook(Evas_Object *obj)
2002 {
2003    ELM_CHECK_WIDTYPE(obj, widtype);
2004    Widget_Data *wd = elm_widget_data_get(obj);
2005    Elm_Map_Group_Class *group_clas;
2006    Elm_Map_Marker_Class *marker_clas;
2007    Eina_List *l;
2008    Event *ev;
2009    Evas_Object *p;
2010    Path_Node *n;
2011    Path_Waypoint *w;
2012    Ecore_Event_Handler *h;
2013    Elm_Map_Route *r;
2014    Elm_Map_Name *na;
2015    Evas_Object *route;
2016
2017    if (!wd) return;
2018    EINA_LIST_FREE(wd->groups_clas, group_clas)
2019      {
2020         if (group_clas->style)
2021           eina_stringshare_del(group_clas->style);
2022         free(group_clas);
2023      }
2024
2025    EINA_LIST_FREE(wd->markers_clas, marker_clas)
2026      {
2027         if (marker_clas->style)
2028           eina_stringshare_del(marker_clas->style);
2029         free(marker_clas);
2030      }
2031
2032    EINA_LIST_FOREACH(wd->s_event_list, l, ev)
2033      {
2034         destroy_event_object(obj, ev);
2035      }
2036
2037    EINA_LIST_FOREACH(wd->route, l, r)
2038      {
2039         EINA_LIST_FREE(r->path, p)
2040           {
2041              evas_object_del(p);
2042           }
2043
2044         EINA_LIST_FREE(r->waypoint, w)
2045           {
2046              if (w->point) eina_stringshare_del(w->point);
2047              free(w);
2048           }
2049
2050         EINA_LIST_FREE(r->nodes, n)
2051           {
2052              if (n->pos.address) eina_stringshare_del(n->pos.address);
2053              free(n);
2054           }
2055
2056         EINA_LIST_FREE(r->handlers, h)
2057           {
2058              ecore_event_handler_del(h);
2059           }
2060
2061         if (r->con_url) ecore_con_url_free(r->con_url);
2062         if (r->info.nodes) eina_stringshare_del(r->info.nodes);
2063         if (r->info.waypoints) eina_stringshare_del(r->info.waypoints);
2064      }
2065
2066    EINA_LIST_FREE(wd->names, na)
2067      {
2068         if (na->address) free(na->address);
2069         if (na->handler) ecore_event_handler_del(na->handler);
2070         if (na->ud.fname)
2071           {
2072              ecore_file_remove(na->ud.fname);
2073              free(na->ud.fname);
2074              na->ud.fname = NULL;
2075           }
2076      }
2077
2078    EINA_LIST_FREE(wd->track, route)
2079      {
2080         evas_object_del(route);
2081      }
2082
2083    if (wd->map) evas_map_free(wd->map);
2084    if (wd->source_names) free(wd->source_names);
2085    if (wd->calc_job) ecore_job_del(wd->calc_job);
2086    if (wd->scr_timer) ecore_timer_del(wd->scr_timer);
2087    if (wd->zoom_animator) ecore_animator_del(wd->zoom_animator);
2088    if (wd->long_timer) ecore_timer_del(wd->long_timer);
2089    if (wd->user_agent) eina_stringshare_del(wd->user_agent);
2090    if (wd->ua) eina_hash_free(wd->ua);
2091    if (wd->markers) free(wd->markers);
2092
2093    free(wd);
2094 }
2095
2096 static void
2097 _del_pre_hook(Evas_Object *obj)
2098 {
2099    ELM_CHECK_WIDTYPE(obj, widtype);
2100    Widget_Data *wd = elm_widget_data_get(obj);
2101    Marker_Group *group;
2102    Elm_Map_Marker *marker;
2103    int i;
2104    Eina_Bool free_marker = EINA_TRUE;
2105    Eina_List *l;
2106
2107    if (!wd) return;
2108    grid_clearall(obj);
2109    for (i = 0; i <= wd->zoom_max; i++)
2110      {
2111         if (!wd->markers[i]) continue;
2112         Eina_Iterator *it = eina_matrixsparse_iterator_new(wd->markers[i]);
2113         Eina_Matrixsparse_Cell *cell;
2114
2115         EINA_ITERATOR_FOREACH(it, cell)
2116           {
2117              l =  eina_matrixsparse_cell_data_get(cell);
2118              EINA_LIST_FREE(l, group)
2119                {
2120                   EINA_LIST_FREE(group->markers, marker)
2121                     {
2122                        evas_object_event_callback_del_full(group->sc, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
2123                                                            _bubble_sc_hints_changed_cb, group);
2124                        if (free_marker) free(marker);
2125                     }
2126                   free(group);
2127                }
2128              free_marker = EINA_FALSE;
2129           }
2130         eina_iterator_free(it);
2131         eina_matrixsparse_free(wd->markers[i]);
2132      }
2133
2134    evas_object_del(wd->sep_maps_markers);
2135    evas_object_del(wd->pan_smart);
2136    wd->pan_smart = NULL;
2137 }
2138
2139 static void
2140 _on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
2141 {
2142    ELM_CHECK_WIDTYPE(obj, widtype);
2143    Widget_Data *wd = elm_widget_data_get(obj);
2144
2145    if (!wd) return;
2146    if (elm_widget_focus_get(obj))
2147      {
2148         edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), "elm,action,focus", "elm");
2149         evas_object_focus_set(wd->obj, EINA_TRUE);
2150      }
2151    else
2152      {
2153         edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), "elm,action,unfocus", "elm");
2154         evas_object_focus_set(wd->obj, EINA_FALSE);
2155      }
2156 }
2157
2158 static void
2159 _theme_hook(Evas_Object *obj)
2160 {
2161    ELM_CHECK_WIDTYPE(obj, widtype);
2162    Widget_Data *wd = elm_widget_data_get(obj);
2163
2164    if (!wd) return;
2165    elm_smart_scroller_object_theme_set(obj, wd->scr, "map", "base", elm_widget_style_get(obj));
2166    //   edje_object_scale_set(wd->scr, elm_widget_scale_get(obj) * _elm_config->scale);
2167    _sizing_eval(obj);
2168 }
2169
2170 static void
2171 _sizing_eval(Evas_Object *obj)
2172 {
2173    ELM_CHECK_WIDTYPE(obj, widtype);
2174    Widget_Data *wd = elm_widget_data_get(obj);
2175    Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
2176
2177    if (!wd) return;
2178    evas_object_size_hint_max_get(wd->scr, &maxw, &maxh);
2179    evas_object_size_hint_min_set(obj, minw, minh);
2180    evas_object_size_hint_max_set(obj, maxw, maxh);
2181 }
2182
2183 static void
2184 _calc_job(void *data)
2185 {
2186    Widget_Data *wd = data;
2187    Evas_Coord minw, minh;
2188
2189    if (!wd) return;
2190    minw = wd->size.w;
2191    minh = wd->size.h;
2192    if (wd->resized)
2193      {
2194         wd->resized = EINA_FALSE;
2195         if (wd->mode != ELM_MAP_ZOOM_MODE_MANUAL)
2196           {
2197              double tz = wd->zoom;
2198              wd->zoom = 0.0;
2199              elm_map_zoom_set(wd->obj, tz);
2200           }
2201      }
2202    if ((minw != wd->minw) || (minh != wd->minh))
2203      {
2204         wd->minw = minw;
2205         wd->minh = minh;
2206         evas_object_smart_callback_call(wd->pan_smart, SIG_CHANGED, NULL);
2207         _sizing_eval(wd->obj);
2208      }
2209    wd->calc_job = NULL;
2210    evas_object_smart_changed(wd->pan_smart);
2211 }
2212
2213 static void
2214 _pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
2215 {
2216    Pan *sd = evas_object_smart_data_get(obj);
2217    if (!sd) return;
2218    if ((x == sd->wd->pan_x) && (y == sd->wd->pan_y)) return;
2219    sd->wd->pan_x = x;
2220    sd->wd->pan_y = y;
2221    evas_object_smart_changed(obj);
2222 }
2223
2224 static void
2225 _pan_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
2226 {
2227    Pan *sd = evas_object_smart_data_get(obj);
2228    if (!sd) return;
2229    if (x) *x = sd->wd->pan_x;
2230    if (y) *y = sd->wd->pan_y;
2231 }
2232
2233 static void
2234 _pan_max_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
2235 {
2236    Pan *sd = evas_object_smart_data_get(obj);
2237    Evas_Coord ow, oh;
2238    if (!sd) return;
2239    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
2240    ow = sd->wd->minw - ow;
2241    if (ow < 0) ow = 0;
2242    oh = sd->wd->minh - oh;
2243    if (oh < 0) oh = 0;
2244    if (x) *x = ow;
2245    if (y) *y = oh;
2246 }
2247
2248 static void
2249 _pan_min_get(Evas_Object *obj __UNUSED__, Evas_Coord *x, Evas_Coord *y)
2250 {
2251    if (x) *x = 0;
2252    if (y) *y = 0;
2253 }
2254
2255 static void
2256 _pan_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
2257 {
2258    Pan *sd = evas_object_smart_data_get(obj);
2259    if (!sd) return;
2260    if (w) *w = sd->wd->minw;
2261    if (h) *h = sd->wd->minh;
2262 }
2263
2264 static void
2265 _pan_add(Evas_Object *obj)
2266 {
2267    Pan *sd;
2268    Evas_Object_Smart_Clipped_Data *cd;
2269    _pan_sc.add(obj);
2270    cd = evas_object_smart_data_get(obj);
2271    if (!cd) return;
2272    sd = calloc(1, sizeof(Pan));
2273    if (!sd) return;
2274    sd->__clipped_data = *cd;
2275    free(cd);
2276    evas_object_smart_data_set(obj, sd);
2277 }
2278
2279 static void
2280 _pan_del(Evas_Object *obj)
2281 {
2282    Pan *sd = evas_object_smart_data_get(obj);
2283    if (!sd) return;
2284    _pan_sc.del(obj);
2285 }
2286
2287 static void
2288 _pan_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
2289 {
2290    Pan *sd = evas_object_smart_data_get(obj);
2291    Evas_Coord ow, oh;
2292    if (!sd) return;
2293    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
2294    if ((ow == w) && (oh == h)) return;
2295    sd->wd->resized = EINA_TRUE;
2296    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
2297    sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd);
2298 }
2299
2300 static void
2301 _pan_calculate(Evas_Object *obj)
2302 {
2303    Pan *sd = evas_object_smart_data_get(obj);
2304    Evas_Coord ox, oy, ow, oh;
2305    Eina_List *l;
2306    Grid *g;
2307    if (!sd) return;
2308    evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
2309    rect_place(sd->wd->obj, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh);
2310    EINA_LIST_FOREACH(sd->wd->grids, l, g)
2311      {
2312         if (sd->wd->zoom == g->zoom) grid_load(sd->wd->obj, g);
2313         grid_place(sd->wd->obj, g, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh);
2314         marker_place(sd->wd->obj, g, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh);
2315         if (!sd->wd->zoom_animator) route_place(sd->wd->obj, g, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh);
2316         if (!sd->wd->zoom_animator) track_place(sd->wd->obj, g, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh);
2317      }
2318 }
2319
2320 static void
2321 _pan_move(Evas_Object *obj, Evas_Coord x __UNUSED__, Evas_Coord y __UNUSED__)
2322 {
2323    Pan *sd = evas_object_smart_data_get(obj);
2324    if (!sd) return;
2325    if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
2326    sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd);
2327 }
2328
2329 static void
2330 _hold_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
2331 {
2332    ELM_CHECK_WIDTYPE(obj, widtype);
2333    Widget_Data *wd = elm_widget_data_get(obj);
2334
2335    if (!wd) return;
2336    elm_smart_scroller_hold_set(wd->scr, 1);
2337 }
2338
2339 static void
2340 _hold_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
2341 {
2342    ELM_CHECK_WIDTYPE(obj, widtype);
2343    Widget_Data *wd = elm_widget_data_get(obj);
2344
2345    if (!wd) return;
2346    elm_smart_scroller_hold_set(wd->scr, 0);
2347 }
2348
2349 static void
2350 _freeze_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
2351 {
2352    ELM_CHECK_WIDTYPE(obj, widtype);
2353    Widget_Data *wd = elm_widget_data_get(obj);
2354
2355    if (!wd) return;
2356    elm_smart_scroller_freeze_set(wd->scr, 1);
2357 }
2358
2359 static void
2360 _freeze_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
2361 {
2362    ELM_CHECK_WIDTYPE(obj, widtype);
2363    Widget_Data *wd = elm_widget_data_get(obj);
2364
2365    if (!wd) return;
2366    elm_smart_scroller_freeze_set(wd->scr, 0);
2367 }
2368
2369 static void
2370 _scr_anim_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2371 {
2372    evas_object_smart_callback_call(data, "scroll,anim,start", NULL);
2373 }
2374
2375 static void
2376 _scr_anim_stop(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2377 {
2378    evas_object_smart_callback_call(data, "scroll,anim,stop", NULL);
2379 }
2380
2381 static void
2382 _scr_drag_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2383 {
2384    Widget_Data *wd = elm_widget_data_get(data);
2385    wd->center_on.enabled = EINA_FALSE;
2386    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_START, NULL);
2387 }
2388
2389 static void
2390 _scr_drag_stop(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2391 {
2392    evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_STOP, NULL);
2393 }
2394
2395 static void
2396 _scr_scroll(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2397 {
2398    evas_object_smart_callback_call(data, SIG_SCROLL, NULL);
2399 }
2400
2401
2402 static void
2403 _group_object_create(Marker_Group *group)
2404 {
2405    const char *style = "radio";
2406    Evas_Object *icon = NULL;
2407
2408    if (group->obj) return;
2409    if ((!group->clas->priv.objs_notused) || (eina_list_count(group->markers) == 1))
2410      {
2411         //set icon and style
2412         if (eina_list_count(group->markers) == 1)
2413           {
2414              Elm_Map_Marker *m = eina_list_data_get(group->markers);
2415              if (m->clas->style)
2416                style = m->clas->style;
2417
2418              if (m->clas->func.icon_get)
2419                icon = m->clas->func.icon_get(group->wd->obj, m, m->data);
2420
2421              group->delete_object = EINA_TRUE;
2422           }
2423         else
2424           {
2425              if (group->clas->style)
2426                style = group->clas->style;
2427
2428              if (group->clas->func.icon_get)
2429                icon = group->clas->func.icon_get(group->wd->obj, group->clas->data);
2430
2431              group->delete_object = EINA_FALSE;
2432           }
2433
2434         group->obj = elm_layout_add(group->wd->obj);
2435         elm_layout_theme_set(group->obj, "map/marker", style, elm_widget_style_get(group->wd->obj));
2436
2437         if (icon) elm_object_content_part_set(group->obj, "elm.icon", icon);
2438
2439         evas_object_smart_member_add(group->obj, group->wd->pan_smart);
2440         elm_widget_sub_object_add(group->wd->obj, group->obj);
2441         evas_object_stack_above(group->obj, group->wd->sep_maps_markers);
2442
2443         if (!group->delete_object)
2444           group->clas->priv.objs_used = eina_list_append(group->clas->priv.objs_used, group->obj);
2445      }
2446    else
2447      {
2448         group->delete_object = EINA_FALSE;
2449
2450         group->obj = eina_list_data_get(group->clas->priv.objs_notused);
2451         group->clas->priv.objs_used = eina_list_append(group->clas->priv.objs_used, group->obj);
2452         group->clas->priv.objs_notused = eina_list_remove(group->clas->priv.objs_notused, group->obj);
2453         evas_object_show(group->obj);
2454      }
2455
2456    edje_object_signal_callback_add(elm_layout_edje_get(group->obj), "open", "elm", _group_open_cb, group);
2457    edje_object_signal_callback_add(elm_layout_edje_get(group->obj), "bringin", "elm", _group_bringin_cb, group);
2458
2459    group->update_nbelems = EINA_TRUE;
2460    group->update_resize = EINA_TRUE;
2461    group->update_raise = EINA_TRUE;
2462
2463    if (group->open) _group_bubble_create(group);
2464 }
2465
2466 static void
2467 _group_object_free(Marker_Group *group)
2468 {
2469    if (!group->obj) return;
2470    if (!group->delete_object)
2471      {
2472         group->clas->priv.objs_notused = eina_list_append(group->clas->priv.objs_notused, group->obj);
2473         group->clas->priv.objs_used = eina_list_remove(group->clas->priv.objs_used, group->obj);
2474         evas_object_hide(group->obj);
2475
2476         edje_object_signal_callback_del(elm_layout_edje_get(group->obj), "open", "elm", _group_open_cb);
2477         edje_object_signal_callback_del(elm_layout_edje_get(group->obj), "bringin", "elm", _group_bringin_cb);
2478      }
2479    else
2480      evas_object_del(group->obj);
2481
2482    group->obj = NULL;
2483    _group_bubble_free(group);
2484 }
2485
2486 static void
2487 _group_bubble_mouse_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2488 {
2489    Marker_Group *group = data;
2490
2491    if (!evas_object_above_get(group->rect)) return;
2492    evas_object_raise(group->bubble);
2493    evas_object_raise(group->sc);
2494    evas_object_raise(group->rect);
2495 }
2496
2497 static void
2498 _group_bubble_create(Marker_Group *group)
2499 {
2500    if (group->bubble) return;
2501
2502    group->wd->opened_bubbles = eina_list_append(group->wd->opened_bubbles, group);
2503    group->bubble = edje_object_add(evas_object_evas_get(group->obj));
2504    _elm_theme_object_set(group->wd->obj, group->bubble, "map", "marker_bubble",
2505                          elm_widget_style_get(group->wd->obj));
2506    evas_object_smart_member_add(group->bubble,
2507                                 group->wd->obj);
2508    elm_widget_sub_object_add(group->wd->obj, group->bubble);
2509
2510    _group_bubble_content_free(group);
2511    if (!_group_bubble_content_update(group))
2512      {
2513         //no content, we can delete the bubble
2514         _group_bubble_free(group);
2515         return;
2516      }
2517
2518    group->rect = evas_object_rectangle_add(evas_object_evas_get(group->obj));
2519    evas_object_color_set(group->rect, 0, 0, 0, 0);
2520    evas_object_repeat_events_set(group->rect, EINA_TRUE);
2521    evas_object_smart_member_add(group->rect, group->wd->obj);
2522    elm_widget_sub_object_add(group->wd->obj, group->rect);
2523
2524    evas_object_event_callback_add(group->rect, EVAS_CALLBACK_MOUSE_UP, _group_bubble_mouse_up_cb, group);
2525
2526    _group_bubble_place(group);
2527 }
2528
2529 static void _bubble_sc_hints_changed_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2530 {
2531    _group_bubble_place(data);
2532 }
2533
2534 static int
2535 _group_bubble_content_update(Marker_Group *group)
2536 {
2537    Eina_List *l;
2538    Elm_Map_Marker *marker;
2539    int i = 0;
2540
2541    if (!group->bubble) return 1;
2542
2543    if (!group->sc)
2544      {
2545         group->sc = elm_scroller_add(group->bubble);
2546         elm_widget_style_set(group->sc, "map_bubble");
2547         elm_scroller_content_min_limit(group->sc, EINA_FALSE, EINA_TRUE);
2548         elm_scroller_policy_set(group->sc, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
2549         elm_scroller_bounce_set(group->sc, _elm_config->thumbscroll_bounce_enable, EINA_FALSE);
2550         edje_object_part_swallow(group->bubble, "elm.swallow.content", group->sc);
2551         evas_object_show(group->sc);
2552         evas_object_smart_member_add(group->sc,
2553                                      group->wd->obj);
2554         elm_widget_sub_object_add(group->wd->obj, group->sc);
2555
2556         group->bx = elm_box_add(group->bubble);
2557         evas_object_size_hint_align_set(group->bx, EVAS_HINT_FILL, EVAS_HINT_FILL);
2558         evas_object_size_hint_weight_set(group->bx, 0.5, 0.5);
2559         elm_box_horizontal_set(group->bx, EINA_TRUE);
2560         evas_object_show(group->bx);
2561
2562         elm_object_content_set(group->sc, group->bx);
2563
2564         evas_object_event_callback_add(group->sc, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
2565                                        _bubble_sc_hints_changed_cb, group);
2566      }
2567
2568    EINA_LIST_FOREACH(group->markers, l, marker)
2569      {
2570         if (i >= group->wd->markers_max_num) break;
2571         if ((!marker->content) && (marker->clas->func.get))
2572           marker->content = marker->clas->func.get(group->wd->obj, marker, marker->data);
2573         else if (marker->content)
2574           elm_box_unpack(group->bx, marker->content);
2575         if (marker->content)
2576           {
2577              elm_box_pack_end(group->bx, marker->content);
2578              i++;
2579           }
2580      }
2581    return i;
2582 }
2583
2584 static void
2585 _group_bubble_content_free(Marker_Group *group)
2586 {
2587    Eina_List *l;
2588    Elm_Map_Marker *marker;
2589
2590    if (!group->sc) return;
2591    EINA_LIST_FOREACH(group->markers, l, marker)
2592      {
2593         if ((marker->content) && (marker->clas->func.del))
2594           marker->clas->func.del(group->wd->obj, marker, marker->data, marker->content);
2595         else if (marker->content)
2596           evas_object_del(marker->content);
2597         marker->content = NULL;
2598      }
2599    evas_object_del(group->sc);
2600    group->sc = NULL;
2601 }
2602
2603 static void
2604 _group_bubble_free(Marker_Group *group)
2605 {
2606    if (!group->bubble) return;
2607    group->wd->opened_bubbles = eina_list_remove(group->wd->opened_bubbles, group);
2608    evas_object_event_callback_del_full(group->sc, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
2609                                        _bubble_sc_hints_changed_cb, group);
2610    evas_object_del(group->bubble);
2611    evas_object_del(group->rect);
2612    group->bubble = NULL;
2613    _group_bubble_content_free(group);
2614 }
2615
2616 static void
2617 _group_bubble_place(Marker_Group *group)
2618 {
2619    Evas_Coord x, y, w;
2620    Evas_Coord xx, yy, ww, hh;
2621    const char *s;
2622
2623    if ((!group->bubble) || (!group->obj)) return;
2624
2625    evas_object_geometry_get(group->obj, &x, &y, &w, NULL);
2626    edje_object_size_min_calc(group->bubble, NULL, &hh);
2627
2628    s = edje_object_data_get(group->bubble, "size_w");
2629    if (s) ww = atoi(s);
2630    else ww = 0;
2631    xx = x + w / 2 - ww / 2;
2632    yy = y-hh;
2633
2634    evas_object_move(group->bubble, xx, yy);
2635    evas_object_resize(group->bubble, ww, hh);
2636    obj_rotate_zoom(group->wd, group->bubble);
2637    evas_object_show(group->bubble);
2638
2639    evas_object_move(group->rect, xx, yy);
2640    evas_object_resize(group->rect, ww, hh);
2641    obj_rotate_zoom(group->wd, group->rect);
2642    evas_object_show(group->rect);
2643 }
2644
2645 static void
2646 _group_bringin_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *soure __UNUSED__)
2647 {
2648    Marker_Group *group = data;
2649    Elm_Map_Marker *marker = eina_list_data_get(group->markers);
2650    if (!marker) return;
2651    group->bringin = EINA_TRUE;
2652    elm_map_geo_region_bring_in(group->wd->obj, marker->longitude, marker->latitude);
2653 }
2654
2655 static void
2656 _group_open_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *soure __UNUSED__)
2657 {
2658    Marker_Group *group = data;
2659
2660    if (group->bringin)
2661      {
2662         group->bringin = EINA_FALSE;
2663         return;
2664      }
2665
2666    if (group->bubble)
2667      {
2668         group->open = EINA_FALSE;
2669         _group_bubble_free(group);
2670         return;
2671      }
2672    group->open = EINA_TRUE;
2673    _group_bubble_create(group);
2674 }
2675
2676 static Eina_Bool
2677 _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
2678 {
2679    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2680    Widget_Data *wd = elm_widget_data_get(obj);
2681    int zoom;
2682    Evas_Coord x = 0;
2683    Evas_Coord y = 0;
2684    Evas_Coord step_x = 0;
2685    Evas_Coord step_y = 0;
2686    Evas_Coord v_w = 0;
2687    Evas_Coord v_h = 0;
2688    Evas_Coord page_x = 0;
2689    Evas_Coord page_y = 0;
2690
2691    if (!wd) return EINA_FALSE;
2692    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
2693    Evas_Event_Key_Down *ev = event_info;
2694    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
2695
2696    elm_smart_scroller_child_pos_get(wd->scr, &x, &y);
2697    elm_smart_scroller_step_size_get(wd->scr, &step_x, &step_y);
2698    elm_smart_scroller_page_size_get(wd->scr, &page_x, &page_y);
2699    elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h);
2700
2701    if ((!strcmp(ev->keyname, "Left")) || (!strcmp(ev->keyname, "KP_Left")))
2702      {
2703         x -= step_x;
2704      }
2705    else if ((!strcmp(ev->keyname, "Right")) || (!strcmp(ev->keyname, "KP_Right")))
2706      {
2707         x += step_x;
2708      }
2709    else if ((!strcmp(ev->keyname, "Up"))  || (!strcmp(ev->keyname, "KP_Up")))
2710      {
2711         y -= step_y;
2712      }
2713    else if ((!strcmp(ev->keyname, "Down")) || (!strcmp(ev->keyname, "KP_Down")))
2714      {
2715         y += step_y;
2716      }
2717    else if ((!strcmp(ev->keyname, "Prior")) || (!strcmp(ev->keyname, "KP_Prior")))
2718      {
2719         if (page_y < 0)
2720           y -= -(page_y * v_h) / 100;
2721         else
2722           y -= page_y;
2723      }
2724    else if ((!strcmp(ev->keyname, "Next")) || (!strcmp(ev->keyname, "KP_Next")))
2725      {
2726         if (page_y < 0)
2727           y += -(page_y * v_h) / 100;
2728         else
2729           y += page_y;
2730      }
2731    else if (!strcmp(ev->keyname, "KP_Add"))
2732      {
2733         zoom = elm_map_zoom_get(obj) + 1;
2734         elm_map_zoom_mode_set(obj, ELM_MAP_ZOOM_MODE_MANUAL);
2735         elm_map_zoom_set(obj, zoom);
2736         return EINA_TRUE;
2737      }
2738    else if (!strcmp(ev->keyname, "KP_Subtract"))
2739      {
2740         zoom = elm_map_zoom_get(obj) - 1;
2741         elm_map_zoom_mode_set(obj, ELM_MAP_ZOOM_MODE_MANUAL);
2742         elm_map_zoom_set(obj, zoom);
2743         return EINA_TRUE;
2744      }
2745    else return EINA_FALSE;
2746
2747    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2748    elm_smart_scroller_child_pos_set(wd->scr, x, y);
2749
2750    return EINA_TRUE;
2751 }
2752
2753 static Eina_Bool
2754 cb_dump_name_attrs(void *data, const char *key, const char *value)
2755 {
2756    Name_Dump *dump = (Name_Dump*)data;
2757    if (!dump) return EINA_FALSE;
2758
2759    if (!strncmp(key, NOMINATIM_ATTR_LON, sizeof(NOMINATIM_ATTR_LON))) dump->lon = atof(value);
2760    else if (!strncmp(key, NOMINATIM_ATTR_LAT, sizeof(NOMINATIM_ATTR_LAT))) dump->lat = atof(value);
2761
2762    return EINA_TRUE;
2763 }
2764
2765
2766 static Eina_Bool
2767 cb_route_dump(void *data, Eina_Simple_XML_Type type, const char *value, unsigned offset __UNUSED__, unsigned length)
2768 {
2769    Route_Dump *dump = data;
2770    if (!dump) return EINA_FALSE;
2771
2772    switch (type)
2773      {
2774       case EINA_SIMPLE_XML_OPEN:
2775       case EINA_SIMPLE_XML_OPEN_EMPTY:
2776         {
2777            const char *attrs;
2778
2779            attrs = eina_simple_xml_tag_attributes_find(value, length);
2780            if (!attrs)
2781              {
2782                 if (!strncmp(value, YOURS_DISTANCE, length)) dump->id = ROUTE_XML_DISTANCE;
2783                 else if (!strncmp(value, YOURS_DESCRIPTION, length)) dump->id = ROUTE_XML_DESCRIPTION;
2784                 else if (!strncmp(value, YOURS_COORDINATES, length)) dump->id = ROUTE_XML_COORDINATES;
2785                 else dump->id = ROUTE_XML_NONE;
2786              }
2787          }
2788         break;
2789       case EINA_SIMPLE_XML_DATA:
2790         {
2791            char *buf = malloc(length);
2792            if (!buf) return EINA_FALSE;
2793            snprintf(buf, length, "%s", value);
2794            if (dump->id == ROUTE_XML_DISTANCE) dump->distance = atof(buf);
2795            else if (!(dump->description) && (dump->id == ROUTE_XML_DESCRIPTION)) dump->description = strdup(buf);
2796            else if (dump->id == ROUTE_XML_COORDINATES) dump->coordinates = strdup(buf);
2797            free(buf);
2798         }
2799         break;
2800       default:
2801         break;
2802      }
2803
2804    return EINA_TRUE;
2805 }
2806
2807 static Eina_Bool
2808 cb_name_dump(void *data, Eina_Simple_XML_Type type, const char *value, unsigned offset __UNUSED__, unsigned length)
2809 {
2810    Name_Dump *dump = data;
2811    if (!dump) return EINA_FALSE;
2812
2813    switch (type)
2814      {
2815       case EINA_SIMPLE_XML_OPEN:
2816       case EINA_SIMPLE_XML_OPEN_EMPTY:
2817         {
2818            const char *attrs;
2819            attrs = eina_simple_xml_tag_attributes_find(value, length);
2820            if (attrs)
2821              {
2822                 if (!strncmp(value, NOMINATIM_RESULT, sizeof(NOMINATIM_RESULT) - 1)) dump->id = NAME_XML_NAME;
2823                 else dump->id = NAME_XML_NONE;
2824
2825                 eina_simple_xml_attributes_parse
2826                   (attrs, length - (attrs - value), cb_dump_name_attrs, dump);
2827              }
2828         }
2829         break;
2830       case EINA_SIMPLE_XML_DATA:
2831         {
2832            char *buf = malloc(length + 1);
2833            if (!buf) return EINA_FALSE;
2834            snprintf(buf, length + 1, "%s", value);
2835            if (dump->id == NAME_XML_NAME) dump->address = strdup(buf);
2836            free(buf);
2837         }
2838         break;
2839       default:
2840         break;
2841      }
2842
2843    return EINA_TRUE;
2844 }
2845
2846 static void
2847 _parse_kml(void *data)
2848 {
2849    Elm_Map_Route *r = (Elm_Map_Route*)data;
2850    if (!r || !r->ud.fname) return;
2851
2852    FILE *f;
2853    char **str;
2854    unsigned int ele, idx;
2855    double lon, lat;
2856    Evas_Object *path;
2857
2858    Route_Dump dump = {0, r->ud.fname, 0.0, NULL, NULL};
2859
2860    f = fopen(r->ud.fname, "rb");
2861    if (f)
2862      {
2863         long sz;
2864
2865         fseek(f, 0, SEEK_END);
2866         sz = ftell(f);
2867         if (sz > 0)
2868           {
2869              char *buf;
2870
2871              fseek(f, 0, SEEK_SET);
2872              buf = malloc(sz);
2873              if (buf)
2874                {
2875                   if (fread(buf, 1, sz, f))
2876                     {
2877                        eina_simple_xml_parse(buf, sz, EINA_TRUE, cb_route_dump, &dump);
2878                        free(buf);
2879                     }
2880                }
2881           }
2882         fclose(f);
2883
2884         if (dump.distance) r->info.distance = dump.distance;
2885         if (dump.description)
2886           {
2887              eina_stringshare_replace(&r->info.waypoints, dump.description);
2888              str = eina_str_split_full(dump.description, "\n", 0, &ele);
2889              r->info.waypoint_count = ele;
2890              for (idx = 0 ; idx < ele ; idx++)
2891                {
2892                   Path_Waypoint *wp = ELM_NEW(Path_Waypoint);
2893                   if (wp)
2894                     {
2895                        wp->wd = r->wd;
2896                        wp->point = eina_stringshare_add(str[idx]);
2897                        DBG("%s", str[idx]);
2898                        r->waypoint = eina_list_append(r->waypoint, wp);
2899                     }
2900                }
2901              if (str && str[0])
2902                {
2903                   free(str[0]);
2904                   free(str);
2905                }
2906           }
2907         else WRN("description is not found !");
2908
2909         if (dump.coordinates)
2910           {
2911              eina_stringshare_replace(&r->info.nodes, dump.coordinates);
2912              str = eina_str_split_full(dump.coordinates, "\n", 0, &ele);
2913              r->info.node_count = ele;
2914              for (idx = 0 ; idx < ele ; idx++)
2915                {
2916                   sscanf(str[idx], "%lf,%lf", &lon, &lat);
2917                   Path_Node *n = ELM_NEW(Path_Node);
2918                   if (n)
2919                     {
2920                        n->wd = r->wd;
2921                        n->pos.lon = lon;
2922                        n->pos.lat = lat;
2923                        n->idx = idx;
2924                        DBG("%lf:%lf", lon, lat);
2925                        n->pos.address = NULL;
2926                        r->nodes = eina_list_append(r->nodes, n);
2927
2928                        path = evas_object_polygon_add(evas_object_evas_get(r->wd->obj));
2929                        evas_object_smart_member_add(path, r->wd->pan_smart);
2930                        r->path = eina_list_append(r->path, path);
2931                     }
2932                }
2933              if (str && str[0])
2934                {
2935                   free(str[0]);
2936                   free(str);
2937                }
2938           }
2939      }
2940 }
2941
2942 static void
2943 _parse_name(void *data)
2944 {
2945    Elm_Map_Name *n = (Elm_Map_Name*)data;
2946    if (!n || !n->ud.fname) return;
2947
2948    FILE *f;
2949
2950    Name_Dump dump = {0, NULL, 0.0, 0.0};
2951
2952    f = fopen(n->ud.fname, "rb");
2953    if (f)
2954      {
2955         long sz;
2956
2957         fseek(f, 0, SEEK_END);
2958         sz = ftell(f);
2959         if (sz > 0)
2960           {
2961              char *buf;
2962
2963              fseek(f, 0, SEEK_SET);
2964              buf = malloc(sz);
2965              if (buf)
2966                {
2967                   if (fread(buf, 1, sz, f))
2968                     {
2969                        eina_simple_xml_parse(buf, sz, EINA_TRUE, cb_name_dump, &dump);
2970                        free(buf);
2971                     }
2972                }
2973           }
2974         fclose(f);
2975
2976         if (dump.address)
2977           {
2978              INF("[%lf : %lf] ADDRESS : %s", n->lon, n->lat, dump.address);
2979              n->address = strdup(dump.address);
2980           }
2981         n->lon = dump.lon;
2982         n->lat = dump.lat;
2983      }
2984 }
2985
2986 static Eina_Bool
2987 _route_complete_cb(void *data, int ev_type __UNUSED__, void *event)
2988 {
2989    Ecore_Con_Event_Url_Complete *ev = event;
2990    Elm_Map_Route *r = (Elm_Map_Route*)data;
2991    Widget_Data *wd = r->wd;
2992
2993    if ((!r) || (!ev)) return EINA_TRUE;
2994    Elm_Map_Route *rr = ecore_con_url_data_get(r->con_url);
2995    ecore_con_url_data_set(r->con_url, NULL);
2996    if (r!=rr) return EINA_TRUE;
2997
2998    if (r->ud.fd) fclose(r->ud.fd);
2999    _parse_kml(r);
3000
3001    if (wd->grids)
3002      {
3003         Evas_Coord ox, oy, ow, oh;
3004         evas_object_geometry_get(wd->obj, &ox, &oy, &ow, &oh);
3005         route_place(wd->obj, eina_list_data_get(wd->grids), wd->pan_x, wd->pan_y, ox, oy, ow, oh);
3006      }
3007    edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
3008                            "elm,state,busy,stop", "elm");
3009    evas_object_smart_callback_call(wd->obj, SIG_ROUTE_LOADED, NULL);
3010    return EINA_TRUE;
3011 }
3012
3013 static Eina_Bool
3014 _name_complete_cb(void *data, int ev_type __UNUSED__, void *event)
3015 {
3016    Ecore_Con_Event_Url_Complete *ev = event;
3017    Elm_Map_Name *n = (Elm_Map_Name*)data;
3018    Widget_Data *wd = n->wd;
3019
3020    if ((!n) || (!ev)) return EINA_TRUE;
3021    Elm_Map_Name *nn = ecore_con_url_data_get(n->con_url);
3022    ecore_con_url_data_set(n->con_url, NULL);
3023    if (n!=nn) return EINA_TRUE;
3024
3025    if (n->ud.fd) fclose(n->ud.fd);
3026    _parse_name(n);
3027
3028    edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
3029                            "elm,state,busy,stop", "elm");
3030    evas_object_smart_callback_call(wd->obj, SIG_NAME_LOADED, NULL);
3031    return EINA_TRUE;
3032 }
3033
3034 static Elm_Map_Name *
3035 _utils_convert_name(const Evas_Object *obj, int method, char *address, double lon, double lat)
3036 {
3037    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3038    Widget_Data *wd = elm_widget_data_get(obj);
3039    char buf[PATH_MAX];
3040    char *source;
3041    int fd;
3042
3043    if ((!wd) || (!wd->src)) return NULL;
3044    Elm_Map_Name *name = ELM_NEW(Elm_Map_Name);
3045    if (!name) return NULL;
3046
3047    snprintf(buf, sizeof(buf), DEST_NAME_XML_FILE);
3048    fd = mkstemp(buf);
3049    if (fd < 0)
3050      {
3051         free(name);
3052         return NULL;
3053      }
3054
3055    name->con_url = ecore_con_url_new(NULL);
3056    name->ud.fname = strdup(buf);
3057    INF("xml file : %s", name->ud.fname);
3058
3059    name->ud.fd = fdopen(fd, "w+");
3060    if ((!name->con_url) || (!name->ud.fd))
3061      {
3062         ecore_con_url_free(name->con_url);
3063         free(name);
3064         return NULL;
3065      }
3066
3067    name->wd = wd;
3068    name->handler = ecore_event_handler_add (ECORE_CON_EVENT_URL_COMPLETE, _name_complete_cb, name);
3069    name->method = method;
3070    if (method == ELM_MAP_NAME_METHOD_SEARCH) name->address = strdup(address);
3071    else if (method == ELM_MAP_NAME_METHOD_REVERSE) name->address = NULL;
3072    name->lon = lon;
3073    name->lat = lat;
3074
3075    source = wd->src->name_url_cb(wd->obj, method, address, lon, lat);
3076    INF("name url = %s", source);
3077
3078    wd->names = eina_list_append(wd->names, name);
3079    ecore_con_url_url_set(name->con_url, source);
3080    ecore_con_url_fd_set(name->con_url, fileno(name->ud.fd));
3081    ecore_con_url_data_set(name->con_url, name);
3082
3083    edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
3084                            "elm,state,busy,start", "elm");
3085    evas_object_smart_callback_call(wd->obj, SIG_NAME_LOAD, NULL);
3086    ecore_con_url_get(name->con_url);
3087    if (source) free(source);
3088
3089    return name;
3090
3091 }
3092
3093 static int idnum = 1;
3094
3095 EAPI Evas_Object *
3096 elm_map_add(Evas_Object *parent)
3097 {
3098    Evas *e;
3099    Widget_Data *wd;
3100    Evas_Coord minw, minh;
3101    Evas_Object *obj;
3102    static Evas_Smart *smart = NULL;
3103    Eina_Bool bounce = _elm_config->thumbscroll_bounce_enable;
3104
3105    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
3106
3107    ELM_SET_WIDTYPE(widtype, "map");
3108    elm_widget_type_set(obj, "map");
3109    elm_widget_sub_object_add(parent, obj);
3110    elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
3111    elm_widget_data_set(obj, wd);
3112    elm_widget_del_hook_set(obj, _del_hook);
3113    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
3114    elm_widget_theme_hook_set(obj, _theme_hook);
3115    elm_widget_can_focus_set(obj, EINA_TRUE);
3116    elm_widget_event_hook_set(obj, _event_hook);
3117
3118    wd->scr = elm_smart_scroller_add(e);
3119    elm_smart_scroller_widget_set(wd->scr, obj);
3120    elm_smart_scroller_object_theme_set(obj, wd->scr, "map", "base", "default");
3121    evas_object_smart_callback_add(wd->scr, "scroll", _scr, obj);
3122    evas_object_smart_callback_add(wd->scr, "drag", _scr, obj);
3123    elm_widget_resize_object_set(obj, wd->scr);
3124    elm_smart_scroller_wheel_disabled_set(wd->scr, EINA_TRUE);
3125
3126    evas_object_smart_callback_add(wd->scr, "animate,start", _scr_anim_start, obj);
3127    evas_object_smart_callback_add(wd->scr, "animate,stop", _scr_anim_stop, obj);
3128    evas_object_smart_callback_add(wd->scr, "drag,start", _scr_drag_start, obj);
3129    evas_object_smart_callback_add(wd->scr, "drag,stop", _scr_drag_stop, obj);
3130    evas_object_smart_callback_add(wd->scr, "scroll", _scr_scroll, obj);
3131
3132    elm_smart_scroller_bounce_allow_set(wd->scr, bounce, bounce);
3133    source_init(obj);
3134
3135    wd->obj = obj;
3136    wd->map = evas_map_new(4);
3137    if (!wd->map) return NULL;
3138
3139    wd->zoom_min = 0xFF;
3140    wd->zoom_max = 0X00;
3141    wd->markers_max_num = 30;
3142    wd->pinch.level = 1.0;
3143    zoom_min_get(obj);
3144    zoom_max_get(obj);
3145    wd->markers = calloc(wd->zoom_max + 1, sizeof(void*));
3146
3147    evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
3148    evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
3149    evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
3150    evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
3151
3152    if (!smart)
3153      {
3154         static Evas_Smart_Class sc;
3155
3156         evas_object_smart_clipped_smart_set(&_pan_sc);
3157         sc = _pan_sc;
3158         sc.name = "elm_map_pan";
3159         sc.version = EVAS_SMART_CLASS_VERSION;
3160         sc.add = _pan_add;
3161         sc.del = _pan_del;
3162         sc.resize = _pan_resize;
3163         sc.move = _pan_move;
3164         sc.calculate = _pan_calculate;
3165         smart = evas_smart_class_new(&sc);
3166      }
3167    if (smart)
3168      {
3169         wd->pan_smart = evas_object_smart_add(e, smart);
3170         wd->pan = evas_object_smart_data_get(wd->pan_smart);
3171         wd->pan->wd = wd;
3172      }
3173
3174    elm_smart_scroller_extern_pan_set(wd->scr, wd->pan_smart,
3175                                      _pan_set, _pan_get, _pan_max_get,
3176                                      _pan_min_get, _pan_child_size_get);
3177
3178    wd->rect = evas_object_rectangle_add(e);
3179    evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_RESIZE,
3180                                   _rect_resize_cb, obj);
3181    evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MOUSE_DOWN,
3182                                   _mouse_down, obj);
3183    evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MOUSE_MOVE,
3184                                   _mouse_move, obj);
3185    evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MOUSE_UP,
3186                                   _mouse_up, obj);
3187    evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MULTI_DOWN,
3188                                   _mouse_multi_down, obj);
3189    evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MULTI_MOVE,
3190                                   _mouse_multi_move, obj);
3191    evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MULTI_UP,
3192                                   _mouse_multi_up, obj);
3193    evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MOUSE_WHEEL,
3194                                   _mouse_wheel_cb, obj);
3195
3196    evas_object_smart_member_add(wd->rect, wd->pan_smart);
3197    elm_widget_sub_object_add(obj, wd->rect);
3198    evas_object_show(wd->rect);
3199    evas_object_color_set(wd->rect, 0, 0, 0, 0);
3200
3201    wd->mode = ELM_MAP_ZOOM_MODE_MANUAL;
3202    wd->id = ((int)getpid() << 16) | idnum;
3203    idnum++;
3204
3205    wd->tsize = 256;
3206    edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
3207                              &minw, &minh);
3208    evas_object_size_hint_min_set(obj, minw, minh);
3209
3210    wd->sep_maps_markers = evas_object_rectangle_add(evas_object_evas_get(obj));
3211    evas_object_smart_member_add(wd->sep_maps_markers, wd->pan_smart);
3212
3213    wd->paused = EINA_TRUE;
3214    elm_map_zoom_set(obj, 0);
3215    wd->paused = EINA_FALSE;
3216    _sizing_eval(obj);
3217
3218    // TODO: convert Elementary to subclassing of Evas_Smart_Class
3219    // TODO: and save some bytes, making descriptions per-class and not instance!
3220    evas_object_smart_callbacks_descriptions_set(obj, _signals);
3221
3222    if (!ecore_file_download_protocol_available("http://"))
3223      {
3224         ERR("Ecore must be built with curl support for the map widget!");
3225      }
3226
3227    return obj;
3228 }
3229
3230 EAPI void
3231 elm_map_zoom_set(Evas_Object *obj, int zoom)
3232 {
3233    ELM_CHECK_WIDTYPE(obj, widtype);
3234    Widget_Data *wd = elm_widget_data_get(obj);
3235    Eina_List *l;
3236    Grid *g, *g_zoom = NULL;
3237    Evas_Coord rx, ry, rw, rh;
3238    Evas_Object *p;
3239    Elm_Map_Route *r;
3240    Evas_Object *route;
3241    int z = 0, zoom_changed = 0, started = 0;
3242
3243    if ((!wd) || (!wd->src) || (wd->zoom_animator)) return;
3244    if (zoom < 0 ) zoom = 0;
3245    if (zoom > wd->src->zoom_max) zoom = wd->src->zoom_max;
3246    if (zoom < wd->src->zoom_min) zoom = wd->src->zoom_min;
3247
3248    if ((wd->zoom - zoom) > 0) wd->zoom_method = ZOOM_METHOD_OUT;
3249    else if ((wd->zoom - zoom) < 0) wd->zoom_method = ZOOM_METHOD_IN;
3250    else wd->zoom_method = ZOOM_METHOD_NONE;
3251    if (wd->zoom != zoom ) zoom_changed = 1;
3252    wd->zoom = zoom;
3253    wd->size.ow = wd->size.w;
3254    wd->size.oh = wd->size.h;
3255    elm_smart_scroller_child_pos_get(wd->scr, &rx, &ry);
3256    elm_smart_scroller_child_viewport_size_get(wd->scr, &rw, &rh);
3257
3258    EINA_LIST_FOREACH(wd->route, l, r)
3259      {
3260         if (r)
3261           {
3262              EINA_LIST_FOREACH(r->path, l, p)
3263                {
3264                   evas_object_polygon_points_clear(p);
3265                }
3266           }
3267      }
3268
3269    EINA_LIST_FOREACH(wd->track, l, route)
3270      {
3271        evas_object_hide(route);
3272      }
3273
3274    if (wd->mode != ELM_MAP_ZOOM_MODE_MANUAL)
3275      {
3276         int p2w, p2h;
3277         int cumulw, cumulh;
3278
3279         cumulw = wd->tsize;
3280         p2w = 0;
3281         while (cumulw <= rw)
3282           {
3283              p2w++;
3284              cumulw *= 2;
3285           }
3286         p2w--;
3287
3288         cumulh = wd->tsize;
3289         p2h = 0;
3290         while (cumulh <= rh)
3291           {
3292              p2h++;
3293              cumulh *= 2;
3294           }
3295         p2h--;
3296
3297         if (wd->mode == ELM_MAP_ZOOM_MODE_AUTO_FIT)
3298           {
3299              if (p2w < p2h) z = p2w;
3300              else z = p2h;
3301           }
3302         else if (wd->mode == ELM_MAP_ZOOM_MODE_AUTO_FILL)
3303           {
3304              if (p2w > p2h) z = p2w;
3305              else z = p2h;
3306           }
3307         wd->zoom = z;
3308      }
3309    wd->size.nw = pow(2.0, wd->zoom) * wd->tsize;
3310    wd->size.nh = pow(2.0, wd->zoom) * wd->tsize;
3311
3312    g = grid_create(obj);
3313    if (g)
3314      {
3315         if (eina_list_count(wd->grids) > 1)
3316           {
3317              g_zoom = eina_list_last(wd->grids)->data;
3318              wd->grids = eina_list_remove(wd->grids, g_zoom);
3319              grid_clear(obj, g_zoom);
3320              free(g_zoom);
3321           }
3322         wd->grids = eina_list_prepend(wd->grids, g);
3323      }
3324    else
3325      {
3326         EINA_LIST_FREE(wd->grids, g)
3327           {
3328              grid_clear(obj, g);
3329              free(g);
3330           }
3331      }
3332
3333    wd->t = 1.0;
3334    if ((wd->size.w > 0) && (wd->size.h > 0))
3335      {
3336         wd->size.spos.x = (double)(rx + (rw / 2)) / (double)wd->size.ow;
3337         wd->size.spos.y = (double)(ry + (rh / 2)) / (double)wd->size.oh;
3338      }
3339    else
3340      {
3341         wd->size.spos.x = 0.5;
3342         wd->size.spos.y = 0.5;
3343      }
3344
3345    if (rw > wd->size.ow) wd->size.spos.x = 0.5;
3346    if (rh > wd->size.oh) wd->size.spos.y = 0.5;
3347    if (wd->size.spos.x > 1.0) wd->size.spos.x = 1.0;
3348    if (wd->size.spos.y > 1.0) wd->size.spos.y = 1.0;
3349
3350    if (wd->paused)
3351      {
3352         zoom_do(obj);
3353         if (wd->calc_job) ecore_job_del(wd->calc_job);
3354         wd->calc_job = ecore_job_add(_calc_job, wd);
3355      }
3356    else
3357      {
3358         if (!wd->zoom_animator)
3359           {
3360              wd->zoom_animator = ecore_animator_add(_zoom_anim, obj);
3361              wd->nosmooth++;
3362              if (wd->nosmooth == 1) _smooth_update(obj);
3363              started = 1;
3364           }
3365      }
3366
3367    if (!wd->paused)
3368      {
3369         if (started) evas_object_smart_callback_call(obj, SIG_ZOOM_START, NULL);
3370         if (!wd->zoom_animator) evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL);
3371      }
3372
3373    if (zoom_changed) evas_object_smart_callback_call(obj, SIG_ZOOM_CHANGE, NULL);
3374 }
3375
3376 EAPI int
3377 elm_map_zoom_get(const Evas_Object *obj)
3378 {
3379    ELM_CHECK_WIDTYPE(obj, widtype) 0;
3380    Widget_Data *wd = elm_widget_data_get(obj);
3381
3382    if (!wd) return 0;
3383    return wd->zoom;
3384 }
3385
3386 EAPI void
3387 elm_map_zoom_mode_set(Evas_Object *obj, Elm_Map_Zoom_Mode mode)
3388 {
3389    ELM_CHECK_WIDTYPE(obj, widtype);
3390    Widget_Data *wd = elm_widget_data_get(obj);
3391
3392    if (!wd) return;
3393    if (wd->mode == mode) return;
3394    wd->mode = mode;
3395
3396    if (wd->mode != ELM_MAP_ZOOM_MODE_MANUAL)
3397      {
3398         int tz = wd->zoom;
3399         wd->zoom = 0;
3400         elm_map_zoom_set(wd->obj, tz);
3401      }
3402 }
3403
3404 EAPI Elm_Map_Zoom_Mode
3405 elm_map_zoom_mode_get(const Evas_Object *obj)
3406 {
3407    ELM_CHECK_WIDTYPE(obj, widtype) ELM_MAP_ZOOM_MODE_MANUAL;
3408    Widget_Data *wd = elm_widget_data_get(obj);
3409
3410    if (!wd) return ELM_MAP_ZOOM_MODE_MANUAL;
3411    return wd->mode;
3412 }
3413
3414 EAPI void
3415 elm_map_geo_region_bring_in(Evas_Object *obj, double lon, double lat)
3416 {
3417    ELM_CHECK_WIDTYPE(obj, widtype);
3418    Widget_Data *wd = elm_widget_data_get(obj);
3419    int rx, ry, rw, rh;
3420
3421    if (!wd) return;
3422    elm_map_utils_convert_geo_into_coord(obj, lon, lat, wd->size.w, &rx, &ry);
3423    elm_smart_scroller_child_viewport_size_get(wd->scr, &rw, &rh);
3424
3425    rx = rx - rw / 2;
3426    ry = ry - rh / 2;
3427
3428    if (wd->zoom_animator)
3429      {
3430         wd->nosmooth--;
3431         if (!wd->nosmooth) _smooth_update(obj);
3432         ecore_animator_del(wd->zoom_animator);
3433         wd->zoom_animator = NULL;
3434         zoom_do(obj);
3435         evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL);
3436      }
3437    elm_smart_scroller_region_bring_in(wd->scr, rx, ry, rw, rh);
3438
3439    wd->center_on.enabled = EINA_TRUE;
3440    wd->center_on.lon = lon;
3441    wd->center_on.lat = lat;
3442 }
3443
3444 EAPI void
3445 elm_map_geo_region_show(Evas_Object *obj, double lon, double lat)
3446 {
3447    ELM_CHECK_WIDTYPE(obj, widtype);
3448    Widget_Data *wd = elm_widget_data_get(obj);
3449    int rx, ry, rw, rh;
3450
3451    if (!wd) return;
3452    elm_map_utils_convert_geo_into_coord(obj, lon, lat, wd->size.w, &rx, &ry);
3453    elm_smart_scroller_child_viewport_size_get(wd->scr, &rw, &rh);
3454
3455    rx = rx - rw / 2;
3456    ry = ry - rh / 2;
3457
3458    if (wd->zoom_animator)
3459      {
3460         wd->nosmooth--;
3461         ecore_animator_del(wd->zoom_animator);
3462         wd->zoom_animator = NULL;
3463         zoom_do(obj);
3464         evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL);
3465      }
3466    elm_smart_scroller_child_region_show(wd->scr, rx, ry, rw, rh);
3467
3468    wd->center_on.enabled = EINA_TRUE;
3469    wd->center_on.lon = lon;
3470    wd->center_on.lat = lat;
3471 }
3472
3473 EAPI void
3474 elm_map_geo_region_get(const Evas_Object *obj, double *lon, double *lat)
3475 {
3476    ELM_CHECK_WIDTYPE(obj, widtype);
3477    Widget_Data *wd = elm_widget_data_get(obj);
3478    Evas_Coord sx, sy, sw, sh;
3479
3480    if (!wd) return;
3481    elm_smart_scroller_child_pos_get(wd->scr, &sx, &sy);
3482    elm_smart_scroller_child_viewport_size_get(wd->scr, &sw, &sh);
3483    sx += sw / 2;
3484    sy += sh / 2;
3485
3486    elm_map_utils_convert_coord_into_geo(obj, sx, sy, wd->size.w, lon, lat);
3487 }
3488
3489 EAPI void
3490 elm_map_paused_set(Evas_Object *obj, Eina_Bool paused)
3491 {
3492    ELM_CHECK_WIDTYPE(obj, widtype);
3493    Widget_Data *wd = elm_widget_data_get(obj);
3494
3495    if (!wd) return;
3496    if (wd->paused == !!paused) return;
3497    wd->paused = paused;
3498    if (wd->paused)
3499      {
3500         if (wd->zoom_animator)
3501           {
3502              if (wd->zoom_animator) ecore_animator_del(wd->zoom_animator);
3503              wd->zoom_animator = NULL;
3504              zoom_do(obj);
3505              evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL);
3506           }
3507      }
3508 }
3509
3510 EAPI void
3511 elm_map_paused_markers_set(Evas_Object *obj, Eina_Bool paused)
3512 {
3513    ELM_CHECK_WIDTYPE(obj, widtype);
3514    Widget_Data *wd = elm_widget_data_get(obj);
3515
3516    if (!wd) return;
3517    if (wd->paused_markers == !!paused) return;
3518    wd->paused_markers = paused;
3519 }
3520
3521 EAPI Eina_Bool
3522 elm_map_paused_get(const Evas_Object *obj)
3523 {
3524    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3525    Widget_Data *wd = elm_widget_data_get(obj);
3526
3527    if (!wd) return EINA_FALSE;
3528    return wd->paused;
3529 }
3530
3531 EAPI Eina_Bool
3532 elm_map_paused_markers_get(const Evas_Object *obj)
3533 {
3534    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3535    Widget_Data *wd = elm_widget_data_get(obj);
3536
3537    if (!wd) return EINA_FALSE;
3538    return wd->paused_markers;
3539 }
3540
3541 EAPI void
3542 elm_map_utils_downloading_status_get(const Evas_Object *obj, int *try_num, int *finish_num)
3543 {
3544    ELM_CHECK_WIDTYPE(obj, widtype);
3545    Widget_Data *wd = elm_widget_data_get(obj);
3546
3547    if (!wd) return;
3548    if (try_num)
3549      {
3550         *try_num = wd->try_num;
3551      }
3552
3553    if (finish_num)
3554      {
3555         *finish_num = wd->finish_num;
3556      }
3557 }
3558
3559 EAPI void
3560 elm_map_utils_convert_coord_into_geo(const Evas_Object *obj, int x, int y, int size, double *lon, double *lat)
3561 {
3562    ELM_CHECK_WIDTYPE(obj, widtype);
3563    Widget_Data *wd = elm_widget_data_get(obj);
3564
3565    if (!wd) return;
3566    int zoom = floor(log(size / 256) / log(2));
3567    if ((wd->src) && (wd->src->coord_into_geo))
3568      {
3569         if (wd->src->coord_into_geo(obj, zoom, x, y, size, lon, lat)) return;
3570      }
3571
3572    if (lon)
3573      {
3574         *lon = x / (double)size * 360.0 - 180;
3575      }
3576    if (lat)
3577      {
3578         double n = ELM_PI - 2.0 * ELM_PI * y / size;
3579         *lat = 180.0 / ELM_PI * atan(0.5 * (exp(n) - exp(-n)));
3580      }
3581 }
3582
3583 EAPI void
3584 elm_map_utils_convert_geo_into_coord(const Evas_Object *obj, double lon, double lat, int size, int *x, int *y)
3585 {
3586    ELM_CHECK_WIDTYPE(obj, widtype);
3587    Widget_Data *wd = elm_widget_data_get(obj);
3588
3589    if (!wd) return;
3590    int zoom = floor(log(size / 256) / log(2));
3591    if ((wd->src) && (wd->src->geo_into_coord))
3592      {
3593         if (wd->src->geo_into_coord(obj, zoom, lon, lat, size, x, y)) return;
3594      }
3595
3596    if (x)
3597      *x = floor((lon + 180.0) / 360.0 * size);
3598    if (y)
3599      *y = floor((1.0 - log( tan(lat * ELM_PI / 180.0) + 1.0 / cos(lat * ELM_PI / 180.0)) / ELM_PI) / 2.0 * size);
3600 }
3601
3602 EAPI Elm_Map_Name *
3603 elm_map_utils_convert_coord_into_name(const Evas_Object *obj, double lon, double lat)
3604 {
3605    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3606    return _utils_convert_name(obj, ELM_MAP_NAME_METHOD_REVERSE, NULL, lon, lat);
3607 }
3608
3609 EAPI Elm_Map_Name *
3610 elm_map_utils_convert_name_into_coord(const Evas_Object *obj, char *address)
3611 {
3612    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3613    if (!address) return NULL;
3614    return _utils_convert_name(obj, ELM_MAP_NAME_METHOD_SEARCH, address, 0.0, 0.0);
3615 }
3616
3617 EAPI void
3618 elm_map_utils_rotate_coord(const Evas_Object *obj __UNUSED__, const Evas_Coord x, const Evas_Coord y, const Evas_Coord cx, const Evas_Coord cy, const double degree, Evas_Coord *xx, Evas_Coord *yy)
3619 {
3620    if ((!xx) || (!yy)) return;
3621
3622    double r = (degree * M_PI) / 180.0;
3623    double tx, ty, ttx, tty;
3624
3625    tx = x - cx;
3626    ty = y - cy;
3627
3628    ttx = tx * cos(r);
3629    tty = tx * sin(r);
3630    tx = ttx + (ty * cos(r + M_PI_2));
3631    ty = tty + (ty * sin(r + M_PI_2));
3632
3633    *xx = tx + cx;
3634    *yy = ty + cy;
3635 }
3636
3637 EAPI Elm_Map_Marker *
3638 elm_map_marker_add(Evas_Object *obj, double lon, double lat, Elm_Map_Marker_Class *clas, Elm_Map_Group_Class *clas_group, void *data)
3639 {
3640    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3641    Widget_Data *wd = elm_widget_data_get(obj);
3642    int i, j;
3643    Eina_List *l;
3644    Marker_Group *group;
3645    int mpi, mpj;
3646    int tabi[9];
3647    int tabj[9];
3648    const char *s;
3649    const char *style;
3650    Evas_Object *o;
3651
3652    if (!wd) return NULL;
3653    EINA_SAFETY_ON_NULL_RETURN_VAL(clas_group, NULL);
3654    EINA_SAFETY_ON_NULL_RETURN_VAL(clas, NULL);
3655
3656    Elm_Map_Marker *marker = ELM_NEW(Elm_Map_Marker);
3657
3658    marker->wd = wd;
3659    marker->clas = clas;
3660    marker->clas_group = clas_group;
3661    marker->longitude = lon;
3662    marker->latitude = lat;
3663    marker->data = data;
3664    marker->x = calloc(wd->zoom_max + 1, sizeof(Evas_Coord));
3665    marker->y = calloc(wd->zoom_max + 1, sizeof(Evas_Coord));
3666    marker->groups = calloc(wd->zoom_max + 1, sizeof(Marker_Group*));
3667
3668    tabi[1] = tabi[4] = tabi[6] = -1;
3669    tabi[2] = tabi[0] = tabi[7] = 0;
3670    tabi[3] = tabi[5] = tabi[8] = 1;
3671
3672    tabj[1] = tabj[2] = tabj[3] = -1;
3673    tabj[4] = tabj[0] = tabj[5] = 0;
3674    tabj[6] = tabj[7] = tabj[8] = 1;
3675
3676    if (!clas_group->priv.set)
3677      {
3678         style = "radio";
3679         if (marker->clas_group && marker->clas_group->style)
3680           style = marker->clas_group->style;
3681
3682         o = edje_object_add(evas_object_evas_get(obj));
3683         _elm_theme_object_set(obj, o, "map/marker", style, elm_widget_style_get(obj));
3684         s = edje_object_data_get(o, "size_w");
3685         if (s) clas_group->priv.edje_w = atoi(s);
3686         else clas_group->priv.edje_w = 0;
3687         s = edje_object_data_get(o, "size_h");
3688         if (s) clas_group->priv.edje_h = atoi(s);
3689         else clas_group->priv.edje_h = 0;
3690         s = edje_object_data_get(o, "size_max_w");
3691         if (s) clas_group->priv.edje_max_w = atoi(s);
3692         else clas_group->priv.edje_max_w = 0;
3693         s = edje_object_data_get(o, "size_max_h");
3694         if (s) clas_group->priv.edje_max_h = atoi(s);
3695         else clas_group->priv.edje_max_h = 0;
3696         evas_object_del(o);
3697
3698         clas_group->priv.set = EINA_TRUE;
3699      }
3700
3701    if (!clas->priv.set)
3702      {
3703         style = "radio";
3704         if (marker->clas && marker->clas->style)
3705           style = marker->clas->style;
3706
3707         o = edje_object_add(evas_object_evas_get(obj));
3708         _elm_theme_object_set(obj, o, "map/marker", style, elm_widget_style_get(obj));
3709         s = edje_object_data_get(o, "size_w");
3710         if (s) clas->priv.edje_w = atoi(s);
3711         else clas->priv.edje_w = 0;
3712         s = edje_object_data_get(o, "size_h");
3713         if (s) clas->priv.edje_h = atoi(s);
3714         else clas->priv.edje_h = 0;
3715         evas_object_del(o);
3716
3717         clas->priv.set = EINA_TRUE;
3718      }
3719
3720    for (i = clas_group->zoom_displayed; i <= wd->zoom_max; i++)
3721      {
3722         elm_map_utils_convert_geo_into_coord(obj, lon, lat, pow(2.0, i)*wd->tsize,
3723                                              &(marker->x[i]), &(marker->y[i]));
3724
3725         //search in the matrixsparse the region where the marker will be
3726         mpi = marker->x[i] / wd->tsize;
3727         mpj = marker->y[i] / wd->tsize;
3728
3729         if (!wd->markers[i])
3730           {
3731              int size =  pow(2.0, i);
3732              wd->markers[i] = eina_matrixsparse_new(size, size, NULL, NULL);
3733           }
3734
3735         group = NULL;
3736         if (i <= clas_group->zoom_grouped)
3737           {
3738              for (j = 0, group = NULL; j < 9 && !group; j++)
3739                {
3740                   EINA_LIST_FOREACH(eina_matrixsparse_data_idx_get(wd->markers[i], mpj + tabj[j], mpi + tabi[j]),
3741                                     l, group)
3742                     {
3743                        if (group->clas == marker->clas_group
3744                            && ELM_RECTS_INTERSECT(marker->x[i]-clas->priv.edje_w/4,
3745                                                   marker->y[i]-clas->priv.edje_h/4, clas->priv.edje_w, clas->priv.edje_h,
3746                                                   group->x-group->w/4, group->y-group->h/4, group->w, group->h))
3747                          {
3748                             group->markers = eina_list_append(group->markers, marker);
3749                             group->update_nbelems = EINA_TRUE;
3750                             group->update_resize = EINA_TRUE;
3751
3752                             group->sum_x += marker->x[i];
3753                             group->sum_y += marker->y[i];
3754                             group->x = group->sum_x / eina_list_count(group->markers);
3755                             group->y = group->sum_y / eina_list_count(group->markers);
3756
3757                             group->w = group->clas->priv.edje_w + group->clas->priv.edje_w/8.
3758                                * eina_list_count(group->markers);
3759                             group->h = group->clas->priv.edje_h + group->clas->priv.edje_h/8.
3760                                * eina_list_count(group->markers);
3761                             if (group->w > group->clas->priv.edje_max_w) group->w = group->clas->priv.edje_max_w;
3762                             if (group->h > group->clas->priv.edje_max_h) group->h = group->clas->priv.edje_max_h;
3763
3764                             if (group->obj && eina_list_count(group->markers) == 2)
3765                               {
3766                                  _group_object_free(group);
3767                                  _group_object_create(group);
3768                               }
3769                             if (group->bubble)
3770                               _group_bubble_content_update(group);
3771
3772                             break;
3773                          }
3774                     }
3775                }
3776           }
3777         if (!group)
3778           {
3779              group = calloc(1, sizeof(Marker_Group));
3780              group->wd = wd;
3781              group->sum_x = marker->x[i];
3782              group->sum_y = marker->y[i];
3783              group->x = marker->x[i];
3784              group->y = marker->y[i];
3785              group->w = clas_group->priv.edje_w;
3786              group->h = clas_group->priv.edje_h;
3787              group->clas = clas_group;
3788
3789              group->markers = eina_list_append(group->markers, marker);
3790              group->update_nbelems = EINA_TRUE;
3791              group->update_resize = EINA_TRUE;
3792
3793              eina_matrixsparse_cell_idx_get(wd->markers[i], mpj, mpi, &(group->cell));
3794
3795              if (!group->cell)
3796                {
3797                   l = eina_list_append(NULL, group);
3798                   eina_matrixsparse_data_idx_set(wd->markers[i], mpj, mpi, l);
3799                   eina_matrixsparse_cell_idx_get(wd->markers[i], mpj, mpi, &(group->cell));
3800                }
3801              else
3802                {
3803                   l = eina_matrixsparse_cell_data_get(group->cell);
3804                   l = eina_list_append(l, group);
3805                   eina_matrixsparse_cell_data_set(group->cell, l);
3806                }
3807           }
3808         marker->groups[i] = group;
3809      }
3810
3811    if (wd->grids)
3812      {
3813         Evas_Coord ox, oy, ow, oh;
3814         evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
3815         marker_place(obj, eina_list_data_get(wd->grids), wd->pan_x, wd->pan_y, ox, oy, ow, oh);
3816      }
3817
3818    return marker;
3819 }
3820
3821 EAPI void
3822 elm_map_marker_remove(Elm_Map_Marker *marker)
3823 {
3824    int i;
3825    Eina_List *groups;
3826    Widget_Data *wd;
3827
3828    EINA_SAFETY_ON_NULL_RETURN(marker);
3829    wd = marker->wd;
3830    if (!wd) return;
3831    for (i = marker->clas_group->zoom_displayed; i <= wd->zoom_max; i++)
3832      {
3833         marker->groups[i]->markers = eina_list_remove(marker->groups[i]->markers, marker);
3834         if (!eina_list_count(marker->groups[i]->markers))
3835           {
3836              groups = eina_matrixsparse_cell_data_get(marker->groups[i]->cell);
3837              groups = eina_list_remove(groups, marker->groups[i]);
3838              eina_matrixsparse_cell_data_set(marker->groups[i]->cell, groups);
3839
3840              _group_object_free(marker->groups[i]);
3841              _group_bubble_free(marker->groups[i]);
3842              free(marker->groups[i]);
3843           }
3844         else
3845           {
3846              marker->groups[i]->sum_x -= marker->x[i];
3847              marker->groups[i]->sum_y -= marker->y[i];
3848
3849              marker->groups[i]->x = marker->groups[i]->sum_x / eina_list_count(marker->groups[i]->markers);
3850              marker->groups[i]->y = marker->groups[i]->sum_y / eina_list_count(marker->groups[i]->markers);
3851
3852              marker->groups[i]->w = marker->groups[i]->clas->priv.edje_w
3853                 + marker->groups[i]->clas->priv.edje_w/8. * eina_list_count(marker->groups[i]->markers);
3854              marker->groups[i]->h = marker->groups[i]->clas->priv.edje_h
3855                 + marker->groups[i]->clas->priv.edje_h/8. * eina_list_count(marker->groups[i]->markers);
3856              if (marker->groups[i]->w > marker->groups[i]->clas->priv.edje_max_w)
3857                marker->groups[i]->w = marker->groups[i]->clas->priv.edje_max_w;
3858              if (marker->groups[i]->h > marker->groups[i]->clas->priv.edje_max_h)
3859                marker->groups[i]->h = marker->groups[i]->clas->priv.edje_max_h;
3860
3861              if ((marker->groups[i]->obj) && (eina_list_count(marker->groups[i]->markers) == 1))
3862                {
3863                   _group_object_free(marker->groups[i]);
3864                   _group_object_create(marker->groups[i]);
3865                }
3866           }
3867      }
3868
3869    if ((marker->content) && (marker->clas->func.del))
3870      marker->clas->func.del(marker->wd->obj, marker, marker->data, marker->content);
3871    else if (marker->content)
3872      evas_object_del(marker->content);
3873
3874    if (marker->x) free(marker->x);
3875    if (marker->y) free(marker->y);
3876    if (marker->groups) free(marker->groups);
3877
3878    free(marker);
3879
3880    if (wd->grids)
3881      {
3882         Evas_Coord ox, oy, ow, oh;
3883         evas_object_geometry_get(wd->obj, &ox, &oy, &ow, &oh);
3884         marker_place(wd->obj, eina_list_data_get(wd->grids), wd->pan_x, wd->pan_y, ox, oy, ow, oh);
3885      }
3886 }
3887
3888 EAPI void
3889 elm_map_marker_region_get(const Elm_Map_Marker *marker, double *lon, double *lat)
3890 {
3891    EINA_SAFETY_ON_NULL_RETURN(marker);
3892    if (lon) *lon = marker->longitude;
3893    if (lat) *lat = marker->latitude;
3894 }
3895
3896 EAPI void
3897 elm_map_marker_bring_in(Elm_Map_Marker *marker)
3898 {
3899    EINA_SAFETY_ON_NULL_RETURN(marker);
3900    elm_map_geo_region_bring_in(marker->wd->obj, marker->longitude, marker->latitude);
3901 }
3902
3903 EAPI void
3904 elm_map_marker_show(Elm_Map_Marker *marker)
3905 {
3906    EINA_SAFETY_ON_NULL_RETURN(marker);
3907    elm_map_geo_region_show(marker->wd->obj, marker->longitude, marker->latitude);
3908 }
3909
3910 EAPI void
3911 elm_map_markers_list_show(Eina_List *markers)
3912 {
3913    int zoom;
3914    double lon, lat;
3915    Eina_List *l;
3916    Elm_Map_Marker *marker, *m_max_lon = NULL, *m_max_lat = NULL, *m_min_lon = NULL, *m_min_lat = NULL;
3917    Evas_Coord rw, rh, xc, yc;
3918    Widget_Data *wd;
3919
3920    EINA_SAFETY_ON_NULL_RETURN(markers);
3921    EINA_LIST_FOREACH(markers, l, marker)
3922      {
3923         wd = marker->wd;
3924
3925         if ((!m_min_lon) || (marker->longitude < m_min_lon->longitude))
3926           m_min_lon = marker;
3927
3928         if ((!m_max_lon) || (marker->longitude > m_max_lon->longitude))
3929           m_max_lon = marker;
3930
3931         if ((!m_min_lat) || (marker->latitude > m_min_lat->latitude))
3932           m_min_lat = marker;
3933
3934         if ((!m_max_lat) || (marker->latitude < m_max_lat->latitude))
3935           m_max_lat = marker;
3936      }
3937
3938    lon = (m_max_lon->longitude - m_min_lon->longitude) / 2. + m_min_lon->longitude;
3939    lat = (m_max_lat->latitude - m_min_lat->latitude) / 2. + m_min_lat->latitude;
3940
3941    elm_smart_scroller_child_viewport_size_get(wd->scr, &rw, &rh);
3942    for (zoom = wd->src->zoom_max; zoom > wd->src->zoom_min; zoom--)
3943      {
3944         Evas_Coord size = pow(2.0, zoom)*wd->tsize;
3945         elm_map_utils_convert_geo_into_coord(wd->obj, lon, lat, size, &xc, &yc);
3946
3947         if ((m_min_lon->x[zoom] - wd->marker_max_w >= xc-rw/2)
3948             && (m_min_lat->y[zoom] - wd->marker_max_h >= yc-rh/2)
3949             && (m_max_lon->x[zoom] + wd->marker_max_w <= xc+rw/2)
3950             && (m_max_lat->y[zoom] + wd->marker_max_h <= yc+rh/2))
3951           break;
3952      }
3953
3954    elm_map_geo_region_show(wd->obj, lon, lat);
3955    elm_map_zoom_set(wd->obj, zoom);
3956 }
3957
3958 EAPI void
3959 elm_map_max_marker_per_group_set(Evas_Object *obj, int max)
3960 {
3961    ELM_CHECK_WIDTYPE(obj, widtype);
3962    Widget_Data *wd = elm_widget_data_get(obj);
3963
3964    if (!wd) return;
3965    wd->markers_max_num = max;
3966 }
3967
3968 EAPI Evas_Object *
3969 elm_map_marker_object_get(const Elm_Map_Marker *marker)
3970 {
3971    EINA_SAFETY_ON_NULL_RETURN_VAL(marker, NULL);
3972    return marker->content;
3973 }
3974
3975 EAPI void
3976 elm_map_marker_update(Elm_Map_Marker *marker)
3977 {
3978    EINA_SAFETY_ON_NULL_RETURN(marker);
3979    if (marker->content)
3980      {
3981         if (marker->clas->func.del)
3982           marker->clas->func.del(marker->wd->obj, marker, marker->data, marker->content);
3983         else
3984           evas_object_del(marker->content);
3985         marker->content = NULL;
3986         _group_bubble_content_update(marker->groups[marker->wd->zoom]);
3987      }
3988 }
3989
3990 EAPI void
3991 elm_map_bubbles_close(Evas_Object *obj)
3992 {
3993    ELM_CHECK_WIDTYPE(obj, widtype);
3994    Widget_Data *wd = elm_widget_data_get(obj);
3995    Marker_Group *group;
3996    Eina_List *l, *l_next;
3997
3998    if (!wd) return;
3999    EINA_LIST_FOREACH_SAFE(wd->opened_bubbles, l, l_next, group)
4000       _group_bubble_free(group);
4001 }
4002
4003 EAPI Elm_Map_Group_Class *
4004 elm_map_group_class_new(Evas_Object *obj)
4005 {
4006    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4007    Widget_Data *wd = elm_widget_data_get(obj);
4008
4009    if (!wd) return NULL;
4010    Elm_Map_Group_Class *clas = calloc(1, sizeof(Elm_Map_Group_Class));
4011    clas->zoom_grouped = wd->zoom_max;
4012    wd->groups_clas = eina_list_append(wd->groups_clas, clas);
4013    return clas;
4014 }
4015
4016 EAPI void
4017 elm_map_group_class_style_set(Elm_Map_Group_Class *clas, const char *style)
4018 {
4019    EINA_SAFETY_ON_NULL_RETURN(clas);
4020    eina_stringshare_replace(&clas->style, style);
4021 }
4022
4023 EAPI void
4024 elm_map_group_class_icon_cb_set(Elm_Map_Group_Class *clas, ElmMapGroupIconGetFunc icon_get)
4025 {
4026    EINA_SAFETY_ON_NULL_RETURN(clas);
4027    clas->func.icon_get = icon_get;
4028 }
4029
4030 EAPI void
4031 elm_map_group_class_data_set(Elm_Map_Group_Class *clas, void *data)
4032 {
4033    EINA_SAFETY_ON_NULL_RETURN(clas);
4034    clas->data = data;
4035 }
4036
4037 EAPI void
4038 elm_map_group_class_zoom_displayed_set(Elm_Map_Group_Class *clas, int zoom)
4039 {
4040    EINA_SAFETY_ON_NULL_RETURN(clas);
4041    clas->zoom_displayed = zoom;
4042 }
4043
4044 EAPI void
4045 elm_map_group_class_zoom_grouped_set(Elm_Map_Group_Class *clas, int zoom)
4046 {
4047    EINA_SAFETY_ON_NULL_RETURN(clas);
4048    clas->zoom_grouped = zoom;
4049 }
4050
4051 EAPI void
4052 elm_map_group_class_hide_set(Evas_Object *obj, Elm_Map_Group_Class *clas, Eina_Bool hide)
4053 {
4054    ELM_CHECK_WIDTYPE(obj, widtype);
4055    Widget_Data *wd = elm_widget_data_get(obj);
4056
4057    if (!wd) return;
4058    EINA_SAFETY_ON_NULL_RETURN(clas);
4059    if (clas->hide == hide) return;
4060    clas->hide = hide;
4061    if (wd->grids)
4062      {
4063         Evas_Coord ox, oy, ow, oh;
4064         evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
4065         marker_place(obj, eina_list_data_get(wd->grids), wd->pan_x, wd->pan_y, ox, oy, ow, oh);
4066      }
4067 }
4068
4069 EAPI Elm_Map_Marker_Class *
4070 elm_map_marker_class_new(Evas_Object *obj)
4071 {
4072    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4073    Widget_Data *wd = elm_widget_data_get(obj);
4074
4075    if (!wd) return NULL;
4076    Elm_Map_Marker_Class *clas = calloc(1, sizeof(Elm_Map_Marker_Class));
4077    wd->markers_clas = eina_list_append(wd->markers_clas, clas);
4078    return clas;
4079 }
4080
4081 EAPI void
4082 elm_map_marker_class_style_set(Elm_Map_Marker_Class *clas, const char *style)
4083 {
4084    EINA_SAFETY_ON_NULL_RETURN(clas);
4085    eina_stringshare_replace(&clas->style, style);
4086 }
4087
4088 EAPI void
4089 elm_map_marker_class_icon_cb_set(Elm_Map_Marker_Class *clas, ElmMapMarkerIconGetFunc icon_get)
4090 {
4091    EINA_SAFETY_ON_NULL_RETURN(clas);
4092    clas->func.icon_get = icon_get;
4093 }
4094
4095 EAPI void
4096 elm_map_marker_class_get_cb_set(Elm_Map_Marker_Class *clas, ElmMapMarkerGetFunc get)
4097 {
4098    EINA_SAFETY_ON_NULL_RETURN(clas);
4099    clas->func.get = get;
4100 }
4101
4102 EAPI void
4103 elm_map_marker_class_del_cb_set(Elm_Map_Marker_Class *clas, ElmMapMarkerDelFunc del)
4104 {
4105    EINA_SAFETY_ON_NULL_RETURN(clas);
4106    clas->func.del = del;
4107 }
4108
4109 EAPI const char **
4110 elm_map_source_names_get(const Evas_Object *obj)
4111 {
4112    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4113    Widget_Data *wd = elm_widget_data_get(obj);
4114
4115    if (!wd) return NULL;
4116    return wd->source_names;
4117 }
4118
4119 EAPI void
4120 elm_map_source_name_set(Evas_Object *obj, const char *source_name)
4121 {
4122    ELM_CHECK_WIDTYPE(obj, widtype);
4123    Widget_Data *wd = elm_widget_data_get(obj);
4124    Map_Sources_Tab *s;
4125    Eina_List *l;
4126    Grid *grid;
4127    int zoom;
4128
4129    if (!wd) return;
4130    if (wd->src)
4131      {
4132         if (!strcmp(wd->src->name, source_name)) return;
4133         if (!wd->src->url_cb) return;
4134      }
4135
4136    EINA_LIST_FREE(wd->grids, grid) grid_clear(obj, grid);
4137    EINA_LIST_FOREACH(wd->map_sources_tab, l, s)
4138      {
4139         if (!strcmp(s->name, source_name))
4140           {
4141              wd->src = s;
4142              break;
4143           }
4144      }
4145    zoom = wd->zoom;
4146    wd->zoom = -1;
4147
4148    if (wd->src)
4149      {
4150         if (wd->src->zoom_max < zoom)
4151           zoom = wd->src->zoom_max;
4152         if (wd->src->zoom_min > zoom)
4153           zoom = wd->src->zoom_min;
4154      }
4155    elm_map_zoom_set(obj, zoom);
4156 }
4157
4158 EAPI const char *
4159 elm_map_source_name_get(const Evas_Object *obj)
4160 {
4161    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4162    Widget_Data *wd = elm_widget_data_get(obj);
4163
4164    if ((!wd) || (!wd->src)) return NULL;
4165    return wd->src->name;
4166 }
4167
4168 EAPI void
4169 elm_map_route_source_set(Evas_Object *obj, Elm_Map_Route_Sources source)
4170 {
4171    ELM_CHECK_WIDTYPE(obj, widtype);
4172    Widget_Data *wd = elm_widget_data_get(obj);
4173
4174    if (!wd) return;
4175    wd->route_source = source;
4176 }
4177
4178 EAPI Elm_Map_Route_Sources
4179 elm_map_route_source_get(const Evas_Object *obj)
4180 {
4181    ELM_CHECK_WIDTYPE(obj, widtype) ELM_MAP_ROUTE_SOURCE_YOURS;
4182    Widget_Data *wd = elm_widget_data_get(obj);
4183
4184    if (!wd) return ELM_MAP_ROUTE_SOURCE_YOURS;
4185    return wd->route_source;
4186 }
4187
4188 EAPI void
4189 elm_map_source_zoom_max_set(Evas_Object *obj, int zoom)
4190 {
4191    ELM_CHECK_WIDTYPE(obj, widtype);
4192    Widget_Data *wd = elm_widget_data_get(obj);
4193
4194    if ((!wd) || (!wd->src)) return;
4195    if ((zoom > wd->zoom_max) || (zoom < wd->zoom_min)) return;
4196    wd->src->zoom_max = zoom;
4197 }
4198
4199 EAPI int
4200 elm_map_source_zoom_max_get(const Evas_Object *obj)
4201 {
4202    ELM_CHECK_WIDTYPE(obj, widtype) 18;
4203    Widget_Data *wd = elm_widget_data_get(obj);
4204
4205    if ((!wd) || (!wd->src)) return 18;
4206    return wd->src->zoom_max;
4207 }
4208
4209 EAPI void
4210 elm_map_source_zoom_min_set(Evas_Object *obj, int zoom)
4211 {
4212    ELM_CHECK_WIDTYPE(obj, widtype);
4213    Widget_Data *wd = elm_widget_data_get(obj);
4214
4215    if ((!wd) || (!wd->src)) return;
4216    if ((zoom > wd->zoom_max) || (zoom < wd->zoom_min)) return;
4217    wd->src->zoom_min = zoom;
4218 }
4219
4220 EAPI int
4221 elm_map_source_zoom_min_get(const Evas_Object *obj)
4222 {
4223    ELM_CHECK_WIDTYPE(obj, widtype) 0;
4224    Widget_Data *wd = elm_widget_data_get(obj);
4225
4226    if ((!wd) || (!wd->src)) return 0;
4227    return wd->src->zoom_min;
4228 }
4229
4230 EAPI void
4231 elm_map_user_agent_set(Evas_Object *obj, const char *user_agent)
4232 {
4233    ELM_CHECK_WIDTYPE(obj, widtype);
4234    Widget_Data *wd = elm_widget_data_get(obj);
4235
4236    if (!wd) return;
4237    if (!wd->user_agent) wd->user_agent = eina_stringshare_add(user_agent);
4238    else eina_stringshare_replace(&wd->user_agent, user_agent);
4239
4240    if (!wd->ua) wd->ua = eina_hash_string_small_new(NULL);
4241    eina_hash_set(wd->ua, "User-Agent", wd->user_agent);
4242 }
4243
4244 EAPI const char *
4245 elm_map_user_agent_get(const Evas_Object *obj)
4246 {
4247    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4248    Widget_Data *wd = elm_widget_data_get(obj);
4249
4250    if (!wd) return NULL;
4251    return wd->user_agent;
4252 }
4253
4254 EAPI Elm_Map_Route *
4255 elm_map_route_add(Evas_Object *obj,
4256                   Elm_Map_Route_Type type,
4257                   Elm_Map_Route_Method method,
4258                   double flon,
4259                   double flat,
4260                   double tlon,
4261                   double tlat)
4262 {
4263    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4264    Widget_Data *wd = elm_widget_data_get(obj);
4265    char buf[PATH_MAX];
4266    char *source;
4267    char *type_name = NULL;
4268    int fd;
4269
4270    if ((!wd) || (!wd->src)) return NULL;
4271
4272    Elm_Map_Route *route = ELM_NEW(Elm_Map_Route);
4273    if (!route) return NULL;
4274
4275    snprintf(buf, sizeof(buf), DEST_ROUTE_XML_FILE);
4276    fd = mkstemp(buf);
4277    if (fd < 0)
4278      {
4279         free(route);
4280         return NULL;
4281      }
4282
4283    route->con_url = ecore_con_url_new(NULL);
4284    route->ud.fname = strdup(buf);
4285    INF("xml file : %s", route->ud.fname);
4286
4287    route->ud.fd = fdopen(fd, "w+");
4288    if ((!route->con_url) || (!route->ud.fd))
4289      {
4290         ecore_con_url_free(route->con_url);
4291         free(route);
4292         return NULL;
4293      }
4294
4295    route->wd = wd;
4296    route->color.r = 255;
4297    route->color.g = 0;
4298    route->color.b = 0;
4299    route->color.a = 255;
4300    route->handlers = eina_list_append
4301      (route->handlers, (void *)ecore_event_handler_add
4302          (ECORE_CON_EVENT_URL_COMPLETE, _route_complete_cb, route));
4303
4304    route->inbound = EINA_FALSE;
4305    route->type = type;
4306    route->method = method;
4307    route->flon = flon;
4308    route->flat = flat;
4309    route->tlon = tlon;
4310    route->tlat = tlat;
4311
4312    switch (type)
4313      {
4314       case ELM_MAP_ROUTE_TYPE_MOTOCAR:
4315         type_name = strdup(ROUTE_TYPE_MOTORCAR);
4316         break;
4317       case ELM_MAP_ROUTE_TYPE_BICYCLE:
4318         type_name = strdup(ROUTE_TYPE_BICYCLE);
4319         break;
4320       case ELM_MAP_ROUTE_TYPE_FOOT:
4321         type_name = strdup(ROUTE_TYPE_FOOT);
4322         break;
4323       default:
4324         break;
4325      }
4326
4327    source = wd->src->route_url_cb(obj, type_name, method, flon, flat, tlon, tlat);
4328    INF("route url = %s", source);
4329
4330    wd->route = eina_list_append(wd->route, route);
4331
4332    ecore_con_url_url_set(route->con_url, source);
4333    ecore_con_url_fd_set(route->con_url, fileno(route->ud.fd));
4334    ecore_con_url_data_set(route->con_url, route);
4335    ecore_con_url_get(route->con_url);
4336    if (type_name) free(type_name);
4337    if (source) free(source);
4338
4339    edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
4340                            "elm,state,busy,start", "elm");
4341    evas_object_smart_callback_call(wd->obj, SIG_ROUTE_LOAD, NULL);
4342    return route;
4343 }
4344
4345 EAPI void
4346 elm_map_route_remove(Elm_Map_Route *route)
4347 {
4348    EINA_SAFETY_ON_NULL_RETURN(route);
4349
4350    Path_Waypoint *w;
4351    Path_Node *n;
4352    Evas_Object *p;
4353    Ecore_Event_Handler *h;
4354
4355    EINA_LIST_FREE(route->path, p)
4356      {
4357         evas_object_del(p);
4358      }
4359
4360    EINA_LIST_FREE(route->waypoint, w)
4361      {
4362         if (w->point) eina_stringshare_del(w->point);
4363         free(w);
4364      }
4365
4366    EINA_LIST_FREE(route->nodes, n)
4367      {
4368         if (n->pos.address) eina_stringshare_del(n->pos.address);
4369         free(n);
4370      }
4371
4372    EINA_LIST_FREE(route->handlers, h)
4373      {
4374         ecore_event_handler_del(h);
4375      }
4376
4377    if (route->ud.fname)
4378      {
4379         ecore_file_remove(route->ud.fname);
4380         free(route->ud.fname);
4381         route->ud.fname = NULL;
4382      }
4383 }
4384
4385 EAPI void
4386 elm_map_route_color_set(Elm_Map_Route *route, int r, int g , int b, int a)
4387 {
4388    EINA_SAFETY_ON_NULL_RETURN(route);
4389    route->color.r = r;
4390    route->color.g = g;
4391    route->color.b = b;
4392    route->color.a = a;
4393 }
4394
4395 EAPI void
4396 elm_map_route_color_get(const Elm_Map_Route *route, int *r, int *g , int *b, int *a)
4397 {
4398    EINA_SAFETY_ON_NULL_RETURN(route);
4399    if (r) *r = route->color.r;
4400    if (g) *g = route->color.g;
4401    if (b) *b = route->color.b;
4402    if (a) *a = route->color.a;
4403 }
4404
4405 EAPI double
4406 elm_map_route_distance_get(const Elm_Map_Route *route)
4407 {
4408    EINA_SAFETY_ON_NULL_RETURN_VAL(route, 0.0);
4409    return route->info.distance;
4410 }
4411
4412 EAPI const char*
4413 elm_map_route_node_get(const Elm_Map_Route *route)
4414 {
4415    EINA_SAFETY_ON_NULL_RETURN_VAL(route, NULL);
4416    return route->info.nodes;
4417 }
4418
4419 EAPI const char*
4420 elm_map_route_waypoint_get(const Elm_Map_Route *route)
4421 {
4422    EINA_SAFETY_ON_NULL_RETURN_VAL(route, NULL);
4423    return route->info.waypoints;
4424 }
4425
4426 EAPI const char *
4427 elm_map_name_address_get(const Elm_Map_Name *name)
4428 {
4429    EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
4430    return name->address;
4431 }
4432
4433 EAPI void
4434 elm_map_name_region_get(const Elm_Map_Name *name, double *lon, double *lat)
4435 {
4436    EINA_SAFETY_ON_NULL_RETURN(name);
4437    if (lon) *lon = name->lon;
4438    if (lat) *lat = name->lat;
4439 }
4440
4441 EAPI void
4442 elm_map_name_remove(Elm_Map_Name *name)
4443 {
4444    EINA_SAFETY_ON_NULL_RETURN(name);
4445    if (name->address)
4446      {
4447         free(name->address);
4448         name->address = NULL;
4449      }
4450    if (name->handler)
4451      {
4452         ecore_event_handler_del(name->handler);
4453         name->handler = NULL;
4454      }
4455    if (name->ud.fname)
4456      {
4457         ecore_file_remove(name->ud.fname);
4458         free(name->ud.fname);
4459         name->ud.fname = NULL;
4460      }
4461 }
4462
4463 EAPI void
4464 elm_map_rotate_set(Evas_Object *obj, double degree, Evas_Coord cx, Evas_Coord cy)
4465 {
4466    ELM_CHECK_WIDTYPE(obj, widtype);
4467    Widget_Data *wd = elm_widget_data_get(obj);
4468
4469    if (!wd) return;
4470    wd->rotate.d = degree;
4471    wd->rotate.cx = cx;
4472    wd->rotate.cy = cy;
4473    wd->calc_job = ecore_job_add(_calc_job, wd);
4474 }
4475
4476 EAPI void
4477 elm_map_rotate_get(const Evas_Object *obj, double *degree, Evas_Coord *cx, Evas_Coord *cy)
4478 {
4479    ELM_CHECK_WIDTYPE(obj, widtype);
4480    Widget_Data *wd = elm_widget_data_get(obj);
4481
4482    if (!wd) return;
4483    if (degree) *degree = wd->rotate.d;
4484    if (cx) *cx = wd->rotate.cx;
4485    if (cy) *cy = wd->rotate.cy;
4486 }
4487
4488 EAPI void
4489 elm_map_wheel_disabled_set(Evas_Object *obj, Eina_Bool disabled)
4490 {
4491    ELM_CHECK_WIDTYPE(obj, widtype);
4492    Widget_Data *wd = elm_widget_data_get(obj);
4493
4494    if (!wd) return;
4495    if ((!wd->wheel_disabled) && (disabled))
4496      evas_object_event_callback_del_full(wd->rect, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel_cb, obj);
4497    else if ((wd->wheel_disabled) && (!disabled))
4498      evas_object_event_callback_add(wd->rect, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel_cb, obj);
4499    wd->wheel_disabled = !!disabled;
4500 }
4501
4502 EAPI Eina_Bool
4503 elm_map_wheel_disabled_get(const Evas_Object *obj)
4504 {
4505    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4506    Widget_Data *wd = elm_widget_data_get(obj);
4507
4508    if (!wd) return EINA_FALSE;
4509    return wd->wheel_disabled;
4510 }
4511
4512 #ifdef ELM_EMAP
4513 EAPI Evas_Object *
4514 elm_map_track_add(Evas_Object *obj, EMap_Route *emap)
4515 {
4516    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4517    Widget_Data *wd = elm_widget_data_get(obj);
4518
4519    if (!wd) return EINA_FALSE;
4520
4521    Evas_Object *route = elm_route_add(obj);
4522    elm_route_emap_set(route, emap);
4523    wd->track = eina_list_append(wd->track, route);
4524
4525    return route;
4526 }
4527 #endif
4528
4529 EAPI void
4530 elm_map_track_remove(Evas_Object *obj, Evas_Object *route)
4531 {
4532    ELM_CHECK_WIDTYPE(obj, widtype) ;
4533    Widget_Data *wd = elm_widget_data_get(obj);
4534
4535    if (!wd) return ;
4536
4537    wd->track = eina_list_remove(wd->track, route);
4538    evas_object_del(route);
4539 }
4540
4541 static char *
4542 _mapnik_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom)
4543 {
4544    char buf[PATH_MAX];
4545    snprintf(buf, sizeof(buf), "http://tile.openstreetmap.org/%d/%d/%d.png",
4546           zoom, x, y);
4547    return strdup(buf);
4548 }
4549
4550 static char *
4551 _osmarender_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom)
4552 {
4553    char buf[PATH_MAX];
4554    snprintf(buf, sizeof(buf),
4555             "http://tah.openstreetmap.org/Tiles/tile/%d/%d/%d.png",
4556             zoom, x, y);
4557    return strdup(buf);
4558 }
4559
4560 static char *
4561 _cyclemap_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom)
4562 {
4563    char buf[PATH_MAX];
4564    snprintf(buf, sizeof(buf),
4565             "http://andy.sandbox.cloudmade.com/tiles/cycle/%d/%d/%d.png",
4566             zoom, x, y);
4567    return strdup(buf);
4568 }
4569
4570 static char *
4571 _maplint_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom)
4572 {
4573    char buf[PATH_MAX];
4574    snprintf(buf, sizeof(buf),
4575             "http://tah.openstreetmap.org/Tiles/maplint/%d/%d/%d.png",
4576             zoom, x, y);
4577    return strdup(buf);
4578 }
4579
4580 static char *_yours_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat)
4581 {
4582    char buf[PATH_MAX];
4583    snprintf(buf, sizeof(buf),
4584             "%s?flat=%lf&flon=%lf&tlat=%lf&tlon=%lf&v=%s&fast=%d&instructions=1",
4585             ROUTE_YOURS_URL, flat, flon, tlat, tlon, type_name, method);
4586
4587    return strdup(buf);
4588 }
4589
4590 // TODO: fix monav api
4591 /*
4592 static char *_monav_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat)
4593 {
4594    char buf[PATH_MAX];
4595    snprintf(buf, sizeof(buf),
4596             "%s?flat=%f&flon=%f&tlat=%f&tlon=%f&v=%s&fast=%d&instructions=1",
4597             ROUTE_MONAV_URL, flat, flon, tlat, tlon, type_name, method);
4598
4599    return strdup(buf);
4600 }
4601 */
4602
4603 // TODO: fix ors api
4604 /*
4605 static char *_ors_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat)
4606 {
4607    char buf[PATH_MAX];
4608    snprintf(buf, sizeof(buf),
4609             "%s?flat=%f&flon=%f&tlat=%f&tlon=%f&v=%s&fast=%d&instructions=1",
4610             ROUTE_ORS_URL, flat, flon, tlat, tlon, type_name, method);
4611
4612    return strdup(buf);
4613 }
4614 */
4615
4616 static char *
4617 _nominatim_url_cb(Evas_Object *obj, int method, char *name, double lon, double lat)
4618 {
4619    ELM_CHECK_WIDTYPE(obj, widtype) strdup("");
4620    Widget_Data *wd = elm_widget_data_get(obj);
4621    char **str;
4622    unsigned int ele, idx;
4623    char search_url[PATH_MAX];
4624    char buf[PATH_MAX];
4625
4626    if (!wd) return strdup("");
4627    if (method == ELM_MAP_NAME_METHOD_SEARCH)
4628      {
4629         search_url[0] = '\0';
4630         str = eina_str_split_full(name, " ", 0, &ele);
4631         for (idx = 0 ; idx < ele ; idx++)
4632           {
4633              eina_strlcat(search_url, str[idx], sizeof(search_url));
4634              if (!(idx == (ele-1))) eina_strlcat(search_url, "+", sizeof(search_url));
4635           }
4636         snprintf(buf, sizeof(buf), "%s/search?q=%s&format=xml&polygon=0&addressdetails=0", NAME_NOMINATIM_URL, search_url);
4637      }
4638    else if (method == ELM_MAP_NAME_METHOD_REVERSE) snprintf(buf, sizeof(buf), "%s/reverse?format=xml&lat=%lf&lon=%lf&zoom=%d&addressdetails=0", NAME_NOMINATIM_URL, lat, lon, wd->zoom);
4639    else strcpy(buf, "");
4640
4641    return strdup(buf);
4642 }