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