Initialize Tizen 2.3
[framework/uifw/elementary.git] / mobile / src / lib / elm_map.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include "elm_widget_map.h"
4
5 EAPI const char ELM_MAP_SMART_NAME[] = "elm_map";
6 EAPI const char ELM_MAP_PAN_SMART_NAME[] = "elm_map_pan";
7
8 #define MAP_ENGINE_OVERLAY_SUPPORT(wsd) (wsd->engine->icon_add && \
9                                         wsd->engine->icon_remove && \
10                                         wsd->engine->object_from_coord && \
11                                         wsd->engine->object_visibility)
12 #define MAP_ENGINE_GROUP_OVERLAY_SUPPORT(wsd) (MAP_ENGINE_OVERLAY_SUPPORT(wsd) && \
13                                               wsd->engine->group_create && \
14                                               wsd->engine->group_remove &&\
15                                               wsd->engine->group_object_add && \
16                                               wsd->engine->group_object_remove)
17
18 #define INTERNAL_ENGINE_NAME    "Elm_Map_Tile"
19 #define OVERLAY_CLASS_ZOOM_MAX  255
20 #define MAX_CONCURRENT_DOWNLOAD 10
21
22 #define ROUND(z) (((z) < 0) ? (int)ceil((z) - 0.005) : (int)floor((z) + 0.005))
23 #define EVAS_MAP_POINT         4
24 #define DEFAULT_TILE_SIZE      256
25 #define MARER_MAX_NUMBER       30
26 #define OVERLAY_GROUPING_SCALE 2
27
28 #define CACHE_ROOT             "/elm_map"
29 #define CACHE_TILE_ROOT        CACHE_ROOT "/%d/%d/%d"
30 #define CACHE_TILE_PATH        "%s/%d.png"
31 #define CACHE_ROUTE_ROOT       CACHE_ROOT "/route"
32 #define CACHE_NAME_ROOT        CACHE_ROOT "/name"
33
34 #define ROUTE_YOURS_URL        "http://www.yournavigation.org/api/dev/route.php"
35 #define ROUTE_TYPE_MOTORCAR    "motocar"
36 #define ROUTE_TYPE_BICYCLE     "bicycle"
37 #define ROUTE_TYPE_FOOT        "foot"
38 #define YOURS_DISTANCE         "distance"
39 #define YOURS_DESCRIPTION      "description"
40 #define YOURS_COORDINATES      "coordinates"
41
42 #define NAME_NOMINATIM_URL     "http://nominatim.openstreetmap.org"
43 #define NOMINATIM_RESULT       "result"
44 #define NOMINATIM_PLACE        "place"
45 #define NOMINATIM_ATTR_LON     "lon"
46 #define NOMINATIM_ATTR_LAT     "lat"
47 #define NOMINATIM_ATTR_ADDRESS "display_name"
48
49 static Eina_Bool ENABLE_MAP_ENGINE_OVERLAYS = EINA_FALSE;
50
51 #ifdef HAVE_ELEMENTARY_ECORE_CON
52
53 static void _overlay_place(Elm_Map_Smart_Data *sd);
54
55 static char *
56 _mapnik_url_cb(const Evas_Object *obj __UNUSED__,
57                int x,
58                int y,
59                int zoom)
60 {
61    char buf[PATH_MAX];
62
63    // ((x+y+zoom)%3)+'a' is requesting map images from distributed
64    // tile servers (eg., a, b, c)
65    snprintf(buf, sizeof(buf), "http://%c.tile.openstreetmap.org/%d/%d/%d.png",
66             ((x + y + zoom) % 3) + 'a', zoom, x, y);
67    return strdup(buf);
68 }
69
70 static char *
71 _osmarender_url_cb(const Evas_Object *obj __UNUSED__,
72                    int x,
73                    int y,
74                    int zoom)
75 {
76    char buf[PATH_MAX];
77
78    snprintf(buf, sizeof(buf),
79             "http://%c.tah.openstreetmap.org/Tiles/tile/%d/%d/%d.png",
80             ((x + y + zoom) % 3) + 'a', zoom, x, y);
81
82    return strdup(buf);
83 }
84
85 static char *
86 _cyclemap_url_cb(const Evas_Object *obj __UNUSED__,
87                  int x,
88                  int y,
89                  int zoom)
90 {
91    char buf[PATH_MAX];
92
93    snprintf(buf, sizeof(buf),
94             "http://%c.tile.opencyclemap.org/cycle/%d/%d/%d.png",
95             ((x + y + zoom) % 3) + 'a', zoom, x, y);
96
97    return strdup(buf);
98 }
99
100 static char *
101 _mapquest_url_cb(const Evas_Object *obj __UNUSED__,
102                  int x,
103                  int y,
104                  int zoom)
105 {
106    char buf[PATH_MAX];
107
108    snprintf(buf, sizeof(buf),
109             "http://otile%d.mqcdn.com/tiles/1.0.0/osm/%d/%d/%d.png",
110             ((x + y + zoom) % 4) + 1, zoom, x, y);
111
112    return strdup(buf);
113 }
114
115 static char *
116 _mapquest_aerial_url_cb(const Evas_Object *obj __UNUSED__,
117                         int x,
118                         int y,
119                         int zoom)
120 {
121    char buf[PATH_MAX];
122
123    snprintf(buf, sizeof(buf), "http://oatile%d.mqcdn.com/naip/%d/%d/%d.png",
124             ((x + y + zoom) % 4) + 1, zoom, x, y);
125
126    return strdup(buf);
127 }
128
129 static char *
130 _yours_url_cb(const Evas_Object *obj __UNUSED__,
131               const char *type_name,
132               int method,
133               double flon,
134               double flat,
135               double tlon,
136               double tlat)
137 {
138    char buf[PATH_MAX];
139
140    snprintf
141      (buf, sizeof(buf),
142      "%s?flat=%lf&flon=%lf&tlat=%lf&tlon=%lf&v=%s&fast=%d&instructions=1",
143      ROUTE_YOURS_URL, flat, flon, tlat, tlon, type_name, method);
144
145    return strdup(buf);
146 }
147
148 // TODO: fix monav api
149 /*
150    static char *
151    _monav_url_cb(const Evas_Object *obj __UNUSED__,
152               char *type_name,
153               int method,
154               double flon,
155               double flat,
156               double tlon,
157               double tlat)
158    {
159    char buf[PATH_MAX];
160
161    snprintf(buf, sizeof(buf),
162             "%s?flat=%f&flon=%f&tlat=%f&tlon=%f&v=%s&fast=%d&instructions=1",
163             ROUTE_MONAV_URL, flat, flon, tlat, tlon, type_name, method);
164
165    return strdup(buf);
166    }
167
168    //TODO: fix ors api
169
170    static char *
171    _ors_url_cb(const Evas_Object *obj __UNUSED__,
172             char *type_name,
173             int method,
174             double flon,
175             double flat,
176             double tlon,
177             double tlat)
178    {
179    char buf[PATH_MAX];
180
181    snprintf(buf, sizeof(buf),
182             "%s?flat=%f&flon=%f&tlat=%f&tlon=%f&v=%s&fast=%d&instructions=1",
183             ROUTE_ORS_URL, flat, flon, tlat, tlon, type_name, method);
184
185    return strdup(buf);
186    }
187  */
188
189 static char *
190 _nominatim_url_cb(const Evas_Object *obj,
191                   int method,
192                   const char *name,
193                   double lon,
194                   double lat)
195 {
196    char **str;
197    char buf[PATH_MAX];
198    unsigned int ele, idx;
199    char search_url[PATH_MAX];
200
201    ELM_MAP_DATA_GET(obj, sd);
202
203    if (method == ELM_MAP_NAME_METHOD_SEARCH)
204      {
205         search_url[0] = '\0';
206         str = eina_str_split_full(name, " ", 0, &ele);
207         for (idx = 0; idx < ele; idx++)
208           {
209              eina_strlcat(search_url, str[idx], sizeof(search_url));
210              if (!(idx == (ele - 1)))
211                eina_strlcat(search_url, "+", sizeof(search_url));
212           }
213         snprintf(buf, sizeof(buf),
214                  "%s/search?q=%s&format=xml&polygon=0&addressdetails=0",
215                  NAME_NOMINATIM_URL, search_url);
216
217         if (str)
218           {
219              if (str[0]) free(str[0]);
220              free(str);
221           }
222      }
223    else if (method == ELM_MAP_NAME_METHOD_REVERSE)
224      snprintf(buf, sizeof(buf),
225               "%s/reverse?format=xml&lat=%lf&lon=%lf&zoom=%d&addressdetails=0",
226               NAME_NOMINATIM_URL, lat, lon, (int)sd->zoom);
227    else strcpy(buf, "");
228
229    return strdup(buf);
230 }
231
232 // Refer : http://wiki.openstreetmap.org/wiki/FAQ
233 // meters per pixel when latitude is 0 (equator)
234 // meters per pixel  = _osm_scale_meter[zoom] * cos (latitude)
235 const double _osm_scale_meter[] =
236 {
237    78206, 39135.758482, 19567.879241, 9783.939621, 4891.969810,
238    2445.984905, 1222.992453, 611.496226, 305.748113, 152.874057, 76.437028,
239    38.218514, 19.109257, 9.554629, 4.777314, 2.388657, 1.194329, 0.597164,
240    0.29858
241 };
242
243 static double
244 _scale_cb(const Evas_Object *obj __UNUSED__,
245           double lon __UNUSED__,
246           double lat,
247           int zoom)
248 {
249    if (zoom < 0 || zoom >= (int)(sizeof(_osm_scale_meter)/sizeof(_osm_scale_meter[0]))) return 0;
250    return _osm_scale_meter[zoom] / cos(lat * ELM_PI / 180.0);
251 }
252
253 const Source_Tile src_tiles[] =
254 {
255    {"Mapnik", 0, 18, _mapnik_url_cb, NULL, NULL, _scale_cb},
256    {"Osmarender", 0, 17, _osmarender_url_cb, NULL, NULL, _scale_cb},
257    {"CycleMap", 0, 16, _cyclemap_url_cb, NULL, NULL, _scale_cb},
258    {"MapQuest", 0, 18, _mapquest_url_cb, NULL, NULL, _scale_cb},
259    {"MapQuest Open Aerial", 0, 11, _mapquest_aerial_url_cb, NULL, NULL,
260     _scale_cb}
261 };
262
263 // FIXME: Fix more open sources
264 const Source_Route src_routes[] =
265 {
266    {"Yours", _yours_url_cb}    // http://www.yournavigation.org/
267    //{"Monav", _monav_url_cb},
268    //{"ORS", _ors_url_cb},     // http://www.openrouteservice.org
269 };
270
271 // Scale in meters
272 const double _scale_tb[] =
273 {
274    10000000, 5000000, 2000000, 1000000, 500000, 200000, 100000, 50000,
275    20000, 10000, 5000, 2000, 1000, 500, 500, 200, 100, 50, 20, 10, 5, 2, 1
276 };
277
278 // FIXME: Add more open sources
279 const Source_Name src_names[] =
280 {
281    {"Nominatim", _nominatim_url_cb}
282 };
283
284 static int id_num = 1;
285
286 static const char SIG_CLICKED[] = "clicked";
287 static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
288 static const char SIG_PRESS[] = "press";
289 static const char SIG_LONGPRESSED[] = "longpressed";
290 static const char SIG_SCROLL[] = "scroll";
291 static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start";
292 static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop";
293 static const char SIG_SCROLL_ANIM_START[] = "scroll,anim,start";
294 static const char SIG_SCROLL_ANIM_STOP[] = "scroll,anim,stop";
295 static const char SIG_ZOOM_START[] = "zoom,start";
296 static const char SIG_ZOOM_STOP[] = "zoom,stop";
297 static const char SIG_ZOOM_CHANGE[] = "zoom,change";
298 static const char SIG_LOADED[] = "loaded";
299 static const char SIG_TILE_LOAD[] = "tile,load";
300 static const char SIG_TILE_LOADED[] = "tile,loaded";
301 static const char SIG_TILE_LOADED_FAIL[] = "tile,loaded,fail";
302 static const char SIG_ROUTE_LOAD[] = "route,load";
303 static const char SIG_ROUTE_LOADED[] = "route,loaded";
304 static const char SIG_ROUTE_LOADED_FAIL[] = "route,loaded,fail";
305 static const char SIG_NAME_LOAD[] = "name,load";
306 static const char SIG_NAME_LOADED[] = "name,loaded";
307 static const char SIG_NAME_LOADED_FAIL[] = "name,loaded,fail";
308 static const char SIG_OVERLAY_CLICKED[] = "overlay,clicked";
309 static const char SIG_OVERLAY_DEL[] = "overlay,del";
310 static const char SIG_LANG_CHANGED[] = "language,changed";
311
312 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
313    {SIG_CLICKED, ""},
314    {SIG_CLICKED_DOUBLE, ""},
315    {SIG_PRESS, ""},
316    {SIG_LONGPRESSED, ""},
317    {SIG_SCROLL, ""},
318    {SIG_SCROLL_DRAG_START, ""},
319    {SIG_SCROLL_DRAG_STOP, ""},
320    {SIG_SCROLL_ANIM_START, ""},
321    {SIG_SCROLL_ANIM_STOP, ""},
322    {SIG_ZOOM_START, ""},
323    {SIG_ZOOM_STOP, ""},
324    {SIG_ZOOM_CHANGE, ""},
325    {SIG_LOADED, ""},
326    {SIG_TILE_LOAD, ""},
327    {SIG_TILE_LOADED, ""},
328    {SIG_TILE_LOADED_FAIL, ""},
329    {SIG_ROUTE_LOAD, ""},
330    {SIG_ROUTE_LOADED, ""},
331    {SIG_ROUTE_LOADED_FAIL, ""},
332    {SIG_NAME_LOAD, ""},
333    {SIG_NAME_LOADED, ""},
334    {SIG_NAME_LOADED_FAIL, ""},
335    {SIG_OVERLAY_CLICKED, ""},
336    {SIG_OVERLAY_DEL, ""},
337    {SIG_LANG_CHANGED, ""},
338    {NULL, NULL}
339 };
340
341 static const Evas_Smart_Interface *_smart_interfaces[] =
342 {
343    (Evas_Smart_Interface *)&ELM_SCROLLABLE_IFACE, NULL
344 };
345
346 EVAS_SMART_SUBCLASS_IFACE_NEW
347   (ELM_MAP_SMART_NAME, _elm_map, Elm_Map_Smart_Class,
348   Elm_Widget_Smart_Class, elm_widget_smart_class_get, _smart_callbacks,
349   _smart_interfaces);
350
351 ELM_INTERNAL_SMART_SUBCLASS_NEW
352   (ELM_MAP_PAN_SMART_NAME, _elm_map_pan, Elm_Map_Pan_Smart_Class,
353   Elm_Pan_Smart_Class, elm_pan_smart_class_get, NULL);
354
355 static Eina_Bool
356 _elm_map_smart_translate(Evas_Object *obj)
357 {
358    evas_object_smart_callback_call(obj, SIG_LANG_CHANGED, NULL);
359    return EINA_TRUE;
360 }
361
362 static void
363 _edj_overlay_size_get(Elm_Map_Smart_Data *sd,
364                       Evas_Coord *w,
365                       Evas_Coord *h)
366 {
367    Evas_Object *edj;
368    const char *s;
369
370    EINA_SAFETY_ON_NULL_RETURN(w);
371    EINA_SAFETY_ON_NULL_RETURN(h);
372
373    edj = edje_object_add(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
374    elm_widget_theme_object_set
375      (ELM_WIDGET_DATA(sd)->obj, edj, "map/marker", "radio",
376      elm_widget_style_get(ELM_WIDGET_DATA(sd)->obj));
377
378    s = edje_object_data_get(edj, "size_w");
379    if (s) *w = atoi(s);
380    else *w = 0;
381
382    s = edje_object_data_get(edj, "size_h");
383    if (s) *h = atoi(s);
384    else *h = 0;
385
386    evas_object_del(edj);
387 }
388
389 static void
390 _rotate_do(Evas_Coord x,
391            Evas_Coord y,
392            Evas_Coord cx,
393            Evas_Coord cy,
394            double degree,
395            Evas_Coord *xx,
396            Evas_Coord *yy)
397 {
398    double r = (degree * M_PI) / 180.0;
399
400    if (xx) *xx = ((x - cx) * cos(r)) + ((y - cy) * cos(r + M_PI_2)) + cx;
401    if (yy) *yy = ((x - cx) * sin(r)) + ((y - cy) * sin(r + M_PI_2)) + cy;
402 }
403
404 static void
405 _obj_rotate(Elm_Map_Smart_Data *sd,
406             Evas_Object *obj)
407 {
408    Evas_Coord w, h, ow, oh;
409
410    evas_map_util_points_populate_from_object(sd->map, obj);
411
412    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
413    evas_object_image_size_get(obj, &w, &h);
414    if ((w > ow) || (h > oh))
415      {
416         evas_map_point_image_uv_set(sd->map, 0, 0, 0);
417         evas_map_point_image_uv_set(sd->map, 1, w, 0);
418         evas_map_point_image_uv_set(sd->map, 2, w, h);
419         evas_map_point_image_uv_set(sd->map, 3, 0, h);
420      }
421    evas_map_util_rotate(sd->map, sd->pan_rotate.d, sd->pan_rotate.cx,
422                         sd->pan_rotate.cy);
423
424    evas_object_map_set(obj, sd->map);
425    evas_object_map_enable_set(obj, EINA_TRUE);
426 }
427
428 static void
429 _obj_place(Evas_Object *obj,
430            Evas_Coord x,
431            Evas_Coord y,
432            Evas_Coord w,
433            Evas_Coord h)
434 {
435    EINA_SAFETY_ON_NULL_RETURN(obj);
436
437    evas_object_move(obj, x, y);
438    evas_object_resize(obj, w, h);
439    evas_object_show(obj);
440 }
441
442 static void
443 _coord_to_region_convert(Elm_Map_Smart_Data *sd,
444                          Evas_Coord x,
445                          Evas_Coord y,
446                          Evas_Coord size,
447                          double *lon,
448                          double *lat)
449 {
450    int zoom;
451
452    EINA_SAFETY_ON_NULL_RETURN(sd);
453
454    zoom = floor(log(size / sd->size.tile) / log(2));
455    if ((sd->src_tile) && (sd->src_tile->coord_to_geo))
456      {
457         if (sd->src_tile->coord_to_geo
458               (ELM_WIDGET_DATA(sd)->obj, zoom, x, y, size, lon, lat))
459           return;
460      }
461
462    if (lon) *lon = (x / (double)size * 360.0) - 180;
463    if (lat)
464      {
465         double n = ELM_PI - (2.0 * ELM_PI * y / size);
466         *lat = 180.0 / ELM_PI *atan(0.5 * (exp(n) - exp(-n)));
467      }
468 }
469
470 static void
471 _region_to_coord_convert(Elm_Map_Smart_Data *sd,
472                          double lon,
473                          double lat,
474                          Evas_Coord size,
475                          Evas_Coord *x,
476                          Evas_Coord *y)
477 {
478    int zoom;
479
480    EINA_SAFETY_ON_NULL_RETURN(sd);
481
482    zoom = floor(log(size / 256) / log(2));
483
484    if (strcmp(sd->engine->name, INTERNAL_ENGINE_NAME))
485      {
486         sd->engine->region_to_canvas
487               (ELM_WIDGET_DATA(sd)->obj, lon, lat, x, y);
488         return;
489      }
490
491    if ((sd->src_tile) && (sd->src_tile->geo_to_coord))
492      {
493         if (sd->src_tile->geo_to_coord
494               (ELM_WIDGET_DATA(sd)->obj, zoom, lon, lat, size, x, y)) return;
495      }
496
497    if (x) *x = floor((lon + 180.0) / 360.0 * size);
498    if (y)
499      *y = floor((1.0 - log(tan(lat * ELM_PI / 180.0) +
500                            (1.0 / cos(lat * ELM_PI / 180.0)))
501                  / ELM_PI) / 2.0 * size);
502 }
503
504 static void
505 _viewport_coord_get(Elm_Map_Smart_Data *sd,
506                     Evas_Coord *vx,
507                     Evas_Coord *vy,
508                     Evas_Coord *vw,
509                     Evas_Coord *vh)
510 {
511    Evas_Coord x, y, w, h;
512
513    EINA_SAFETY_ON_NULL_RETURN(sd);
514
515    sd->s_iface->content_pos_get(ELM_WIDGET_DATA(sd)->obj, &x, &y);
516    sd->s_iface->content_viewport_size_get(ELM_WIDGET_DATA(sd)->obj, &w, &h);
517
518    if (w > sd->size.w) x -= ((w - sd->size.w) / 2);
519    if (h > sd->size.h) y -= ((h - sd->size.h) / 2);
520    if (vx) *vx = x;
521    if (vy) *vy = y;
522    if (vw) *vw = w;
523    if (vh) *vh = h;
524 }
525
526 // Map coordinates to canvas geometry without rotate
527 static void
528 _coord_to_canvas_no_rotation(Elm_Map_Smart_Data *sd,
529                              Evas_Coord x,
530                              Evas_Coord y,
531                              Evas_Coord *xx,
532                              Evas_Coord *yy)
533 {
534    Evas_Coord vx, vy, sx, sy;
535
536    if (!strcmp(sd->engine->name, INTERNAL_ENGINE_NAME))
537      {
538         _viewport_coord_get(sd, &vx, &vy, NULL, NULL);
539         evas_object_geometry_get(sd->pan_obj, &sx, &sy, NULL, NULL);
540         if (xx) *xx = x - vx + sx;
541         if (yy) *yy = y - vy + sy;
542    }
543    else
544      {
545         if (xx) *xx = x;
546         if (yy) *yy = y;
547      }
548 }
549
550 // Map coordinates to canvas geometry
551 static void
552 _coord_to_canvas(Elm_Map_Smart_Data *sd,
553                  Evas_Coord x,
554                  Evas_Coord y,
555                  Evas_Coord *xx,
556                  Evas_Coord *yy)
557 {
558    _coord_to_canvas_no_rotation(sd, x, y, &x, &y);
559    if (!strcmp(sd->engine->name, INTERNAL_ENGINE_NAME))
560      {
561         _rotate_do(x, y, sd->pan_rotate.cx, sd->pan_rotate.cy, sd->pan_rotate.d, &x, &y);
562      }
563    if (xx) *xx = x;
564    if (yy) *yy = y;
565 }
566
567 // Canvas geometry to map coordinates
568 static void
569 _canvas_to_coord(Elm_Map_Smart_Data *sd,
570                  Evas_Coord x,
571                  Evas_Coord y,
572                  Evas_Coord *xx,
573                  Evas_Coord *yy)
574 {
575    Evas_Coord vx, vy, sx, sy;
576
577    _viewport_coord_get(sd, &vx, &vy, NULL, NULL);
578    evas_object_geometry_get(sd->pan_obj, &sx, &sy, NULL, NULL);
579    _rotate_do(x - sx + vx, y - sy + vy, sd->pan_rotate.cx - sx + vx,
580               sd->pan_rotate.cy - sy + vy, -sd->pan_rotate.d, &x, &y);
581    if (xx) *xx = x;
582    if (yy) *yy = y;
583 }
584
585 static void
586 _grid_item_coord_get(Grid_Item *gi,
587                      int *x,
588                      int *y,
589                      int *w,
590                      int *h)
591 {
592    EINA_SAFETY_ON_NULL_RETURN(gi);
593
594    if (x) *x = gi->x * gi->wsd->size.tile;
595    if (y) *y = gi->y * gi->wsd->size.tile;
596    if (w) *w = gi->wsd->size.tile;
597    if (h) *h = gi->wsd->size.tile;
598 }
599
600 static Eina_Bool
601 _grid_item_in_viewport(Grid_Item *gi)
602 {
603    Evas_Coord vx, vy, vw, vh;
604    Evas_Coord x, y, w, h;
605
606    EINA_SAFETY_ON_NULL_RETURN_VAL(gi, EINA_FALSE);
607
608    _viewport_coord_get(gi->wsd, &vx, &vy, &vw, &vh);
609    _grid_item_coord_get(gi, &x, &y, &w, &h);
610
611    return ELM_RECTS_INTERSECT(x, y, w, h, vx, vy, vw, vh);
612 }
613
614 static Eina_Bool
615 _loaded_timeout_cb(void *data)
616 {
617    Elm_Map_Smart_Data *sd = data;
618
619    EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
620
621    sd->loaded_timer = NULL;
622    if (!(sd->download_num) && !(sd->download_idler))
623      evas_object_smart_callback_call
624        (ELM_WIDGET_DATA(sd)->obj, SIG_LOADED, NULL);
625    return ECORE_CALLBACK_CANCEL;
626 }
627
628 static void
629 _grid_item_update(Grid_Item *gi)
630 {
631    Evas_Load_Error err;
632
633    EINA_SAFETY_ON_NULL_RETURN(gi);
634
635    evas_object_image_file_set(gi->img, gi->file, NULL);
636    if (!gi->wsd->zoom_timer && !gi->wsd->scr_timer)
637      evas_object_image_smooth_scale_set(gi->img, EINA_TRUE);
638    else evas_object_image_smooth_scale_set(gi->img, EINA_FALSE);
639
640    err = evas_object_image_load_error_get(gi->img);
641    if (err != EVAS_LOAD_ERROR_NONE)
642      {
643         ERR("Image loading error (%s): %s", gi->file, evas_load_error_str(err));
644         ecore_file_remove(gi->file);
645         gi->file_have = EINA_FALSE;
646      }
647    else
648      {
649         Evas_Coord x, y, w, h;
650
651         _grid_item_coord_get(gi, &x, &y, &w, &h);
652         _coord_to_canvas_no_rotation(gi->wsd, x, y, &x, &y);
653         _obj_place(gi->img, x, y, w, h);
654         _obj_rotate(gi->wsd, gi->img);
655         gi->file_have = EINA_TRUE;
656      }
657
658    if (gi->wsd->loaded_timer) ecore_timer_del(gi->wsd->loaded_timer);
659    gi->wsd->loaded_timer = ecore_timer_add(0.25, _loaded_timeout_cb, gi->wsd);
660 }
661
662 static void
663 _grid_item_load(Grid_Item *gi)
664 {
665    EINA_SAFETY_ON_NULL_RETURN(gi);
666
667    if (gi->file_have) _grid_item_update(gi);
668    else if (!gi->job)
669      {
670         gi->wsd->download_list = eina_list_remove(gi->wsd->download_list, gi);
671         gi->wsd->download_list = eina_list_append(gi->wsd->download_list, gi);
672      }
673 }
674
675 static void
676 _grid_item_unload(Grid_Item *gi)
677 {
678    EINA_SAFETY_ON_NULL_RETURN(gi);
679
680    if (gi->file_have)
681      {
682         evas_object_hide(gi->img);
683         evas_object_image_file_set(gi->img, NULL, NULL);
684      }
685    else if (gi->job)
686      {
687         ecore_file_download_abort(gi->job);
688         ecore_file_remove(gi->file);
689         gi->job = NULL;
690         gi->wsd->try_num--;
691      }
692    else gi->wsd->download_list = eina_list_remove(gi->wsd->download_list, gi);
693 }
694
695 static Grid_Item *
696 _grid_item_create(Grid *g,
697                   Evas_Coord x,
698                   Evas_Coord y)
699 {
700    char buf[PATH_MAX];
701    char buf2[PATH_MAX];
702    Grid_Item *gi;
703    char *url;
704
705    EINA_SAFETY_ON_NULL_RETURN_VAL(g, NULL);
706
707    gi = ELM_NEW(Grid_Item);
708    gi->wsd = g->wsd;
709    gi->g = g;
710    gi->x = x;
711    gi->y = y;
712
713    gi->file_have = EINA_FALSE;
714    gi->job = NULL;
715
716    gi->img = evas_object_image_add
717        (evas_object_evas_get(ELM_WIDGET_DATA(g->wsd)->obj));
718    evas_object_image_smooth_scale_set(gi->img, EINA_FALSE);
719    evas_object_image_scale_hint_set(gi->img, EVAS_IMAGE_SCALE_HINT_DYNAMIC);
720    evas_object_image_filled_set(gi->img, EINA_TRUE);
721    evas_object_smart_member_add(gi->img, g->wsd->pan_obj);
722    evas_object_pass_events_set(gi->img, EINA_TRUE);
723    evas_object_stack_below(gi->img, g->wsd->sep_maps_overlays);
724
725    {
726       const char *cachedir;
727
728 #ifdef ELM_EFREET
729       snprintf(buf, sizeof(buf), "%s" CACHE_TILE_ROOT, efreet_cache_home_get(),
730                g->wsd->id, g->zoom, x);
731       (void)cachedir;
732 #else
733       cachedir = getenv("XDG_CACHE_HOME");
734       snprintf(buf, sizeof(buf), "%s/%s" CACHE_TILE_ROOT, getenv("HOME"),
735                cachedir ? : "/.config", g->wsd->id, g->zoom, x);
736 #endif
737    }
738
739    snprintf(buf2, sizeof(buf2), CACHE_TILE_PATH, buf, y);
740    if (!ecore_file_exists(buf)) ecore_file_mkpath(buf);
741
742    eina_stringshare_replace(&gi->file, buf2);
743    url = g->wsd->src_tile->url_cb(ELM_WIDGET_DATA(g->wsd)->obj, x, y, g->zoom);
744    if ((!url) || (!strlen(url)))
745      {
746         eina_stringshare_replace(&gi->url, NULL);
747         ERR("Getting source url failed: %s", gi->file);
748      }
749    else eina_stringshare_replace(&gi->url, url);
750
751    if (url) free(url);
752    eina_matrixsparse_data_idx_set(g->grid, y, x, gi);
753
754    return gi;
755 }
756
757 static void
758 _grid_item_free(Grid_Item *gi)
759 {
760    EINA_SAFETY_ON_NULL_RETURN(gi);
761
762    _grid_item_unload(gi);
763    if (gi->g && gi->g->grid)
764      eina_matrixsparse_data_idx_set(gi->g->grid, gi->y, gi->x, NULL);
765    if (gi->url) eina_stringshare_del(gi->url);
766    if (gi->file_have) ecore_file_remove(gi->file);
767    if (gi->file) eina_stringshare_del(gi->file);
768    if (gi->img) evas_object_del(gi->img);
769
770    free(gi);
771 }
772
773 static void
774 _downloaded_cb(void *data,
775                const char *file __UNUSED__,
776                int status)
777 {
778    Grid_Item *gi = data;
779
780    if (status == 200)
781      {
782         DBG("Download success from %s to %s", gi->url, gi->file);
783
784         _grid_item_update(gi);
785         gi->wsd->finish_num++;
786         evas_object_smart_callback_call
787           (ELM_WIDGET_DATA(gi->wsd)->obj, SIG_TILE_LOADED, NULL);
788      }
789    else
790      {
791         WRN("Download failed from %s to %s (%d) ", gi->url, gi->file, status);
792
793         ecore_file_remove(gi->file);
794         gi->file_have = EINA_FALSE;
795         evas_object_smart_callback_call
796           (ELM_WIDGET_DATA(gi->wsd)->obj, SIG_TILE_LOADED_FAIL, NULL);
797      }
798
799    gi->job = NULL;
800    gi->wsd->download_num--;
801    if (!gi->wsd->download_num)
802      edje_object_signal_emit(ELM_WIDGET_DATA(gi->wsd)->resize_obj,
803                              "elm,state,busy,stop", "elm");
804 }
805
806 static Eina_Bool
807 _download_job(void *data)
808 {
809    Elm_Map_Smart_Data *sd = data;
810    Eina_List *l, *ll;
811    Grid_Item *gi;
812
813    if (!eina_list_count(sd->download_list))
814      {
815         sd->download_idler = NULL;
816         return ECORE_CALLBACK_CANCEL;
817      }
818
819    EINA_LIST_REVERSE_FOREACH_SAFE(sd->download_list, l, ll, gi)
820    {
821       Eina_Bool ret;
822
823       if ((gi->g->zoom != sd->zoom) || !(_grid_item_in_viewport(gi)))
824         {
825            sd->download_list = eina_list_remove(sd->download_list, gi);
826            continue;
827         }
828       if (sd->download_num >= MAX_CONCURRENT_DOWNLOAD)
829         return ECORE_CALLBACK_RENEW;
830
831       ret = ecore_file_download_full
832           (gi->url, gi->file, _downloaded_cb, NULL, gi, &(gi->job), sd->ua);
833
834       if ((!ret) || (!gi->job))
835         ERR("Can't start to download from %s to %s", gi->url, gi->file);
836       else
837         {
838            sd->download_list = eina_list_remove(sd->download_list, gi);
839            sd->try_num++;
840            sd->download_num++;
841            evas_object_smart_callback_call
842              (ELM_WIDGET_DATA(sd)->obj, SIG_TILE_LOAD, NULL);
843            if (sd->download_num == 1)
844              edje_object_signal_emit(ELM_WIDGET_DATA(sd)->resize_obj,
845                                      "elm,state,busy,start", "elm");
846         }
847    }
848
849    return ECORE_CALLBACK_RENEW;
850 }
851
852 static void
853 _grid_viewport_get(Grid *g,
854                    int *x,
855                    int *y,
856                    int *w,
857                    int *h)
858 {
859    int xx, yy, ww, hh;
860    Evas_Coord vx, vy, vw, vh;
861
862    EINA_SAFETY_ON_NULL_RETURN(g);
863
864    _viewport_coord_get(g->wsd, &vx, &vy, &vw, &vh);
865    if (vx < 0) vx = 0;
866    if (vy < 0) vy = 0;
867
868    xx = (vx / g->wsd->size.tile) - 1;
869    if (xx < 0) xx = 0;
870
871    yy = (vy / g->wsd->size.tile) - 1;
872    if (yy < 0) yy = 0;
873
874    ww = (vw / g->wsd->size.tile) + 3;
875    if (xx + ww >= g->tw) ww = g->tw - xx;
876
877    hh = (vh / g->wsd->size.tile) + 3;
878    if (yy + hh >= g->th) hh = g->th - yy;
879
880    if (x) *x = xx;
881    if (y) *y = yy;
882    if (w) *w = ww;
883    if (h) *h = hh;
884 }
885
886 static void
887 _grid_unload(Grid *g)
888 {
889    Eina_Matrixsparse_Cell *cell;
890    Eina_Iterator *it;
891    Grid_Item *gi;
892
893    EINA_SAFETY_ON_NULL_RETURN(g);
894
895    it = eina_matrixsparse_iterator_new(g->grid);
896    EINA_ITERATOR_FOREACH(it, cell)
897      {
898         gi = eina_matrixsparse_cell_data_get(cell);
899         _grid_item_unload(gi);
900      }
901    eina_iterator_free(it);
902 }
903
904 static void
905 _grid_load(Grid *g)
906 {
907    Eina_Matrixsparse_Cell *cell;
908    int x, y, xx, yy, ww, hh;
909    Eina_Iterator *it;
910    Grid_Item *gi;
911
912    EINA_SAFETY_ON_NULL_RETURN(g);
913
914    it = eina_matrixsparse_iterator_new(g->grid);
915    EINA_ITERATOR_FOREACH(it, cell)
916      {
917         gi = eina_matrixsparse_cell_data_get(cell);
918         if (!_grid_item_in_viewport(gi)) _grid_item_unload(gi);
919      }
920    eina_iterator_free(it);
921
922    _grid_viewport_get(g, &xx, &yy, &ww, &hh);
923    for (y = yy; y < yy + hh; y++)
924      {
925         for (x = xx; x < xx + ww; x++)
926           {
927              gi = eina_matrixsparse_data_idx_get(g->grid, y, x);
928              if (!gi) gi = _grid_item_create(g, x, y);
929              _grid_item_load(gi);
930           }
931      }
932 }
933
934 static void
935 _grid_place(Elm_Map_Smart_Data *sd)
936 {
937    Eina_List *l;
938    Grid *g;
939
940    EINA_SAFETY_ON_NULL_RETURN(sd);
941
942    EINA_LIST_FOREACH(sd->grids, l, g)
943      {
944         if (sd->zoom == g->zoom) _grid_load(g);
945         else _grid_unload(g);
946      }
947    if (!sd->download_idler)
948      sd->download_idler = ecore_idler_add(_download_job, sd);
949 }
950
951 static void
952 _grid_all_create(Elm_Map_Smart_Data *sd)
953 {
954    int zoom;
955
956    EINA_SAFETY_ON_NULL_RETURN(sd->src_tile);
957
958    for (zoom = sd->src_tile->zoom_min; zoom <= sd->src_tile->zoom_max; zoom++)
959      {
960         Grid *g;
961         int tnum;
962
963         g = ELM_NEW(Grid);
964         g->wsd = sd;
965         g->zoom = zoom;
966         tnum = pow(2.0, g->zoom);
967         g->tw = tnum;
968         g->th = tnum;
969         g->grid = eina_matrixsparse_new(g->th, g->tw, NULL, NULL);
970         sd->grids = eina_list_append(sd->grids, g);
971      }
972 }
973
974 static void
975 _grid_all_clear(Elm_Map_Smart_Data *sd)
976 {
977    Grid *g;
978
979    EINA_SAFETY_ON_NULL_RETURN(sd);
980
981    EINA_LIST_FREE (sd->grids, g)
982      {
983         Eina_Matrixsparse_Cell *cell;
984         Eina_Iterator *it = eina_matrixsparse_iterator_new(g->grid);
985
986         EINA_ITERATOR_FOREACH(it, cell)
987           {
988              Grid_Item *gi;
989
990              gi = eina_matrixsparse_cell_data_get(cell);
991              if (gi) _grid_item_free(gi);
992           }
993         eina_iterator_free(it);
994
995         eina_matrixsparse_free(g->grid);
996         free(g);
997      }
998 }
999
1000 static void
1001 _track_place(Elm_Map_Smart_Data *sd)
1002 {
1003 #ifdef ELM_EMAP
1004    Eina_List *l;
1005    Evas_Coord size;
1006    Evas_Object *route;
1007    Evas_Coord px, py, ow, oh;
1008    int xmin, xmax, ymin, ymax;
1009
1010    px = sd->pan_x;
1011    py = sd->pan_y;
1012    _viewport_coord_get(sd, NULL, NULL, &ow, &oh);
1013
1014    size = sd->size.w;
1015
1016    EINA_LIST_FOREACH(sd->track, l, route)
1017      {
1018         double lon_min, lon_max;
1019         double lat_min, lat_max;
1020
1021         elm_route_longitude_min_max_get(route, &lon_min, &lon_max);
1022         elm_route_latitude_min_max_get(route, &lat_min, &lat_max);
1023         _region_to_coord_convert(sd, lon_min, lat_max, size, &xmin, &ymin);
1024         _region_to_coord_convert(sd, lon_max, lat_min, size, &xmax, &ymax);
1025
1026         if ( !(xmin < px && xmax < px) && !(xmin > px + ow && xmax > px + ow))
1027           {
1028              if ((ymin < py && ymax < py) ||
1029                  (ymin > py + oh && ymax > py + oh))
1030                {
1031                   //display the route
1032                   evas_object_move(route, xmin - px, ymin - py);
1033                   evas_object_resize(route, xmax - xmin, ymax - ymin);
1034
1035                   evas_object_raise(route);
1036                   _obj_rotate(sd, route);
1037                   evas_object_show(route);
1038
1039                   continue;
1040                }
1041           }
1042         //the route is not display
1043         evas_object_hide(route);
1044      }
1045 #else
1046    (void)sd;
1047 #endif
1048 }
1049
1050 static void
1051 _smooth_update(Elm_Map_Smart_Data *sd)
1052 {
1053    Eina_List *l;
1054    Grid *g;
1055
1056    EINA_LIST_FOREACH(sd->grids, l, g)
1057      {
1058         Eina_Iterator *it = eina_matrixsparse_iterator_new(g->grid);
1059         Eina_Matrixsparse_Cell *cell;
1060
1061         EINA_ITERATOR_FOREACH(it, cell)
1062           {
1063              Grid_Item *gi = eina_matrixsparse_cell_data_get(cell);
1064              if (_grid_item_in_viewport(gi))
1065                evas_object_image_smooth_scale_set(gi->img, EINA_TRUE);
1066           }
1067         eina_iterator_free(it);
1068      }
1069 }
1070
1071 static Eina_Bool
1072 _zoom_timeout_cb(void *data)
1073 {
1074    Elm_Map_Smart_Data *sd = data;
1075
1076    _smooth_update(sd);
1077    sd->zoom_timer = NULL;
1078    evas_object_smart_callback_call
1079      (ELM_WIDGET_DATA(sd)->obj, SIG_ZOOM_STOP, NULL);
1080
1081    return ECORE_CALLBACK_CANCEL;
1082 }
1083
1084 static void
1085 _zoom(Elm_Map_Smart_Data *sd, double zoom, int animation)
1086 {
1087    if (zoom > sd->zoom_max) zoom = sd->zoom_max;
1088    else if (zoom < sd->zoom_min) zoom = sd->zoom_min;
1089
1090    sd->engine->zoom(ELM_WIDGET_DATA(sd)->obj, zoom, animation);
1091    sd->zoom_detail = zoom;
1092    sd->zoom = ROUND(sd->zoom_detail);
1093
1094    if (strcmp(sd->engine->name, INTERNAL_ENGINE_NAME))
1095      _overlay_place(sd);
1096
1097    if (sd->zoom_timer) ecore_timer_del(sd->zoom_timer);
1098    else
1099      evas_object_smart_callback_call
1100        (ELM_WIDGET_DATA(sd)->obj, SIG_ZOOM_START, NULL);
1101
1102    sd->zoom_timer = ecore_timer_add(0.25, _zoom_timeout_cb, sd);
1103    evas_object_smart_callback_call
1104      (ELM_WIDGET_DATA(sd)->obj, SIG_ZOOM_CHANGE, NULL);
1105 }
1106
1107 static void
1108 _sizing_eval(Elm_Map_Smart_Data *sd)
1109 {
1110    Evas_Coord maxw = -1, maxh = -1;
1111
1112    evas_object_size_hint_max_get(ELM_WIDGET_DATA(sd)->obj, &maxw, &maxh);
1113    evas_object_size_hint_max_set(ELM_WIDGET_DATA(sd)->obj, maxw, maxh);
1114 }
1115
1116 static void
1117 _changed_size_hints_cb(void *data,
1118                        Evas *e __UNUSED__,
1119                        Evas_Object *obj __UNUSED__,
1120                        void *event_info __UNUSED__)
1121 {
1122    _sizing_eval(data);
1123 }
1124
1125 static Eina_Bool
1126 _scr_timeout_cb(void *data)
1127 {
1128    Elm_Map_Smart_Data *sd = data;
1129
1130    _smooth_update(sd);
1131    sd->scr_timer = NULL;
1132    evas_object_smart_callback_call
1133      (ELM_WIDGET_DATA(sd)->obj, SIG_SCROLL_DRAG_STOP, NULL);
1134
1135    return ECORE_CALLBACK_CANCEL;
1136 }
1137
1138 static void
1139 _scroll_cb(Evas_Object *obj,
1140            void *data __UNUSED__)
1141 {
1142    ELM_MAP_DATA_GET(obj, sd);
1143
1144    if (sd->scr_timer) ecore_timer_del(sd->scr_timer);
1145    else
1146      evas_object_smart_callback_call
1147        (ELM_WIDGET_DATA(sd)->obj, SIG_SCROLL_DRAG_START, NULL);
1148    sd->scr_timer = ecore_timer_add(0.25, _scr_timeout_cb, sd);
1149    evas_object_smart_callback_call(ELM_WIDGET_DATA(sd)->obj, SIG_SCROLL, NULL);
1150 }
1151
1152 static void
1153 _scroll_animate_start_cb(Evas_Object *obj,
1154                          void *data __UNUSED__)
1155 {
1156    ELM_MAP_DATA_GET(obj, sd);
1157
1158    evas_object_smart_callback_call
1159      (ELM_WIDGET_DATA(sd)->obj, SIG_SCROLL_ANIM_START, NULL);
1160 }
1161
1162 static void
1163 _scroll_animate_stop_cb(Evas_Object *obj,
1164                         void *data __UNUSED__)
1165 {
1166    ELM_MAP_DATA_GET(obj, sd);
1167
1168    evas_object_smart_callback_call
1169      (ELM_WIDGET_DATA(sd)->obj, SIG_SCROLL_ANIM_STOP, NULL);
1170 }
1171
1172 static Eina_Bool
1173 _long_press_cb(void *data)
1174 {
1175    Elm_Map_Smart_Data *sd = data;
1176
1177    sd->long_timer = NULL;
1178    evas_object_smart_callback_call
1179      (ELM_WIDGET_DATA(sd)->obj, SIG_LONGPRESSED, &sd->ev);
1180
1181    return ECORE_CALLBACK_CANCEL;
1182 }
1183
1184 static void
1185 _mouse_down_cb(void *data,
1186                Evas *evas __UNUSED__,
1187                Evas_Object *obj __UNUSED__,
1188                void *event_info)
1189 {
1190    Elm_Map_Smart_Data *sd = data;
1191    Evas_Event_Mouse_Down *ev = event_info;
1192
1193    if (ev->button != 1) return;
1194    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) sd->on_hold = EINA_TRUE;
1195    else sd->on_hold = EINA_FALSE;
1196
1197    if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
1198      evas_object_smart_callback_call
1199        (ELM_WIDGET_DATA(sd)->obj, SIG_CLICKED_DOUBLE, ev);
1200    else
1201      evas_object_smart_callback_call
1202        (ELM_WIDGET_DATA(sd)->obj, SIG_PRESS, ev);
1203
1204    if (sd->long_timer) ecore_timer_del(sd->long_timer);
1205    sd->ev = *ev;
1206    sd->long_timer =
1207      ecore_timer_add(_elm_config->longpress_timeout, _long_press_cb, sd);
1208 }
1209
1210 static void
1211 _mouse_up_cb(void *data,
1212              Evas *evas __UNUSED__,
1213              Evas_Object *obj __UNUSED__,
1214              void *event_info)
1215 {
1216    Elm_Map_Smart_Data *sd = data;
1217    Evas_Event_Mouse_Up *ev = event_info;
1218
1219    EINA_SAFETY_ON_NULL_RETURN(ev);
1220
1221    if (ev->button != 1) return;
1222
1223    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) sd->on_hold = EINA_TRUE;
1224    else sd->on_hold = EINA_FALSE;
1225
1226    if (sd->long_timer)
1227      {
1228         ecore_timer_del(sd->long_timer);
1229         sd->long_timer = NULL;
1230      }
1231
1232    if (!sd->on_hold)
1233      evas_object_smart_callback_call
1234        (ELM_WIDGET_DATA(sd)->obj, SIG_CLICKED, ev);
1235    if (!sd->on_hold && MAP_ENGINE_OVERLAY_SUPPORT(sd))
1236      {
1237          Map_Engine_Object *engobj = NULL;
1238          Elm_Map_Overlay *overlay;
1239          Eina_List *l;
1240
1241          ELM_MAP_ENG_OBJECT_FIND(sd->engine->object_from_coord, engobj, ELM_WIDGET_DATA(sd)->obj, ev->output.x, ev->output.y);
1242
1243          if (!engobj)return;
1244
1245         EINA_LIST_FOREACH(sd->overlays, l, overlay)
1246         {
1247            if ( overlay->engobj == engobj )
1248            {
1249                evas_object_smart_callback_call
1250                       (ELM_WIDGET_DATA(overlay->wsd)->obj, SIG_OVERLAY_CLICKED, overlay);
1251                if (overlay->cb)
1252                   overlay->cb(overlay->cb_data, ELM_WIDGET_DATA(overlay->wsd)->obj, overlay);
1253                break;
1254            }
1255         }
1256    }
1257
1258    sd->on_hold = EINA_FALSE;
1259 }
1260
1261 static void
1262 _mouse_wheel_cb(void *data,
1263                 Evas *e __UNUSED__,
1264                 Evas_Object *obj __UNUSED__,
1265                 void *event_info)
1266 {
1267    Elm_Map_Smart_Data *sd = data;
1268
1269    if (!sd->paused)
1270      {
1271         Evas_Event_Mouse_Wheel *ev = event_info;
1272
1273         _zoom(sd, sd->zoom_detail - ((double)ev->z /10), 0);
1274      }
1275 }
1276
1277 static void
1278 _region_max_min_get(Eina_List *overlays,
1279                     double *max_longitude,
1280                     double *min_longitude,
1281                     double *max_latitude,
1282                     double *min_latitude)
1283 {
1284    double max_lon = -180, min_lon = 180;
1285    double max_lat = -90, min_lat = 90;
1286    Elm_Map_Overlay *overlay;
1287
1288    EINA_LIST_FREE (overlays, overlay)
1289      {
1290         double lon, lat;
1291
1292         if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
1293           {
1294              Overlay_Default *ovl = overlay->ovl;
1295
1296              lon = ovl->lon;
1297              lat = ovl->lat;
1298           }
1299         else if (overlay->type == ELM_MAP_OVERLAY_TYPE_CLASS)
1300           {
1301              // FIXME: class center coord is alright??
1302              Overlay_Class *ovl = overlay->ovl;
1303              double max_lo, min_lo, max_la, min_la;
1304
1305              _region_max_min_get
1306                (ovl->members, &max_lo, &min_lo, &max_la, &min_la);
1307              lon = (max_lo + min_lo) / 2;
1308              lat = (max_la + min_la) / 2;
1309           }
1310         else if (overlay->type == ELM_MAP_OVERLAY_TYPE_BUBBLE)
1311           {
1312              Overlay_Bubble *ovl = overlay->ovl;
1313
1314              lon = ovl->lon;
1315              lat = ovl->lat;
1316           }
1317         else
1318           {
1319              WRN("Not supported overlay type: %d", overlay->type);
1320              continue;
1321           }
1322         if (lon > max_lon) max_lon = lon;
1323         if (lon < min_lon) min_lon = lon;
1324         if (lat > max_lat) max_lat = lat;
1325         if (lat < min_lat) min_lat = lat;
1326      }
1327
1328    if (max_longitude) *max_longitude = max_lon;
1329    if (min_longitude) *min_longitude = min_lon;
1330    if (max_latitude) *max_latitude = max_lat;
1331    if (min_latitude) *min_latitude = min_lat;
1332 }
1333
1334 static Evas_Object *
1335 _icon_dup(Evas_Object *icon,
1336           Evas_Object *parent)
1337 {
1338    Evas_Object *dupp;
1339    Evas_Coord w, h;
1340
1341    if (!icon || !parent) return NULL;
1342    dupp = evas_object_image_filled_add(evas_object_evas_get(parent));
1343    evas_object_image_source_set(dupp, icon);
1344    // Set size as origin' sizse for proxy
1345    evas_object_geometry_get(icon, NULL, NULL, &w, &h);
1346    if (w <= 0 || h <= 0)
1347      {
1348         evas_object_size_hint_min_get(icon, &w, &h);
1349         evas_object_size_hint_min_set(dupp, w, h);
1350      }
1351    else evas_object_resize(dupp, w, h);
1352    // Original should have size for proxy
1353    evas_object_resize(icon, w, h);
1354
1355    return dupp;
1356 }
1357
1358 static void
1359 _overlay_clicked_cb(void *data,
1360                     Evas *e __UNUSED__,
1361                     Evas_Object *obj __UNUSED__,
1362                     void *ev __UNUSED__)
1363 {
1364    Elm_Map_Overlay *overlay = data;
1365
1366    EINA_SAFETY_ON_NULL_RETURN(data);
1367
1368    evas_object_smart_callback_call
1369      (ELM_WIDGET_DATA(overlay->wsd)->obj, SIG_OVERLAY_CLICKED, overlay);
1370    if (overlay->cb)
1371      overlay->cb(overlay->cb_data, ELM_WIDGET_DATA(overlay->wsd)->obj, overlay);
1372 }
1373
1374 static void
1375 _overlay_default_hide(Overlay_Default *ovl)
1376 {
1377    EINA_SAFETY_ON_NULL_RETURN(ovl);
1378
1379    if (ovl->content) evas_object_hide(ovl->content);
1380    if (ovl->icon) evas_object_hide(ovl->icon);
1381    if (ovl->clas_content) evas_object_hide(ovl->clas_content);
1382    if (ovl->clas_icon) evas_object_hide(ovl->clas_icon);
1383    if (ovl->layout) evas_object_hide(ovl->layout);
1384    if (ovl->base->engobj) ELM_MAP_ENG_OBJECT_SET(ovl->wsd->engine->object_visibility, ELM_WIDGET_DATA(ovl->wsd)->obj, ovl->base->engobj, 0);
1385 }
1386
1387 static void
1388 _overlay_default_show(Overlay_Default *ovl)
1389 {
1390    Evas_Object *disp = NULL;
1391    Evas_Coord x, y, w, h;
1392    Eina_Bool  show_engobj = EINA_FALSE;
1393
1394    EINA_SAFETY_ON_NULL_RETURN(ovl);
1395
1396    show_engobj = (ovl->base->engobj && NULL == ovl->base->grp->klass) ? EINA_TRUE : EINA_FALSE;
1397
1398    if (ovl->x == -1 || ovl->y == -1)
1399     {
1400         _overlay_default_hide(ovl);
1401         return;
1402     }
1403
1404
1405
1406    evas_object_hide(ovl->layout);
1407    if (ovl->content)
1408     {
1409        if (EINA_FALSE == show_engobj)
1410        {
1411            disp = ovl->content;
1412            evas_object_geometry_get(disp, NULL, NULL, &w, &h);
1413            if (w <= 0 || h <= 0) evas_object_size_hint_min_get(disp, &w, &h);
1414          ovl->w = w;
1415                  ovl->h = h;
1416        }
1417     }
1418     else if (!(ovl->icon) && ovl->clas_content)
1419          {
1420             disp = ovl->clas_content;
1421             evas_object_geometry_get(disp, NULL, NULL, &w, &h);
1422             if (w <= 0 || h <= 0) evas_object_size_hint_min_get(disp, &w, &h);
1423          }
1424          else if (EINA_FALSE == show_engobj)
1425          {
1426              if (ovl->icon)
1427                 evas_object_show(ovl->icon);
1428              else if (ovl->clas_icon)
1429                 evas_object_show(ovl->clas_icon);
1430              disp = ovl->layout;
1431              w = ovl->w;
1432              h = ovl->h;
1433          }
1434
1435    if (show_engobj)//to display engine object the overlay must NOT belong to class
1436     {
1437         ELM_MAP_ENG_OBJECT_SET(ovl->wsd->engine->object_visibility, ELM_WIDGET_DATA(ovl->wsd)->obj, ovl->base->engobj, 1);
1438         if (ovl->content) evas_object_hide(ovl->content);
1439     }
1440
1441     if (disp && EINA_FALSE == show_engobj)
1442      {
1443        _coord_to_canvas(ovl->wsd, ovl->x, ovl->y, &x, &y);
1444        _obj_place(disp, x - (w / 2), y - (h / 2), w, h);
1445      }
1446 }
1447
1448 static void
1449 _overlay_default_coord_get(Overlay_Default *ovl,
1450                            Evas_Coord *x,
1451                            Evas_Coord *y,
1452                            Evas_Coord *w,
1453                            Evas_Coord *h)
1454 {
1455    EINA_SAFETY_ON_NULL_RETURN(ovl);
1456
1457    if (x) *x = ovl->x;
1458    if (y) *y = ovl->y;
1459    if (w) *w = ovl->w;
1460    if (h) *h = ovl->h;
1461 }
1462
1463 static void
1464 _overlay_default_coord_set(Overlay_Default *ovl,
1465                            Evas_Coord x,
1466                            Evas_Coord y)
1467 {
1468    EINA_SAFETY_ON_NULL_RETURN(ovl);
1469
1470    ovl->x = x;
1471    ovl->y = y;
1472 }
1473
1474 static void
1475 _overlay_default_coord_update(Overlay_Default *ovl)
1476 {
1477    EINA_SAFETY_ON_NULL_RETURN(ovl);
1478
1479    _region_to_coord_convert
1480      (ovl->wsd, ovl->lon, ovl->lat, ovl->wsd->size.w, &ovl->x, &ovl->y);
1481 }
1482
1483 static void
1484 _overlay_default_layout_text_update(Overlay_Default *ovl,
1485                                     const char *text)
1486 {
1487    if (!ovl->content && !ovl->icon && !ovl->clas_content && !ovl->clas_icon)
1488      elm_layout_text_set(ovl->layout, "elm.text", text);
1489 }
1490
1491 static void
1492 _overlay_default_content_update(Overlay_Default *ovl,
1493                                 Evas_Object *content,
1494                                 Elm_Map_Overlay *overlay)
1495 {
1496    EINA_SAFETY_ON_NULL_RETURN(ovl);
1497
1498    if (ovl->content == content) return;
1499    if (ovl->content) evas_object_del(ovl->content);
1500    ovl->content = content;
1501    if (!strcmp(ovl->wsd->engine->name, INTERNAL_ENGINE_NAME))
1502      evas_object_smart_member_add(ovl->content, ovl->wsd->pan_obj);
1503    else
1504      evas_object_smart_member_add(ovl->content, ELM_WIDGET_DATA(ovl->wsd)->obj);
1505    evas_object_stack_above(ovl->content, ovl->wsd->sep_maps_overlays);
1506
1507    if (ovl->content)
1508      evas_object_event_callback_add(ovl->content, EVAS_CALLBACK_MOUSE_DOWN,
1509                                     _overlay_clicked_cb, overlay);
1510 }
1511
1512 static void
1513 _overlay_default_layout_update(Overlay_Default *ovl)
1514 {
1515    EINA_SAFETY_ON_NULL_RETURN(ovl);
1516
1517    if (ovl->icon)
1518      {
1519         evas_object_color_set(ovl->layout, 255, 255, 255, 255);
1520         elm_layout_theme_set
1521           (ovl->layout, "map/marker", "empty",
1522           elm_widget_style_get(ELM_WIDGET_DATA(ovl->wsd)->obj));
1523         elm_object_part_content_set(ovl->layout, "elm.icon", ovl->icon);
1524      }
1525    else if (!ovl->icon && ovl->clas_icon)
1526      {
1527         evas_object_color_set(ovl->layout, 255, 255, 255, 255);
1528         elm_layout_theme_set
1529           (ovl->layout, "map/marker", "empty",
1530           elm_widget_style_get(ELM_WIDGET_DATA(ovl->wsd)->obj));
1531         elm_object_part_content_set(ovl->layout, "elm.icon", ovl->clas_icon);
1532      }
1533    else
1534      {
1535         evas_object_color_set
1536           (ovl->layout, ovl->c.r, ovl->c.g, ovl->c.b, ovl->c.a);
1537         elm_layout_theme_set
1538           (ovl->layout, "map/marker", "radio",
1539           elm_widget_style_get(ELM_WIDGET_DATA(ovl->wsd)->obj));
1540      }
1541 }
1542
1543 static void
1544 _overlay_default_class_content_update(Overlay_Default *ovl,
1545                                       Evas_Object *content)
1546 {
1547    EINA_SAFETY_ON_NULL_RETURN(ovl);
1548
1549    if (ovl->clas_content) evas_object_del(ovl->clas_content);
1550    ovl->clas_content = _icon_dup(content, ovl->layout);
1551    if (!strcmp(ovl->wsd->engine->name, INTERNAL_ENGINE_NAME))
1552      evas_object_smart_member_add(ovl->clas_content, ovl->wsd->pan_obj);
1553    else
1554      evas_object_smart_member_add(ovl->clas_content, ELM_WIDGET_DATA(ovl->wsd)->obj);
1555    evas_object_stack_above(ovl->clas_content, ovl->wsd->sep_maps_overlays);
1556    _overlay_default_layout_update(ovl);
1557 }
1558
1559 static Evas_Object*
1560 _img_from_icon(Evas *e __UNUSED__, Evas_Object *icon)
1561 {
1562    char *icon_file = NULL;
1563    Evas_Object *img;
1564    img = elm_image_object_get(icon);
1565    if ( EVAS_LOAD_ERROR_NONE != evas_object_image_load_error_get(img) )
1566     {
1567         ERR("Failed to load image file : %s", icon_file);
1568         evas_object_del(img);
1569         return NULL;
1570     }
1571     return img;
1572 }
1573
1574 static void
1575 _overlay_engine_icon_create(Elm_Map_Overlay *overlay,
1576                             Evas_Object *icon)
1577 {
1578    char *imgbuffer = NULL;
1579    int w = 0;
1580    int h = 0;
1581    Overlay_Default *ovl = (Overlay_Default*)(overlay->ovl);
1582
1583    Evas_Object *img = _img_from_icon(evas_object_evas_get(ELM_WIDGET_DATA(overlay->wsd)->obj), icon);
1584
1585    EINA_SAFETY_ON_NULL_RETURN(img);
1586
1587    imgbuffer = (char*)evas_object_image_data_get(img, EINA_FALSE);
1588
1589    EINA_SAFETY_ON_NULL_RETURN(imgbuffer);
1590
1591    evas_object_image_size_get(img, &w, &h);
1592
1593    if (overlay->engobj)
1594       ELM_MAP_ENG_OBJECT_DELETE(overlay->wsd->engine->icon_remove,  ELM_WIDGET_DATA(overlay->wsd)->obj, overlay->engobj);
1595
1596    ELM_MAP_ENG_OBJECT_CREATE(overlay->wsd->engine->icon_add, overlay->engobj,  ELM_WIDGET_DATA(overlay->wsd)->obj, imgbuffer, w, h, ovl->lon, ovl->lat);
1597
1598    if (ovl->layout)
1599       evas_object_hide(ovl->layout);//we do not show the evas object
1600 }
1601
1602 static void
1603 _overlay_default_engine_icon_create_or_update(Elm_Map_Overlay *overlay,
1604                              Evas_Object *icon)
1605 {
1606    Overlay_Default *ovl = (Overlay_Default*)(overlay->ovl);
1607
1608    if (ovl->icon == icon )
1609       return;
1610
1611    _overlay_engine_icon_create(overlay, icon);
1612
1613    if ( ovl->icon )
1614       evas_object_del(icon);
1615    ovl->icon = icon;
1616 }
1617
1618 static void
1619 _overlay_default_engine_content_create_or_update(Elm_Map_Overlay *overlay,
1620                              Evas_Object *content)
1621 {
1622    Overlay_Default *ovl = (Overlay_Default*)(overlay->ovl);
1623    Eina_Bool img_or_icon = evas_object_smart_type_check(content, "elm_icon") |
1624    evas_object_smart_type_check(content, "elm_image");
1625
1626    if (ovl->content == content )
1627       return;
1628
1629    if ( ovl->content )
1630       evas_object_del(content);
1631    ovl->content = NULL;
1632    if (img_or_icon)
1633     {
1634        _overlay_engine_icon_create(overlay, content);
1635        ovl->content = content;
1636     }
1637    else
1638     {
1639        _overlay_default_content_update(overlay->ovl, content, overlay);//if not image/icon go with normal flow
1640     }
1641 }
1642
1643
1644 static void
1645 _overlay_default_icon_update(Overlay_Default *ovl,
1646                              Evas_Object *icon)
1647 {
1648    EINA_SAFETY_ON_NULL_RETURN(ovl);
1649    Elm_Map_Overlay *overlay = ovl->base;
1650
1651    if (ovl->icon == icon) return;
1652
1653    if (MAP_ENGINE_OVERLAY_SUPPORT(overlay->wsd))
1654     {
1655        _overlay_default_engine_icon_create_or_update(overlay, icon);
1656     }
1657    else
1658     {
1659        if (ovl->icon) evas_object_del(ovl->icon);
1660            ovl->icon = icon;
1661        _overlay_default_layout_update(ovl);
1662     }
1663 }
1664
1665 static void
1666 _overlay_default_class_icon_update(Overlay_Default *ovl,
1667                                    Evas_Object *icon)
1668 {
1669    EINA_SAFETY_ON_NULL_RETURN(ovl);
1670
1671    if (ovl->clas_icon) evas_object_del(ovl->clas_icon);
1672    ovl->clas_icon = _icon_dup(icon, ovl->layout);
1673    _overlay_default_layout_update(ovl);
1674 }
1675
1676 static void
1677 _overlay_default_color_update(Overlay_Default *ovl,
1678                               Color c)
1679 {
1680    EINA_SAFETY_ON_NULL_RETURN(ovl);
1681
1682    ovl->c = c;
1683    _overlay_default_layout_update(ovl);
1684 }
1685
1686 static void
1687 _overlay_default_free(Overlay_Default *ovl)
1688 {
1689    EINA_SAFETY_ON_NULL_RETURN(ovl);
1690
1691    if (ovl->content) evas_object_del(ovl->content);
1692    if (ovl->icon) evas_object_del(ovl->icon);
1693    if (ovl->clas_content) evas_object_del(ovl->clas_content);
1694    if (ovl->clas_icon) evas_object_del(ovl->clas_icon);
1695    if (ovl->layout) evas_object_del(ovl->layout);
1696
1697    free(ovl);
1698 }
1699
1700 static Overlay_Default *
1701 _overlay_default_new(Elm_Map_Overlay *overlay,
1702                      double lon,
1703                      double lat,
1704                      Color c,
1705                      double scale)
1706 {
1707    Overlay_Default *ovl;
1708
1709    EINA_SAFETY_ON_NULL_RETURN_VAL(overlay, NULL);
1710
1711    overlay->engobj = NULL;
1712
1713    ovl = ELM_NEW(Overlay_Default);
1714    ovl->wsd = overlay->wsd;
1715    _edj_overlay_size_get(ovl->wsd, &(ovl->w), &(ovl->h));
1716    ovl->w *= scale;
1717    ovl->h *= scale;
1718    ovl->layout = elm_layout_add(ELM_WIDGET_DATA(ovl->wsd)->obj);
1719    if (!strcmp(ovl->wsd->engine->name, INTERNAL_ENGINE_NAME))
1720      evas_object_smart_member_add(ovl->layout, ovl->wsd->pan_obj);
1721    else
1722      evas_object_smart_member_add(ovl->layout, ELM_WIDGET_DATA(ovl->wsd)->obj);
1723    evas_object_stack_above(ovl->layout, ovl->wsd->sep_maps_overlays);
1724    elm_layout_theme_set(ovl->layout, "map/marker", "radio",
1725                         elm_widget_style_get(ELM_WIDGET_DATA(ovl->wsd)->obj));
1726    evas_object_event_callback_add(ovl->layout, EVAS_CALLBACK_MOUSE_DOWN,
1727                                   _overlay_clicked_cb, overlay);
1728    ovl->lon = lon;
1729    ovl->lat = lat;
1730    ovl->base = overlay;
1731    _overlay_default_color_update(ovl, c);
1732
1733    return ovl;
1734 }
1735
1736 static void
1737 _overlay_group_hide(Overlay_Group *grp)
1738 {
1739    EINA_SAFETY_ON_NULL_RETURN(grp);
1740
1741    if (grp->ovl) _overlay_default_hide(grp->ovl);
1742 }
1743
1744 static void
1745 _overlay_group_show(Overlay_Group *grp)
1746 {
1747    EINA_SAFETY_ON_NULL_RETURN(grp);
1748
1749    if (grp->ovl) _overlay_default_show(grp->ovl);
1750 }
1751
1752 static void
1753 _overlay_group_coord_member_update(Overlay_Group *grp,
1754                                    Evas_Coord x,
1755                                    Evas_Coord y,
1756                                    Eina_List *members)
1757 {
1758    char text[32];
1759
1760    EINA_SAFETY_ON_NULL_RETURN(grp);
1761
1762    if (!grp->ovl) return;
1763
1764    _overlay_default_coord_set(grp->ovl, x, y);
1765    _coord_to_region_convert
1766      (grp->wsd, x, y, grp->wsd->size.w, &grp->lon, &grp->lat);
1767
1768    if (grp->members) eina_list_free(grp->members);
1769    grp->members = members;
1770    snprintf(text, sizeof(text), "%d", eina_list_count(members));
1771
1772    _overlay_default_layout_text_update(grp->ovl, text);
1773 }
1774
1775 static void
1776 _overlay_group_icon_update(Overlay_Group *grp,
1777                            Evas_Object *icon)
1778 {
1779    EINA_SAFETY_ON_NULL_RETURN(grp);
1780
1781    if (grp->ovl)
1782      _overlay_default_icon_update
1783        (grp->ovl, _icon_dup(icon, ELM_WIDGET_DATA(grp->wsd)->obj));
1784 }
1785
1786 static void
1787 _overlay_group_content_update(Overlay_Group *grp,
1788                               Evas_Object *content,
1789                               Elm_Map_Overlay *overlay)
1790 {
1791    EINA_SAFETY_ON_NULL_RETURN(grp);
1792
1793    _overlay_default_content_update
1794       (grp->ovl, _icon_dup(content, ELM_WIDGET_DATA(grp->wsd)->obj), overlay);
1795
1796    return;
1797 }
1798
1799 static void
1800 _overlay_group_color_update(Overlay_Group *grp,
1801                             Color c)
1802 {
1803    EINA_SAFETY_ON_NULL_RETURN(grp);
1804
1805    _overlay_default_color_update(grp->ovl, c);
1806 }
1807
1808 static void
1809 _overlay_group_cb_set(Overlay_Group *grp,
1810                       Elm_Map_Overlay_Get_Cb cb,
1811                       void *data)
1812 {
1813    EINA_SAFETY_ON_NULL_RETURN(grp);
1814
1815    grp->overlay->cb = cb;
1816    grp->overlay->data = data;
1817 }
1818
1819 static void
1820 _overlay_group_free(Overlay_Group *grp)
1821 {
1822    EINA_SAFETY_ON_NULL_RETURN(grp);
1823
1824    if (grp->overlay) free(grp->overlay);
1825    if (grp->ovl) _overlay_default_free(grp->ovl);
1826    if (grp->members) eina_list_free(grp->members);
1827
1828    free(grp);
1829 }
1830
1831 static Overlay_Group *
1832 _overlay_group_new(Elm_Map_Smart_Data *sd)
1833 {
1834    Overlay_Group *grp;
1835    Color c = {0x90, 0xee, 0x90, 0xff};
1836
1837    grp = ELM_NEW(Overlay_Group);
1838    grp->wsd = sd;
1839    grp->overlay = ELM_NEW(Elm_Map_Overlay);  // this is a virtual overlay
1840    grp->overlay->wsd = sd;
1841    grp->overlay->type = ELM_MAP_OVERLAY_TYPE_GROUP;
1842    grp->overlay->ovl = grp;
1843    grp->ovl = _overlay_default_new(grp->overlay, -1, -1, c, 1);
1844
1845    return grp;
1846 }
1847
1848 static void
1849 _overlay_class_cb_set(Overlay_Class *ovl,
1850                       Elm_Map_Overlay_Get_Cb cb,
1851                       void *data)
1852 {
1853    Eina_List *l;
1854    Elm_Map_Overlay *overlay;
1855
1856    EINA_SAFETY_ON_NULL_RETURN(ovl);
1857
1858    // Update class members' callbacks
1859    EINA_LIST_FOREACH(ovl->members, l, overlay)
1860      _overlay_group_cb_set(overlay->grp, cb, data);
1861 }
1862
1863 static void
1864 _overlay_class_icon_update(Overlay_Class *ovl,
1865                            Evas_Object *icon)
1866 {
1867    Eina_List *l;
1868    Elm_Map_Overlay *overlay;
1869
1870    EINA_SAFETY_ON_NULL_RETURN(ovl);
1871
1872    if (ovl->icon == icon) return;
1873    if (ovl->icon) evas_object_del(ovl->icon);
1874    ovl->icon = icon;
1875    // For using proxy, it should have size and be shown but moved away to hide.
1876    evas_object_resize(icon, 32, 32);
1877    evas_object_move(icon, -9999, -9999);
1878    evas_object_show(icon);
1879
1880    // Update class members' class icons
1881    EINA_LIST_FOREACH(ovl->members, l, overlay)
1882      {
1883         _overlay_group_icon_update(overlay->grp, icon);
1884
1885         if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
1886           _overlay_default_class_icon_update(overlay->ovl, icon);
1887      }
1888 }
1889
1890 static void
1891 _overlay_class_content_update(Overlay_Class *ovl,
1892                               Evas_Object *content)
1893 {
1894    Eina_List *l;
1895    Elm_Map_Overlay *overlay;
1896
1897    EINA_SAFETY_ON_NULL_RETURN(ovl);
1898
1899    if (ovl->content == content) return;
1900    if (ovl->content) evas_object_del(ovl->content);
1901    ovl->content = content;
1902    // For using proxy, it should have size and be shown but moved away to hide.
1903    // content should have it's own size
1904    evas_object_move(content, -9999, -9999);
1905
1906    // Update class members' class contents
1907    EINA_LIST_FOREACH(ovl->members, l, overlay)
1908      {
1909         _overlay_group_content_update(overlay->grp, content, overlay);
1910
1911         if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
1912           _overlay_default_class_content_update(overlay->ovl, content);
1913      }
1914 }
1915
1916 static void
1917 _overlay_class_color_update(Overlay_Class *ovl,
1918                             Color c)
1919 {
1920    Eina_List *l;
1921    Elm_Map_Overlay *overlay;
1922
1923    EINA_SAFETY_ON_NULL_RETURN(ovl);
1924
1925    // Update class members' class contents
1926    EINA_LIST_FOREACH(ovl->members, l, overlay)
1927      _overlay_group_color_update(overlay->grp, c);
1928 }
1929
1930 static void
1931 _overlay_class_free(Overlay_Class *clas)
1932 {
1933    Eina_List *l;
1934    Elm_Map_Overlay *overlay;
1935
1936    EINA_SAFETY_ON_NULL_RETURN(clas);
1937
1938    // Update class members' class contents
1939    EINA_LIST_FOREACH(clas->members, l, overlay)
1940      {
1941         overlay->grp->klass = NULL;
1942         _overlay_group_content_update(overlay->grp, NULL, NULL);
1943         _overlay_group_icon_update(overlay->grp, NULL);
1944
1945         if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
1946           {
1947              _overlay_default_class_content_update(overlay->ovl, NULL);
1948              _overlay_default_class_icon_update(overlay->ovl, NULL);
1949           }
1950      }
1951    if (clas->icon) evas_object_del(clas->icon);
1952    if (clas->members) eina_list_free(clas->members);
1953
1954    free(clas);
1955 }
1956
1957 static Overlay_Class *
1958 _overlay_class_new(Elm_Map_Smart_Data *sd)
1959 {
1960    Overlay_Class *ovl;
1961
1962    ovl = ELM_NEW(Overlay_Class);
1963    ovl->wsd = sd;
1964    ovl->icon = NULL;
1965    ovl->zoom_max = OVERLAY_CLASS_ZOOM_MAX;
1966
1967    return ovl;
1968 }
1969
1970 static void
1971 _overlay_bubble_coord_update(Overlay_Bubble *bubble)
1972 {
1973    EINA_SAFETY_ON_NULL_RETURN(bubble);
1974
1975    if (bubble->pobj)
1976      {
1977         Evas_Coord x, y, w, h;
1978
1979         evas_object_geometry_get(bubble->pobj, &x, &y, &w, &h);
1980         bubble->x = x + (w / 2);
1981         bubble->y = y - (bubble->h / 2);
1982         _canvas_to_coord
1983           (bubble->wsd, bubble->x, bubble->y, &(bubble->x), &(bubble->y));
1984         _coord_to_region_convert
1985           (bubble->wsd, bubble->x, bubble->y, bubble->wsd->size.w,
1986           &(bubble->lon), &(bubble->lat));
1987      }
1988    else
1989      {
1990         _region_to_coord_convert(bubble->wsd, bubble->lon, bubble->lat,
1991                                  bubble->wsd->size.w, &bubble->x, &bubble->y);
1992      }
1993 }
1994
1995 static void
1996 _overlay_bubble_coord_get(Overlay_Bubble *bubble,
1997                           Evas_Coord *x,
1998                           Evas_Coord *y,
1999                           Evas_Coord *w,
2000                           Evas_Coord *h)
2001 {
2002    EINA_SAFETY_ON_NULL_RETURN(bubble);
2003
2004    if (!(bubble->pobj))
2005      {
2006         if (x) *x = bubble->x;
2007         if (y) *y = bubble->y;
2008         if (w) *w = bubble->w;
2009         if (h) *h = bubble->h;
2010      }
2011    else
2012      {
2013         if (x) *x = 0;
2014         if (y) *y = 0;
2015         if (w) *w = 0;
2016         if (h) *h = 0;
2017      }
2018 }
2019
2020 static Eina_Bool
2021 _overlay_bubble_show_hide(Overlay_Bubble *bubble,
2022                           Eina_Bool visible)
2023 {
2024    EINA_SAFETY_ON_NULL_RETURN_VAL(bubble, EINA_FALSE);
2025    EINA_SAFETY_ON_NULL_RETURN_VAL(bubble->obj, EINA_FALSE);
2026
2027    if (!visible) evas_object_hide(bubble->obj);
2028    else if (bubble->pobj && !evas_object_visible_get(bubble->pobj))
2029      {
2030         evas_object_hide(bubble->obj);
2031         visible = EINA_FALSE;
2032      }
2033    else
2034      {
2035         _coord_to_canvas
2036           (bubble->wsd, bubble->x, bubble->y, &(bubble->x), &(bubble->y));
2037         _obj_place(bubble->obj, bubble->x - (bubble->w / 2),
2038                    bubble->y - (bubble->h / 2), bubble->w, bubble->h);
2039         evas_object_raise(bubble->obj);
2040      }
2041    return visible;
2042 }
2043
2044 static void
2045 _overlay_bubble_free(Overlay_Bubble *bubble)
2046 {
2047    EINA_SAFETY_ON_NULL_RETURN(bubble);
2048
2049    evas_object_del(bubble->bx);
2050    evas_object_del(bubble->sc);
2051    evas_object_del(bubble->obj);
2052
2053    free(bubble);
2054 }
2055
2056 static Overlay_Bubble *
2057 _overlay_bubble_new(Elm_Map_Overlay *overlay)
2058 {
2059    Evas_Coord h;
2060    const char *s;
2061    Overlay_Bubble *bubble;
2062
2063    EINA_SAFETY_ON_NULL_RETURN_VAL(overlay, NULL);
2064
2065    bubble = ELM_NEW(Overlay_Bubble);
2066    bubble->wsd = overlay->wsd;
2067
2068    bubble->obj =
2069      edje_object_add(evas_object_evas_get(ELM_WIDGET_DATA(overlay->wsd)->obj));
2070    elm_widget_theme_object_set
2071      (ELM_WIDGET_DATA(overlay->wsd)->obj, bubble->obj, "map", "marker_bubble",
2072      elm_widget_style_get(ELM_WIDGET_DATA(overlay->wsd)->obj));
2073
2074    evas_object_event_callback_add(bubble->obj, EVAS_CALLBACK_MOUSE_DOWN,
2075                                   _overlay_clicked_cb, overlay);
2076
2077    // FIXME: different from upstream.
2078    // elm_widget_sub_object_add will fail if edje is used as parent object.
2079    bubble->sc = elm_scroller_add(ELM_WIDGET_DATA(overlay->wsd)->obj);
2080    elm_widget_style_set(bubble->sc, "map_bubble");
2081    elm_scroller_content_min_limit(bubble->sc, EINA_FALSE, EINA_TRUE);
2082    elm_scroller_policy_set
2083      (bubble->sc, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
2084    elm_scroller_bounce_set
2085      (bubble->sc, _elm_config->thumbscroll_bounce_enable, EINA_FALSE);
2086    edje_object_part_swallow(bubble->obj, "elm.swallow.content", bubble->sc);
2087
2088    bubble->bx = elm_box_add(bubble->sc);
2089    evas_object_size_hint_align_set(bubble->bx, EVAS_HINT_FILL, EVAS_HINT_FILL);
2090    evas_object_size_hint_weight_set
2091      (bubble->bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
2092    elm_box_horizontal_set(bubble->bx, EINA_TRUE);
2093    elm_object_content_set(bubble->sc, bubble->bx);
2094
2095    s = edje_object_data_get(bubble->obj, "size_w");
2096    if (s) bubble->w = atoi(s);
2097    else bubble->w = 0;
2098
2099    edje_object_size_min_calc(bubble->obj, NULL, &(bubble->h));
2100    s = edje_object_data_get(bubble->obj, "size_h");
2101    if (s) h = atoi(s);
2102    else h = 0;
2103
2104    if (bubble->h < h) bubble->h = h;
2105
2106    bubble->lon = -1;
2107    bubble->lat = -1;
2108    bubble->x = -1;
2109    bubble->y = -1;
2110
2111    return bubble;
2112 }
2113
2114 static void
2115 _overlay_route_color_update(Overlay_Route *ovl,
2116                             Color c)
2117 {
2118    EINA_SAFETY_ON_NULL_RETURN(ovl);
2119
2120    evas_object_color_set(ovl->obj, c.r, c.g, c.b, c.a);
2121 }
2122
2123 static void
2124 _overlay_route_hide(Overlay_Route *ovl)
2125 {
2126    EINA_SAFETY_ON_NULL_RETURN(ovl);
2127
2128    evas_object_hide(ovl->obj);
2129 }
2130
2131 static void
2132 _overlay_route_show(Overlay_Route *r)
2133 {
2134    Path *p;
2135    Eina_List *l;
2136    Path_Node *n;
2137
2138    EINA_SAFETY_ON_NULL_RETURN(r);
2139    EINA_SAFETY_ON_NULL_RETURN(r->wsd);
2140
2141    evas_object_polygon_points_clear(r->obj);
2142    EINA_LIST_FOREACH(r->nodes, l, n)
2143      {
2144         p = eina_list_nth(r->paths, n->idx);
2145         if (!p) continue;
2146
2147         _region_to_coord_convert
2148           (r->wsd, n->pos.lon, n->pos.lat, r->wsd->size.w, &p->x, &p->y);
2149         _coord_to_canvas(r->wsd, p->x, p->y, &p->x, &p->y);
2150      }
2151    EINA_LIST_FOREACH(r->paths, l, p)
2152      evas_object_polygon_point_add(r->obj, p->x - 3, p->y - 3);
2153
2154    EINA_LIST_REVERSE_FOREACH(r->paths, l, p)
2155      evas_object_polygon_point_add(r->obj, p->x + 3, p->y + 3);
2156
2157    evas_object_show(r->obj);
2158 }
2159
2160 static void
2161 _overlay_route_free(Overlay_Route *route)
2162 {
2163    Path *p;
2164    Path_Node *n;
2165
2166    EINA_SAFETY_ON_NULL_RETURN(route);
2167
2168    evas_object_del(route->obj);
2169
2170    EINA_LIST_FREE (route->paths, p)
2171      free(p);
2172
2173    EINA_LIST_FREE (route->nodes, n)
2174      {
2175         if (n->pos.address) eina_stringshare_del(n->pos.address);
2176         free(n);
2177      }
2178
2179    free(route);
2180 }
2181
2182 static Overlay_Route *
2183 _overlay_route_new(Elm_Map_Smart_Data *sd,
2184                    const Elm_Map_Route *route,
2185                    Color c)
2186 {
2187    Eina_List *l;
2188    Path_Node *n;
2189    Overlay_Route *ovl;
2190
2191    EINA_SAFETY_ON_NULL_RETURN_VAL(route, NULL);
2192
2193    ovl = ELM_NEW(Overlay_Route);
2194    ovl->wsd = sd;
2195    ovl->obj =
2196      evas_object_polygon_add(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
2197    if (!strcmp(ovl->wsd->engine->name, INTERNAL_ENGINE_NAME))
2198      evas_object_smart_member_add(ovl->obj, sd->pan_obj);
2199    else
2200      evas_object_smart_member_add(ovl->obj, ELM_WIDGET_DATA(ovl->wsd)->obj);
2201
2202    _overlay_route_color_update(ovl, c);
2203
2204    EINA_LIST_FOREACH(route->nodes, l, n)
2205      {
2206         Path *path;
2207         Path_Node *node;
2208
2209         node = ELM_NEW(Path_Node);
2210         node->idx = n->idx;
2211         node->pos.lon = n->pos.lon;
2212         node->pos.lat = n->pos.lat;
2213         if (n->pos.address) node->pos.address = strdup(n->pos.address);
2214         ovl->nodes = eina_list_append(ovl->nodes, node);
2215
2216         path = ELM_NEW(Path);
2217         ovl->paths = eina_list_append(ovl->paths, path);
2218      }
2219
2220    return ovl;
2221 }
2222
2223 static void
2224 _overlay_line_color_update(Overlay_Line *ovl,
2225                            Color c)
2226 {
2227    EINA_SAFETY_ON_NULL_RETURN(ovl);
2228
2229    evas_object_color_set(ovl->obj, c.r, c.g, c.b, c.a);
2230 }
2231
2232 static void
2233 _overlay_line_hide(Overlay_Line *ovl)
2234 {
2235    EINA_SAFETY_ON_NULL_RETURN(ovl);
2236
2237    if (ovl->obj) evas_object_hide(ovl->obj);
2238 }
2239
2240 static void
2241 _overlay_line_show(Overlay_Line *ovl)
2242 {
2243    Evas_Coord fx, fy, tx, ty;
2244    Elm_Map_Smart_Data *sd = ovl->wsd;
2245
2246    _region_to_coord_convert(sd, ovl->flon, ovl->flat, sd->size.w, &fx, &fy);
2247    _region_to_coord_convert(sd, ovl->tlon, ovl->tlat, sd->size.w, &tx, &ty);
2248    _coord_to_canvas(sd, fx, fy, &fx, &fy);
2249    _coord_to_canvas(sd, tx, ty, &tx, &ty);
2250    evas_object_line_xy_set(ovl->obj, fx, fy, tx, ty);
2251    evas_object_show(ovl->obj);
2252 }
2253
2254 static void
2255 _overlay_line_free(Overlay_Line *ovl)
2256 {
2257    EINA_SAFETY_ON_NULL_RETURN(ovl);
2258
2259    evas_object_del(ovl->obj);
2260    free(ovl);
2261 }
2262
2263 static Overlay_Line *
2264 _overlay_line_new(Elm_Map_Smart_Data *sd,
2265                   double flon,
2266                   double flat,
2267                   double tlon,
2268                   double tlat,
2269                   Color c)
2270 {
2271    Overlay_Line *ovl;
2272
2273    ovl = ELM_NEW(Overlay_Line);
2274    ovl->wsd = sd;
2275    ovl->flon = flon;
2276    ovl->flat = flat;
2277    ovl->tlon = tlon;
2278    ovl->tlat = tlat;
2279    ovl->obj =
2280      evas_object_line_add(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
2281    evas_object_smart_member_add(ovl->obj, sd->pan_obj);
2282    _overlay_line_color_update(ovl, c);
2283
2284    return ovl;
2285 }
2286
2287 static void
2288 _overlay_polygon_color_update(Overlay_Polygon *ovl,
2289                               Color c)
2290 {
2291    EINA_SAFETY_ON_NULL_RETURN(ovl);
2292
2293    evas_object_color_set(ovl->obj, c.r, c.g, c.b, c.a);
2294 }
2295
2296 static void
2297 _overlay_polygon_hide(Overlay_Polygon *ovl)
2298 {
2299    EINA_SAFETY_ON_NULL_RETURN(ovl);
2300
2301    if (ovl->obj) evas_object_hide(ovl->obj);
2302 }
2303
2304 static void
2305 _overlay_polygon_show(Overlay_Polygon *ovl)
2306 {
2307    Eina_List *l;
2308    Region *r;
2309    Elm_Map_Smart_Data *sd;
2310
2311    EINA_SAFETY_ON_NULL_RETURN(ovl);
2312
2313    sd = ovl->wsd;
2314
2315    evas_object_polygon_points_clear(ovl->obj);
2316    EINA_LIST_FOREACH(ovl->regions, l, r)
2317      {
2318         Evas_Coord x, y;
2319
2320         _region_to_coord_convert(sd, r->lon, r->lat, sd->size.w, &x, &y);
2321         _coord_to_canvas(sd, x, y, &x, &y);
2322         evas_object_polygon_point_add(ovl->obj, x, y);
2323      }
2324    evas_object_show(ovl->obj);
2325 }
2326
2327 static void
2328 _overlay_polygon_free(Overlay_Polygon *ovl)
2329 {
2330    Region *r;
2331
2332    EINA_SAFETY_ON_NULL_RETURN(ovl);
2333
2334    evas_object_del(ovl->obj);
2335
2336    EINA_LIST_FREE (ovl->regions, r)
2337      free(r);
2338
2339    free(ovl);
2340 }
2341
2342 static Overlay_Polygon *
2343 _overlay_polygon_new(Elm_Map_Smart_Data *sd, Color c)
2344 {
2345    Overlay_Polygon *ovl;
2346
2347    ovl = ELM_NEW(Overlay_Polygon);
2348    ovl->wsd = sd;
2349    ovl->obj =
2350      evas_object_polygon_add(evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj));
2351    evas_object_smart_member_add(ovl->obj, sd->pan_obj);
2352    _overlay_polygon_color_update(ovl, c);
2353
2354    return ovl;
2355 }
2356
2357 static void
2358 _overlay_circle_color_update(Overlay_Circle *ovl,
2359                              Color c)
2360 {
2361    Evas_Object *obj;
2362
2363    EINA_SAFETY_ON_NULL_RETURN(ovl);
2364
2365    obj = elm_layout_edje_get(ovl->obj);
2366    evas_object_color_set(obj, c.r, c.g, c.b, c.a);
2367 }
2368
2369 static void
2370 _overlay_circle_hide(Overlay_Circle *ovl)
2371 {
2372    EINA_SAFETY_ON_NULL_RETURN(ovl);
2373
2374    if (ovl->obj) evas_object_hide(ovl->obj);
2375 }
2376
2377 static void
2378 _overlay_circle_show(Overlay_Circle *ovl)
2379 {
2380    double r;
2381    Evas_Coord x, y;
2382    Elm_Map_Smart_Data *sd;
2383
2384    EINA_SAFETY_ON_NULL_RETURN(ovl);
2385
2386    sd = ovl->wsd;
2387
2388    r = (ovl->ratio) * sd->size.w;
2389    _region_to_coord_convert(sd, ovl->lon, ovl->lat, sd->size.w, &x, &y);
2390    _coord_to_canvas(sd, x, y, &x, &y);
2391    _obj_place(ovl->obj, x - r, y - r, r * 2, r * 2);
2392 }
2393
2394 static void
2395 _overlay_circle_free(Overlay_Circle *ovl)
2396 {
2397    EINA_SAFETY_ON_NULL_RETURN(ovl);
2398
2399    evas_object_del(ovl->obj);
2400    free(ovl);
2401 }
2402
2403 static Overlay_Circle *
2404 _overlay_circle_new(Elm_Map_Smart_Data *sd,
2405                     double lon,
2406                     double lat,
2407                     double radius,
2408                     Color c)
2409 {
2410    Overlay_Circle *ovl;
2411
2412    ovl = ELM_NEW(Overlay_Circle);
2413    ovl->wsd = sd;
2414    ovl->lon = lon;
2415    ovl->lat = lat;
2416    ovl->radius = radius;
2417    ovl->ratio = radius / sd->size.w;
2418
2419    ovl->obj = elm_layout_add(ELM_WIDGET_DATA(sd)->obj);
2420    evas_object_smart_member_add(ovl->obj, sd->pan_obj);
2421    evas_object_stack_above(ovl->obj, sd->sep_maps_overlays);
2422    elm_layout_theme_set(ovl->obj, "map/circle", "base",
2423                         elm_widget_style_get(ELM_WIDGET_DATA(sd)->obj));
2424    _overlay_circle_color_update(ovl, c);
2425
2426    return ovl;
2427 }
2428
2429 static void
2430 _overlay_scale_color_update(Overlay_Scale *ovl,
2431                             Color c)
2432 {
2433    EINA_SAFETY_ON_NULL_RETURN(ovl);
2434
2435    evas_object_color_set(ovl->obj, c.r, c.g, c.b, c.a);
2436 }
2437
2438 static void
2439 _overlay_scale_hide(Overlay_Scale *ovl)
2440 {
2441    EINA_SAFETY_ON_NULL_RETURN(ovl);
2442
2443    if (ovl->obj) evas_object_hide(ovl->obj);
2444 }
2445
2446 static void
2447 _overlay_scale_show(Overlay_Scale *ovl)
2448 {
2449    double text;
2450    Evas_Coord w;
2451    char buf[32];
2452    double meter;
2453    double lon, lat;
2454    Elm_Map_Smart_Data *sd;
2455
2456    EINA_SAFETY_ON_NULL_RETURN(ovl);
2457
2458    sd = ovl->wsd;
2459
2460    if ((int)(sizeof(_scale_tb)/sizeof(double)) <= sd->zoom)
2461      {
2462         ERR("Zoom level is too high");
2463         return;
2464      }
2465
2466    elm_map_region_get(ELM_WIDGET_DATA(sd)->obj, &lon, &lat);
2467    meter =
2468      sd->src_tile->scale_cb(ELM_WIDGET_DATA(sd)->obj, lon, lat, sd->zoom);
2469
2470    if (meter == 0)
2471      {
2472         ERR("Scale callback returns a value below zero");
2473         return;
2474      }
2475
2476    w = (_scale_tb[sd->zoom] / meter) * (sd->zoom_detail - sd->zoom + 1);
2477
2478    text = _scale_tb[sd->zoom] / 1000;
2479    if (text < 1) snprintf(buf, sizeof(buf), "%d m", (int)(text * 1000));
2480    else snprintf(buf, sizeof(buf), "%d km", (int)text);
2481
2482    elm_layout_text_set(ovl->obj, "elm.text", buf);
2483    _obj_place(ovl->obj, ovl->x, ovl->y, w, ovl->h);
2484 }
2485
2486 static void
2487 _overlay_scale_free(Overlay_Scale *ovl)
2488 {
2489    EINA_SAFETY_ON_NULL_RETURN(ovl);
2490
2491    evas_object_del(ovl->obj);
2492    free(ovl);
2493 }
2494
2495 static Overlay_Scale *
2496 _overlay_scale_new(Elm_Map_Smart_Data *sd,
2497                    Evas_Coord x,
2498                    Evas_Coord y,
2499                    Color c)
2500 {
2501    const char *s;
2502    Overlay_Scale *ovl;
2503
2504    ovl = ELM_NEW(Overlay_Scale);
2505    ovl->wsd = sd;
2506    ovl->x = x;
2507    ovl->y = y;
2508
2509    ovl->obj = elm_layout_add(ELM_WIDGET_DATA(sd)->obj);
2510    evas_object_smart_member_add(ovl->obj, sd->pan_obj);
2511    evas_object_stack_above(ovl->obj, sd->sep_maps_overlays);
2512    elm_layout_theme_set(ovl->obj, "map/scale", "base",
2513                         elm_widget_style_get(ELM_WIDGET_DATA(sd)->obj));
2514    s = edje_object_data_get(elm_layout_edje_get(ovl->obj), "size_w");
2515
2516    if (s) ovl->w = atoi(s);
2517    else ovl->w = 100;
2518
2519    s = edje_object_data_get(elm_layout_edje_get(ovl->obj), "size_h");
2520    if (s) ovl->h = atoi(s);
2521    else ovl->h = 60;
2522
2523    _overlay_scale_color_update(ovl, c);
2524
2525    return ovl;
2526 }
2527
2528 static void
2529 _overlay_grouping(Eina_List *clas_membs,
2530                   Elm_Map_Overlay *boss)
2531 {
2532    Eina_List *l;
2533    Elm_Map_Overlay *memb;
2534    Eina_List *grp_membs = NULL;
2535    int sum_x = 0, sum_y = 0, cnt = 0;
2536    Evas_Coord bx = 0, by = 0, bw = 0, bh = 0;
2537
2538    EINA_SAFETY_ON_NULL_RETURN(clas_membs);
2539    EINA_SAFETY_ON_NULL_RETURN(boss);
2540
2541    if (boss->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
2542      _overlay_default_coord_get(boss->ovl, &bx, &by, &bw, &bh);
2543    else if (boss->type == ELM_MAP_OVERLAY_TYPE_BUBBLE)
2544      _overlay_bubble_coord_get(boss->ovl, &bx, &by, &bw, &bh);
2545
2546    EINA_LIST_FOREACH(clas_membs, l, memb)
2547      {
2548         Evas_Coord x = 0, y = 0, w = 0, h = 0;
2549
2550         if (boss == memb || memb->grp->in) continue;
2551         if ((memb->hide) || (memb->zoom_min > memb->wsd->zoom)) continue;
2552
2553         if (memb->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
2554           _overlay_default_coord_get(memb->ovl, &x, &y, &w, &h);
2555         else if (memb->type == ELM_MAP_OVERLAY_TYPE_BUBBLE)
2556           _overlay_bubble_coord_get(memb->ovl, &x, &y, &w, &h);
2557
2558         if (bw <= 0 || bh <= 0 || w <= 0 || h <= 0) continue;
2559         if (ELM_RECTS_INTERSECT(x, y, w, h, bx, by,
2560                                 bw * OVERLAY_GROUPING_SCALE,
2561                                 bh * OVERLAY_GROUPING_SCALE))
2562           {
2563              // Join group.
2564              memb->grp->boss = EINA_FALSE;
2565              memb->grp->in = EINA_TRUE;
2566              sum_x += x;
2567              sum_y += y;
2568              cnt++;
2569              grp_membs = eina_list_append(grp_membs, memb);
2570           }
2571      }
2572
2573    if (cnt >= 1)
2574      {
2575         // Mark as boss
2576         boss->grp->boss = EINA_TRUE;
2577         boss->grp->in = EINA_TRUE;
2578         sum_x = (sum_x + bx) / (cnt + 1);
2579         sum_y = (sum_y + by) / (cnt + 1);
2580         grp_membs = eina_list_append(grp_membs, boss);
2581         _overlay_group_coord_member_update(boss->grp, sum_x, sum_y, grp_membs);
2582
2583         // Append group to all overlay list
2584         boss->wsd->group_overlays =
2585           eina_list_append(boss->wsd->group_overlays, boss->grp->overlay);
2586      }
2587 }
2588
2589 static void
2590 _overlay_show(Elm_Map_Overlay *overlay)
2591 {
2592    Elm_Map_Smart_Data *sd = overlay->wsd;
2593
2594    if (overlay->paused) return;
2595    if ((overlay->grp) && (overlay->grp->klass) && (overlay->grp->klass->paused))
2596      return;
2597
2598    overlay->visible = EINA_TRUE;
2599    if (overlay->type == ELM_MAP_OVERLAY_TYPE_CLASS)
2600      {
2601         overlay->visible = EINA_FALSE;
2602         return;
2603      }
2604    if (overlay->grp)
2605      {
2606         if ((overlay->grp->in) ||
2607             (overlay->hide) || (overlay->zoom_min > sd->zoom))
2608           overlay->visible = EINA_FALSE;
2609
2610         if ((overlay->grp->klass) &&
2611             ((overlay->grp->klass->hide) ||
2612              (overlay->grp->klass->zoom_min > sd->zoom)))
2613           overlay->visible = EINA_FALSE;
2614      }
2615
2616    switch (overlay->type)
2617      {
2618       case ELM_MAP_OVERLAY_TYPE_DEFAULT:
2619         if (overlay->visible) _overlay_default_show(overlay->ovl);
2620         else _overlay_default_hide(overlay->ovl);
2621         break;
2622
2623       case ELM_MAP_OVERLAY_TYPE_GROUP:
2624         if (overlay->visible) _overlay_group_show(overlay->ovl);
2625         else _overlay_group_hide(overlay->ovl);
2626         break;
2627
2628       case ELM_MAP_OVERLAY_TYPE_BUBBLE:
2629         overlay->visible =
2630           _overlay_bubble_show_hide(overlay->ovl, overlay->visible);
2631         break;
2632
2633       case ELM_MAP_OVERLAY_TYPE_ROUTE:
2634         if (overlay->visible) _overlay_route_show(overlay->ovl);
2635         else _overlay_route_hide(overlay->ovl);
2636         break;
2637
2638       case ELM_MAP_OVERLAY_TYPE_LINE:
2639         if (overlay->visible) _overlay_line_show(overlay->ovl);
2640         else _overlay_line_hide(overlay->ovl);
2641         break;
2642
2643       case ELM_MAP_OVERLAY_TYPE_POLYGON:
2644         if (overlay->visible) _overlay_polygon_show(overlay->ovl);
2645         else _overlay_polygon_hide(overlay->ovl);
2646         break;
2647
2648       case ELM_MAP_OVERLAY_TYPE_CIRCLE:
2649         if (overlay->visible) _overlay_circle_show(overlay->ovl);
2650         else _overlay_circle_hide(overlay->ovl);
2651         break;
2652
2653       case ELM_MAP_OVERLAY_TYPE_SCALE:
2654         if (overlay->visible) _overlay_scale_show(overlay->ovl);
2655         else _overlay_scale_hide(overlay->ovl);
2656         break;
2657
2658       default:
2659         ERR("Invalid overlay type to show: %d", overlay->type);
2660      }
2661 }
2662
2663 static void
2664 _overlay_place(Elm_Map_Smart_Data *sd)
2665 {
2666    Eina_List *l, *ll;
2667    Elm_Map_Overlay *overlay;
2668
2669    eina_list_free(sd->group_overlays);
2670    sd->group_overlays = NULL;
2671
2672    EINA_LIST_FOREACH(sd->overlays, l, overlay)
2673      {
2674         // Reset groups
2675         if (overlay->type == ELM_MAP_OVERLAY_TYPE_CLASS) continue;
2676         overlay->grp->in = EINA_FALSE;
2677         overlay->grp->boss = EINA_FALSE;
2678         _overlay_group_hide(overlay->grp);
2679
2680         // Update overlays' coord
2681         if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
2682           _overlay_default_coord_update(overlay->ovl);
2683         else if (overlay->type == ELM_MAP_OVERLAY_TYPE_BUBBLE)
2684           _overlay_bubble_coord_update(overlay->ovl);
2685      }
2686
2687    // Classify into group boss or follwer
2688    EINA_LIST_FOREACH(sd->overlays, l, overlay)
2689      {
2690         Elm_Map_Overlay *boss;
2691         Overlay_Class *clas;
2692
2693         if (overlay->type != ELM_MAP_OVERLAY_TYPE_CLASS) continue;
2694         if (overlay->hide || (overlay->zoom_min > sd->zoom)) continue;
2695
2696         clas = overlay->ovl;
2697         if (clas->zoom_max < sd->zoom) continue;
2698         EINA_LIST_FOREACH(clas->members, ll, boss)
2699           {
2700              if (boss->type == ELM_MAP_OVERLAY_TYPE_CLASS) continue;
2701              if (boss->hide || (boss->zoom_min > sd->zoom)) continue;
2702              if (boss->grp->in) continue;
2703              _overlay_grouping(clas->members, boss);
2704           }
2705      }
2706
2707    // Place group overlays and overlays
2708    EINA_LIST_FOREACH(sd->group_overlays, l, overlay)
2709      _overlay_show(overlay);
2710    EINA_LIST_FOREACH(sd->overlays, l, overlay)
2711      _overlay_show(overlay);
2712 }
2713
2714 static Evas_Object *
2715 _overlay_obj_get(const Elm_Map_Overlay *overlay)
2716 {
2717    EINA_SAFETY_ON_NULL_RETURN_VAL(overlay, NULL);
2718
2719    if (overlay->type == ELM_MAP_OVERLAY_TYPE_GROUP)
2720      {
2721         Overlay_Group *ovl = overlay->ovl;
2722         Overlay_Default *df = ovl->ovl;
2723
2724         return df->layout;
2725      }
2726    else if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
2727      {
2728         Overlay_Default *ovl = overlay->ovl;
2729
2730         return ovl->layout;
2731      }
2732    else
2733      {
2734         ERR("Not supported overlay type: %d", overlay->type);
2735         return NULL;
2736      }
2737 }
2738
2739 static Eina_Bool
2740 _xml_name_attrs_dump_cb(void *data,
2741                         const char *key,
2742                         const char *value)
2743 {
2744    Name_Dump *dump = (Name_Dump *)data;
2745
2746    EINA_SAFETY_ON_NULL_RETURN_VAL(dump, EINA_FALSE);
2747    EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
2748    EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
2749
2750    if (!strncmp(key, NOMINATIM_ATTR_LON, sizeof(NOMINATIM_ATTR_LON)))
2751      dump->lon = _elm_atof(value);
2752    else if (!strncmp(key, NOMINATIM_ATTR_LAT, sizeof(NOMINATIM_ATTR_LAT)))
2753      dump->lat = _elm_atof(value);
2754    else if (!strncmp(key, NOMINATIM_ATTR_ADDRESS, sizeof(NOMINATIM_ATTR_ADDRESS)))
2755      {
2756         if (!dump->address)
2757           dump->address = strdup(value);
2758      }
2759
2760    return EINA_TRUE;
2761 }
2762
2763 static Eina_Bool
2764 _xml_route_dump_cb(void *data,
2765                    Eina_Simple_XML_Type type,
2766                    const char *value,
2767                    unsigned offset __UNUSED__,
2768                    unsigned length)
2769 {
2770    Route_Dump *dump = data;
2771
2772    EINA_SAFETY_ON_NULL_RETURN_VAL(dump, EINA_FALSE);
2773    EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
2774
2775    switch (type)
2776      {
2777       case EINA_SIMPLE_XML_OPEN:
2778       case EINA_SIMPLE_XML_OPEN_EMPTY:
2779       {
2780          const char *attrs;
2781
2782          attrs = eina_simple_xml_tag_attributes_find(value, length);
2783          if (!attrs)
2784            {
2785               if (!strncmp(value, YOURS_DISTANCE, length))
2786                 dump->id = ROUTE_XML_DISTANCE;
2787               else if (!strncmp(value, YOURS_DESCRIPTION, length))
2788                 dump->id = ROUTE_XML_DESCRIPTION;
2789               else if (!strncmp(value, YOURS_COORDINATES, length))
2790                 dump->id = ROUTE_XML_COORDINATES;
2791               else dump->id = ROUTE_XML_NONE;
2792            }
2793       }
2794       break;
2795
2796       case EINA_SIMPLE_XML_DATA:
2797       {
2798          char *buf = malloc(length);
2799
2800          if (!buf) return EINA_FALSE;
2801
2802          snprintf(buf, length, "%s", value);
2803          if (dump->id == ROUTE_XML_DISTANCE) dump->distance = _elm_atof(buf);
2804          else if (!(dump->description) && (dump->id == ROUTE_XML_DESCRIPTION))
2805            dump->description = strdup(buf);
2806          else if (dump->id == ROUTE_XML_COORDINATES)
2807            dump->coordinates = strdup(buf);
2808
2809          free(buf);
2810       }
2811       break;
2812
2813       default:
2814         break;
2815      }
2816
2817    return EINA_TRUE;
2818 }
2819
2820 static Eina_Bool
2821 _xml_name_dump_cb(void *data,
2822                   Eina_Simple_XML_Type type,
2823                   const char *value,
2824                   unsigned offset __UNUSED__,
2825                   unsigned length)
2826 {
2827    Name_Dump *dump = data;
2828
2829    EINA_SAFETY_ON_NULL_RETURN_VAL(dump, EINA_FALSE);
2830    EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
2831
2832    switch (type)
2833      {
2834       case EINA_SIMPLE_XML_OPEN:
2835       case EINA_SIMPLE_XML_OPEN_EMPTY:
2836       {
2837          const char *attrs;
2838          attrs = eina_simple_xml_tag_attributes_find(value, length);
2839          if (attrs)
2840            {
2841               if (!strncmp(value, NOMINATIM_RESULT,
2842                            sizeof(NOMINATIM_RESULT) - 1))
2843                 dump->id = NAME_XML_NAME;
2844               else dump->id = NAME_XML_NONE;
2845
2846               eina_simple_xml_attributes_parse
2847                 (attrs, length - (attrs - value), _xml_name_attrs_dump_cb,
2848                 dump);
2849            }
2850       }
2851       break;
2852
2853       case EINA_SIMPLE_XML_DATA:
2854       {
2855          char *buf = malloc(length + 1);
2856
2857          if (!buf) return EINA_FALSE;
2858          snprintf(buf, length + 1, "%s", value);
2859          if (dump->id == NAME_XML_NAME) dump->address = strdup(buf);
2860          free(buf);
2861       }
2862       break;
2863
2864       default:
2865         break;
2866      }
2867
2868    return EINA_TRUE;
2869 }
2870
2871 static Eina_Bool
2872 _xml_name_dump_list_cb(void *data,
2873                        Eina_Simple_XML_Type type,
2874                        const char *value,
2875                        unsigned offset,
2876                        unsigned length)
2877 {
2878    Elm_Map_Name_List *name_list = data;
2879    Elm_Map_Name *name;
2880    Name_Dump dump = {0, NULL, 0.0, 0.0};
2881    _xml_name_dump_cb(&dump, type, value, offset, length);
2882    name = calloc(1, sizeof(Elm_Map_Name));
2883    if (!name) return EINA_FALSE;
2884    if (dump.address)
2885      {
2886         name->address = strdup(dump.address);
2887         name->lon = dump.lon;
2888         name->lat = dump.lat;
2889         name->wsd = name_list->wsd;
2890         name_list->names = eina_list_append(name_list->names, name);
2891         name->wsd->names = eina_list_append(name->wsd->names, name);
2892      }
2893   else
2894     free(name);
2895
2896    return EINA_TRUE;
2897 }
2898
2899
2900 static void
2901 _kml_parse(Elm_Map_Route *r)
2902 {
2903    FILE *f;
2904    char **str;
2905    double lon, lat;
2906    unsigned int ele, idx;
2907
2908    EINA_SAFETY_ON_NULL_RETURN(r);
2909    EINA_SAFETY_ON_NULL_RETURN(r->fname);
2910
2911    Route_Dump dump = {0, r->fname, 0.0, NULL, NULL};
2912
2913    f = fopen(r->fname, "rb");
2914    if (f)
2915      {
2916         long sz;
2917
2918         fseek(f, 0, SEEK_END);
2919         sz = ftell(f);
2920         if (sz > 0)
2921           {
2922              char *buf = malloc(sz + 1);
2923              if (buf)
2924                {
2925                   memset(buf, 0, sz + 1);
2926                   rewind(f);
2927                   if (fread(buf, 1, sz, f))
2928                     {
2929                        eina_simple_xml_parse
2930                          (buf, sz, EINA_TRUE, _xml_route_dump_cb, &dump);
2931                     }
2932                   else
2933                     free(buf);
2934                }
2935           }
2936         fclose(f);
2937
2938         if (dump.distance) r->info.distance = dump.distance;
2939         if (dump.description)
2940           {
2941              eina_stringshare_replace(&r->info.waypoints, dump.description);
2942              str = eina_str_split_full(dump.description, "\n", 0, &ele);
2943              r->info.waypoint_count = ele;
2944              for (idx = 0; idx < ele; idx++)
2945                {
2946                   Path_Waypoint *wp = ELM_NEW(Path_Waypoint);
2947
2948                   if (wp)
2949                     {
2950                        wp->wsd = r->wsd;
2951                        wp->point = eina_stringshare_add(str[idx]);
2952                        DBG("%s", str[idx]);
2953                        r->waypoint = eina_list_append(r->waypoint, wp);
2954                     }
2955                }
2956              if (str && str[0])
2957                {
2958                   free(str[0]);
2959                   free(str);
2960                }
2961           }
2962         else WRN("description is not found !");
2963
2964         if (dump.coordinates)
2965           {
2966              eina_stringshare_replace(&r->info.nodes, dump.coordinates);
2967              str = eina_str_split_full(dump.coordinates, "\n", 0, &ele);
2968              r->info.node_count = ele;
2969              for (idx = 0; idx < ele; idx++)
2970                {
2971                   Path_Node *n = ELM_NEW(Path_Node);
2972
2973                   sscanf(str[idx], "%lf,%lf", &lon, &lat);
2974                   if (n)
2975                     {
2976                        n->wsd = r->wsd;
2977                        n->pos.lon = lon;
2978                        n->pos.lat = lat;
2979                        n->idx = idx;
2980                        DBG("%lf:%lf", lon, lat);
2981                        n->pos.address = NULL;
2982                        r->nodes = eina_list_append(r->nodes, n);
2983                     }
2984                }
2985              if (str && str[0])
2986                {
2987                   free(str[0]);
2988                   free(str);
2989                }
2990           }
2991      }
2992 }
2993
2994 static void
2995 _name_parse(Elm_Map_Name *n)
2996 {
2997    FILE *f;
2998
2999    EINA_SAFETY_ON_NULL_RETURN(n);
3000    EINA_SAFETY_ON_NULL_RETURN(n->fname);
3001
3002    Name_Dump dump = {0, NULL, 0.0, 0.0};
3003
3004    f = fopen(n->fname, "rb");
3005    if (f)
3006      {
3007         long sz;
3008
3009         fseek(f, 0, SEEK_END);
3010         sz = ftell(f);
3011         if (sz > 0)
3012           {
3013              char *buf = malloc(sz + 1);
3014              if (buf)
3015                {
3016                   memset(buf, 0, sz + 1);
3017                   rewind(f);
3018                   if (fread(buf, 1, sz, f))
3019                     {
3020                        eina_simple_xml_parse
3021                          (buf, sz, EINA_TRUE, _xml_name_dump_cb, &dump);
3022                     }
3023                   free(buf);
3024                }
3025           }
3026         fclose(f);
3027
3028         if (dump.address)
3029           {
3030              INF("[%lf : %lf] ADDRESS : %s", n->lon, n->lat, dump.address);
3031              n->address = strdup(dump.address);
3032           }
3033         n->lon = dump.lon;
3034         n->lat = dump.lat;
3035      }
3036 }
3037
3038 static void
3039 _name_list_parse(Elm_Map_Name_List *nl)
3040 {
3041    FILE *f;
3042    EINA_SAFETY_ON_NULL_RETURN(nl);
3043    EINA_SAFETY_ON_NULL_RETURN(nl->fname);
3044
3045    f = fopen(nl->fname, "rb");
3046    if (f)
3047      {
3048         long sz;
3049
3050         fseek(f, 0, SEEK_END);
3051         sz = ftell(f);
3052         if (sz > 0)
3053           {
3054              char *buf = malloc(sz + 1);
3055              if (buf)
3056                {
3057                   memset(buf, 0, sz + 1);
3058                   rewind(f);
3059                   if (fread(buf, 1, sz, f))
3060                     {
3061                        eina_simple_xml_parse
3062                          (buf, sz, EINA_TRUE, _xml_name_dump_list_cb, nl);
3063                     }
3064                   else
3065                     free(buf);
3066                }
3067           }
3068         fclose(f);
3069      }
3070 }
3071
3072 static void
3073 _route_cb(void *data,
3074           const char *file,
3075           int status)
3076 {
3077    Elm_Map_Route *route;
3078    Elm_Map_Smart_Data *sd;
3079
3080    EINA_SAFETY_ON_NULL_RETURN(data);
3081    EINA_SAFETY_ON_NULL_RETURN(file);
3082
3083    route = data;
3084    sd = route->wsd;
3085
3086    route->job = NULL;
3087    if (status == 200)
3088      {
3089         _kml_parse(route);
3090         INF("Route request success from (%lf, %lf) to (%lf, %lf)",
3091             route->flon, route->flat, route->tlon, route->tlat);
3092         if (route->cb) route->cb(route->data, ELM_WIDGET_DATA(sd)->obj, route);
3093         evas_object_smart_callback_call
3094           (ELM_WIDGET_DATA(sd)->obj, SIG_ROUTE_LOADED, NULL);
3095      }
3096    else
3097      {
3098         ERR("Route request failed: %d", status);
3099         if (route->cb) route->cb(route->data, ELM_WIDGET_DATA(sd)->obj, NULL);
3100         evas_object_smart_callback_call
3101           (ELM_WIDGET_DATA(sd)->obj, SIG_ROUTE_LOADED_FAIL, NULL);
3102      }
3103
3104    edje_object_signal_emit(ELM_WIDGET_DATA(sd)->resize_obj,
3105                            "elm,state,busy,stop", "elm");
3106 }
3107
3108 static void
3109 _name_cb(void *data,
3110          const char *file,
3111          int status)
3112 {
3113    Elm_Map_Name *name;
3114    Elm_Map_Smart_Data *sd;
3115
3116    EINA_SAFETY_ON_NULL_RETURN(data);
3117    EINA_SAFETY_ON_NULL_RETURN(file);
3118
3119    name = data;
3120    sd = name->wsd;
3121
3122    name->job = NULL;
3123    if (status == 200)
3124      {
3125         _name_parse(name);
3126         INF("Name request success address:%s, lon:%lf, lat:%lf",
3127             name->address, name->lon, name->lat);
3128         if (name->cb) name->cb(name->data, ELM_WIDGET_DATA(sd)->obj, name);
3129         evas_object_smart_callback_call
3130           (ELM_WIDGET_DATA(sd)->obj, SIG_NAME_LOADED, NULL);
3131      }
3132    else
3133      {
3134         ERR("Name request failed: %d", status);
3135         if (name->cb) name->cb(name->data, ELM_WIDGET_DATA(sd)->obj, NULL);
3136         evas_object_smart_callback_call
3137           (ELM_WIDGET_DATA(sd)->obj, SIG_NAME_LOADED_FAIL, NULL);
3138      }
3139    edje_object_signal_emit(ELM_WIDGET_DATA(sd)->resize_obj,
3140                            "elm,state,busy,stop", "elm");
3141 }
3142
3143 static void
3144 _name_list_cb(void *data,
3145               const char *file,
3146               int status)
3147 {
3148    Elm_Map_Name_List *name_list;
3149    Elm_Map_Smart_Data *sd;
3150
3151    EINA_SAFETY_ON_NULL_RETURN(data);
3152    EINA_SAFETY_ON_NULL_RETURN(file);
3153
3154    name_list = data;
3155    sd = name_list->wsd;
3156
3157    name_list->job = NULL;
3158    if (status == 200)
3159      {
3160         _name_list_parse(name_list);
3161         INF("Name List request success address");
3162         if (name_list->cb)
3163           name_list->cb(name_list->data, ELM_WIDGET_DATA(sd)->obj,
3164                         name_list->names);
3165         evas_object_smart_callback_call
3166           (ELM_WIDGET_DATA(sd)->obj, SIG_NAME_LOADED, NULL);
3167      }
3168    else
3169      {
3170         ERR("Name List request failed: %d", status);
3171         if (name_list->cb)
3172           name_list->cb(name_list->data, ELM_WIDGET_DATA(sd)->obj, NULL);
3173         evas_object_smart_callback_call
3174           (ELM_WIDGET_DATA(sd)->obj, SIG_NAME_LOADED_FAIL, NULL);
3175      }
3176    edje_object_signal_emit(ELM_WIDGET_DATA(sd)->resize_obj,
3177                            "elm,state,busy,stop", "elm");
3178    free(name_list->fname);
3179    free(name_list);
3180 }
3181
3182
3183 static char *
3184 _prepare_download()
3185 {
3186    char fname[PATH_MAX];
3187      {
3188         const char *cachedir;
3189
3190 #ifdef ELM_EFREET
3191         snprintf(fname, sizeof(fname), "%s" CACHE_NAME_ROOT,
3192                  efreet_cache_home_get());
3193         (void)cachedir;
3194 #else
3195         cachedir = getenv("XDG_CACHE_HOME");
3196         snprintf(fname, sizeof(fname), "%s/%s" CACHE_NAME_ROOT, getenv("HOME"),
3197                  cachedir ? : "/.config");
3198 #endif
3199         if (!ecore_file_exists(fname)) ecore_file_mkpath(fname);
3200      }
3201    return strdup(fname);
3202 }
3203
3204
3205 static Elm_Map_Name *
3206 _name_request(const Evas_Object *obj,
3207               int method,
3208               const char *address,
3209               double lon,
3210               double lat,
3211               Elm_Map_Name_Cb name_cb,
3212               void *data)
3213 {
3214    char *url;
3215    Elm_Map_Name *name;
3216    char *fname, fname2[PATH_MAX];
3217
3218    ELM_MAP_DATA_GET(obj, sd);
3219    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->src_name, NULL);
3220
3221    fname = _prepare_download();
3222    url = sd->src_name->url_cb
3223    (ELM_WIDGET_DATA(sd)->obj, method, address, lon, lat);
3224    if (!url)
3225      {
3226         ERR("Name URL is NULL");
3227         free(fname);
3228         return NULL;
3229      }
3230
3231    name = ELM_NEW(Elm_Map_Name);
3232    name->wsd = sd;
3233    snprintf(fname2, sizeof(fname2), "%s/%d", fname, rand());
3234    name->fname = strdup(fname2);
3235    name->method = method;
3236    if (method == ELM_MAP_NAME_METHOD_SEARCH) name->address = strdup(address);
3237    else if (method == ELM_MAP_NAME_METHOD_REVERSE)
3238      {
3239         name->lon = lon;
3240         name->lat = lat;
3241      }
3242    name->cb = name_cb;
3243    name->data = data;
3244
3245    if (!ecore_file_download_full(url, name->fname, _name_cb, NULL, name,
3246                                  &(name->job), sd->ua) || !(name->job))
3247      {
3248         ERR("Can't request Name from %s to %s", url, name->fname);
3249         if (name->address) free(name->address);
3250         free(name->fname);
3251         free(name);
3252         free(fname);
3253         return NULL;
3254      }
3255    INF("Name requested from %s to %s", url, name->fname);
3256    free(url);
3257    free(fname);
3258
3259    sd->names = eina_list_append(sd->names, name);
3260    evas_object_smart_callback_call
3261      (ELM_WIDGET_DATA(sd)->obj, SIG_NAME_LOAD, name);
3262    edje_object_signal_emit(ELM_WIDGET_DATA(sd)->resize_obj,
3263                            "elm,state,busy,start", "elm");
3264    return name;
3265 }
3266
3267
3268 static Eina_List *
3269 _name_list_request(const Evas_Object *obj,
3270               int method,
3271               const char *address,
3272               double lon,
3273               double lat,
3274               Elm_Map_Name_List_Cb name_cb,
3275               void *data)
3276 {
3277    char *url;
3278    Elm_Map_Name_List *name_list;
3279    char *fname, fname2[PATH_MAX];
3280
3281    ELM_MAP_DATA_GET(obj, sd);
3282    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->src_name, NULL);
3283
3284    fname = _prepare_download();
3285    url = sd->src_name->url_cb
3286    (ELM_WIDGET_DATA(sd)->obj, method, address, lon, lat);
3287    if (!url)
3288      {
3289         ERR("Name URL is NULL");
3290         free(fname);
3291         return NULL;
3292      }
3293    name_list = ELM_NEW(Elm_Map_Name_List);
3294    name_list->wsd = sd;
3295    snprintf(fname2, sizeof(fname2), "%s/%d", fname, rand());
3296    name_list->fname = strdup(fname2);
3297    name_list->cb = name_cb;
3298    name_list->data = data;
3299    if (!ecore_file_download_full(url, name_list->fname, _name_list_cb,
3300                                  NULL, name_list,
3301                                  &(name_list->job), sd->ua) || !(name_list->job))
3302      {
3303         ERR("Can't request Name from %s to %s", url, name_list->fname);
3304         free(name_list->fname);
3305         free(name_list);
3306         free(fname);
3307         return NULL;
3308      }
3309    INF("Name requested from %s to %s", url, name_list->fname);
3310    free(url);
3311    free(fname);
3312
3313    evas_object_smart_callback_call
3314      (ELM_WIDGET_DATA(sd)->obj, SIG_NAME_LOAD, name_list->names);
3315    edje_object_signal_emit(ELM_WIDGET_DATA(sd)->resize_obj,
3316                            "elm,state,busy,start", "elm");
3317    return name_list->names;
3318 }
3319
3320
3321 static Evas_Event_Flags
3322 _pinch_zoom_start_cb(void *data,
3323                      void *event_info __UNUSED__)
3324 {
3325    Elm_Map_Smart_Data *sd = data;
3326
3327    EINA_SAFETY_ON_NULL_RETURN_VAL(data, EVAS_EVENT_FLAG_NONE);
3328
3329    sd->pinch_zoom = sd->zoom_detail;
3330
3331    return EVAS_EVENT_FLAG_NONE;
3332 }
3333
3334 static Evas_Event_Flags
3335 _pinch_zoom_cb(void *data,
3336                void *event_info)
3337 {
3338    Elm_Map_Smart_Data *sd = data;
3339
3340    EINA_SAFETY_ON_NULL_RETURN_VAL(sd, EVAS_EVENT_FLAG_NONE);
3341
3342    if (!sd->paused)
3343      {
3344         Elm_Gesture_Zoom_Info *ei = event_info;
3345
3346         _zoom(sd, sd->pinch_zoom + ei->zoom - 1, 0);
3347      }
3348
3349    return EVAS_EVENT_FLAG_NONE;
3350 }
3351
3352 static Evas_Event_Flags
3353 _pinch_rotate_cb(void *data,
3354                  void *event_info)
3355 {
3356    Elm_Map_Smart_Data *sd = data;
3357
3358    EINA_SAFETY_ON_NULL_RETURN_VAL(sd, EVAS_EVENT_FLAG_NONE);
3359
3360    if (!sd->paused)
3361      {
3362         int x, y, w, h;
3363         int angle;
3364         Elm_Gesture_Rotate_Info *ei = event_info;
3365         evas_object_geometry_get(ELM_WIDGET_DATA(sd)->obj, &x, &y, &w, &h);
3366         sd->pinch_rotate.d = sd->pinch_rotate.a + ei->angle - ei->base_angle;
3367         angle = (int)(sd->pinch_rotate.d);
3368         x = x + ((double)w * 0.5);
3369         y = y + ((double)h * 0.5);
3370         sd->engine->rotate(ELM_WIDGET_DATA(sd)->obj, angle, x, y, 0);
3371         _overlay_place(sd);
3372      }
3373
3374    return EVAS_EVENT_FLAG_NONE;
3375 }
3376
3377 static Evas_Event_Flags
3378 _pinch_rotate_end_cb(void *data,
3379                      void *event_info __UNUSED__)
3380 {
3381    Elm_Map_Smart_Data *sd = data;
3382
3383    EINA_SAFETY_ON_NULL_RETURN_VAL(sd, EVAS_EVENT_FLAG_NONE);
3384
3385    sd->pinch_rotate.a = sd->pinch_rotate.d;
3386
3387    return EVAS_EVENT_FLAG_NONE;
3388 }
3389
3390 static Evas_Event_Flags
3391 _pinch_momentum_start_cb(void *data,
3392                          void *ei)
3393 {
3394    Elm_Map_Smart_Data *sd = data;
3395    EINA_SAFETY_ON_NULL_RETURN_VAL(sd, EVAS_EVENT_FLAG_NONE);
3396    Elm_Gesture_Momentum_Info *mi = ei;
3397
3398    if (strcmp(sd->engine->name, INTERNAL_ENGINE_NAME) &&
3399        (mi->n == 1))
3400      {
3401         sd->pinch_pan.st = mi->tx;
3402         sd->pinch_pan.x = mi->x1;
3403         sd->pinch_pan.y = mi->y1;
3404         _overlay_place(sd);
3405      }
3406    // FIXME: Because n line move has some bouncing bug,
3407    // perpect is calculated here
3408    if (sd->pinch_pan.perspect >= 90)
3409      sd->pinch_pan.perspect = 90;
3410    else if (sd->pinch_pan.perspect <= 0)
3411      sd->pinch_pan.perspect = 0;
3412    sd->pinch_pan.perspect_y = mi->y1;
3413
3414    return EVAS_EVENT_FLAG_NONE;
3415 }
3416
3417 static Evas_Event_Flags
3418 _pinch_momentum_move_cb(void *data,
3419                         void *ei)
3420 {
3421    Elm_Map_Smart_Data *sd = data;
3422    EINA_SAFETY_ON_NULL_RETURN_VAL(sd, EVAS_EVENT_FLAG_NONE);
3423    Elm_Gesture_Momentum_Info *mi = ei;
3424
3425    if (strcmp(sd->engine->name, INTERNAL_ENGINE_NAME) &&
3426        (mi->n == 1))
3427      {
3428         sd->engine->pan(ELM_WIDGET_DATA(sd)->obj, sd->pinch_pan.x,
3429                         sd->pinch_pan.y, mi->x2, mi->y2);
3430         sd->pinch_pan.x = mi->x2;
3431         sd->pinch_pan.y = mi->y2;
3432         _overlay_place(sd);
3433      }
3434    // FIXME: Because n line move has some bouncing bug,
3435    // perpect is calculated here
3436    sd->pinch_pan.perspect += (mi->y2 - sd->pinch_pan.perspect_y);
3437    sd->pinch_pan.perspect_y = mi->y2;
3438
3439    return EVAS_EVENT_FLAG_NONE;
3440 }
3441
3442 static Evas_Event_Flags
3443 _pinch_momentum_end_cb(void *data,
3444                         void *ei)
3445 {
3446    Elm_Map_Smart_Data *sd = data;
3447    EINA_SAFETY_ON_NULL_RETURN_VAL(sd, EVAS_EVENT_FLAG_NONE);
3448    Elm_Gesture_Momentum_Info *mi = ei;
3449
3450    if (strcmp(sd->engine->name, INTERNAL_ENGINE_NAME) &&
3451        (mi->n == 1))
3452      {
3453         sd->engine->pan(ELM_WIDGET_DATA(sd)->obj, sd->pinch_pan.x,
3454                         sd->pinch_pan.y,
3455                         sd->pinch_pan.x + (mi->mx)/25,
3456                         sd->pinch_pan.y + (mi->my)/25);
3457         _overlay_place(sd);
3458      }
3459
3460    return EVAS_EVENT_FLAG_NONE;
3461 }
3462
3463 static Evas_Event_Flags
3464 _pinch_n_lines_move_cb(void *data,
3465                        void *ei)
3466 {
3467    Elm_Map_Smart_Data *sd = data;
3468    EINA_SAFETY_ON_NULL_RETURN_VAL(sd, EVAS_EVENT_FLAG_NONE);
3469    Elm_Gesture_Line_Info *li = ei;
3470
3471    if (strcmp(sd->engine->name, INTERNAL_ENGINE_NAME) &&
3472        (li->momentum.n == 2) &&
3473        (((170 <= li->angle) && (li->angle <=190)) ||
3474         (350 <= li->angle) || (li->angle <=10)))
3475      {
3476         sd->engine->perpective(ELM_WIDGET_DATA(sd)->obj, sd->pinch_pan.perspect, 0);
3477      }
3478
3479    return EVAS_EVENT_FLAG_NONE;
3480 }
3481
3482 static Evas_Event_Flags
3483 _pinch_n_lines_end_cb(void *data,
3484                       void *ei)
3485 {
3486    Elm_Map_Smart_Data *sd = data;
3487    EINA_SAFETY_ON_NULL_RETURN_VAL(sd, EVAS_EVENT_FLAG_NONE);
3488    Elm_Gesture_Line_Info *li = ei;
3489
3490    if (strcmp(sd->engine->name, INTERNAL_ENGINE_NAME) &&
3491        (li->momentum.n == 2) &&
3492        (((170 <= li->angle) && (li->angle <=190)) ||
3493         (350 <= li->angle) || (li->angle <=10)))
3494      {
3495         sd->engine->perpective(ELM_WIDGET_DATA(sd)->obj, sd->pinch_pan.perspect, 0);
3496      }
3497
3498    return EVAS_EVENT_FLAG_NONE;
3499 }
3500 static void
3501 _elm_map_pan_smart_pos_set(Evas_Object *obj,
3502                            Evas_Coord x,
3503                            Evas_Coord y)
3504 {
3505    ELM_MAP_PAN_DATA_GET(obj, psd);
3506
3507    if ((x == psd->wsd->pan_x) && (y == psd->wsd->pan_y)) return;
3508
3509    psd->wsd->pan_x = x;
3510    psd->wsd->pan_y = y;
3511
3512    evas_object_smart_changed(obj);
3513 }
3514
3515 static void
3516 _elm_map_pan_smart_pos_get(const Evas_Object *obj,
3517                            Evas_Coord *x,
3518                            Evas_Coord *y)
3519 {
3520    ELM_MAP_PAN_DATA_GET(obj, psd);
3521
3522    if (x) *x = psd->wsd->pan_x;
3523    if (y) *y = psd->wsd->pan_y;
3524 }
3525
3526 static void
3527 _elm_map_pan_smart_pos_max_get(const Evas_Object *obj,
3528                                Evas_Coord *x,
3529                                Evas_Coord *y)
3530 {
3531    Evas_Coord ow, oh;
3532
3533    ELM_MAP_PAN_DATA_GET(obj, psd);
3534
3535    evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3536    ow = psd->wsd->size.w - ow;
3537    oh = psd->wsd->size.h - oh;
3538
3539    if (ow < 0) ow = 0;
3540    if (oh < 0) oh = 0;
3541    if (x) *x = ow;
3542    if (y) *y = oh;
3543 }
3544
3545 static void
3546 _elm_map_pan_smart_pos_min_get(const Evas_Object *obj __UNUSED__,
3547                                Evas_Coord *x,
3548                                Evas_Coord *y)
3549 {
3550    if (x) *x = 0;
3551    if (y) *y = 0;
3552 }
3553
3554 static void
3555 _elm_map_pan_smart_content_size_get(const Evas_Object *obj,
3556                                     Evas_Coord *w,
3557                                     Evas_Coord *h)
3558 {
3559    ELM_MAP_PAN_DATA_GET(obj, psd);
3560
3561    if (w) *w = psd->wsd->size.w;
3562    if (h) *h = psd->wsd->size.h;
3563 }
3564
3565 static void
3566 _elm_map_pan_smart_add(Evas_Object *obj)
3567 {
3568    /* here just to allocate our extended data */
3569    EVAS_SMART_DATA_ALLOC(obj, Elm_Map_Pan_Smart_Data);
3570
3571    ELM_PAN_CLASS(_elm_map_pan_parent_sc)->base.add(obj);
3572 }
3573
3574 static void
3575 _elm_map_pan_smart_resize(Evas_Object *obj,
3576                           Evas_Coord w __UNUSED__,
3577                           Evas_Coord h __UNUSED__)
3578 {
3579    ELM_MAP_PAN_DATA_GET(obj, psd);
3580
3581    _sizing_eval(psd->wsd);
3582    if (!psd->wsd->calc_job.zoom_changed)
3583      {
3584         psd->wsd->calc_job.zoom_changed = EINA_TRUE;
3585         psd->wsd->calc_job.zoom_anim = EINA_FALSE;
3586         psd->wsd->calc_job.zoom = psd->wsd->zoom;
3587      }
3588    evas_object_smart_changed(obj);
3589 }
3590
3591 static Evas_Object *
3592 _map_pan_add(Evas_Object *obj)
3593 {
3594    Evas_Coord minw, minh;
3595    ELM_MAP_DATA_GET(obj, sd);
3596
3597    if (!sd->s_iface)
3598      {
3599         sd->layout = edje_object_add(evas_object_evas_get(obj));
3600         elm_widget_theme_object_set
3601            (obj, sd->layout , "map", "base", elm_widget_style_get(obj));
3602
3603         /* common scroller hit rectangle setup */
3604         sd->hit_rect = evas_object_rectangle_add(evas_object_evas_get(obj));
3605         evas_object_smart_member_add(sd->hit_rect, obj);
3606         elm_widget_sub_object_add(obj, sd->hit_rect);
3607         evas_object_color_set(sd->hit_rect, 0, 0, 0, 0);
3608         evas_object_show(sd->hit_rect);
3609         evas_object_repeat_events_set(sd->hit_rect, EINA_TRUE);
3610
3611         /* interface's add() routine issued AFTER the object's smart_add() */
3612         sd->s_iface = evas_object_smart_interface_get
3613            (obj, ELM_SCROLLABLE_IFACE_NAME);
3614
3615         sd->s_iface->objects_set(obj, sd->layout, sd->hit_rect);
3616         edje_object_size_min_calc(sd->layout, &minw, &minh);
3617         evas_object_size_hint_min_set(obj, minw, minh);
3618         sd->s_iface->wheel_disabled_set(obj, EINA_TRUE);
3619         sd->s_iface->bounce_allow_set
3620            (obj, _elm_config->thumbscroll_bounce_enable,
3621             _elm_config->thumbscroll_bounce_enable);
3622         sd->s_iface->extern_pan_set(obj, sd->pan_obj);
3623
3624      }
3625
3626    evas_object_show(sd->layout);
3627    sd->s_iface->animate_start_cb_set(obj, _scroll_animate_start_cb);
3628    sd->s_iface->animate_stop_cb_set(obj, _scroll_animate_stop_cb);
3629    sd->s_iface->scroll_cb_set(obj, _scroll_cb);
3630
3631    sd->sep_maps_overlays =
3632       evas_object_rectangle_add(evas_object_evas_get(obj));
3633    elm_widget_sub_object_add(obj, sd->sep_maps_overlays);
3634    evas_object_smart_member_add(sd->sep_maps_overlays, sd->pan_obj);
3635
3636    sd->map = evas_map_new(EVAS_MAP_POINT);
3637
3638    srand(time(NULL));
3639    sd->id = ((int)getpid() << 16) | id_num;
3640    id_num++;
3641    _grid_all_create(sd);
3642
3643    // FIXME: Tile Provider is better to provide default tile size!
3644    sd->tsize = DEFAULT_TILE_SIZE;
3645    sd->size.w = sd->tsize;
3646    sd->size.h = sd->tsize;
3647    sd->size.tile = sd->tsize;
3648
3649    if (!ecore_file_download_protocol_available("http://"))
3650      ERR("Ecore must be built with curl support for the map widget!");
3651    return sd->layout;
3652 }
3653
3654 static void
3655 _map_pan_del(Evas_Object *obj)
3656 {
3657    Elm_Map_Route *r;
3658    Elm_Map_Name *na;
3659    Eina_List *l, *ll;
3660    Evas_Object *track;
3661    Elm_Map_Overlay *overlay;
3662    ELM_MAP_DATA_GET(obj, sd);
3663
3664    EINA_LIST_FOREACH_SAFE(sd->routes, l, ll, r)
3665      elm_map_route_del(r);
3666    eina_list_free(sd->routes);
3667    sd->routes = NULL;
3668
3669    EINA_LIST_FOREACH_SAFE(sd->names, l, ll, na)
3670      elm_map_name_del(na);
3671    eina_list_free(sd->names);
3672    sd->names = NULL;
3673
3674    EINA_LIST_FOREACH_SAFE(sd->overlays, l, ll, overlay)
3675      elm_map_overlay_del(overlay);
3676    eina_list_free(sd->overlays);
3677    sd->overlays = NULL;
3678
3679    eina_list_free(sd->group_overlays);
3680    sd->group_overlays = NULL;
3681    eina_list_free(sd->all_overlays);
3682    sd->all_overlays = NULL;
3683
3684    EINA_LIST_FREE (sd->track, track)
3685      evas_object_del(track);
3686    sd->track = NULL;
3687
3688    if (sd->scr_timer)
3689      {
3690         ecore_timer_del(sd->scr_timer);
3691         sd->scr_timer = NULL;
3692      }
3693    if (sd->zoom_animator)
3694      {
3695         ecore_animator_del(sd->zoom_animator);
3696         sd->zoom_animator = NULL;
3697      }
3698    _grid_all_clear(sd);
3699    if (sd->download_idler) 
3700     {   ecore_idler_del(sd->download_idler);
3701         sd->download_idler = NULL;
3702     }
3703    if (sd->download_list) eina_list_free(sd->download_list);
3704
3705    {
3706       char buf[4096];
3707       const char *cachedir;
3708
3709 #ifdef ELM_EFREET
3710       snprintf(buf, sizeof(buf), "%s" CACHE_ROOT, efreet_cache_home_get());
3711       (void)cachedir;
3712 #else
3713       cachedir = getenv("XDG_CACHE_HOME");
3714       snprintf(buf, sizeof(buf), "%s/%s" CACHE_ROOT, getenv("HOME"),
3715                cachedir ? : "/.config");
3716 #endif
3717       if (!ecore_file_recursive_rm(buf))
3718         ERR("Deletion of %s failed", buf);
3719    }
3720    if (sd->map)
3721      {
3722         evas_map_free(sd->map);
3723         sd->map = NULL;
3724      }
3725
3726    evas_object_smart_member_del(sd->sep_maps_overlays);
3727    elm_widget_sub_object_del(obj, sd->sep_maps_overlays);
3728    evas_object_del(sd->sep_maps_overlays);
3729    sd->sep_maps_overlays = NULL;
3730
3731    sd->s_iface->scroll_cb_set(obj, NULL);
3732    sd->s_iface->animate_stop_cb_set(obj, NULL);
3733    sd->s_iface->animate_start_cb_set(obj, NULL);
3734 }
3735
3736 static void
3737 _map_pan_show(Evas_Object *obj, double lon, double lat, int animation)
3738 {
3739    int x, y, w, h;
3740    ELM_MAP_DATA_GET(obj, sd);
3741
3742    _region_to_coord_convert
3743      (sd, lon, lat, sd->size.w, &x, &y);
3744    _viewport_coord_get(sd, NULL, NULL, &w, &h);
3745    x = x - (w / 2);
3746    y = y - (h / 2);
3747
3748    if (animation)
3749       sd->s_iface->region_bring_in(ELM_WIDGET_DATA(sd)->obj, x, y, w, h);
3750    else
3751       sd->s_iface->content_region_show(ELM_WIDGET_DATA(sd)->obj, x, y, w, h);
3752 }
3753
3754 static void
3755 _map_pan_zoom_do(Elm_Map_Smart_Data *sd,
3756          double zoom)
3757 {
3758    Evas_Coord vx, vy, vw, vh;
3759    Evas_Coord ow, oh;
3760
3761    if (zoom > sd->src_tile->zoom_max) zoom = sd->src_tile->zoom_max;
3762    else if (zoom < sd->src_tile->zoom_min)
3763      zoom = sd->src_tile->zoom_min;
3764
3765    ow = sd->size.w;
3766    oh = sd->size.h;
3767    sd->size.tile = pow(2.0, (zoom - sd->zoom)) * sd->tsize;
3768    sd->size.w = pow(2.0, sd->zoom) * sd->size.tile;
3769    sd->size.h = sd->size.w;
3770
3771    // Fix to zooming with (viewport center vx, vy) as the center to prevent
3772    // from zooming with (0,0) as the cetner. (scroller default behavior)
3773    _viewport_coord_get(sd, &vx, &vy, &vw, &vh);
3774    if ((vw > 0) && (vh > 0) && (ow > 0) && (oh > 0))
3775      {
3776         Evas_Coord x, y;
3777         double sx, sy;
3778
3779         if (vw > ow) sx = 0.5;
3780         else sx = (double)(vx + (double)(vw / 2)) / ow;
3781         if (vh > oh) sy = 0.5;
3782         else sy = (double)(vy + (double)(vh / 2)) / oh;
3783
3784         if (sx > 1.0) sx = 1.0;
3785         if (sy > 1.0) sy = 1.0;
3786
3787         x = ceil((sx * sd->size.w) - (vw / 2));
3788         y = ceil((sy * sd->size.h) - (vh / 2));
3789         if (x < 0) x = 0;
3790         else if (x > (sd->size.w - vw))
3791           x = sd->size.w - vw;
3792         if (y < 0) y = 0;
3793         else if (y > (sd->size.h - vh))
3794           y = sd->size.h - vh;
3795         sd->s_iface->content_region_show
3796           (ELM_WIDGET_DATA(sd)->obj, x, y, vw, vh);
3797      }
3798
3799    evas_object_smart_callback_call(sd->pan_obj, "changed", NULL);
3800    evas_object_smart_changed(sd->pan_obj);
3801 }
3802
3803 static Eina_Bool
3804 _zoom_anim_cb(void *data)
3805 {
3806    Elm_Map_Smart_Data *sd = data;
3807
3808    if (sd->ani.cnt <= 0)
3809      {
3810         sd->zoom_animator = NULL;
3811         evas_object_smart_changed(sd->pan_obj);
3812
3813         return ECORE_CALLBACK_CANCEL;
3814      }
3815    else
3816      {
3817         sd->ani.zoom += sd->ani.diff;
3818         sd->ani.cnt--;
3819         sd->zoom_detail = sd->ani.zoom;
3820         sd->zoom = ROUND(sd->zoom_detail);
3821         _map_pan_zoom_do(sd, sd->ani.zoom);
3822
3823         return ECORE_CALLBACK_RENEW;
3824      }
3825 }
3826
3827 static void
3828 _map_pan_zoom(Evas_Object *obj, double zoom, int animation)
3829 {
3830    ELM_MAP_DATA_GET(obj, sd);
3831
3832    if (sd->mode == ELM_MAP_ZOOM_MODE_MANUAL)
3833      {
3834         if (animation)
3835           {
3836              sd->ani.cnt = 10;
3837              sd->ani.zoom = sd->zoom;
3838              sd->ani.diff = (double)(zoom - sd->zoom) / 10;
3839              if (sd->zoom_animator) ecore_animator_del(sd->zoom_animator);
3840              sd->zoom_animator = ecore_animator_add(_zoom_anim_cb, sd);
3841           }
3842         else
3843           {
3844              sd->zoom_detail = zoom;
3845              sd->zoom = ROUND(sd->zoom_detail);
3846              _map_pan_zoom_do(sd, zoom);
3847           }
3848      }
3849    else
3850      {
3851         double diff;
3852         Evas_Coord w, h;
3853         Evas_Coord vw, vh;
3854
3855         w = sd->size.w;
3856         h = sd->size.h;
3857         _viewport_coord_get(sd, NULL, NULL, &vw, &vh);
3858
3859         if (sd->mode == ELM_MAP_ZOOM_MODE_AUTO_FIT)
3860           {
3861              if ((w < vw) && (h < vh))
3862                {
3863                   diff = 0.001;
3864                   while ((w < vw) && (h < vh))
3865                     {
3866                        zoom += diff;
3867                        w = pow(2.0, zoom) * sd->tsize;
3868                        h = pow(2.0, zoom) * sd->tsize;
3869                     }
3870                }
3871              else
3872                {
3873                   diff = -0.001;
3874                   while ((w > vw) || (h > vh))
3875                     {
3876                        zoom += diff;
3877                        w = pow(2.0, zoom) * sd->tsize;
3878                        h = pow(2.0, zoom) * sd->tsize;
3879                     }
3880                }
3881           }
3882         else if (sd->mode == ELM_MAP_ZOOM_MODE_AUTO_FILL)
3883           {
3884              if ((w < vw) || (h < vh))
3885                {
3886                   diff = 0.01;
3887                   while ((w < vw) || (h < vh))
3888                     {
3889                        zoom += diff;
3890                        w = pow(2.0, zoom) * sd->tsize;
3891                        h = pow(2.0, zoom) * sd->tsize;
3892                     }
3893                }
3894              else
3895                {
3896                   diff = -0.01;
3897                   while ((w > vw) && (h > vh))
3898                     {
3899                        zoom += diff;
3900                        w = pow(2.0, zoom) * sd->tsize;
3901                        h = pow(2.0, zoom) * sd->tsize;
3902                     }
3903                }
3904           }
3905         sd->zoom_detail = zoom;
3906         sd->zoom = ROUND(sd->zoom_detail);
3907         _map_pan_zoom_do(sd, zoom);
3908      }
3909 }
3910
3911 static void
3912 _map_pan_rotate(Evas_Object *obj, double angle, int x, int y, int animation __UNUSED__)
3913 {
3914    ELM_MAP_DATA_GET(obj, sd);
3915    sd->pan_rotate.d = angle;
3916    sd->pan_rotate.cx = x;
3917    sd->pan_rotate.cy = y;
3918    evas_object_smart_changed(sd->pan_obj);
3919 }
3920
3921 static void
3922 _map_pan_rotate_get(const Evas_Object *obj, double *angle, int *x, int *y)
3923 {
3924    ELM_MAP_DATA_GET(obj, sd);
3925    if (angle) *angle = sd->pan_rotate.d;
3926    if (x) *x = sd->pan_rotate.cx;
3927    if (y) *y = sd->pan_rotate.cy;
3928 }
3929
3930 static void
3931 _map_pan_perspective_set(Evas_Object *obj __UNUSED__, double perpective __UNUSED__, int animate __UNUSED__)
3932 {
3933    WRN("Not implemented function");
3934 }
3935
3936 static void
3937 _map_pan_region_get(const Evas_Object *obj, double *lon, double *lat)
3938 {
3939    double tlon, tlat;
3940    Evas_Coord vx, vy, vw, vh;
3941    ELM_MAP_DATA_GET(obj, sd);
3942
3943    _viewport_coord_get(sd, &vx, &vy, &vw, &vh);
3944    _coord_to_region_convert
3945      (sd, vx + vw / 2, vy + vh / 2, sd->size.w, &tlon, &tlat);
3946    if (lon) *lon = tlon;
3947    if (lat) *lat = tlat;
3948 }
3949
3950 static void
3951 _map_pan_canvas_to_region(const Evas_Object *obj, int x, int y, double *lon, double *lat)
3952 {
3953    ELM_MAP_DATA_GET(obj, sd);
3954    _canvas_to_coord(sd, x, y, &x, &y);
3955    _coord_to_region_convert(sd, x, y, sd->size.w, lon, lat);
3956 }
3957
3958 static void
3959 _map_pan_region_to_canvas(const Evas_Object *obj, double lon, double lat, int *x, int *y)
3960 {
3961    ELM_MAP_DATA_GET(obj, sd);
3962    _region_to_coord_convert(sd, lon, lat, sd->size.w, x, y);
3963    _coord_to_canvas(sd, *x, *y, x, y);
3964 }
3965
3966 static void
3967 _move_unimplemented(Evas_Object *obj __UNUSED__, int x __UNUSED__, int y __UNUSED__)
3968 {
3969    WRN("move is not implemented");
3970 }
3971
3972 static void
3973 _resize_unimplemented(Evas_Object *obj __UNUSED__, int w __UNUSED__, int y __UNUSED__)
3974 {
3975    WRN("resize is not implemented");
3976 }
3977
3978 static void
3979 _key_set_unimplemented(Evas_Object *obj __UNUSED__, const char *key __UNUSED__)
3980 {
3981    WRN("key set is not implemented");
3982 }
3983
3984 static void
3985 _pan_unimplemented(Evas_Object *obj __UNUSED__, int x_1 __UNUSED__, int y_1 __UNUSED__, int x_2 __UNUSED__, int y_2 __UNUSED__)
3986 {
3987    WRN("pan is not implemented");
3988 }
3989
3990 static void
3991 _canvas_to_region_unimplemented(const Evas_Object *obj __UNUSED__, int x __UNUSED__, int y __UNUSED__, double *lon __UNUSED__, double *lat __UNUSED__)
3992 {
3993    WRN("canvas to region is not implemented");
3994 }
3995
3996 static void
3997 _region_to_canvas_unimplemented(const Evas_Object *obj __UNUSED__, double lon __UNUSED__, double lat __UNUSED__, int *x __UNUSED__, int *y __UNUSED__)
3998 {
3999    WRN("region to canvas is not implemented");
4000 }
4001
4002 static void
4003 _map_pan_overlays_show(Elm_Map_Smart_Data *sd, Eina_List *overlays)
4004 {
4005    double max_lon, min_lon, max_lat, min_lat, lon, lat;
4006    int zoom, zoom_max;
4007    Evas_Coord vw, vh;
4008
4009    EINA_SAFETY_ON_NULL_RETURN(sd);
4010    EINA_SAFETY_ON_NULL_RETURN(overlays);
4011
4012    _region_max_min_get(overlays, &max_lon, &min_lon, &max_lat, &min_lat);
4013    lon = (max_lon + min_lon) / 2;
4014    lat = (max_lat + min_lat) / 2;
4015
4016    zoom = sd->src_tile->zoom_min;
4017    _viewport_coord_get(sd, NULL, NULL, &vw, &vh);
4018    if (sd->src_tile->zoom_max < sd->zoom_max)
4019      zoom_max = sd->src_tile->zoom_max;
4020    else zoom_max = sd->zoom_max;
4021    while (zoom <= zoom_max)
4022      {
4023         Evas_Coord size, max_x, max_y, min_x, min_y;
4024
4025         size = pow(2.0, zoom) * sd->tsize;
4026         _region_to_coord_convert
4027           (sd, min_lon, max_lat, size, &min_x, &max_y);
4028         _region_to_coord_convert
4029           (sd, max_lon, min_lat, size, &max_x, &min_y);
4030         if ((max_x - min_x) > vw || (max_y - min_y) > vh) break;
4031         zoom++;
4032      }
4033    zoom--;
4034
4035    sd->engine->zoom(ELM_WIDGET_DATA(sd)->obj, zoom, 0);
4036    sd->engine->show(ELM_WIDGET_DATA(sd)->obj, lon, lat, EINA_FALSE);
4037 }
4038
4039 static void
4040 _calc_job(Elm_Map_Smart_Data *sd)
4041 {
4042    if (sd->calc_job.zoom_changed)
4043      {
4044         _map_pan_zoom(ELM_WIDGET_DATA(sd)->obj, sd->calc_job.zoom, sd->calc_job.zoom_anim);
4045         sd->calc_job.zoom_changed = EINA_FALSE;
4046      }
4047    if (!sd->zoom_animator && sd->calc_job.show_changed)
4048      {
4049         _map_pan_show(ELM_WIDGET_DATA(sd)->obj, sd->calc_job.lon, sd->calc_job.lat,
4050                       sd->calc_job.show_anim);
4051         sd->calc_job.show_changed = EINA_FALSE;
4052      }
4053    if (!sd->zoom_animator && sd->calc_job.overlays_changed)
4054      {
4055         _map_pan_overlays_show(sd, sd->calc_job.overlays);
4056         sd->calc_job.overlays_changed = EINA_FALSE;
4057      }
4058 }
4059
4060 static void
4061 _elm_map_pan_smart_calculate(Evas_Object *obj)
4062 {
4063    Evas_Coord w, h;
4064
4065    ELM_MAP_PAN_DATA_GET(obj, psd);
4066
4067    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
4068    if (w <= 0 || h <= 0) return;
4069
4070    _grid_place(psd->wsd);
4071    _overlay_place(psd->wsd);
4072    _track_place(psd->wsd);
4073    _calc_job(psd->wsd);
4074 }
4075
4076 static void
4077 _elm_map_pan_smart_move(Evas_Object *obj,
4078                         Evas_Coord x __UNUSED__,
4079                         Evas_Coord y __UNUSED__)
4080 {
4081    EINA_SAFETY_ON_NULL_RETURN(obj);
4082
4083    evas_object_smart_changed(obj);
4084 }
4085
4086 static void
4087 _elm_map_pan_smart_set_user(Elm_Map_Pan_Smart_Class *sc)
4088 {
4089    ELM_PAN_CLASS(sc)->base.add = _elm_map_pan_smart_add;
4090    ELM_PAN_CLASS(sc)->base.move = _elm_map_pan_smart_move;
4091    ELM_PAN_CLASS(sc)->base.resize = _elm_map_pan_smart_resize;
4092    ELM_PAN_CLASS(sc)->base.calculate = _elm_map_pan_smart_calculate;
4093
4094    ELM_PAN_CLASS(sc)->pos_set = _elm_map_pan_smart_pos_set;
4095    ELM_PAN_CLASS(sc)->pos_get = _elm_map_pan_smart_pos_get;
4096    ELM_PAN_CLASS(sc)->pos_max_get = _elm_map_pan_smart_pos_max_get;
4097    ELM_PAN_CLASS(sc)->pos_min_get = _elm_map_pan_smart_pos_min_get;
4098    ELM_PAN_CLASS(sc)->content_size_get =
4099      _elm_map_pan_smart_content_size_get;
4100 }
4101
4102 static Eina_Bool
4103 _elm_map_smart_on_focus(Evas_Object *obj)
4104 {
4105    ELM_MAP_DATA_GET(obj, sd);
4106
4107    if (elm_widget_focus_get(obj))
4108      {
4109         edje_object_signal_emit
4110           (ELM_WIDGET_DATA(sd)->resize_obj, "elm,action,focus", "elm");
4111         evas_object_focus_set(ELM_WIDGET_DATA(sd)->resize_obj, EINA_TRUE);
4112      }
4113    else
4114      {
4115         edje_object_signal_emit
4116           (ELM_WIDGET_DATA(sd)->resize_obj, "elm,action,unfocus", "elm");
4117         evas_object_focus_set(ELM_WIDGET_DATA(sd)->resize_obj, EINA_FALSE);
4118      }
4119
4120    return EINA_TRUE;
4121 }
4122
4123 static Eina_Bool
4124 _elm_map_smart_theme(Evas_Object *obj)
4125 {
4126    ELM_MAP_DATA_GET(obj, sd);
4127
4128    if (!ELM_WIDGET_CLASS(_elm_map_parent_sc)->theme(obj))
4129      return EINA_FALSE;
4130
4131    _sizing_eval(sd);
4132
4133    return EINA_TRUE;
4134 }
4135
4136 static Eina_Bool
4137 _elm_map_smart_event(Evas_Object *obj,
4138                      Evas_Object *src __UNUSED__,
4139                      Evas_Callback_Type type,
4140                      void *event_info)
4141 {
4142    Evas_Coord vh;
4143    Evas_Coord x, y;
4144    Evas_Event_Key_Down *ev = event_info;
4145    Evas_Coord step_x, step_y, page_x, page_y;
4146
4147    ELM_MAP_DATA_GET(obj, sd);
4148
4149    if (elm_widget_disabled_get(obj)) return EINA_FALSE;
4150    if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
4151    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
4152
4153    sd->s_iface->content_pos_get(obj, &x, &y);
4154    sd->s_iface->step_size_get(obj, &step_x, &step_y);
4155    sd->s_iface->page_size_get(obj, &page_x, &page_y);
4156    sd->s_iface->content_viewport_size_get(obj, NULL, &vh);
4157
4158    if ((!strcmp(ev->keyname, "Left")) ||
4159        ((!strcmp(ev->keyname, "KP_Left")) && (!ev->string)))
4160      {
4161         x -= step_x;
4162      }
4163    else if ((!strcmp(ev->keyname, "Right")) ||
4164             ((!strcmp(ev->keyname, "KP_Right")) && (!ev->string)))
4165      {
4166         x += step_x;
4167      }
4168    else if ((!strcmp(ev->keyname, "Up")) ||
4169             ((!strcmp(ev->keyname, "KP_Up")) && (!ev->string)))
4170      {
4171         y -= step_y;
4172      }
4173    else if ((!strcmp(ev->keyname, "Down")) ||
4174             ((!strcmp(ev->keyname, "KP_Down")) && (!ev->string)))
4175      {
4176         y += step_y;
4177      }
4178    else if ((!strcmp(ev->keyname, "Prior")) ||
4179             ((!strcmp(ev->keyname, "KP_Prior")) && (!ev->string)))
4180      {
4181         if (page_y < 0)
4182           y -= -(page_y * vh) / 100;
4183         else
4184           y -= page_y;
4185      }
4186    else if ((!strcmp(ev->keyname, "Next")) ||
4187             ((!strcmp(ev->keyname, "KP_Next")) && (!ev->string)))
4188      {
4189         if (page_y < 0)
4190           y += -(page_y * vh) / 100;
4191         else
4192           y += page_y;
4193      }
4194    else if (!strcmp(ev->keyname, "KP_Add"))
4195      {
4196         _zoom(sd, sd->zoom + 1, 1);
4197         return EINA_TRUE;
4198      }
4199    else if (!strcmp(ev->keyname, "KP_Subtract"))
4200      {
4201         _zoom(sd, sd->zoom - 1, 1);
4202         return EINA_TRUE;
4203      }
4204    else return EINA_FALSE;
4205
4206    ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
4207    sd->s_iface->content_pos_set(obj, x, y, EINA_TRUE);
4208
4209    return EINA_TRUE;
4210 }
4211
4212 static void
4213 _source_tile_set(Elm_Map_Smart_Data *sd,
4214                  const char *source_name)
4215 {
4216    Source_Tile *s;
4217    Eina_List *l;
4218
4219    EINA_SAFETY_ON_NULL_RETURN(source_name);
4220
4221    if (sd->src_tile && !strcmp(sd->src_tile->name, source_name))
4222      return;
4223
4224    EINA_LIST_FOREACH(sd->src_tiles, l, s)
4225      {
4226         if (!strcmp(s->name, source_name))
4227           {
4228              sd->src_tile = s;
4229              break;
4230           }
4231      }
4232    if (!sd->src_tile)
4233      {
4234         ERR("source name (%s) is not found", source_name);
4235         return;
4236      }
4237
4238    if (sd->src_tile->zoom_max < sd->zoom)
4239      sd->zoom = sd->src_tile->zoom_max;
4240    else if (sd->src_tile->zoom_min > sd->zoom)
4241      sd->zoom = sd->src_tile->zoom_min;
4242
4243    if (sd->src_tile->zoom_max < sd->zoom_max)
4244      sd->zoom_max = sd->src_tile->zoom_max;
4245    if (sd->src_tile->zoom_min > sd->zoom_min)
4246      sd->zoom_min = sd->src_tile->zoom_min;
4247
4248    _grid_all_clear(sd);
4249    _grid_all_create(sd);
4250    sd->zoom_detail = sd->zoom;
4251    _map_pan_zoom_do(sd, sd->zoom);
4252 }
4253
4254 static void
4255 _source_route_set(Elm_Map_Smart_Data *sd,
4256                   const char *source_name)
4257 {
4258    Source_Route *s;
4259    Eina_List *l;
4260
4261    EINA_SAFETY_ON_NULL_RETURN(source_name);
4262
4263    if (sd->src_route && !strcmp(sd->src_route->name, source_name))
4264      return;
4265
4266    EINA_LIST_FOREACH(sd->src_routes, l, s)
4267      {
4268         if (!strcmp(s->name, source_name))
4269           {
4270              sd->src_route = s;
4271              break;
4272           }
4273      }
4274    if (!sd->src_route)
4275      {
4276         ERR("source name (%s) is not found", source_name);
4277         return;
4278      }
4279 }
4280
4281 static void
4282 _source_name_set(Elm_Map_Smart_Data *sd,
4283                  const char *source_name)
4284 {
4285    Source_Name *s;
4286    Eina_List *l;
4287
4288    EINA_SAFETY_ON_NULL_RETURN(source_name);
4289
4290    if (sd->src_name && !strcmp(sd->src_name->name, source_name))
4291      return;
4292
4293    EINA_LIST_FOREACH(sd->src_names, l, s)
4294      {
4295         if (!strcmp(s->name, source_name))
4296           {
4297              sd->src_name = s;
4298              break;
4299           }
4300      }
4301    if (!sd->src_name)
4302      {
4303         ERR("source name (%s) is not found", source_name);
4304         return;
4305      }
4306 }
4307
4308 static Eina_Bool
4309 _source_mod_cb(Eina_Module *m,
4310                     void *data)
4311 {
4312    const char *file;
4313    Elm_Map_Smart_Data *sd = data;
4314
4315    Elm_Map_Module_Source_Name_Func name_cb;
4316    Elm_Map_Module_Add_Func add_cb;
4317    Elm_Map_Module_Key_Set_Func key_set_cb;
4318    Elm_Map_Module_Del_Func del_cb;
4319    Elm_Map_Module_Move_Func move_cb;
4320    Elm_Map_Module_Resize_Func resize_cb;
4321    Elm_Map_Module_Region_Get_Func region_get_cb;
4322    Elm_Map_Module_Pan_Func pan_cb;
4323    Elm_Map_Module_Show_Func show_cb;
4324    Elm_Map_Module_Zoom_Func zoom_cb;
4325    Elm_Map_Module_Rotate_Func rotate_cb;
4326    Elm_Map_Module_Rotate_Get_Func rotate_get_cb;
4327    Elm_Map_Module_Canvas_to_Region_Func canvas_to_region_cb;
4328    Elm_Map_Module_Region_to_Canvas_Func region_to_canvas_cb;
4329    Elm_Map_Module_Perspective_Set_Func perpective_cb;
4330    Elm_Map_Module_Tile_Url_Func tile_url_cb;
4331    Elm_Map_Module_Tile_Scale_Func scale_cb;
4332    Elm_Map_Module_Tile_Zoom_Min_Func zoom_min;
4333    Elm_Map_Module_Tile_Zoom_Max_Func zoom_max;
4334    Elm_Map_Module_Tile_Geo_to_Coord_Func geo_to_coord;
4335    Elm_Map_Module_Tile_Coord_to_Geo_Func coord_to_geo;
4336    Elm_Map_Module_Route_Url_Func route_url_cb;
4337    Elm_Map_Module_Name_Url_Func name_url_cb;
4338
4339    EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
4340
4341    file = eina_module_file_get(m);
4342    if (!eina_module_load(m))
4343      {
4344         ERR("Could not load module \"%s\": %s", file,
4345             eina_error_msg_get(eina_error_get()));
4346         return EINA_FALSE;
4347      }
4348    name_cb = eina_module_symbol_get(m, "map_module_source_name_get");
4349    if (!name_cb)
4350      {
4351         name_cb = eina_module_symbol_get(m, "map_module_name_get");
4352         if (!name_cb)
4353           {
4354              WRN("Could not find map module name from module \"%s\": %s",
4355                  file, eina_error_msg_get(eina_error_get()));
4356              eina_module_unload(m);
4357              return EINA_FALSE;
4358           }
4359      }
4360
4361    // Find Map Engine
4362    zoom_min = eina_module_symbol_get(m, "map_module_zoom_min_get");
4363    zoom_max = eina_module_symbol_get(m, "map_module_zoom_max_get");
4364    add_cb = eina_module_symbol_get(m, "map_module_add");
4365    key_set_cb = eina_module_symbol_get(m, "map_module_key_set");
4366    del_cb = eina_module_symbol_get(m, "map_module_del");
4367    move_cb = eina_module_symbol_get(m, "map_module_move");
4368    resize_cb = eina_module_symbol_get(m, "map_module_resize");
4369    region_get_cb = eina_module_symbol_get(m, "map_module_region_get");
4370    pan_cb = eina_module_symbol_get(m, "map_module_pan");
4371    show_cb = eina_module_symbol_get(m, "map_module_show");
4372    zoom_cb = eina_module_symbol_get(m, "map_module_zoom");
4373    rotate_cb = eina_module_symbol_get(m, "map_module_rotate");
4374    rotate_get_cb = eina_module_symbol_get(m, "map_module_rotate_get");
4375    perpective_cb = eina_module_symbol_get(m, "map_module_perpective_set");
4376    canvas_to_region_cb = eina_module_symbol_get(m, "map_module_canvas_to_region");
4377    region_to_canvas_cb = eina_module_symbol_get(m, "map_module_region_to_canvas");
4378    if (zoom_min && zoom_max && add_cb && del_cb && show_cb && zoom_cb && rotate_cb && rotate_get_cb && perpective_cb)
4379      {
4380         INF("Map ENGINE module is loaded \"%s\"",  file);
4381         Source_Engine *s;
4382         s = ELM_NEW(Source_Engine);
4383         s->name = name_cb();
4384         s->zoom_min = zoom_min();
4385         s->zoom_max = zoom_max();
4386         s->add = add_cb;
4387         s->key_set = key_set_cb;
4388         s->del = del_cb;
4389         if (move_cb) s->move = move_cb;
4390         else s->move = _move_unimplemented;
4391         if (resize_cb) s->resize = resize_cb;
4392         else s->resize = _resize_unimplemented;
4393         s->region_get = region_get_cb;
4394         if (pan_cb) s->pan = pan_cb;
4395         else s->pan = _pan_unimplemented;
4396         s->show = show_cb;
4397         s->zoom = zoom_cb;
4398         s->rotate = rotate_cb;
4399         s->rotate_get = rotate_get_cb;
4400         s->perpective = perpective_cb;
4401         if (canvas_to_region_cb) s->canvas_to_region = canvas_to_region_cb;
4402         else s->canvas_to_region = _canvas_to_region_unimplemented;
4403         if (region_to_canvas_cb) s->region_to_canvas = region_to_canvas_cb;
4404         else s->region_to_canvas = _region_to_canvas_unimplemented;
4405 //NLP specific changes
4406 //Turn off/on map engine overlays with this variable during compilation
4407 //put all the engine overlay symbol loading inside this condition
4408        if ( ENABLE_MAP_ENGINE_OVERLAYS )
4409         {
4410            s->icon_add =  eina_module_symbol_get(m, "map_module_icon_add");
4411            s->icon_remove = eina_module_symbol_get(m, "map_module_icon_remove");
4412            s->object_from_coord =  eina_module_symbol_get(m, "map_module_get_object_from_coord");
4413            s->object_visibility =   eina_module_symbol_get(m, "map_module_object_visibility_set");
4414            s->object_visibility_range = eina_module_symbol_get(m, "map_module_object_zoom_range_set");
4415            s->group_create = eina_module_symbol_get(m, "map_module_group_create");
4416            s->group_remove = eina_module_symbol_get(m, "map_module_group_remove");
4417            s->group_object_add = eina_module_symbol_get(m, "map_module_group_object_add");
4418            s->group_object_remove = eina_module_symbol_get(m, "map_module_group_object_remove");
4419        }
4420
4421         sd->engines = eina_list_append(sd->engines, s);
4422      }
4423
4424    // Find TILE module
4425    tile_url_cb = eina_module_symbol_get(m, "map_module_tile_url_get");
4426    zoom_min = eina_module_symbol_get(m, "map_module_tile_zoom_min_get");
4427    zoom_max = eina_module_symbol_get(m, "map_module_tile_zoom_max_get");
4428    geo_to_coord = eina_module_symbol_get(m, "map_module_tile_geo_to_coord");
4429    coord_to_geo = eina_module_symbol_get(m, "map_module_tile_coord_to_geo");
4430    scale_cb = eina_module_symbol_get(m, "map_module_tile_scale_get");
4431    if (tile_url_cb && zoom_min && zoom_max && geo_to_coord && coord_to_geo && scale_cb)
4432      {
4433         INF("Map TILE module is loaded \"%s\"",  file);
4434         Source_Tile *s;
4435         s = ELM_NEW(Source_Tile);
4436         s->name = name_cb();
4437         s->zoom_min = zoom_min();
4438         s->zoom_max = zoom_max();
4439         s->url_cb = tile_url_cb;
4440         s->geo_to_coord = geo_to_coord;
4441         s->coord_to_geo = coord_to_geo;
4442         s->scale_cb = scale_cb;
4443         sd->src_tiles = eina_list_append(sd->src_tiles, s);
4444      }
4445
4446    // Find ROUTE module
4447    route_url_cb = eina_module_symbol_get(m, "map_module_route_url_get");
4448    if (route_url_cb)
4449      {
4450         INF("Map ROUTE module is loaded \"%s\"",  file);
4451         Source_Route *s;
4452         s = ELM_NEW(Source_Route);
4453         s->name = name_cb();
4454         s->url_cb = route_url_cb;
4455         sd->src_routes = eina_list_append(sd->src_routes, s);
4456      }
4457
4458    // Find NAME module
4459    name_url_cb = eina_module_symbol_get(m, "map_module_name_url_get");
4460    if (name_url_cb)
4461      {
4462         INF("Map NAME module is loaded \"%s\"",  file);
4463         Source_Name *s;
4464         s = ELM_NEW(Source_Name);
4465         s->name = name_cb();
4466         s->url_cb = name_url_cb;
4467         sd->src_names = eina_list_append(sd->src_names, s);
4468      }
4469    return EINA_TRUE;
4470 }
4471
4472 static void
4473 _source_all_unload(Elm_Map_Smart_Data *sd)
4474 {
4475    int idx = 0;
4476    Source_Tile *s;
4477
4478    for (idx = 0; sd->src_tile_names[idx]; idx++)
4479      eina_stringshare_del(sd->src_tile_names[idx]);
4480    for (idx = 0; sd->src_route_names[idx]; idx++)
4481      eina_stringshare_del(sd->src_route_names[idx]);
4482    for (idx = 0; sd->src_name_names[idx]; idx++)
4483      eina_stringshare_del(sd->src_name_names[idx]);
4484
4485    EINA_LIST_FREE(sd->src_tiles, s) free(s);
4486    EINA_LIST_FREE(sd->src_routes, s) free(s);
4487    EINA_LIST_FREE(sd->src_names, s) free(s);
4488
4489    eina_module_list_free(sd->src_mods);
4490 }
4491
4492
4493 static void
4494 _source_all_load(Elm_Map_Smart_Data *sd)
4495 {
4496    Source_Engine *engine;
4497    Source_Tile *src_tile;
4498    Source_Route *src_route;
4499    Source_Name *src_name;
4500    unsigned int idx;
4501    Eina_List *l;
4502
4503    // Load hard coded TILE source
4504    for (idx = 0; idx < (sizeof(src_tiles) / sizeof(Source_Tile)); idx++)
4505      {
4506         src_tile = ELM_NEW(Source_Tile);
4507         src_tile->name = src_tiles[idx].name;
4508         src_tile->zoom_min = src_tiles[idx].zoom_min;
4509         src_tile->zoom_max = src_tiles[idx].zoom_max;
4510         src_tile->url_cb = src_tiles[idx].url_cb;
4511         src_tile->geo_to_coord = src_tiles[idx].geo_to_coord;
4512         src_tile->coord_to_geo = src_tiles[idx].coord_to_geo;
4513         src_tile->scale_cb = src_tiles[idx].scale_cb;
4514         sd->src_tiles = eina_list_append(sd->src_tiles, src_tile);
4515      }
4516    // Load hard coded ROUTE source
4517    for (idx = 0; idx < (sizeof(src_routes) / sizeof(Source_Route)); idx++)
4518      {
4519         src_route = ELM_NEW(Source_Route);
4520         src_route->name = src_routes[idx].name;
4521         src_route->url_cb = src_routes[idx].url_cb;
4522         sd->src_routes = eina_list_append(sd->src_routes, src_route);
4523      }
4524    // Load from hard coded NAME source
4525    for (idx = 0; idx < (sizeof(src_names) / sizeof(Source_Name)); idx++)
4526      {
4527         src_name = ELM_NEW(Source_Name);
4528         src_name->name = src_names[idx].name;
4529         src_name->url_cb = src_names[idx].url_cb;
4530         sd->src_names = eina_list_append(sd->src_names, src_name);
4531      }
4532    // Load Internal Default Map Engine
4533    engine = ELM_NEW(Source_Engine);
4534    engine->name = INTERNAL_ENGINE_NAME;
4535    engine->zoom_min = src_tiles[0].zoom_min;
4536    engine->zoom_max = src_tiles[0].zoom_max;
4537    engine->add = _map_pan_add;
4538    engine->key_set = _key_set_unimplemented;
4539    engine->del = _map_pan_del;
4540    engine->pan = _pan_unimplemented;
4541    engine->show = _map_pan_show;
4542    engine->zoom = _map_pan_zoom;
4543    engine->rotate = _map_pan_rotate;
4544    engine->rotate_get = _map_pan_rotate_get;
4545    engine->perpective = _map_pan_perspective_set;
4546    engine->region_get = _map_pan_region_get;
4547    engine->canvas_to_region = _map_pan_canvas_to_region;
4548    engine->region_to_canvas = _map_pan_region_to_canvas;
4549    sd->engines = eina_list_append(sd->engines, engine);
4550
4551    // Load from modules
4552    sd->src_mods = eina_module_list_get(sd->src_mods, MODULES_PATH, 1,
4553                                        &_source_mod_cb, sd);
4554
4555    // Set default source
4556    sd->engine = eina_list_nth(sd->engines, 0);
4557    sd->src_tile = eina_list_nth(sd->src_tiles, 0);
4558    sd->src_route = eina_list_nth(sd->src_routes, 0);
4559    sd->src_name = eina_list_nth(sd->src_names, 0);
4560
4561    // Make name string of sources
4562    idx = 0;
4563    sd->engine_names = calloc((eina_list_count(sd->engines) + 1),
4564                                  sizeof(const char *));
4565    EINA_LIST_FOREACH(sd->engines, l, engine)
4566      {
4567         eina_stringshare_replace(&sd->engine_names[idx], engine->name);
4568         INF("engine : %s", sd->engine_names[idx]);
4569         idx++;
4570      }
4571    idx = 0;
4572    sd->src_tile_names = calloc((eina_list_count(sd->src_tiles) + 1),
4573                                sizeof(const char *));
4574    EINA_LIST_FOREACH(sd->src_tiles, l, src_tile)
4575      {
4576         eina_stringshare_replace(&sd->src_tile_names[idx], src_tile->name);
4577         INF("source tile: %s", sd->src_tile_names[idx]);
4578         idx++;
4579      }
4580    idx = 0;
4581    sd->src_route_names = calloc((eina_list_count(sd->src_routes) + 1),
4582                                 sizeof(const char *));
4583    EINA_LIST_FOREACH(sd->src_routes, l, src_route)
4584      {
4585         eina_stringshare_replace(&sd->src_route_names[idx], src_route->name);
4586         INF("source route: %s", sd->src_route_names[idx]);
4587         idx++;
4588      }
4589    idx = 0;
4590    sd->src_name_names = calloc((eina_list_count(sd->src_names) + 1),
4591                                sizeof(const char *));
4592    EINA_LIST_FOREACH(sd->src_names, l, src_name)
4593      {
4594         eina_stringshare_replace(&sd->src_name_names[idx], src_name->name);
4595         INF("source name: %s", sd->src_name_names[idx]);
4596         idx++;
4597      }
4598 }
4599
4600 static void
4601 _elm_map_smart_add(Evas_Object *obj)
4602 {
4603    Evas_Object *layout;
4604    Elm_Map_Pan_Smart_Data *pan_data;
4605    EVAS_SMART_DATA_ALLOC(obj, Elm_Map_Smart_Data);
4606
4607    ELM_WIDGET_CLASS(_elm_map_parent_sc)->base.add(obj);
4608
4609    elm_widget_can_focus_set(obj, EINA_TRUE);
4610
4611    priv->pan_obj = evas_object_smart_add
4612       (evas_object_evas_get(obj), _elm_map_pan_smart_class_new());
4613    pan_data = evas_object_smart_data_get(priv->pan_obj);
4614    pan_data->wsd = priv;
4615
4616    _source_all_load(priv);
4617    layout = priv->engine->add(obj);
4618    elm_widget_resize_object_set(obj, layout);
4619
4620    evas_object_event_callback_add
4621      (obj, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb, priv);
4622    evas_object_event_callback_add
4623      (obj, EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb, priv);
4624    evas_object_event_callback_add
4625      (obj, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel_cb, priv);
4626    evas_object_event_callback_add
4627       (obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints_cb, priv);
4628
4629    priv->g_layer = elm_gesture_layer_add(obj);
4630    if (!priv->g_layer) ERR("elm_gesture_layer_add() failed");
4631    elm_gesture_layer_attach(priv->g_layer, obj);
4632    elm_gesture_layer_cb_set
4633      (priv->g_layer, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_START,
4634      _pinch_zoom_start_cb, priv);
4635    elm_gesture_layer_cb_set
4636      (priv->g_layer, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_MOVE,
4637      _pinch_zoom_cb, priv);
4638    elm_gesture_layer_cb_set
4639      (priv->g_layer, ELM_GESTURE_ROTATE, ELM_GESTURE_STATE_MOVE,
4640      _pinch_rotate_cb, priv);
4641    elm_gesture_layer_cb_set
4642      (priv->g_layer, ELM_GESTURE_ROTATE, ELM_GESTURE_STATE_END,
4643      _pinch_rotate_end_cb, priv);
4644    elm_gesture_layer_cb_set
4645      (priv->g_layer, ELM_GESTURE_ROTATE, ELM_GESTURE_STATE_ABORT,
4646      _pinch_rotate_end_cb, priv);
4647    elm_gesture_layer_cb_set
4648      (priv->g_layer, ELM_GESTURE_MOMENTUM, ELM_GESTURE_STATE_START,
4649      _pinch_momentum_start_cb, priv);
4650    elm_gesture_layer_cb_set
4651      (priv->g_layer, ELM_GESTURE_MOMENTUM, ELM_GESTURE_STATE_MOVE,
4652      _pinch_momentum_move_cb, priv);
4653    elm_gesture_layer_cb_set
4654      (priv->g_layer, ELM_GESTURE_MOMENTUM, ELM_GESTURE_STATE_END,
4655      _pinch_momentum_end_cb, priv);
4656    elm_gesture_layer_cb_set
4657      (priv->g_layer, ELM_GESTURE_N_LINES, ELM_GESTURE_STATE_MOVE,
4658      _pinch_n_lines_move_cb, priv);
4659    elm_gesture_layer_cb_set
4660      (priv->g_layer, ELM_GESTURE_N_LINES, ELM_GESTURE_STATE_END,
4661      _pinch_n_lines_end_cb, priv);
4662
4663    priv->mode = ELM_MAP_ZOOM_MODE_MANUAL;
4664    priv->zoom_min = priv->engine->zoom_min;
4665    priv->zoom_max = priv->engine->zoom_max;
4666    priv->zoom = 0;
4667    priv->zoom_detail = 0;
4668
4669    priv->engine->zoom(obj, 0, 0);
4670 }
4671
4672 static void
4673 _elm_map_smart_del(Evas_Object *obj)
4674 {
4675    Source_Engine *e;
4676    ELM_MAP_DATA_GET(obj, sd);
4677
4678    if (sd->zoom_timer) ecore_timer_del(sd->zoom_timer);
4679    if (sd->long_timer) ecore_timer_del(sd->long_timer);
4680    if (sd->loaded_timer) ecore_timer_del(sd->loaded_timer);
4681
4682    if (sd->user_agent) eina_stringshare_del(sd->user_agent);
4683    if (sd->ua) eina_hash_free(sd->ua);
4684
4685    sd->engine->del(obj);
4686    EINA_LIST_FREE(sd->engines, e)
4687      {
4688         if (e->key) free(e->key);
4689         free(e);
4690      }
4691    _source_all_unload(sd);
4692
4693    evas_object_del(sd->pan_obj);
4694    ELM_WIDGET_CLASS(_elm_map_parent_sc)->base.del(obj);
4695 }
4696
4697 static void
4698 _elm_map_smart_calculate(Evas_Object *obj)
4699 {
4700    ELM_MAP_DATA_GET(obj, sd);
4701
4702    if (strcmp(sd->engine->name, INTERNAL_ENGINE_NAME))
4703      _overlay_place(sd);
4704 }
4705
4706 static void
4707 _elm_map_smart_move(Evas_Object *obj,
4708                     Evas_Coord x,
4709                     Evas_Coord y)
4710 {
4711    ELM_MAP_DATA_GET(obj, sd);
4712
4713    ELM_WIDGET_CLASS(_elm_map_parent_sc)->base.move(obj, x, y);
4714
4715    if (!strcmp(sd->engine->name, INTERNAL_ENGINE_NAME))
4716       evas_object_move(sd->hit_rect, x, y);
4717    else
4718      {
4719         sd->engine->move(obj, x, y);
4720         _overlay_place(sd);
4721      }
4722 }
4723
4724 static void
4725 _elm_map_smart_resize(Evas_Object *obj,
4726                       Evas_Coord w,
4727                       Evas_Coord h)
4728 {
4729    ELM_MAP_DATA_GET(obj, sd);
4730
4731    ELM_WIDGET_CLASS(_elm_map_parent_sc)->base.resize(obj, w, h);
4732
4733    if (!strcmp(sd->engine->name, INTERNAL_ENGINE_NAME))
4734       evas_object_resize(sd->hit_rect, w, h);
4735    else
4736      {
4737         sd->engine->resize(obj, w, h);
4738         _overlay_place(sd);
4739      }
4740 }
4741
4742 static void
4743 _elm_map_smart_member_add(Evas_Object *obj,
4744                           Evas_Object *member)
4745 {
4746    ELM_MAP_DATA_GET(obj, sd);
4747
4748    ELM_WIDGET_CLASS(_elm_map_parent_sc)->base.member_add(obj, member);
4749
4750    if (sd->hit_rect)
4751      evas_object_raise(sd->hit_rect);
4752 }
4753
4754 static void
4755 _elm_map_smart_set_user(Elm_Map_Smart_Class *sc)
4756 {
4757    ELM_WIDGET_CLASS(sc)->base.add = _elm_map_smart_add;
4758    ELM_WIDGET_CLASS(sc)->base.del = _elm_map_smart_del;
4759    ELM_WIDGET_CLASS(sc)->base.calculate = _elm_map_smart_calculate;
4760
4761    ELM_WIDGET_CLASS(sc)->base.move = _elm_map_smart_move;
4762    ELM_WIDGET_CLASS(sc)->base.resize = _elm_map_smart_resize;
4763    ELM_WIDGET_CLASS(sc)->base.member_add = _elm_map_smart_member_add;
4764
4765    ELM_WIDGET_CLASS(sc)->on_focus = _elm_map_smart_on_focus;
4766    ELM_WIDGET_CLASS(sc)->theme = _elm_map_smart_theme;
4767    ELM_WIDGET_CLASS(sc)->event = _elm_map_smart_event;
4768    ELM_WIDGET_CLASS(sc)->translate = _elm_map_smart_translate;
4769 }
4770 #endif
4771
4772 EAPI const Elm_Map_Smart_Class *
4773 elm_map_smart_class_get(void)
4774 {
4775 #ifdef HAVE_ELEMENTARY_ECORE_CON
4776    static Elm_Map_Smart_Class _sc =
4777      ELM_MAP_SMART_CLASS_INIT_NAME_VERSION(ELM_MAP_SMART_NAME);
4778    static const Elm_Map_Smart_Class *class = NULL;
4779    Evas_Smart_Class *esc = (Evas_Smart_Class *)&_sc;
4780
4781    if (class) return class;
4782
4783    _elm_map_smart_set(&_sc);
4784    esc->callbacks = _smart_callbacks;
4785    class = &_sc;
4786
4787    return class;
4788 #else
4789    return NULL;
4790 #endif
4791 }
4792
4793 EAPI Evas_Object *
4794 elm_map_add(Evas_Object *parent)
4795 {
4796 #ifdef HAVE_ELEMENTARY_ECORE_CON
4797    Evas_Object *obj;
4798
4799    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
4800
4801    obj = elm_widget_add(_elm_map_smart_class_new(), parent);
4802    if (!obj) return NULL;
4803
4804    if (!elm_widget_sub_object_add(parent, obj))
4805      ERR("could not add %p as sub object of %p", obj, parent);
4806
4807    return obj;
4808 #else
4809    (void)parent;
4810    return NULL;
4811 #endif
4812 }
4813
4814 EAPI void
4815 elm_map_engine_key_set(Evas_Object *obj,
4816                        const char *engine_name,
4817                        const char *key)
4818 {
4819    ELM_MAP_CHECK(obj);
4820    ELM_MAP_DATA_GET(obj, sd);
4821    EINA_SAFETY_ON_NULL_RETURN(engine_name);
4822    EINA_SAFETY_ON_NULL_RETURN(key);
4823
4824    Eina_List *l;
4825    Source_Engine *e;
4826
4827    EINA_LIST_FOREACH(sd->engines, l, e)
4828      {
4829         if (!strcmp(e->name, engine_name))
4830           {
4831              if (e->key) free(e->key);
4832              e->key = strdup(key);
4833              e->key_set(obj, key);
4834              break;
4835           }
4836      }
4837 }
4838
4839
4840 EAPI void
4841 elm_map_zoom_set(Evas_Object *obj,
4842                  int zoom)
4843 {
4844 #ifdef HAVE_ELEMENTARY_ECORE_CON
4845
4846    ELM_MAP_CHECK(obj);
4847    ELM_MAP_DATA_GET(obj, sd);
4848    EINA_SAFETY_ON_NULL_RETURN(sd->src_tile);
4849
4850    Eina_Bool animation;
4851
4852    if (sd->mode != ELM_MAP_ZOOM_MODE_MANUAL) return;
4853    if (zoom < 0) zoom = 0;
4854    if (sd->zoom == zoom) return;
4855
4856    if (sd->paused) animation = EINA_FALSE;
4857    else animation = EINA_TRUE;
4858
4859    if (!strcmp(sd->engine->name, INTERNAL_ENGINE_NAME))
4860      {
4861         sd->calc_job.zoom_changed = EINA_TRUE;
4862         sd->calc_job.zoom_anim = animation;
4863         sd->calc_job.zoom = zoom;
4864         evas_object_smart_changed(sd->pan_obj);
4865      }
4866    else _zoom(sd, zoom, 1);
4867
4868 #else
4869    (void)obj;
4870    (void)zoom;
4871 #endif
4872 }
4873
4874 EAPI int
4875 elm_map_zoom_get(const Evas_Object *obj)
4876 {
4877 #ifdef HAVE_ELEMENTARY_ECORE_CON
4878    ELM_MAP_CHECK(obj) 0;
4879    ELM_MAP_DATA_GET(obj, sd);
4880
4881    return sd->zoom;
4882 #else
4883    (void)obj;
4884    return 0;
4885 #endif
4886 }
4887
4888 EAPI void
4889 elm_map_zoom_mode_set(Evas_Object *obj,
4890                       Elm_Map_Zoom_Mode mode)
4891 {
4892 #ifdef HAVE_ELEMENTARY_ECORE_CON
4893    ELM_MAP_CHECK(obj);
4894    ELM_MAP_DATA_GET(obj, sd);
4895
4896    if ((mode == ELM_MAP_ZOOM_MODE_MANUAL) && (sd->mode == !!mode)) return;
4897
4898    sd->mode = mode;
4899    if (!strcmp(sd->engine->name, INTERNAL_ENGINE_NAME))
4900      {
4901         sd->calc_job.zoom_changed = EINA_TRUE;
4902         sd->calc_job.zoom_anim = EINA_FALSE;
4903         sd->calc_job.zoom = sd->zoom;
4904         evas_object_smart_changed(sd->pan_obj);
4905      }
4906    else ERR("Engine(%s) do not support zoom mode", sd->engine->name);
4907
4908 #else
4909    (void)obj;
4910    (void)mode;
4911 #endif
4912 }
4913
4914 EAPI Elm_Map_Zoom_Mode
4915 elm_map_zoom_mode_get(const Evas_Object *obj)
4916 {
4917 #ifdef HAVE_ELEMENTARY_ECORE_CON
4918    ELM_MAP_CHECK(obj) ELM_MAP_ZOOM_MODE_MANUAL;
4919    ELM_MAP_DATA_GET(obj, sd);
4920
4921    return sd->mode;
4922 #else
4923    (void)obj;
4924    return ELM_MAP_ZOOM_MODE_MANUAL;
4925 #endif
4926 }
4927
4928 EAPI void
4929 elm_map_zoom_max_set(Evas_Object *obj,
4930                      int zoom)
4931 {
4932 #ifdef HAVE_ELEMENTARY_ECORE_CON
4933    ELM_MAP_CHECK(obj);
4934    ELM_MAP_DATA_GET(obj, sd);
4935    EINA_SAFETY_ON_NULL_RETURN(sd->src_tile);
4936
4937    sd->zoom_max = zoom;
4938 #else
4939    (void)obj;
4940    (void)zoom;
4941 #endif
4942 }
4943
4944 EAPI int
4945 elm_map_zoom_max_get(const Evas_Object *obj)
4946 {
4947 #ifdef HAVE_ELEMENTARY_ECORE_CON
4948    ELM_MAP_CHECK(obj) - 1;
4949    ELM_MAP_DATA_GET(obj, sd);
4950    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->src_tile, -1);
4951
4952    return sd->zoom_max;
4953 #else
4954    (void)obj;
4955    return -1;
4956 #endif
4957 }
4958
4959 EAPI void
4960 elm_map_zoom_min_set(Evas_Object *obj,
4961                      int zoom)
4962 {
4963 #ifdef HAVE_ELEMENTARY_ECORE_CON
4964    ELM_MAP_CHECK(obj);
4965    ELM_MAP_DATA_GET(obj, sd);
4966    EINA_SAFETY_ON_NULL_RETURN(sd->src_tile);
4967
4968    sd->zoom_min = zoom;
4969 #else
4970    (void)obj;
4971    (void)zoom;
4972 #endif
4973 }
4974
4975 EAPI int
4976 elm_map_zoom_min_get(const Evas_Object *obj)
4977 {
4978 #ifdef HAVE_ELEMENTARY_ECORE_CON
4979    ELM_MAP_CHECK(obj) - 1;
4980    ELM_MAP_DATA_GET(obj, sd);
4981    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->src_tile, -1);
4982
4983    return sd->zoom_min;
4984 #else
4985    (void)obj;
4986    return -1;
4987 #endif
4988 }
4989
4990 EAPI void
4991 elm_map_region_bring_in(Evas_Object *obj,
4992                         double lon,
4993                         double lat)
4994 {
4995 #ifdef HAVE_ELEMENTARY_ECORE_CON
4996    ELM_MAP_CHECK(obj);
4997    ELM_MAP_DATA_GET(obj, sd);
4998
4999    if (!strcmp(sd->engine->name, INTERNAL_ENGINE_NAME))
5000      {
5001         sd->calc_job.show_changed = EINA_TRUE;
5002         sd->calc_job.show_anim = EINA_TRUE;
5003         sd->calc_job.lon = lon;
5004         sd->calc_job.lat = lat;
5005         evas_object_smart_changed(sd->pan_obj);
5006      }
5007    else
5008      {
5009         sd->engine->show(obj, lon, lat, 1);
5010         _overlay_place(sd);
5011      }
5012 #else
5013    (void)obj;
5014    (void)lon;
5015    (void)lat;
5016 #endif
5017 }
5018
5019 EAPI void
5020 elm_map_region_show(Evas_Object *obj,
5021                     double lon,
5022                     double lat)
5023 {
5024 #ifdef HAVE_ELEMENTARY_ECORE_CON
5025    ELM_MAP_CHECK(obj);
5026    ELM_MAP_DATA_GET(obj, sd);
5027
5028    if (!strcmp(sd->engine->name, INTERNAL_ENGINE_NAME))
5029      {
5030         sd->calc_job.show_changed = EINA_TRUE;
5031         sd->calc_job.show_anim = EINA_FALSE;
5032         sd->calc_job.lon = lon;
5033         sd->calc_job.lat = lat;
5034         evas_object_smart_changed(sd->pan_obj);
5035      }
5036    else
5037      {
5038         sd->engine->show(obj, lon, lat, 0);
5039         _overlay_place(sd);
5040      }
5041
5042 #else
5043    (void)obj;
5044    (void)lon;
5045    (void)lat;
5046 #endif
5047 }
5048
5049 EAPI void
5050 elm_map_region_get(const Evas_Object *obj,
5051                    double *lon,
5052                    double *lat)
5053 {
5054 #ifdef HAVE_ELEMENTARY_ECORE_CON
5055
5056    ELM_MAP_CHECK(obj);
5057    ELM_MAP_DATA_GET(obj, sd);
5058
5059    double tlon, tlat;
5060    sd->engine->region_get(obj, &tlon, &tlat);
5061    if (lon) *lon = tlon;
5062    if (lat) *lat = tlat;
5063 #else
5064    (void)obj;
5065    (void)lon;
5066    (void)lat;
5067 #endif
5068 }
5069
5070 EAPI void
5071 elm_map_paused_set(Evas_Object *obj,
5072                    Eina_Bool paused)
5073 {
5074 #ifdef HAVE_ELEMENTARY_ECORE_CON
5075    ELM_MAP_CHECK(obj);
5076    ELM_MAP_DATA_GET(obj, sd);
5077
5078    if (sd->paused == !!paused) return;
5079    sd->paused = !!paused;
5080
5081    if (!strcmp(sd->engine->name, INTERNAL_ENGINE_NAME))
5082      {
5083         if (paused)
5084           {
5085              if (sd->zoom_animator)
5086                {
5087                   if (sd->zoom_animator) ecore_animator_del(sd->zoom_animator);
5088                   sd->zoom_animator = NULL;
5089                   sd->zoom_detail = sd->zoom;
5090                   _map_pan_zoom_do(sd, sd->zoom);
5091                }
5092              edje_object_signal_emit(ELM_WIDGET_DATA(sd)->resize_obj,
5093                                      "elm,state,busy,stop", "elm");
5094           }
5095         else
5096           {
5097              if (sd->download_num >= 1)
5098                 edje_object_signal_emit(ELM_WIDGET_DATA(sd)->resize_obj,
5099                                         "elm,state,busy,start", "elm");
5100           }
5101      }
5102
5103 #else
5104    (void)obj;
5105    (void)paused;
5106 #endif
5107 }
5108
5109 EAPI Eina_Bool
5110 elm_map_paused_get(const Evas_Object *obj)
5111 {
5112 #ifdef HAVE_ELEMENTARY_ECORE_CON
5113    ELM_MAP_CHECK(obj) EINA_FALSE;
5114    ELM_MAP_DATA_GET(obj, sd);
5115
5116    return sd->paused;
5117 #else
5118    (void)obj;
5119    return EINA_FALSE;
5120 #endif
5121 }
5122
5123 EAPI void
5124 elm_map_rotate_set(Evas_Object *obj,
5125                    double degree,
5126                    Evas_Coord cx,
5127                    Evas_Coord cy)
5128 {
5129 #ifdef HAVE_ELEMENTARY_ECORE_CON
5130    ELM_MAP_CHECK(obj);
5131    ELM_MAP_DATA_GET(obj, sd);
5132
5133    sd->engine->rotate(obj, degree, cx, cy, degree);
5134 #else
5135    (void)obj;
5136    (void)degree;
5137    (void)cx;
5138    (void)cy;
5139 #endif
5140 }
5141
5142 EAPI void
5143 elm_map_rotate_get(const Evas_Object *obj,
5144                    double *degree,
5145                    Evas_Coord *cx,
5146                    Evas_Coord *cy)
5147 {
5148 #ifdef HAVE_ELEMENTARY_ECORE_CON
5149    ELM_MAP_CHECK(obj);
5150    ELM_MAP_DATA_GET(obj, sd);
5151
5152    sd->engine->rotate_get(obj, degree, cx, cy);
5153 #else
5154    (void)obj;
5155    (void)degree;
5156    (void)cx;
5157    (void)cy;
5158 #endif
5159 }
5160
5161 EAPI void
5162 elm_map_wheel_disabled_set(Evas_Object *obj,
5163                            Eina_Bool disabled)
5164 {
5165 #ifdef HAVE_ELEMENTARY_ECORE_CON
5166    ELM_MAP_CHECK(obj);
5167    ELM_MAP_DATA_GET(obj, sd);
5168
5169    if ((!sd->wheel_disabled) && (disabled))
5170      evas_object_event_callback_del_full
5171        (obj, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel_cb, sd);
5172    else if ((sd->wheel_disabled) && (!disabled))
5173      evas_object_event_callback_add
5174        (obj, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel_cb, sd);
5175    sd->wheel_disabled = !!disabled;
5176 #else
5177    (void)obj;
5178    (void)disabled;
5179 #endif
5180 }
5181
5182 EAPI Eina_Bool
5183 elm_map_wheel_disabled_get(const Evas_Object *obj)
5184 {
5185 #ifdef HAVE_ELEMENTARY_ECORE_CON
5186    ELM_MAP_CHECK(obj) EINA_FALSE;
5187    ELM_MAP_DATA_GET(obj, sd);
5188
5189    return sd->wheel_disabled;
5190 #else
5191    (void)obj;
5192    return EINA_FALSE;
5193 #endif
5194 }
5195
5196 EAPI void
5197 elm_map_tile_load_status_get(const Evas_Object *obj,
5198                              int *try_num,
5199                              int *finish_num)
5200 {
5201 #ifdef HAVE_ELEMENTARY_ECORE_CON
5202    ELM_MAP_CHECK(obj);
5203    ELM_MAP_DATA_GET(obj, sd);
5204
5205    if (try_num) *try_num = sd->try_num;
5206    if (finish_num) *finish_num = sd->finish_num;
5207 #else
5208    (void)obj;
5209    (void)try_num;
5210    (void)finish_num;
5211 #endif
5212 }
5213
5214 EAPI void
5215 elm_map_canvas_to_region_convert(const Evas_Object *obj,
5216                                  Evas_Coord x,
5217                                  Evas_Coord y,
5218                                  double *lon,
5219                                  double *lat)
5220 {
5221 #ifdef HAVE_ELEMENTARY_ECORE_CON
5222    ELM_MAP_CHECK(obj);
5223    ELM_MAP_DATA_GET(obj, sd);
5224    EINA_SAFETY_ON_NULL_RETURN(lon);
5225    EINA_SAFETY_ON_NULL_RETURN(lat);
5226
5227    sd->engine->canvas_to_region(obj, x, y, lon, lat);
5228 #else
5229    (void)obj;
5230    (void)x;
5231    (void)y;
5232    (void)lon;
5233    (void)lat;
5234 #endif
5235 }
5236
5237 EAPI void
5238 elm_map_region_to_canvas_convert(const Evas_Object *obj,
5239                                  double lon,
5240                                  double lat,
5241                                  Evas_Coord *x,
5242                                  Evas_Coord *y)
5243 {
5244 #ifdef HAVE_ELEMENTARY_ECORE_CON
5245    ELM_MAP_CHECK(obj);
5246    ELM_MAP_DATA_GET(obj, sd);
5247    EINA_SAFETY_ON_NULL_RETURN(x);
5248    EINA_SAFETY_ON_NULL_RETURN(y);
5249
5250    sd->engine->region_to_canvas(obj, lon, lat, x, y);
5251 #else
5252    (void)obj;
5253    (void)lon;
5254    (void)lat;
5255    (void)x;
5256    (void)y;
5257 #endif
5258 }
5259
5260 EAPI void
5261 elm_map_user_agent_set(Evas_Object *obj,
5262                        const char *user_agent)
5263 {
5264 #ifdef HAVE_ELEMENTARY_ECORE_CON
5265    ELM_MAP_CHECK(obj);
5266    ELM_MAP_DATA_GET(obj, sd);
5267    EINA_SAFETY_ON_NULL_RETURN(user_agent);
5268
5269    eina_stringshare_replace(&sd->user_agent, user_agent);
5270
5271    if (!sd->ua) sd->ua = eina_hash_string_small_new(NULL);
5272    eina_hash_set(sd->ua, "User-Agent", sd->user_agent);
5273 #else
5274    (void)obj;
5275    (void)user_agent;
5276 #endif
5277 }
5278
5279 EAPI const char *
5280 elm_map_user_agent_get(const Evas_Object *obj)
5281 {
5282 #ifdef HAVE_ELEMENTARY_ECORE_CON
5283    ELM_MAP_CHECK(obj) NULL;
5284    ELM_MAP_DATA_GET(obj, sd);
5285
5286    return sd->user_agent;
5287 #else
5288    (void)obj;
5289    return NULL;
5290 #endif
5291 }
5292
5293 EAPI void
5294 elm_map_engine_set(Evas_Object *obj,
5295                    const char *engine_name)
5296 {
5297    ELM_MAP_CHECK(obj);
5298    ELM_MAP_DATA_GET(obj, sd);
5299    EINA_SAFETY_ON_NULL_RETURN(engine_name);
5300
5301    Source_Engine *engine = NULL;
5302    Source_Engine *e;
5303    Eina_List *l;
5304    Evas_Object *layout;
5305    double lon, lat;
5306
5307    if (sd->engine && !strcmp(sd->engine->name, engine_name))
5308       return;
5309
5310    EINA_LIST_FOREACH(sd->engines, l, e)
5311      {
5312         if (!strcmp(e->name, engine_name))
5313           {
5314              engine = e;
5315              break;
5316           }
5317      }
5318    if (!engine)
5319      {
5320         ERR("Engine name (%s) is not found", engine_name);
5321         return;
5322      }
5323    layout = engine->add(obj);
5324    if (!layout)
5325      {
5326         engine->del(obj);
5327         ERR("%s engine can not be added", engine->name);
5328         return;
5329      }
5330    sd->engine->region_get(obj, &lon, &lat);
5331    sd->engine->del(obj);
5332    sd->engine = engine;
5333
5334    if (sd->engine->key)
5335       sd->engine->key_set(obj, sd->engine->key);
5336
5337    if (sd->engine->zoom_max < sd->zoom)
5338      sd->zoom = sd->engine->zoom_max;
5339    else if (sd->engine->zoom_min > sd->zoom)
5340      sd->zoom = sd->engine->zoom_min;
5341
5342    if (sd->engine->zoom_max < sd->zoom_max)
5343      sd->zoom_max = sd->engine->zoom_max;
5344    if (sd->engine->zoom_min > sd->zoom_min)
5345      sd->zoom_min = sd->engine->zoom_min;
5346
5347    evas_object_hide(ELM_WIDGET_DATA(sd)->resize_obj);
5348    elm_widget_resize_object_set(obj, layout);
5349    sd->engine->zoom(obj, sd->zoom, 0);
5350    sd->engine->show(obj, lon, lat, 0);
5351 }
5352
5353 EAPI const char *
5354 elm_map_engine_get(const Evas_Object *obj)
5355 {
5356    ELM_MAP_CHECK(obj) NULL;
5357    ELM_MAP_DATA_GET(obj, sd);
5358
5359    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->src_tile, NULL);
5360
5361    return sd->engine->name;
5362 }
5363
5364 EAPI const char **
5365 elm_map_engines_get(const Evas_Object *obj)
5366 {
5367    ELM_MAP_CHECK(obj) NULL;
5368    ELM_MAP_DATA_GET(obj, sd);
5369
5370    return sd->engine_names;
5371 }
5372
5373 EAPI void
5374 elm_map_source_set(Evas_Object *obj,
5375                    Elm_Map_Source_Type type,
5376                    const char *source_name)
5377 {
5378 #ifdef HAVE_ELEMENTARY_ECORE_CON
5379    ELM_MAP_CHECK(obj);
5380    ELM_MAP_DATA_GET(obj, sd);
5381    EINA_SAFETY_ON_NULL_RETURN(source_name);
5382
5383    if (strcmp(sd->engine->name, INTERNAL_ENGINE_NAME))
5384      {
5385         ERR("Current engine is not %s", INTERNAL_ENGINE_NAME);
5386         return;
5387      }
5388
5389    if (type == ELM_MAP_SOURCE_TYPE_TILE)
5390       _source_tile_set(sd, source_name);
5391    else if (type == ELM_MAP_SOURCE_TYPE_ROUTE)
5392      _source_route_set(sd, source_name);
5393    else if (type == ELM_MAP_SOURCE_TYPE_NAME)
5394      _source_name_set(sd, source_name);
5395    else ERR("Not supported map source type: %d", type);
5396
5397 #else
5398    (void)obj;
5399    (void)type;
5400    (void)source_name;
5401 #endif
5402 }
5403
5404 EAPI const char *
5405 elm_map_source_get(const Evas_Object *obj,
5406                    Elm_Map_Source_Type type)
5407 {
5408 #ifdef HAVE_ELEMENTARY_ECORE_CON
5409    ELM_MAP_CHECK(obj) NULL;
5410    ELM_MAP_DATA_GET(obj, sd);
5411
5412    if (strcmp(sd->engine->name, INTERNAL_ENGINE_NAME))
5413      {
5414         ERR("Current engine is not %s", INTERNAL_ENGINE_NAME);
5415         return NULL;
5416      }
5417    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->src_tile, NULL);
5418
5419    if (type == ELM_MAP_SOURCE_TYPE_TILE) return sd->src_tile->name;
5420    else if (type == ELM_MAP_SOURCE_TYPE_ROUTE)
5421      return sd->src_route->name;
5422    else if (type == ELM_MAP_SOURCE_TYPE_NAME)
5423      return sd->src_name->name;
5424    else ERR("Not supported map source type: %d", type);
5425
5426    return NULL;
5427 #else
5428    (void)obj;
5429    (void)type;
5430    return NULL;
5431 #endif
5432 }
5433
5434 EAPI const char **
5435 elm_map_sources_get(const Evas_Object *obj,
5436                     Elm_Map_Source_Type type)
5437 {
5438 #ifdef HAVE_ELEMENTARY_ECORE_CON
5439    ELM_MAP_CHECK(obj) NULL;
5440    ELM_MAP_DATA_GET(obj, sd);
5441
5442    if (type == ELM_MAP_SOURCE_TYPE_TILE) return sd->src_tile_names;
5443    else if (type == ELM_MAP_SOURCE_TYPE_ROUTE)
5444      return sd->src_route_names;
5445    else if (type == ELM_MAP_SOURCE_TYPE_NAME)
5446      return sd->src_name_names;
5447    else ERR("Not supported map source type: %d", type);
5448
5449    return NULL;
5450 #else
5451    (void)obj;
5452    (void)type;
5453    return NULL;
5454 #endif
5455 }
5456
5457 EAPI Elm_Map_Route *
5458 elm_map_route_add(Evas_Object *obj,
5459                   Elm_Map_Route_Type type,
5460                   Elm_Map_Route_Method method,
5461                   double flon,
5462                   double flat,
5463                   double tlon,
5464                   double tlat,
5465                   Elm_Map_Route_Cb route_cb,
5466                   void *data)
5467 {
5468 #ifdef HAVE_ELEMENTARY_ECORE_CON
5469    char *url;
5470    char *type_name;
5471    Elm_Map_Route *route;
5472    char fname[PATH_MAX], fname2[PATH_MAX];
5473
5474    ELM_MAP_CHECK(obj) NULL;
5475    ELM_MAP_DATA_GET(obj, sd);
5476
5477    EINA_SAFETY_ON_NULL_RETURN_VAL(sd->src_route, NULL);
5478
5479    {
5480       const char *cachedir;
5481
5482 #ifdef ELM_EFREET
5483       snprintf(fname, sizeof(fname), "%s" CACHE_ROUTE_ROOT,
5484                efreet_cache_home_get());
5485       (void)cachedir;
5486 #else
5487       cachedir = getenv("XDG_CACHE_HOME");
5488       snprintf(fname, sizeof(fname), "%s/%s" CACHE_ROUTE_ROOT, getenv("HOME"),
5489                cachedir ? : "/.config");
5490 #endif
5491       if (!ecore_file_exists(fname)) ecore_file_mkpath(fname);
5492    }
5493
5494    if (type == ELM_MAP_ROUTE_TYPE_MOTOCAR)
5495      type_name = strdup(ROUTE_TYPE_MOTORCAR);
5496    else if (type == ELM_MAP_ROUTE_TYPE_BICYCLE)
5497      type_name = strdup(ROUTE_TYPE_BICYCLE);
5498    else if (type == ELM_MAP_ROUTE_TYPE_FOOT)
5499      type_name = strdup(ROUTE_TYPE_FOOT);
5500    else type_name = NULL;
5501
5502    url = sd->src_route->url_cb(obj, type_name, method, flon, flat, tlon, tlat);
5503    if (!url)
5504      {
5505         ERR("Route URL is NULL");
5506         if (type_name) free(type_name);
5507         return NULL;
5508      }
5509    if (type_name) free(type_name);
5510
5511    route = ELM_NEW(Elm_Map_Route);
5512    route->wsd = sd;
5513    snprintf(fname2, sizeof(fname2), "%s/%d", fname, rand());
5514    route->fname = strdup(fname2);
5515    route->type = type;
5516    route->method = method;
5517    route->flon = flon;
5518    route->flat = flat;
5519    route->tlon = tlon;
5520    route->tlat = tlat;
5521    route->cb = route_cb;
5522    route->data = data;
5523
5524    if (!ecore_file_download_full(url, route->fname, _route_cb, NULL, route,
5525                                  &(route->job), sd->ua) || !(route->job))
5526      {
5527         ERR("Can't request Route from %s to %s", url, route->fname);
5528         free(route->fname);
5529         free(route);
5530         return NULL;
5531      }
5532    INF("Route requested from %s to %s", url, route->fname);
5533    free(url);
5534
5535    sd->routes = eina_list_append(sd->routes, route);
5536    evas_object_smart_callback_call
5537      (ELM_WIDGET_DATA(sd)->obj, SIG_ROUTE_LOAD, route);
5538    edje_object_signal_emit(ELM_WIDGET_DATA(sd)->resize_obj,
5539                            "elm,state,busy,start", "elm");
5540    return route;
5541 #else
5542    (void)obj;
5543    (void)type;
5544    (void)method;
5545    (void)flon;
5546    (void)flat;
5547    (void)tlon;
5548    (void)tlat;
5549    (void)route_cb;
5550    (void)data;
5551    return NULL;
5552 #endif
5553 }
5554
5555 EAPI void
5556 elm_map_route_del(Elm_Map_Route *route)
5557 {
5558 #ifdef HAVE_ELEMENTARY_ECORE_CON
5559    Path_Waypoint *w;
5560    Path_Node *n;
5561
5562    EINA_SAFETY_ON_NULL_RETURN(route);
5563    EINA_SAFETY_ON_NULL_RETURN(route->wsd);
5564    ELM_MAP_CHECK(ELM_WIDGET_DATA(route->wsd)->obj);
5565
5566    if (route->job) ecore_file_download_abort(route->job);
5567
5568    EINA_LIST_FREE (route->waypoint, w)
5569      {
5570         if (w->point) eina_stringshare_del(w->point);
5571         free(w);
5572      }
5573
5574    EINA_LIST_FREE (route->nodes, n)
5575      {
5576         if (n->pos.address) eina_stringshare_del(n->pos.address);
5577         free(n);
5578      }
5579
5580    if (route->fname)
5581      {
5582         ecore_file_remove(route->fname);
5583         free(route->fname);
5584      }
5585
5586    route->wsd->routes = eina_list_remove(route->wsd->routes, route);
5587    free(route);
5588 #else
5589    (void)route;
5590 #endif
5591 }
5592
5593 EAPI double
5594 elm_map_route_distance_get(const Elm_Map_Route *route)
5595 {
5596 #ifdef HAVE_ELEMENTARY_ECORE_CON
5597    EINA_SAFETY_ON_NULL_RETURN_VAL(route, 0.0);
5598    return route->info.distance;
5599 #else
5600    (void)route;
5601    return 0.0;
5602 #endif
5603 }
5604
5605 EAPI const char *
5606 elm_map_route_node_get(const Elm_Map_Route *route)
5607 {
5608 #ifdef HAVE_ELEMENTARY_ECORE_CON
5609    EINA_SAFETY_ON_NULL_RETURN_VAL(route, NULL);
5610    return route->info.nodes;
5611 #else
5612    (void)route;
5613    return NULL;
5614 #endif
5615 }
5616
5617 EAPI const char *
5618 elm_map_route_waypoint_get(const Elm_Map_Route *route)
5619 {
5620 #ifdef HAVE_ELEMENTARY_ECORE_CON
5621    EINA_SAFETY_ON_NULL_RETURN_VAL(route, NULL);
5622    return route->info.waypoints;
5623 #else
5624    (void)route;
5625    return NULL;
5626 #endif
5627 }
5628
5629 EAPI Elm_Map_Name *
5630 elm_map_name_add(const Evas_Object *obj,
5631                  const char *address,
5632                  double lon,
5633                  double lat,
5634                  Elm_Map_Name_Cb name_cb,
5635                  void *data)
5636 {
5637 #ifdef HAVE_ELEMENTARY_ECORE_CON
5638    ELM_MAP_CHECK(obj) NULL;
5639
5640    if (address)
5641      return _name_request(obj, ELM_MAP_NAME_METHOD_SEARCH, address, 0, 0,
5642                           name_cb, data);
5643    else
5644      return _name_request(obj, ELM_MAP_NAME_METHOD_REVERSE, NULL, lon, lat,
5645                           name_cb, data);
5646 #else
5647    (void)obj;
5648    (void)address;
5649    (void)lon;
5650    (void)lat;
5651    (void)name_cb;
5652    (void)data;
5653    return NULL;
5654 #endif
5655 }
5656
5657 EAPI void
5658 elm_map_name_search(const Evas_Object *obj,
5659                   const char *address,
5660                   Elm_Map_Name_List_Cb name_cb,
5661                   void *data)
5662 {
5663 #ifdef HAVE_ELEMENTARY_ECORE_CON
5664    ELM_MAP_CHECK(obj);
5665    if (address)
5666      _name_list_request(obj, ELM_MAP_NAME_METHOD_SEARCH, address, 0, 0,
5667                         name_cb, data);
5668 #else
5669    (void) obj;
5670    (void) address;
5671    (void) name_cb;
5672    (void) data;
5673 #endif
5674 }
5675
5676 EAPI void
5677 elm_map_name_del(Elm_Map_Name *name)
5678 {
5679 #ifdef HAVE_ELEMENTARY_ECORE_CON
5680    EINA_SAFETY_ON_NULL_RETURN(name);
5681    EINA_SAFETY_ON_NULL_RETURN(name->wsd);
5682    ELM_MAP_CHECK(ELM_WIDGET_DATA(name->wsd)->obj);
5683
5684    if (name->job) ecore_file_download_abort(name->job);
5685    if (name->address) free(name->address);
5686    if (name->fname)
5687      {
5688         ecore_file_remove(name->fname);
5689         free(name->fname);
5690      }
5691
5692    name->wsd->names = eina_list_remove(name->wsd->names, name);
5693    free(name);
5694 #else
5695    (void)name;
5696 #endif
5697 }
5698
5699 EAPI const char *
5700 elm_map_name_address_get(const Elm_Map_Name *name)
5701 {
5702 #ifdef HAVE_ELEMENTARY_ECORE_CON
5703    EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
5704    EINA_SAFETY_ON_NULL_RETURN_VAL(name->wsd, NULL);
5705    ELM_MAP_CHECK(ELM_WIDGET_DATA(name->wsd)->obj) NULL;
5706
5707    return name->address;
5708 #else
5709    (void)name;
5710    return NULL;
5711 #endif
5712 }
5713
5714 EAPI void
5715 elm_map_name_region_get(const Elm_Map_Name *name,
5716                         double *lon,
5717                         double *lat)
5718 {
5719 #ifdef HAVE_ELEMENTARY_ECORE_CON
5720    EINA_SAFETY_ON_NULL_RETURN(name);
5721    EINA_SAFETY_ON_NULL_RETURN(name->wsd);
5722    ELM_MAP_CHECK(ELM_WIDGET_DATA(name->wsd)->obj);
5723
5724    if (lon) *lon = name->lon;
5725    if (lat) *lat = name->lat;
5726 #else
5727    (void)name;
5728    (void)lon;
5729    (void)lat;
5730 #endif
5731 }
5732
5733 EAPI Elm_Map_Overlay *
5734 elm_map_overlay_add(Evas_Object *obj,
5735                     double lon,
5736                     double lat)
5737 {
5738 #ifdef HAVE_ELEMENTARY_ECORE_CON
5739    Elm_Map_Overlay *overlay;
5740
5741    ELM_MAP_CHECK(obj) NULL;
5742    ELM_MAP_DATA_GET(obj, sd);
5743
5744    overlay = ELM_NEW(Elm_Map_Overlay);
5745    overlay->wsd = sd;
5746    overlay->type = ELM_MAP_OVERLAY_TYPE_DEFAULT;
5747    overlay->c.r = 0x87;
5748    overlay->c.g = 0xce;
5749    overlay->c.b = 0xeb;
5750    overlay->c.a = 255;
5751    overlay->ovl = _overlay_default_new(overlay, lon, lat, overlay->c, 1);
5752    overlay->grp = _overlay_group_new(sd);
5753    sd->overlays = eina_list_append(sd->overlays, overlay);
5754
5755    if (!strcmp(overlay->wsd->engine->name, INTERNAL_ENGINE_NAME))
5756      evas_object_smart_changed(overlay->wsd->pan_obj);
5757    else _overlay_place(sd);
5758
5759    return overlay;
5760 #else
5761    (void)obj;
5762    (void)lon;
5763    (void)lat;
5764    return NULL;
5765 #endif
5766 }
5767
5768 EAPI Eina_List *
5769 elm_map_overlays_get(Evas_Object *obj)
5770 {
5771 #ifdef HAVE_ELEMENTARY_ECORE_CON
5772    Eina_List *l;
5773    Elm_Map_Overlay *ovl;
5774
5775    ELM_MAP_CHECK(obj) NULL;
5776    ELM_MAP_DATA_GET(obj, sd);
5777
5778    eina_list_free(sd->all_overlays);
5779    sd->all_overlays = NULL;
5780
5781    EINA_LIST_FOREACH(sd->overlays, l, ovl)
5782      sd->all_overlays = eina_list_append(sd->all_overlays, ovl);
5783    EINA_LIST_FOREACH(sd->group_overlays, l, ovl)
5784      sd->all_overlays = eina_list_append(sd->all_overlays, ovl);
5785
5786    return sd->all_overlays;
5787 #else
5788    (void)obj;
5789    return NULL;
5790 #endif
5791 }
5792
5793 EAPI void
5794 elm_map_overlay_del(Elm_Map_Overlay *overlay)
5795 {
5796 #ifdef HAVE_ELEMENTARY_ECORE_CON
5797    EINA_SAFETY_ON_NULL_RETURN(overlay);
5798    EINA_SAFETY_ON_NULL_RETURN(overlay->wsd);
5799    ELM_MAP_CHECK(ELM_WIDGET_DATA(overlay->wsd)->obj);
5800
5801    evas_object_smart_callback_call
5802      (ELM_WIDGET_DATA(overlay->wsd)->obj, SIG_OVERLAY_DEL, overlay);
5803    if (overlay->del_cb)
5804      overlay->del_cb
5805        (overlay->del_cb_data, ELM_WIDGET_DATA(overlay->wsd)->obj, overlay);
5806
5807    if (overlay->grp)
5808      {
5809         if (overlay->grp->klass)
5810           elm_map_overlay_class_remove(overlay->grp->klass, overlay);
5811         _overlay_group_free(overlay->grp);
5812      }
5813
5814    if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
5815      _overlay_default_free(overlay->ovl);
5816    else if (overlay->type == ELM_MAP_OVERLAY_TYPE_BUBBLE)
5817      _overlay_bubble_free(overlay->ovl);
5818    else if (overlay->type == ELM_MAP_OVERLAY_TYPE_CLASS)
5819      _overlay_class_free(overlay->ovl);
5820    else if (overlay->type == ELM_MAP_OVERLAY_TYPE_ROUTE)
5821      _overlay_route_free(overlay->ovl);
5822    else if (overlay->type == ELM_MAP_OVERLAY_TYPE_LINE)
5823      _overlay_line_free(overlay->ovl);
5824    else if (overlay->type == ELM_MAP_OVERLAY_TYPE_POLYGON)
5825      _overlay_polygon_free(overlay->ovl);
5826    else if (overlay->type == ELM_MAP_OVERLAY_TYPE_CIRCLE)
5827      _overlay_circle_free(overlay->ovl);
5828    else if (overlay->type == ELM_MAP_OVERLAY_TYPE_SCALE)
5829      _overlay_scale_free(overlay->ovl);
5830    else ERR("Invalid overlay type: %d", overlay->type);
5831
5832    overlay->wsd->overlays = eina_list_remove(overlay->wsd->overlays, overlay);
5833    evas_object_smart_changed(overlay->wsd->pan_obj);
5834
5835    if (overlay->engobj)
5836       ELM_MAP_ENG_OBJECT_DELETE(overlay->wsd->engine->icon_remove,  ELM_WIDGET_DATA(overlay->wsd)->obj, overlay->engobj);
5837    free(overlay);
5838 #else
5839    (void)overlay;
5840 #endif
5841 }
5842
5843 EAPI Elm_Map_Overlay_Type
5844 elm_map_overlay_type_get(const Elm_Map_Overlay *overlay)
5845 {
5846 #ifdef HAVE_ELEMENTARY_ECORE_CON
5847    EINA_SAFETY_ON_NULL_RETURN_VAL(overlay, ELM_MAP_OVERLAY_TYPE_NONE);
5848    EINA_SAFETY_ON_NULL_RETURN_VAL(overlay->wsd, ELM_MAP_OVERLAY_TYPE_NONE);
5849    ELM_MAP_CHECK(ELM_WIDGET_DATA(overlay->wsd)->obj) ELM_MAP_OVERLAY_TYPE_NONE;
5850
5851    return overlay->type;
5852 #else
5853    (void)overlay;
5854    return ELM_MAP_OVERLAY_TYPE_NONE;
5855 #endif
5856 }
5857
5858 EAPI void
5859 elm_map_overlay_data_set(Elm_Map_Overlay *overlay,
5860                          void *data)
5861 {
5862 #ifdef HAVE_ELEMENTARY_ECORE_CON
5863    EINA_SAFETY_ON_NULL_RETURN(overlay);
5864    EINA_SAFETY_ON_NULL_RETURN(overlay->wsd);
5865    ELM_MAP_CHECK(ELM_WIDGET_DATA(overlay->wsd)->obj);
5866
5867    overlay->data = data;
5868 #else
5869    (void)overlay;
5870    (void)data;
5871 #endif
5872 }
5873
5874 EAPI void *
5875 elm_map_overlay_data_get(const Elm_Map_Overlay *overlay)
5876 {
5877 #ifdef HAVE_ELEMENTARY_ECORE_CON
5878    EINA_SAFETY_ON_NULL_RETURN_VAL(overlay, NULL);
5879    EINA_SAFETY_ON_NULL_RETURN_VAL(overlay->wsd, NULL);
5880    ELM_MAP_CHECK(ELM_WIDGET_DATA(overlay->wsd)->obj) NULL;
5881
5882    return overlay->data;
5883 #else
5884    (void)overlay;
5885    return NULL;
5886 #endif
5887 }
5888
5889 EAPI void
5890 elm_map_overlay_hide_set(Elm_Map_Overlay *overlay,
5891                          Eina_Bool hide)
5892 {
5893 #ifdef HAVE_ELEMENTARY_ECORE_CON
5894    EINA_SAFETY_ON_NULL_RETURN(overlay);
5895    EINA_SAFETY_ON_NULL_RETURN(overlay->wsd);
5896    ELM_MAP_CHECK(ELM_WIDGET_DATA(overlay->wsd)->obj);
5897
5898    if (overlay->hide == !!hide) return;
5899    overlay->hide = hide;
5900
5901    evas_object_smart_changed(overlay->wsd->pan_obj);
5902 #else
5903    (void)overlay;
5904    (void)hide;
5905 #endif
5906 }
5907
5908 EAPI Eina_Bool
5909 elm_map_overlay_hide_get(const Elm_Map_Overlay *overlay)
5910 {
5911 #ifdef HAVE_ELEMENTARY_ECORE_CON
5912    EINA_SAFETY_ON_NULL_RETURN_VAL(overlay, EINA_FALSE);
5913    EINA_SAFETY_ON_NULL_RETURN_VAL(overlay->wsd, EINA_FALSE);
5914    ELM_MAP_CHECK(ELM_WIDGET_DATA(overlay->wsd)->obj) EINA_FALSE;
5915
5916    return overlay->hide;
5917 #else
5918    (void)overlay;
5919    return EINA_FALSE;
5920 #endif
5921 }
5922
5923 EAPI void
5924 elm_map_overlay_displayed_zoom_min_set(Elm_Map_Overlay *overlay,
5925                                        int zoom)
5926 {
5927 #ifdef HAVE_ELEMENTARY_ECORE_CON
5928    EINA_SAFETY_ON_NULL_RETURN(overlay);
5929    EINA_SAFETY_ON_NULL_RETURN(overlay->wsd);
5930    ELM_MAP_CHECK(ELM_WIDGET_DATA(overlay->wsd)->obj);
5931
5932    overlay->zoom_min = zoom;
5933    evas_object_smart_changed(overlay->wsd->pan_obj);
5934 #else
5935    (void)overlay;
5936    (void)zoom;
5937 #endif
5938 }
5939
5940 EAPI int
5941 elm_map_overlay_displayed_zoom_min_get(const Elm_Map_Overlay *overlay)
5942 {
5943 #ifdef HAVE_ELEMENTARY_ECORE_CON
5944    EINA_SAFETY_ON_NULL_RETURN_VAL(overlay, 0);
5945    EINA_SAFETY_ON_NULL_RETURN_VAL(overlay->wsd, 0);
5946    ELM_MAP_CHECK(ELM_WIDGET_DATA(overlay->wsd)->obj) 0;
5947
5948    return overlay->zoom_min;
5949 #else
5950    (void)overlay;
5951    return 0;
5952 #endif
5953 }
5954
5955 EAPI void
5956 elm_map_overlay_paused_set(Elm_Map_Overlay *overlay,
5957                            Eina_Bool paused)
5958 {
5959 #ifdef HAVE_ELEMENTARY_ECORE_CON
5960    EINA_SAFETY_ON_NULL_RETURN(overlay);
5961    EINA_SAFETY_ON_NULL_RETURN(overlay->wsd);
5962    ELM_MAP_CHECK(ELM_WIDGET_DATA(overlay->wsd)->obj);
5963
5964    if (overlay->paused == !!paused) return;
5965    overlay->paused = paused;
5966
5967    evas_object_smart_changed(overlay->wsd->pan_obj);
5968 #else
5969    (void)overlay;
5970    (void)paused;
5971 #endif
5972 }
5973
5974 EAPI Eina_Bool
5975 elm_map_overlay_paused_get(const Elm_Map_Overlay *overlay)
5976 {
5977 #ifdef HAVE_ELEMENTARY_ECORE_CON
5978    EINA_SAFETY_ON_NULL_RETURN_VAL(overlay, EINA_FALSE);
5979    EINA_SAFETY_ON_NULL_RETURN_VAL(overlay->wsd, EINA_FALSE);
5980    ELM_MAP_CHECK(ELM_WIDGET_DATA(overlay->wsd)->obj) EINA_FALSE;
5981
5982    return overlay->paused;
5983 #else
5984    (void)overlay;
5985    return EINA_FALSE;
5986 #endif
5987 }
5988
5989 EAPI Eina_Bool
5990 elm_map_overlay_visible_get(const Elm_Map_Overlay *overlay)
5991 {
5992 #ifdef HAVE_ELEMENTARY_ECORE_CON
5993    EINA_SAFETY_ON_NULL_RETURN_VAL(overlay, EINA_FALSE);
5994    EINA_SAFETY_ON_NULL_RETURN_VAL(overlay->wsd, EINA_FALSE);
5995    ELM_MAP_CHECK(ELM_WIDGET_DATA(overlay->wsd)->obj) EINA_FALSE;
5996
5997    return overlay->visible;
5998 #else
5999    (void)overlay;
6000    return EINA_FALSE;
6001 #endif
6002 }
6003
6004 EAPI void
6005 elm_map_overlay_show(Elm_Map_Overlay *overlay)
6006 {
6007 #ifdef HAVE_ELEMENTARY_ECORE_CON
6008    EINA_SAFETY_ON_NULL_RETURN(overlay);
6009    EINA_SAFETY_ON_NULL_RETURN(overlay->wsd);
6010    ELM_MAP_CHECK(ELM_WIDGET_DATA(overlay->wsd)->obj);
6011
6012    if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
6013      {
6014         Overlay_Default *ovl = overlay->ovl;
6015
6016         elm_map_region_show
6017           (ELM_WIDGET_DATA(overlay->wsd)->obj, ovl->lon, ovl->lat);
6018      }
6019    else if (overlay->type == ELM_MAP_OVERLAY_TYPE_BUBBLE)
6020      {
6021         Overlay_Bubble *ovl = overlay->ovl;
6022
6023         elm_map_region_show
6024           (ELM_WIDGET_DATA(overlay->wsd)->obj, ovl->lon, ovl->lat);
6025      }
6026    else if (overlay->type == ELM_MAP_OVERLAY_TYPE_CLASS)
6027      {
6028         Overlay_Class *ovl = overlay->ovl;
6029         double lon, lat, max_lo, min_lo, max_la, min_la;
6030
6031         _region_max_min_get(ovl->members, &max_lo, &min_lo, &max_la, &min_la);
6032         lon = (max_lo + min_lo) / 2;
6033         lat = (max_la + min_la) / 2;
6034         elm_map_region_show(ELM_WIDGET_DATA(overlay->wsd)->obj, lon, lat);
6035      }
6036    else ERR("Not supported overlay type: %d", overlay->type);
6037
6038    evas_object_smart_changed(overlay->wsd->pan_obj);
6039 #else
6040    (void)overlay;
6041 #endif
6042 }
6043
6044 EAPI void
6045 elm_map_overlays_show(Eina_List *overlays)
6046 {
6047 #ifdef HAVE_ELEMENTARY_ECORE_CON
6048    Elm_Map_Smart_Data *sd;
6049    Elm_Map_Overlay *overlay;
6050
6051    EINA_SAFETY_ON_NULL_RETURN(overlays);
6052    EINA_SAFETY_ON_FALSE_RETURN(eina_list_count(overlays));
6053
6054    overlay = eina_list_data_get(overlays);
6055    sd = overlay->wsd;
6056
6057    if (!strcmp(sd->engine->name, INTERNAL_ENGINE_NAME))
6058      {
6059         sd->calc_job.overlays_changed = EINA_TRUE;
6060         sd->calc_job.overlays = overlays;
6061         evas_object_smart_changed(sd->pan_obj);
6062      }
6063    else ERR("Engine(%s) do not support overlays show", sd->engine->name);
6064
6065 #else
6066    (void)overlays;
6067 #endif
6068 }
6069
6070 EAPI void
6071 elm_map_overlay_region_set(Elm_Map_Overlay *overlay,
6072                            double lon,
6073                            double lat)
6074 {
6075 #ifdef HAVE_ELEMENTARY_ECORE_CON
6076    EINA_SAFETY_ON_NULL_RETURN(overlay);
6077    EINA_SAFETY_ON_NULL_RETURN(overlay->wsd);
6078    ELM_MAP_CHECK(ELM_WIDGET_DATA(overlay->wsd)->obj);
6079
6080    if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
6081      {
6082         Overlay_Default *ovl = overlay->ovl;
6083
6084         ovl->lon = lon;
6085         ovl->lat = lat;
6086      }
6087    else if (overlay->type == ELM_MAP_OVERLAY_TYPE_BUBBLE)
6088      {
6089         Overlay_Bubble *ovl = overlay->ovl;
6090
6091         ovl->pobj = NULL;
6092         ovl->lon = lon;
6093         ovl->lat = lat;
6094      }
6095    else ERR("Not supported overlay type: %d", overlay->type);
6096
6097    if (!strcmp(overlay->wsd->engine->name, INTERNAL_ENGINE_NAME))
6098      evas_object_smart_changed(overlay->wsd->pan_obj);
6099    else _overlay_place(overlay->wsd);
6100 #else
6101    (void)overlay;
6102    (void)lon;
6103    (void)lat;
6104 #endif
6105 }
6106
6107 EAPI void
6108 elm_map_overlay_region_get(const Elm_Map_Overlay *overlay,
6109                            double *lon,
6110                            double *lat)
6111 {
6112 #ifdef HAVE_ELEMENTARY_ECORE_CON
6113    EINA_SAFETY_ON_NULL_RETURN(overlay);
6114    EINA_SAFETY_ON_NULL_RETURN(overlay->wsd);
6115    ELM_MAP_CHECK(ELM_WIDGET_DATA(overlay->wsd)->obj);
6116
6117    if (overlay->type == ELM_MAP_OVERLAY_TYPE_GROUP)
6118      {
6119         Overlay_Group *ovl = overlay->ovl;
6120
6121         if (lon) *lon = ovl->lon;
6122         if (lat) *lat = ovl->lat;
6123      }
6124    else if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
6125      {
6126         const Overlay_Default *ovl = overlay->ovl;
6127
6128         if (lon) *lon = ovl->lon;
6129         if (lat) *lat = ovl->lat;
6130      }
6131    else if (overlay->type == ELM_MAP_OVERLAY_TYPE_BUBBLE)
6132      {
6133         const Overlay_Bubble *ovl = overlay->ovl;
6134
6135         if (lon) *lon = ovl->lon;
6136         if (lat) *lat = ovl->lat;
6137      }
6138    else ERR("Not supported overlay type: %d", overlay->type);
6139 #else
6140    (void)overlay;
6141    (void)lon;
6142    (void)lat;
6143 #endif
6144 }
6145
6146 EAPI void
6147 elm_map_overlay_icon_set(Elm_Map_Overlay *overlay,
6148                          Evas_Object *icon)
6149 {
6150 #ifdef HAVE_ELEMENTARY_ECORE_CON
6151    EINA_SAFETY_ON_NULL_RETURN(overlay);
6152    EINA_SAFETY_ON_NULL_RETURN(icon);
6153    EINA_SAFETY_ON_NULL_RETURN(overlay->wsd);
6154    ELM_MAP_CHECK(ELM_WIDGET_DATA(overlay->wsd)->obj);
6155
6156    if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
6157    {
6158        _overlay_default_icon_update(overlay->ovl, icon);
6159    }
6160    else if (overlay->type == ELM_MAP_OVERLAY_TYPE_CLASS)
6161    {
6162        _overlay_class_icon_update(overlay->ovl, icon);
6163    }
6164    else ERR("Not supported overlay type: %d", overlay->type);
6165
6166    evas_object_smart_changed(overlay->wsd->pan_obj);
6167 #else
6168    (void)overlay;
6169    (void)icon;
6170 #endif
6171 }
6172
6173 EAPI const Evas_Object *
6174 elm_map_overlay_icon_get(const Elm_Map_Overlay *overlay)
6175 {
6176 #ifdef HAVE_ELEMENTARY_ECORE_CON
6177    EINA_SAFETY_ON_NULL_RETURN_VAL(overlay, NULL);
6178    EINA_SAFETY_ON_NULL_RETURN_VAL(overlay->wsd, NULL);
6179    ELM_MAP_CHECK(ELM_WIDGET_DATA(overlay->wsd)->obj) NULL;
6180
6181    if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
6182      {
6183         const Overlay_Default *ovl = overlay->ovl;
6184
6185         return ovl->icon;
6186      }
6187    else if (overlay->type == ELM_MAP_OVERLAY_TYPE_CLASS)
6188      {
6189         const Overlay_Class *ovl = overlay->ovl;
6190
6191         return ovl->icon;
6192      }
6193    else
6194      {
6195         ERR("Not supported overlay type: %d", overlay->type);
6196         return NULL;
6197      }
6198 #else
6199    (void)overlay;
6200    return NULL;
6201 #endif
6202 }
6203
6204 EAPI void
6205 elm_map_overlay_content_set(Elm_Map_Overlay *overlay,
6206                             Evas_Object *content)
6207 {
6208 #ifdef HAVE_ELEMENTARY_ECORE_CON
6209    EINA_SAFETY_ON_NULL_RETURN(overlay);
6210    EINA_SAFETY_ON_NULL_RETURN(content);
6211    EINA_SAFETY_ON_NULL_RETURN(overlay->wsd);
6212    ELM_MAP_CHECK(ELM_WIDGET_DATA(overlay->wsd)->obj);
6213
6214    if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
6215    {
6216      if (MAP_ENGINE_OVERLAY_SUPPORT(overlay->wsd))
6217       {
6218           _overlay_default_engine_content_create_or_update(overlay, content);
6219       }
6220      else
6221          _overlay_default_content_update(overlay->ovl, content, overlay);
6222    }
6223    else if (overlay->type == ELM_MAP_OVERLAY_TYPE_CLASS)
6224        _overlay_class_content_update(overlay->ovl, content);
6225    else ERR("Not supported overlay type: %d", overlay->type);
6226
6227    if (!strcmp(overlay->wsd->engine->name, INTERNAL_ENGINE_NAME))
6228        evas_object_smart_changed(overlay->wsd->pan_obj);
6229    else _overlay_place(overlay->wsd);
6230 #else
6231    (void)overlay;
6232    (void)content;
6233 #endif
6234 }
6235
6236 EAPI const Evas_Object *
6237 elm_map_overlay_content_get(const Elm_Map_Overlay *overlay)
6238 {
6239 #ifdef HAVE_ELEMENTARY_ECORE_CON
6240    EINA_SAFETY_ON_NULL_RETURN_VAL(overlay, NULL);
6241    EINA_SAFETY_ON_NULL_RETURN_VAL(overlay->wsd, NULL);
6242
6243    ELM_MAP_CHECK(ELM_WIDGET_DATA(overlay->wsd)->obj) NULL;
6244
6245    if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
6246      {
6247         const Overlay_Default *ovl = overlay->ovl;
6248         return ovl->content;
6249      }
6250    else if (overlay->type == ELM_MAP_OVERLAY_TYPE_CLASS)
6251      {
6252         const Overlay_Class *ovl = overlay->ovl;
6253         return ovl->content;
6254      }
6255    else
6256      {
6257         ERR("Not supported overlay type: %d", overlay->type);
6258         return NULL;
6259      }
6260 #else
6261    (void)overlay;
6262    return NULL;
6263 #endif
6264 }
6265
6266 EAPI void
6267 elm_map_overlay_color_set(Elm_Map_Overlay *overlay,
6268                           int r,
6269                           int g,
6270                           int b,
6271                           int a)
6272 {
6273 #ifdef HAVE_ELEMENTARY_ECORE_CON
6274    EINA_SAFETY_ON_NULL_RETURN(overlay);
6275    EINA_SAFETY_ON_NULL_RETURN(overlay->wsd);
6276    ELM_MAP_CHECK(ELM_WIDGET_DATA(overlay->wsd)->obj);
6277
6278    overlay->c.r = r;
6279    overlay->c.g = g;
6280    overlay->c.b = b;
6281    overlay->c.a = a;
6282
6283    if (overlay->type == ELM_MAP_OVERLAY_TYPE_CLASS)
6284      _overlay_class_color_update(overlay->ovl, overlay->c);
6285    else if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
6286      _overlay_default_color_update(overlay->ovl, overlay->c);
6287    else if (overlay->type == ELM_MAP_OVERLAY_TYPE_ROUTE)
6288      _overlay_route_color_update(overlay->ovl, overlay->c);
6289    else if (overlay->type == ELM_MAP_OVERLAY_TYPE_CIRCLE)
6290      _overlay_circle_color_update(overlay->ovl, overlay->c);
6291    else
6292      {
6293         ERR("Not supported overlay type: %d", overlay->type);
6294      }
6295
6296 #else
6297    (void)overlay;
6298    (void)r;
6299    (void)g;
6300    (void)b;
6301    (void)a;
6302 #endif
6303 }
6304
6305 EAPI void
6306 elm_map_overlay_color_get(const Elm_Map_Overlay *overlay,
6307                           int *r,
6308                           int *g,
6309                           int *b,
6310                           int *a)
6311 {
6312 #ifdef HAVE_ELEMENTARY_ECORE_CON
6313    EINA_SAFETY_ON_NULL_RETURN(overlay);
6314    EINA_SAFETY_ON_NULL_RETURN(overlay->wsd);
6315    ELM_MAP_CHECK(ELM_WIDGET_DATA(overlay->wsd)->obj);
6316
6317    if (overlay->type == ELM_MAP_OVERLAY_TYPE_ROUTE)
6318      {
6319         if (r) *r = overlay->c.r;
6320         if (g) *g = overlay->c.g;
6321         if (b) *b = overlay->c.b;
6322         if (a) *a = overlay->c.a;
6323      }
6324    else ERR("Not supported overlay type: %d", overlay->type);
6325 #else
6326    (void)overlay;
6327    (void)r;
6328    (void)g;
6329    (void)b;
6330    (void)a;
6331 #endif
6332 }
6333
6334 EAPI void
6335 elm_map_overlay_get_cb_set(Elm_Map_Overlay *overlay,
6336                            Elm_Map_Overlay_Get_Cb get_cb,
6337                            void *data)
6338 {
6339 #ifdef HAVE_ELEMENTARY_ECORE_CON
6340    EINA_SAFETY_ON_NULL_RETURN(overlay);
6341    EINA_SAFETY_ON_NULL_RETURN(overlay->wsd);
6342    ELM_MAP_CHECK(ELM_WIDGET_DATA(overlay->wsd)->obj);
6343
6344    overlay->cb = get_cb;
6345    overlay->cb_data = data;
6346
6347    if (overlay->type == ELM_MAP_OVERLAY_TYPE_CLASS)
6348      _overlay_class_cb_set(overlay->ovl, get_cb, data);
6349 #else
6350    (void)overlay;
6351    (void)get_cb;
6352    (void)data;
6353 #endif
6354 }
6355
6356 EAPI void
6357 elm_map_overlay_del_cb_set(Elm_Map_Overlay *overlay,
6358                            Elm_Map_Overlay_Del_Cb del_cb,
6359                            void *data)
6360 {
6361 #ifdef HAVE_ELEMENTARY_ECORE_CON
6362    EINA_SAFETY_ON_NULL_RETURN(overlay);
6363    EINA_SAFETY_ON_NULL_RETURN(overlay->wsd);
6364    ELM_MAP_CHECK(ELM_WIDGET_DATA(overlay->wsd)->obj);
6365
6366    overlay->del_cb = del_cb;
6367    overlay->del_cb_data = data;
6368 #else
6369    (void)overlay;
6370    (void)del_cb;
6371    (void)data;
6372 #endif
6373 }
6374
6375 EAPI Elm_Map_Overlay *
6376 elm_map_overlay_class_add(Evas_Object *obj)
6377 {
6378 #ifdef HAVE_ELEMENTARY_ECORE_CON
6379    Elm_Map_Overlay *overlay;
6380    Overlay_Class *ovl;
6381
6382    ELM_MAP_CHECK(obj) NULL;
6383    ELM_MAP_DATA_GET(obj, sd);
6384
6385    overlay = ELM_NEW(Elm_Map_Overlay);
6386    overlay->wsd = sd;
6387    overlay->type = ELM_MAP_OVERLAY_TYPE_CLASS;
6388    overlay->ovl = _overlay_class_new(sd);
6389    overlay->c.r = 0x90;
6390    overlay->c.g = 0xee;
6391    overlay->c.b = 0x90;
6392    overlay->c.a = 0xff;
6393    sd->overlays = eina_list_append(sd->overlays, overlay);
6394    ovl = (Overlay_Class*)(overlay->ovl);
6395   //create groupmapobject
6396   //ELM_MAP_ENG_OBJECT_CREATE(sd->engine->group_create, overlay->engobj, ELM_WIDGET_DATA(overlay->wsd)->obj, ovl->lon, ovl->lat);
6397
6398    ovl->base = overlay;
6399
6400    evas_object_smart_changed(sd->pan_obj);
6401    return overlay;
6402 #else
6403    (void)obj;
6404    return NULL;
6405 #endif
6406 }
6407
6408 EAPI void
6409 elm_map_overlay_class_append(Elm_Map_Overlay *klass,
6410                              Elm_Map_Overlay *overlay)
6411 {
6412 #ifdef HAVE_ELEMENTARY_ECORE_CON
6413    Overlay_Class *class_ovl;
6414
6415    EINA_SAFETY_ON_NULL_RETURN(klass);
6416    EINA_SAFETY_ON_NULL_RETURN(overlay);
6417    EINA_SAFETY_ON_NULL_RETURN(klass->wsd);
6418    ELM_MAP_CHECK(ELM_WIDGET_DATA(klass->wsd)->obj);
6419    EINA_SAFETY_ON_FALSE_RETURN(klass->type == ELM_MAP_OVERLAY_TYPE_CLASS);
6420
6421    class_ovl = klass->ovl;
6422    if (eina_list_data_find(class_ovl->members, overlay))
6423      {
6424         ERR("Already added overlay into clas");
6425         return;
6426      }
6427    class_ovl->members = eina_list_append(class_ovl->members, overlay);
6428
6429    // Update group by class
6430    overlay->grp->klass = klass;
6431    _overlay_group_icon_update(overlay->grp, class_ovl->icon);
6432    _overlay_group_content_update(overlay->grp, class_ovl->content, overlay);
6433    _overlay_group_color_update(overlay->grp, klass->c);
6434    _overlay_group_cb_set(overlay->grp, klass->cb, klass->data);
6435    if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
6436      {
6437          _overlay_default_class_icon_update(overlay->ovl, class_ovl->icon);
6438          _overlay_default_class_content_update(overlay->ovl, class_ovl->content);
6439          if (overlay->engobj)
6440             ELM_MAP_ENG_OBJECT_SET(overlay->wsd->engine->object_visibility, ELM_WIDGET_DATA(overlay->wsd)->obj, overlay->engobj, 0);
6441      }
6442
6443    evas_object_smart_changed(klass->wsd->pan_obj);
6444 #else
6445    (void)klass;
6446    (void)overlay;
6447 #endif
6448 }
6449
6450 EAPI void
6451 elm_map_overlay_class_remove(Elm_Map_Overlay *klass,
6452                              Elm_Map_Overlay *overlay)
6453 {
6454 #ifdef HAVE_ELEMENTARY_ECORE_CON
6455    Overlay_Class *ovl;
6456
6457    EINA_SAFETY_ON_NULL_RETURN(klass);
6458    EINA_SAFETY_ON_NULL_RETURN(overlay);
6459    EINA_SAFETY_ON_NULL_RETURN(klass->wsd);
6460    ELM_MAP_CHECK(ELM_WIDGET_DATA(klass->wsd)->obj);
6461    EINA_SAFETY_ON_FALSE_RETURN(klass->type == ELM_MAP_OVERLAY_TYPE_CLASS);
6462
6463    ovl = klass->ovl;
6464    ovl->members = eina_list_remove(ovl->members, overlay);
6465
6466    overlay->grp->klass = NULL;
6467    _overlay_group_icon_update(overlay->grp, NULL);
6468    _overlay_group_content_update(overlay->grp, NULL, NULL);
6469    if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
6470      {
6471         _overlay_default_class_icon_update(overlay->ovl, NULL);
6472         _overlay_default_class_content_update(overlay->ovl, NULL);
6473         if (overlay->engobj)
6474            ELM_MAP_ENG_OBJECT_SET(overlay->wsd->engine->object_visibility, ELM_WIDGET_DATA(overlay->wsd)->obj, overlay->engobj, 1);
6475      }
6476
6477    evas_object_smart_changed(klass->wsd->pan_obj);
6478 #else
6479    (void)klass;
6480    (void)overlay;
6481 #endif
6482 }
6483
6484 EAPI void
6485 elm_map_overlay_class_zoom_max_set(Elm_Map_Overlay *klass,
6486                                    int zoom)
6487 {
6488 #ifdef HAVE_ELEMENTARY_ECORE_CON
6489    Overlay_Class *ovl;
6490
6491    EINA_SAFETY_ON_NULL_RETURN(klass);
6492    EINA_SAFETY_ON_NULL_RETURN(klass->wsd);
6493    ELM_MAP_CHECK(ELM_WIDGET_DATA(klass->wsd)->obj);
6494    EINA_SAFETY_ON_FALSE_RETURN(klass->type == ELM_MAP_OVERLAY_TYPE_CLASS);
6495
6496    ovl = klass->ovl;
6497    if (ovl->zoom_max == !!zoom) return;
6498    ovl->zoom_max = zoom;
6499
6500    evas_object_smart_changed(klass->wsd->pan_obj);
6501 #else
6502    (void)klass;
6503    (void)zoom;
6504 #endif
6505 }
6506
6507 EAPI int
6508 elm_map_overlay_class_zoom_max_get(const Elm_Map_Overlay *klass)
6509 {
6510 #ifdef HAVE_ELEMENTARY_ECORE_CON
6511    const Overlay_Class *ovl;
6512
6513    EINA_SAFETY_ON_NULL_RETURN_VAL(klass, OVERLAY_CLASS_ZOOM_MAX);
6514    EINA_SAFETY_ON_NULL_RETURN_VAL(klass->wsd, OVERLAY_CLASS_ZOOM_MAX);
6515    ELM_MAP_CHECK(ELM_WIDGET_DATA(klass->wsd)->obj) OVERLAY_CLASS_ZOOM_MAX;
6516
6517    EINA_SAFETY_ON_FALSE_RETURN_VAL
6518      (klass->type == ELM_MAP_OVERLAY_TYPE_CLASS, OVERLAY_CLASS_ZOOM_MAX);
6519
6520    ovl = klass->ovl;
6521    return ovl->zoom_max;
6522 #else
6523    (void)klass;
6524    return OVERLAY_CLASS_ZOOM_MAX;
6525 #endif
6526 }
6527
6528 EAPI Eina_List *
6529 elm_map_overlay_group_members_get(const Elm_Map_Overlay *grp)
6530 {
6531 #ifdef HAVE_ELEMENTARY_ECORE_CON
6532    Overlay_Group *ovl;
6533
6534    EINA_SAFETY_ON_NULL_RETURN_VAL(grp, NULL);
6535    EINA_SAFETY_ON_NULL_RETURN_VAL(grp->wsd, NULL);
6536    ELM_MAP_CHECK(ELM_WIDGET_DATA(grp->wsd)->obj) NULL;
6537
6538    EINA_SAFETY_ON_FALSE_RETURN_VAL
6539      (grp->type == ELM_MAP_OVERLAY_TYPE_GROUP, NULL);
6540
6541    ovl = grp->ovl;
6542    return ovl->members;
6543 #else
6544    (void)grp;
6545    return NULL;
6546 #endif
6547 }
6548
6549 EAPI Elm_Map_Overlay *
6550 elm_map_overlay_bubble_add(Evas_Object *obj)
6551 {
6552 #ifdef HAVE_ELEMENTARY_ECORE_CON
6553    Elm_Map_Overlay *overlay;
6554    Overlay_Bubble *ovl;
6555
6556    ELM_MAP_CHECK(obj) NULL;
6557    ELM_MAP_DATA_GET(obj, sd);
6558
6559    overlay = ELM_NEW(Elm_Map_Overlay);
6560    overlay->wsd = sd;
6561    overlay->type = ELM_MAP_OVERLAY_TYPE_BUBBLE;
6562    overlay->c.r = 255;
6563    overlay->c.g = 255;
6564    overlay->c.b = 255;
6565    overlay->c.a = 255;
6566    overlay->ovl = _overlay_bubble_new(overlay);
6567    overlay->grp = _overlay_group_new(sd);
6568    sd->overlays = eina_list_append(sd->overlays, overlay);
6569    ovl = (Overlay_Bubble*)(overlay->ovl);
6570    ovl->base = overlay;
6571
6572    evas_object_smart_changed(sd->pan_obj);
6573    return overlay;
6574 #else
6575    (void)obj;
6576    return NULL;
6577 #endif
6578 }
6579
6580 EAPI void
6581 elm_map_overlay_bubble_follow(Elm_Map_Overlay *bubble,
6582                               const Elm_Map_Overlay *parent)
6583 {
6584 #ifdef HAVE_ELEMENTARY_ECORE_CON
6585    Overlay_Bubble *ovl;
6586    Evas_Object *pobj;
6587
6588    EINA_SAFETY_ON_NULL_RETURN(bubble);
6589    EINA_SAFETY_ON_NULL_RETURN(parent);
6590    ELM_MAP_CHECK(ELM_WIDGET_DATA(bubble->wsd)->obj);
6591    EINA_SAFETY_ON_FALSE_RETURN(bubble->type == ELM_MAP_OVERLAY_TYPE_BUBBLE);
6592
6593    ovl = bubble->ovl;
6594    pobj = _overlay_obj_get(parent);
6595    if (!pobj) return;
6596
6597    ovl->pobj = pobj;
6598    evas_object_smart_changed(bubble->wsd->pan_obj);
6599 #else
6600    (void)bubble;
6601    (void)parent;
6602 #endif
6603 }
6604
6605 EAPI void
6606 elm_map_overlay_bubble_content_append(Elm_Map_Overlay *bubble,
6607                                       Evas_Object *content)
6608 {
6609 #ifdef HAVE_ELEMENTARY_ECORE_CON
6610    Overlay_Bubble *bb;
6611
6612    EINA_SAFETY_ON_NULL_RETURN(bubble);
6613    EINA_SAFETY_ON_NULL_RETURN(content);
6614    ELM_MAP_CHECK(ELM_WIDGET_DATA(bubble->wsd)->obj);
6615    EINA_SAFETY_ON_FALSE_RETURN(bubble->type == ELM_MAP_OVERLAY_TYPE_BUBBLE);
6616
6617    bb = bubble->ovl;
6618    elm_box_pack_end(bb->bx, content);
6619
6620    evas_object_smart_changed(bubble->wsd->pan_obj);
6621 #else
6622    (void)bubble;
6623    (void)content;
6624 #endif
6625 }
6626
6627 EAPI void
6628 elm_map_overlay_bubble_content_clear(Elm_Map_Overlay *bubble)
6629 {
6630 #ifdef HAVE_ELEMENTARY_ECORE_CON
6631    Overlay_Bubble *bb;
6632
6633    EINA_SAFETY_ON_NULL_RETURN(bubble);
6634    ELM_MAP_CHECK(ELM_WIDGET_DATA(bubble->wsd)->obj);
6635    EINA_SAFETY_ON_FALSE_RETURN(bubble->type == ELM_MAP_OVERLAY_TYPE_BUBBLE);
6636
6637    bb = bubble->ovl;
6638    elm_box_clear(bb->bx);
6639
6640    evas_object_smart_changed(bubble->wsd->pan_obj);
6641 #else
6642    (void)bubble;
6643 #endif
6644 }
6645
6646 EAPI Elm_Map_Overlay *
6647 elm_map_overlay_route_add(Evas_Object *obj,
6648                           const Elm_Map_Route *route)
6649 {
6650 #ifdef HAVE_ELEMENTARY_ECORE_CON
6651    Elm_Map_Overlay *overlay;
6652
6653    ELM_MAP_CHECK(obj) NULL;
6654    ELM_MAP_DATA_GET(obj, sd);
6655
6656    EINA_SAFETY_ON_NULL_RETURN_VAL(route, NULL);
6657    EINA_SAFETY_ON_NULL_RETURN_VAL(route->wsd, NULL);
6658    EINA_SAFETY_ON_FALSE_RETURN_VAL
6659      (obj == ELM_WIDGET_DATA(route->wsd)->obj, NULL);
6660
6661    overlay = ELM_NEW(Elm_Map_Overlay);
6662    overlay->wsd = sd;
6663    overlay->type = ELM_MAP_OVERLAY_TYPE_ROUTE;
6664    overlay->c.r = 0xff;
6665    overlay->c.g = 0x00;
6666    overlay->c.b = 0x00;
6667    overlay->c.a = 0xff;
6668    overlay->ovl = _overlay_route_new(sd, route, overlay->c);
6669    overlay->grp = _overlay_group_new(sd);
6670    sd->overlays = eina_list_append(sd->overlays, overlay);
6671
6672    evas_object_smart_changed(sd->pan_obj);
6673    return overlay;
6674 #else
6675    (void)obj;
6676    (void)route;
6677    return NULL;
6678 #endif
6679 }
6680
6681 EAPI Elm_Map_Overlay *
6682 elm_map_overlay_line_add(Evas_Object *obj,
6683                          double flon,
6684                          double flat,
6685                          double tlon,
6686                          double tlat)
6687 {
6688 #ifdef HAVE_ELEMENTARY_ECORE_CON
6689    Elm_Map_Overlay *overlay;
6690    Overlay_Line *ovl = NULL;
6691
6692    ELM_MAP_CHECK(obj) NULL;
6693    ELM_MAP_DATA_GET(obj, sd);
6694
6695    overlay = ELM_NEW(Elm_Map_Overlay);
6696    overlay->wsd = sd;
6697    overlay->type = ELM_MAP_OVERLAY_TYPE_LINE;
6698    overlay->c.r = 0xff;
6699    overlay->c.g = 0x00;
6700    overlay->c.b = 0x00;
6701    overlay->c.a = 0xff;
6702    overlay->ovl = _overlay_line_new(sd, flon, flat, tlon, tlat, overlay->c);
6703    overlay->grp = _overlay_group_new(sd);
6704    sd->overlays = eina_list_append(sd->overlays, overlay);
6705    ovl = (Overlay_Line*)(overlay->ovl);
6706    ovl->base = overlay;
6707
6708    evas_object_smart_changed(sd->pan_obj);
6709    return overlay;
6710 #else
6711    (void)obj;
6712    (void)flon;
6713    (void)flat;
6714    (void)tlon;
6715    (void)tlat;
6716    return NULL;
6717 #endif
6718 }
6719
6720 EAPI Elm_Map_Overlay *
6721 elm_map_overlay_polygon_add(Evas_Object *obj)
6722 {
6723 #ifdef HAVE_ELEMENTARY_ECORE_CON
6724    Elm_Map_Overlay *overlay;
6725    Overlay_Polygon *ovl = NULL;
6726
6727    ELM_MAP_CHECK(obj) NULL;
6728    ELM_MAP_DATA_GET(obj, sd);
6729
6730    overlay = ELM_NEW(Elm_Map_Overlay);
6731    overlay->wsd = sd;
6732    overlay->type = ELM_MAP_OVERLAY_TYPE_POLYGON;
6733    overlay->c.r = 0xdc;
6734    overlay->c.g = 0x14;
6735    overlay->c.b = 0x3c;
6736    overlay->c.a = 220;
6737    overlay->ovl = _overlay_polygon_new(sd, overlay->c);
6738    overlay->grp = _overlay_group_new(sd);
6739    sd->overlays = eina_list_append(sd->overlays, overlay);
6740    evas_object_smart_changed(sd->pan_obj);
6741    ovl = (Overlay_Polygon*)(overlay->ovl);
6742    ovl->base = overlay;
6743    return overlay;
6744 #else
6745    (void)obj;
6746    return NULL;
6747 #endif
6748 }
6749
6750 EAPI void
6751 elm_map_overlay_polygon_region_add(Elm_Map_Overlay *overlay,
6752                                    double lon,
6753                                    double lat)
6754 {
6755 #ifdef HAVE_ELEMENTARY_ECORE_CON
6756    Overlay_Polygon *ovl;
6757    Region *r;
6758
6759    EINA_SAFETY_ON_NULL_RETURN(overlay);
6760    ELM_MAP_CHECK(ELM_WIDGET_DATA(overlay->wsd)->obj);
6761    EINA_SAFETY_ON_FALSE_RETURN(overlay->type == ELM_MAP_OVERLAY_TYPE_POLYGON);
6762
6763    ovl = overlay->ovl;
6764    r = ELM_NEW(Region);
6765    r->lon = lon;
6766    r->lat = lat;
6767    ovl->regions = eina_list_append(ovl->regions, r);
6768
6769    evas_object_smart_changed(ovl->wsd->pan_obj);
6770 #else
6771    (void)overlay;
6772    (void)lon;
6773    (void)lat;
6774 #endif
6775 }
6776
6777 EAPI Elm_Map_Overlay *
6778 elm_map_overlay_circle_add(Evas_Object *obj,
6779                            double lon,
6780                            double lat,
6781                            double radius)
6782 {
6783 #ifdef HAVE_ELEMENTARY_ECORE_CON
6784    Elm_Map_Overlay *overlay;
6785
6786    ELM_MAP_CHECK(obj) NULL;
6787    ELM_MAP_DATA_GET(obj, sd);
6788
6789    overlay = ELM_NEW(Elm_Map_Overlay);
6790    overlay->wsd = sd;
6791    overlay->type = ELM_MAP_OVERLAY_TYPE_CIRCLE;
6792    overlay->c.r = 0xdc;
6793    overlay->c.g = 0x14;
6794    overlay->c.b = 0x3c;
6795    overlay->c.a = 220;
6796    overlay->ovl = _overlay_circle_new(sd, lon, lat, radius, overlay->c);
6797    overlay->grp = _overlay_group_new(sd);
6798    sd->overlays = eina_list_append(sd->overlays, overlay);
6799
6800    evas_object_smart_changed(sd->pan_obj);
6801    return overlay;
6802 #else
6803    (void)obj;
6804    (void)lon;
6805    (void)lat;
6806    (void)radius;
6807    return NULL;
6808 #endif
6809 }
6810
6811 EAPI Elm_Map_Overlay *
6812 elm_map_overlay_scale_add(Evas_Object *obj,
6813                           Evas_Coord x,
6814                           Evas_Coord y)
6815 {
6816 #ifdef HAVE_ELEMENTARY_ECORE_CON
6817    Elm_Map_Overlay *overlay;
6818    Overlay_Scale *ovl = NULL;
6819
6820    ELM_MAP_CHECK(obj) NULL;
6821    ELM_MAP_DATA_GET(obj, sd);
6822
6823    overlay = ELM_NEW(Elm_Map_Overlay);
6824    overlay->wsd = sd;
6825    overlay->type = ELM_MAP_OVERLAY_TYPE_SCALE;
6826    overlay->c.r = 0;
6827    overlay->c.g = 0;
6828    overlay->c.b = 0;
6829    overlay->c.a = 255;
6830    overlay->ovl = _overlay_scale_new(sd, x, y, overlay->c);
6831    overlay->grp = _overlay_group_new(sd);
6832    sd->overlays = eina_list_append(sd->overlays, overlay);
6833    ovl = (Overlay_Scale*)(overlay->ovl);
6834    ovl->base = overlay;
6835
6836    evas_object_smart_changed(sd->pan_obj);
6837    return overlay;
6838 #else
6839    (void)obj;
6840    (void)x;
6841    (void)y;
6842    return NULL;
6843 #endif
6844 }
6845
6846 #ifdef ELM_EMAP
6847 EAPI Evas_Object *
6848 elm_map_track_add(Evas_Object *obj,
6849                   void *emap)
6850 {
6851 #ifdef HAVE_ELEMENTARY_ECORE_CON
6852    EMap_Route *emapr = emap;
6853    Evas_Object *route;
6854
6855    ELM_MAP_CHECK(obj) NULL;
6856    ELM_MAP_DATA_GET(obj, sd);
6857
6858    route = elm_route_add(obj);
6859    elm_route_emap_set(route, emapr);
6860    sd->track = eina_list_append(sd->track, route);
6861
6862    return route;
6863 #else
6864    (void)obj;
6865    (void)emap;
6866    return NULL;
6867 #endif
6868 }
6869
6870 EAPI void
6871 elm_map_track_remove(Evas_Object *obj,
6872                      Evas_Object *route)
6873 {
6874 #ifdef HAVE_ELEMENTARY_ECORE_CON
6875    ELM_MAP_CHECK(obj);
6876    ELM_MAP_DATA_GET(obj, sd);
6877
6878    sd->track = eina_list_remove(sd->track, route);
6879    evas_object_del(route);
6880 #else
6881    (void)obj;
6882    (void)route;
6883 #endif
6884 }
6885
6886 #else
6887 EAPI Evas_Object *
6888 elm_map_track_add(Evas_Object *obj __UNUSED__,
6889                   void *emap __UNUSED__)
6890 {
6891    return NULL;
6892 }
6893
6894 EAPI void
6895 elm_map_track_remove(Evas_Object *obj __UNUSED__,
6896                      Evas_Object *route __UNUSED__)
6897 {
6898 }
6899 #endif