Elementary map: split route & track (watchwolf's suggestion)
authorgouache <gouache@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Fri, 20 May 2011 05:55:15 +0000 (05:55 +0000)
committergouache <gouache@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Fri, 20 May 2011 05:55:15 +0000 (05:55 +0000)
git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/elementary@59548 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/bin/test_map.c
src/lib/Elementary.h.in
src/lib/elm_map.c

index 8704ed1..8a07a29 100644 (file)
@@ -22,12 +22,13 @@ typedef struct Map_Source
 static Elm_Map_Marker_Class *itc1, *itc2, *itc_parking;
 static Elm_Map_Group_Class *itc_group1, *itc_group2, *itc_group_parking;
 
-static Evas_Object *rect, *menu;
+static Evas_Object *rect, *menu, *fs_win;
 static int nb_elts;
 /*static Elm_Map_Marker *markers[MARKER_MAX];*/
 static Elm_Map_Marker *route_from, *route_to;
 static Elm_Map_Route *route;
 static Elm_Map_Name *name;
+static Elm_Map_Track *track;
 static const char **source_names = NULL;
 static Evas_Coord old_x, old_y;
 static Evas_Coord old_d;
@@ -51,6 +52,19 @@ static Evas_Object * _marker_get(Evas_Object *obj, Elm_Map_Marker *marker __UNUS
 static Evas_Object * _group_icon_get(Evas_Object *obj, void *data);
 
 static void
+my_map_gpx_fileselector_done(void *data, Evas_Object *obj __UNUSED__, void *event_info)
+{
+   const char *selected = event_info;
+
+   if (selected)
+     {
+        printf("Selected file: %s\n", selected);
+        track = elm_map_track_add(data, selected);
+     }
+   evas_object_del(fs_win);
+}
+
+static void
 my_map_clicked(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
 {
    printf("clicked\n");
@@ -322,6 +336,57 @@ map_zoom_fill(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED
 }
 
 static void
+map_track_add(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   Evas_Object *fs, *bg, *vbox, *hbox, *sep;
+
+   fs_win = elm_win_add(NULL, "fileselector", ELM_WIN_BASIC);
+   elm_win_title_set(fs_win, "File Selector");
+   elm_win_autodel_set(fs_win, 1);
+
+   bg = elm_bg_add(fs_win);
+   elm_win_resize_object_add(fs_win, bg);
+   evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(bg);
+
+   vbox = elm_box_add(fs_win);
+   elm_win_resize_object_add(fs_win, vbox);
+   evas_object_size_hint_weight_set(vbox, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_show(vbox);
+
+   fs = elm_fileselector_add(fs_win);
+   elm_fileselector_is_save_set(fs, EINA_TRUE);
+   elm_fileselector_expandable_set(fs, EINA_FALSE);
+   elm_fileselector_path_set(fs, getenv("HOME"));
+   evas_object_size_hint_weight_set(fs, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+   evas_object_size_hint_align_set(fs, EVAS_HINT_FILL, EVAS_HINT_FILL);
+   elm_box_pack_end(vbox, fs);
+   evas_object_show(fs);
+
+   evas_object_smart_callback_add(fs, "done", my_map_gpx_fileselector_done, data);
+
+   sep = elm_separator_add(fs_win);
+   elm_separator_horizontal_set(sep, EINA_TRUE);
+   elm_box_pack_end(vbox, sep);
+   evas_object_show(sep);
+
+   hbox = elm_box_add(fs_win);
+   elm_box_horizontal_set(hbox, EINA_TRUE);
+   elm_box_pack_end(vbox, hbox);
+   evas_object_show(hbox);
+
+   evas_object_resize(fs_win, 240, 350);
+   evas_object_show(fs_win);
+}
+
+
+static void
+map_track_remove(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+   elm_map_track_remove(track);
+}
+
+static void
 map_rotate_cw(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
 {
    double d;
@@ -557,6 +622,8 @@ _map_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event
         elm_menu_item_add(menu, NULL, NULL, "Zoom -", map_zoom_out, data);
         elm_menu_item_add(menu, NULL, NULL, "Zoom Fit", map_zoom_fit, data);
         elm_menu_item_add(menu, NULL, NULL, "Zoom Fill", map_zoom_fill, data);
+        elm_menu_item_add(menu, NULL, NULL, "Add Track", map_track_add, data);
+        elm_menu_item_add(menu, NULL, NULL, "Remove Track", map_track_remove, data);
         elm_menu_item_add(menu, NULL, NULL, "Add Marker", NULL, NULL);
         elm_menu_item_add(menu, NULL, NULL, "Rotate CW", map_rotate_cw, data);
         elm_menu_item_add(menu, NULL, NULL, "Rotate CCW", map_rotate_ccw, data);
index b5b7794..199c22e 100644 (file)
@@ -2342,6 +2342,7 @@ extern "C" {
    typedef struct _Elm_Map_Group_Class     Elm_Map_Group_Class;
    typedef struct _Elm_Map_Route           Elm_Map_Route;
    typedef struct _Elm_Map_Name            Elm_Map_Name;
+   typedef struct _Elm_Map_Track           Elm_Map_Track;
 
    typedef Evas_Object *(*ElmMapMarkerGetFunc)      (Evas_Object *obj, Elm_Map_Marker *marker, void *data);
    typedef void         (*ElmMapMarkerDelFunc)      (Evas_Object *obj, Elm_Map_Marker *marker, void *data, Evas_Object *o);
@@ -2421,6 +2422,10 @@ extern "C" {
    EAPI void                  elm_map_rotate_get(const Evas_Object *obj, double *degree, Evas_Coord *cx, Evas_Coord *cy) EINA_ARG_NONNULL(1, 2, 3, 4);
    EAPI void                  elm_map_wheel_disabled_set(Evas_Object *obj, Eina_Bool disabled) EINA_ARG_NONNULL(1);
    EAPI Eina_Bool             elm_map_wheel_disabled_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
+   EAPI Elm_Map_Track        *elm_map_track_add(Evas_Object *obj, const char *gpx_file) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_track_remove(Elm_Map_Track *track) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_track_color_set(Elm_Map_Track *track, int r, int g , int b, int a) EINA_ARG_NONNULL(1);
+   EAPI void                  elm_map_track_color_get(const Elm_Map_Track *track, int *r, int *g , int *b, int *a) EINA_ARG_NONNULL(1);
 
    /* smart callbacks called:
     * "clicked" - when image clicked
index 91a5e61..ef599eb 100644 (file)
@@ -61,11 +61,12 @@ typedef struct _Grid Grid;
 typedef struct _Grid_Item Grid_Item;
 typedef struct _Marker_Group Marker_Group;
 typedef struct _Event Event;
-typedef struct _Route_Node Route_Node;
-typedef struct _Route_Waypoint Route_Waypoint;
+typedef struct _Path_Node Path_Node;
+typedef struct _Path_Waypoint Path_Waypoint;
 typedef struct _Url_Data Url_Data;
 typedef struct _Route_Dump Route_Dump;
 typedef struct _Name_Dump Name_Dump;
+typedef struct _Track_Dump Track_Dump;
 
 #define DEST_DIR_ZOOM_PATH "/tmp/elm_map/%d/%d/"
 #define DEST_DIR_PATH DEST_DIR_ZOOM_PATH"%d/"
@@ -94,6 +95,13 @@ typedef struct _Name_Dump Name_Dump;
 #define PINCH_ZOOM_MIN 0.1
 #define PINCH_ZOOM_MAX 5.0
 
+#define GPX_NAME "name>"
+#define GPX_COORDINATES "trkpt "
+#define GPX_LON "lon"
+#define GPX_LAT "lat"
+#define GPX_ELE "ele>"
+#define GPX_TIME "time>"
+
 // Map sources
 // Currently the size of a tile must be 256*256
 // and the size of the map must be pow(2.0, z)*tile_size
@@ -220,8 +228,8 @@ struct _Elm_Map_Route
 {
    Widget_Data *wd;
 
-   Route_Node *n;
-   Route_Waypoint *w;
+   Path_Node *n;
+   Path_Waypoint *w;
    Ecore_Con_Url *con_url;
 
    int type;
@@ -253,7 +261,7 @@ struct _Elm_Map_Route
    Eina_Bool inbound : 1;
 };
 
-struct _Route_Node
+struct _Path_Node
 {
    Widget_Data *wd;
 
@@ -264,7 +272,7 @@ struct _Route_Node
    } pos;
 };
 
-struct _Route_Waypoint
+struct _Path_Waypoint
 {
    Widget_Data *wd;
 
@@ -283,6 +291,37 @@ struct _Elm_Map_Name
    Ecore_Event_Handler *handler;
 };
 
+struct _Elm_Map_Track
+{
+   Widget_Data *wd;
+
+   Path_Node *n;
+   Path_Waypoint *w;
+
+   int x, y;
+   double flon, flat, tlon, tlat;
+
+   Eina_List *nodes, *path;
+   Eina_List *waypoint;
+
+   struct {
+      int node_count;
+      int waypoint_count;
+      const char *nodes;
+      const char *waypoints;
+      double distance; /* unit : km */
+   } info;
+
+   struct {
+      int r;
+      int g;
+      int b;
+      int a;
+   } color;
+
+   Eina_Bool inbound : 1;
+};
+
 struct _Grid_Item
 {
    Widget_Data *wd;
@@ -374,6 +413,7 @@ struct _Widget_Data
    Eina_Hash *ua;
    const char *user_agent;
    Eina_List *route;
+   Eina_List *track;
    Evas_Event_Mouse_Down ev;
    Eina_List *names;
    int multi_count;
@@ -402,6 +442,7 @@ struct _Widget_Data
    Evas_Map *map;
    Ecore_Timer *zoom_timer;
    Map_Sources_Tab *src;
+   const char *gpx_file;
 };
 
 struct _Pan
@@ -474,6 +515,22 @@ enum _Zoom_Method
    ZOOM_METHOD_LAST
 } Zoom_Mode;
 
+struct _Track_Dump
+{
+   Elm_Map_Track *track;
+   int idx;
+   double lon;
+   double lat;
+};
+
+enum _Track_Xml_Attribute
+{
+   TRACK_XML_NONE,
+   TRACK_XML_COORDINATES,
+   TRACK_XML_LAST
+} Track_Xml_Attibute;
+
+
 static const char *widtype = NULL;
 
 static const char SIG_CHANGED[] = "changed";
@@ -556,6 +613,7 @@ static void _mouse_multi_up(void *data, Evas *evas, Evas_Object *obj, void *even
 static void _mouse_multi_move(void *data, Evas *evas, Evas_Object *obj, void *event_info);
 
 static void route_place(Evas_Object *obj, Grid *g, Evas_Coord px, Evas_Coord py, Evas_Coord ox, Evas_Coord oy, Evas_Coord ow, Evas_Coord oh);
+static void track_place(Evas_Object *obj, Grid *g, Evas_Coord px, Evas_Coord py, Evas_Coord ox, Evas_Coord oy, Evas_Coord ow, Evas_Coord oh);
 
 static int
 get_multi_device(Evas_Object *obj)
@@ -755,12 +813,91 @@ obj_rotate_zoom(void *data, Evas_Object *obj)
 }
 
 static void
+track_place(Evas_Object *obj, Grid *g __UNUSED__, Evas_Coord px, Evas_Coord py, Evas_Coord ox __UNUSED__, Evas_Coord oy __UNUSED__, Evas_Coord ow, Evas_Coord oh)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype);
+   Widget_Data *wd = elm_widget_data_get(obj);
+   Eina_List *lr, *lp, *ln;
+   Path_Node *n;
+   Evas_Object *p;
+   Elm_Map_Track *t;
+   int nodes;
+   int x, y, rx, ry;
+   double a;
+
+   if (!wd) return;
+   Evas_Coord size = pow(2.0, wd->zoom)*wd->tsize;
+
+   EINA_LIST_FOREACH(wd->track, lr, t)
+     {
+        EINA_LIST_FOREACH(t->path, lp, p)
+          {
+             evas_object_polygon_points_clear(p);
+          }
+
+        evas_object_geometry_get(wd->rect, &rx, &ry, NULL, NULL);
+        nodes = eina_list_count(t->nodes);
+
+        EINA_LIST_FOREACH(t->nodes, ln, n)
+          {
+             if (t->inbound)
+               {
+                  elm_map_utils_convert_geo_into_coord(wd->obj, n->pos.lon, n->pos.lat, size, &x, &y);
+                  if ((x >= px - ow) && (x <= (px + ow*2)) &&
+                      (y >= py - oh) && (y <= (py + oh*2)))
+                    {
+                       x = x - px + rx;
+                       y = y - py + ry;
+
+                       p = eina_list_nth(t->path, n->idx);
+                       a = (double)(y - t->y) / (double)(x - t->x);
+                       if ((abs(a) >= 1) || (t->x == x))
+                         {
+                            evas_object_polygon_point_add(p, t->x - 3, t->y);
+                            evas_object_polygon_point_add(p, t->x + 3, t->y);
+                            evas_object_polygon_point_add(p, x + 3, y);
+                            evas_object_polygon_point_add(p, x - 3, y);
+                         }
+                       else
+                         {
+                            evas_object_polygon_point_add(p, t->x, t->y - 3);
+                            evas_object_polygon_point_add(p, t->x, t->y + 3);
+                            evas_object_polygon_point_add(p, x, y + 3);
+                            evas_object_polygon_point_add(p, x, y - 3);
+                         }
+
+                       evas_object_color_set(p, t->color.r, t->color.g, t->color.b, t->color.a);
+                       evas_object_raise(p);
+                       obj_rotate_zoom(obj, p);
+                       evas_object_show(p);
+                       t->x = x;
+                       t->y = y;
+                    }
+                  else t->inbound = EINA_FALSE;
+               }
+             else
+               {
+                  elm_map_utils_convert_geo_into_coord(wd->obj, n->pos.lon, n->pos.lat, size, &x, &y);
+                  if ((x >= px - ow) && (x <= (px + ow*2)) &&
+                      (y >= py - oh) && (y <= (py + oh*2)))
+                    {
+                       t->x = x - px + rx;
+                       t->y = y - py + ry;
+                       t->inbound = EINA_TRUE;
+                    }
+                  else t->inbound = EINA_FALSE;
+               }
+          }
+          t->inbound = EINA_FALSE;
+     }
+}
+static void
 route_place(Evas_Object *obj, Grid *g __UNUSED__, Evas_Coord px, Evas_Coord py, Evas_Coord ox __UNUSED__, Evas_Coord oy __UNUSED__, Evas_Coord ow, Evas_Coord oh)
 {
    ELM_CHECK_WIDTYPE(obj, widtype);
    Widget_Data *wd = elm_widget_data_get(obj);
    Eina_List *lr, *lp, *ln;
-   Route_Node *n;
+   Path_Node *n;
    Evas_Object *p;
    Elm_Map_Route *r;
    int nodes;
@@ -1943,11 +2080,12 @@ _del_hook(Evas_Object *obj)
    Eina_List *l;
    Event *ev;
    Evas_Object *p;
-   Route_Node *n;
-   Route_Waypoint *w;
+   Path_Node *n;
+   Path_Waypoint *w;
    Ecore_Event_Handler *h;
    Elm_Map_Route *r;
    Elm_Map_Name *na;
+   Elm_Map_Track *t;
 
    if (!wd) return;
    EINA_LIST_FREE(wd->groups_clas, group_clas)
@@ -2010,6 +2148,20 @@ _del_hook(Evas_Object *obj)
           }
      }
 
+   EINA_LIST_FOREACH(wd->track, l, t)
+     {
+        EINA_LIST_FREE(t->path, p)
+          {
+             evas_object_del(p);
+          }
+
+        EINA_LIST_FREE(t->nodes, n)
+          {
+             if (n->pos.address) eina_stringshare_del(n->pos.address);
+             free(n);
+          }
+     }
+
    if (wd->map) evas_map_free(wd->map);
    if (wd->source_names) free(wd->source_names);
    if (wd->calc_job) ecore_job_del(wd->calc_job);
@@ -2242,6 +2394,7 @@ _pan_calculate(Evas_Object *obj)
         grid_place(sd->wd->obj, g, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh);
         marker_place(sd->wd->obj, g, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh);
         if (!sd->wd->zoom_animator) route_place(sd->wd->obj, g, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh);
+        if (!sd->wd->zoom_animator) track_place(sd->wd->obj, g, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh);
      }
 }
 
@@ -2817,7 +2970,7 @@ _parse_kml(void *data)
              r->info.waypoint_count = ele;
              for (idx = 0 ; idx < ele ; idx++)
                {
-                  Route_Waypoint *wp = ELM_NEW(Route_Waypoint);
+                  Path_Waypoint *wp = ELM_NEW(Path_Waypoint);
                   if (wp)
                     {
                        wp->wd = r->wd;
@@ -2842,7 +2995,7 @@ _parse_kml(void *data)
              for (idx = 0 ; idx < ele ; idx++)
                {
                   sscanf(str[idx], "%lf,%lf", &lon, &lat);
-                  Route_Node *n = ELM_NEW(Route_Node);
+                  Path_Node *n = ELM_NEW(Path_Node);
                   if (n)
                     {
                        n->wd = r->wd;
@@ -3018,6 +3171,66 @@ _utils_convert_name(const Evas_Object *obj, int method, char *address, double lo
 
 }
 
+static Eina_Bool
+cb_dump_track_attr(void *data, const char *key, const char *value)
+{
+   Track_Dump *dump = data;
+   Evas_Object *path;
+   double d;
+
+   if (!dump) return EINA_FALSE;
+   if (!strcmp(GPX_LON, key))
+     {
+        sscanf(value, "%lf", &d);
+        dump->lon  = d;
+     }
+   else if (!strcmp(GPX_LAT, key))
+     {
+        sscanf(value, "%lf", &d);
+        dump->lat  = d;
+     }
+
+   if ((dump->lon) && (dump->lat))
+     {
+        Path_Node *n = ELM_NEW(Path_Node);
+        if (n)
+          {
+             n->wd = dump->track->wd;
+             n->pos.lon = dump->lon;
+             n->pos.lat = dump->lat;
+             n->idx = dump->idx++;
+             INF("[%d] %lf:%lf", n->idx, dump->lon, dump->lat);
+             n->pos.address = NULL;
+             dump->track->nodes = eina_list_append(dump->track->nodes, n);
+
+             path = evas_object_polygon_add(evas_object_evas_get(dump->track->wd->obj));
+             evas_object_smart_member_add(path, dump->track->wd->pan_smart);
+             dump->track->path = eina_list_append(dump->track->path, path);
+             dump->lon = 0.0;
+             dump->lat = 0.0;
+          }
+     }
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+cb_track_dump(void *data, Eina_Simple_XML_Type type, const char *content, unsigned offset __UNUSED__, unsigned length __UNUSED__)
+{
+   Track_Dump *d = data;
+
+   if (!d) return EINA_FALSE;
+   if (type == EINA_SIMPLE_XML_OPEN)
+     {
+        if (!strncmp(GPX_COORDINATES, content, strlen(GPX_COORDINATES)))
+          {
+             const char *tags = eina_simple_xml_tag_attributes_find(content, length);
+             eina_simple_xml_attributes_parse(tags, length - (tags - content), cb_dump_track_attr, d);
+          }
+     }
+   return EINA_TRUE;
+}
+
 static int idnum = 1;
 
 /**
@@ -3178,6 +3391,7 @@ elm_map_zoom_set(Evas_Object *obj, int zoom)
    Evas_Coord rx, ry, rw, rh;
    Evas_Object *p;
    Elm_Map_Route *r;
+   Elm_Map_Track *t;
    int z = 0, zoom_changed = 0, started = 0;
 
    if ((!wd) || (!wd->src) || (wd->zoom_animator)) return;
@@ -3206,6 +3420,17 @@ elm_map_zoom_set(Evas_Object *obj, int zoom)
           }
      }
 
+   EINA_LIST_FOREACH(wd->track, l, t)
+     {
+        if (t)
+          {
+             EINA_LIST_FOREACH(t->path, l, p)
+               {
+                  evas_object_polygon_points_clear(p);
+               }
+          }
+     }
+
    if (wd->mode != ELM_MAP_ZOOM_MODE_MANUAL)
      {
         int p2w, p2h;
@@ -4741,8 +4966,8 @@ elm_map_route_remove(Elm_Map_Route *route)
 {
    EINA_SAFETY_ON_NULL_RETURN(route);
 
-   Route_Waypoint *w;
-   Route_Node *n;
+   Path_Waypoint *w;
+   Path_Node *n;
    Evas_Object *p;
    Ecore_Event_Handler *h;
 
@@ -5015,6 +5240,152 @@ elm_map_wheel_disabled_get(const Evas_Object *obj)
    return wd->wheel_disabled;
 }
 
+/**
+ * Add a track on the map
+ *
+ * @param obj The map object
+ * @param  the type if transport
+ *
+ * @return The Track object
+ *
+ * @ingroup Map
+ */
+EAPI Elm_Map_Track *
+elm_map_track_add(Evas_Object *obj, const char *gpx_file)
+{
+   ELM_CHECK_WIDTYPE(obj, widtype) NULL;
+   Widget_Data *wd = elm_widget_data_get(obj);
+   FILE *f;
+
+   if (!wd) return EINA_FALSE;
+
+   Elm_Map_Track *track = ELM_NEW(Elm_Map_Track);
+   if (!track) return NULL;
+   track->wd = wd;
+   track->inbound = EINA_FALSE;
+   track->color.r = 0;
+   track->color.g = 0;
+   track->color.b = 255;
+   track->color.a = 255;
+
+   Track_Dump dump = {track, 0, 0.0, 0.0};
+   if (!wd->gpx_file) wd->gpx_file = eina_stringshare_add(gpx_file);
+   else eina_stringshare_replace(&wd->gpx_file, gpx_file);
+
+   f = fopen(gpx_file, "rb");
+   if (f)
+   {
+      long sz;
+
+      fseek(f, 0, SEEK_END);
+      sz = ftell(f);
+      if (sz > 0)
+      {
+         char *buf;
+
+         fseek(f, 0, SEEK_SET);
+         buf = malloc(sz);
+         if (buf)
+         {
+            if (fread(buf, 1, sz, f))
+              {
+                 eina_simple_xml_parse(buf, sz, EINA_TRUE, cb_track_dump, &dump);
+                 free(buf);
+              }
+         }
+      }
+      fclose(f);
+   }
+   else
+   {
+      ERR("can't open the file %s", gpx_file);
+      return NULL;
+   }
+   DBG("[Done] Load GPX file %s", gpx_file);
+
+   wd->track = eina_list_append(wd->track, track);
+   if (wd->grids)
+     {
+        Evas_Coord ox, oy, ow, oh;
+        evas_object_geometry_get(wd->obj, &ox, &oy, &ow, &oh);
+        track_place(wd->obj, eina_list_data_get(wd->grids), wd->pan_x, wd->pan_y, ox, oy, ow, oh);
+     }
+
+   return track;
+}
+
+/**
+ * Remove a track from the map
+ *
+ * @param track The track to remove
+ *
+ * @ingroup Map
+ */
+
+EAPI void
+elm_map_track_remove(Elm_Map_Track *track)
+{
+   EINA_SAFETY_ON_NULL_RETURN(track);
+
+   Path_Node *n;
+   Evas_Object *p;
+
+   EINA_LIST_FREE(track->path, p)
+     {
+        evas_object_del(p);
+     }
+
+   EINA_LIST_FREE(track->nodes, n)
+     {
+        if (n->pos.address) eina_stringshare_del(n->pos.address);
+        free(n);
+     }
+}
+
+/**
+ * Set the option used for the background color
+ *
+ * @param track The track object
+ * @param r
+ * @param g
+ * @param b
+ * @param a
+ *
+ * This sets the color used for the track
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_track_color_set(Elm_Map_Track *track, int r, int g , int b, int a)
+{
+   EINA_SAFETY_ON_NULL_RETURN(track);
+   track->color.r = r;
+   track->color.g = g;
+   track->color.b = b;
+   track->color.a = a;
+}
+
+/**
+ * Get the option used for the background color
+ *
+ * @param track The track object
+ * @param r
+ * @param g
+ * @param b
+ * @param a
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_track_color_get(const Elm_Map_Track *track, int *r, int *g , int *b, int *a)
+{
+   EINA_SAFETY_ON_NULL_RETURN(track);
+   if (r) *r = track->color.r;
+   if (g) *g = track->color.g;
+   if (b) *b = track->color.b;
+   if (a) *a = track->color.a;
+}
+
 static char *
 _mapnik_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom)
 {