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