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