elm: add elm_route: widget to display a route on elm_map. Currently the widget use lines, in the futur it will use edje

SVN revision: 60703
This commit is contained in:
Jonathan Atton 2011-06-26 17:36:18 +00:00
parent 133cc990c3
commit d47854c49f
5 changed files with 358 additions and 200 deletions

View File

@ -28,7 +28,7 @@ static int nb_elts;
static Elm_Map_Marker *route_from, *route_to;
static Elm_Map_Route *route;
static Elm_Map_Name *name;
static Elm_Map_Track *track;
static Evas_Object *track;
static const char **source_names = NULL;
static Evas_Coord old_x, old_y;
static Evas_Coord old_d;
@ -280,13 +280,13 @@ my_map_name_loaded(void *data, Evas_Object *obj __UNUSED__, void *event_info __U
}
static void
map_show_seoul(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
map_show_urmatt(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
{
Eina_Bool b = elm_map_paused_get(data);
elm_map_paused_set(data, EINA_TRUE);
elm_map_zoom_mode_set(data, ELM_MAP_ZOOM_MODE_MANUAL);
elm_map_geo_region_show(data, 126.977969, 37.566535);
elm_map_zoom_set(data, 18);
elm_map_geo_region_show(data,7.325201, 48.526813);
elm_map_zoom_set(data, 12);
elm_map_paused_set(data, b);
}
@ -388,7 +388,7 @@ map_track_add(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED
static void
map_track_remove(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
{
elm_map_track_remove(track);
elm_map_track_remove(data, track);
}
static void
@ -631,7 +631,7 @@ _map_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event
menu = elm_menu_add(obj);
item = elm_menu_item_add(menu, NULL, NULL, "Source", NULL, NULL);
_populate(data, item);
elm_menu_item_add(menu, NULL, NULL, "Show Seoul", map_show_seoul, data);
elm_menu_item_add(menu, NULL, NULL, "Show Urmatt", map_show_urmatt, data);
elm_menu_item_add(menu, NULL, NULL, "Bring Seoul", map_bring_seoul, data);
elm_menu_item_add(menu, NULL, NULL, "Paused Set", map_paused_set, data);
elm_menu_item_add(menu, NULL, NULL, "Paused Unset", map_paused_unset, data);

View File

@ -4173,12 +4173,9 @@ extern "C" {
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);
#ifdef ELM_EMAP
EAPI Elm_Map_Track *elm_map_track_add(Evas_Object *obj, EMap_Route *emap) EINA_ARG_NONNULL(1);
EAPI EMap_Route *elm_map_track_emap_get(Elm_Map_Track *track) EINA_ARG_NONNULL(1);
EAPI Evas_Object *elm_map_track_add(Evas_Object *obj, EMap_Route *emap) EINA_ARG_NONNULL(1);
#endif
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);
EAPI void elm_map_track_remove(Evas_Object *obj, Evas_Object *route) EINA_ARG_NONNULL(1);
/* smart callbacks called:
* "clicked" - when image clicked
@ -4197,6 +4194,17 @@ extern "C" {
* "scroll,drag,stop" - dragging the contents around has stopped
*/
/* Route */
EAPI Evas_Object *elm_route_add(Evas_Object *parent);
#ifdef ELM_EMAP
EAPI Eina_Bool elm_route_emap_set(Evas_Object *obj, EMap_Route *emap);
#endif
EAPI double elm_route_lon_min_get(Evas_Object *obj);
EAPI double elm_route_lat_min_get(Evas_Object *obj);
EAPI double elm_route_lon_max_get(Evas_Object *obj);
EAPI double elm_route_lat_max_get(Evas_Object *obj);
/* panel */
typedef enum _Elm_Panel_Orient
{

View File

@ -82,6 +82,7 @@ elm_list.c \
elm_main.c \
elm_mapbuf.c \
elm_map.c \
elm_route.c \
elm_menu.c \
elm_module.c \
elm_notify.c \

View File

@ -287,28 +287,6 @@ struct _Elm_Map_Name
Ecore_Event_Handler *handler;
};
struct _Elm_Map_Track
{
Widget_Data *wd;
#ifdef ELM_EMAP
EMap_Route *emap;
#endif
int x, y;
Eina_List *nodes, *path;
struct {
int r;
int g;
int b;
int a;
} color;
Eina_Bool inbound : 1;
};
struct _Grid_Item
{
Widget_Data *wd;
@ -505,14 +483,6 @@ 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,
@ -834,72 +804,35 @@ track_place(Evas_Object *obj, Grid *g __UNUSED__, Evas_Coord px, Evas_Coord py,
#ifdef ELM_EMAP
ELM_CHECK_WIDTYPE(obj, widtype);
Widget_Data *wd = elm_widget_data_get(obj);
Eina_List *lr, *lp, *ln;
EMap_Route_Node *n;
Evas_Object *p;
Elm_Map_Track *t;
int nodes;
int x, y, rx, ry;
Eina_List *l;
Evas_Object *route;
int xmin, xmax, ymin, ymax;
if (!wd) return;
Evas_Coord size = pow(2.0, wd->zoom)*wd->tsize;
EINA_LIST_FOREACH(wd->track, lr, t)
EINA_LIST_FOREACH(wd->track, l, route)
{
EINA_LIST_FOREACH(t->path, lp, p)
{
evas_object_polygon_points_clear(p);
}
elm_map_utils_convert_geo_into_coord(wd->obj, elm_route_lon_min_get(route), elm_route_lat_max_get(route), size, &xmin, &ymin);
elm_map_utils_convert_geo_into_coord(wd->obj, elm_route_lon_max_get(route), elm_route_lat_min_get(route), size, &xmax, &ymax);
evas_object_geometry_get(wd->rect, &rx, &ry, NULL, NULL);
nodes = eina_list_count(emap_route_nodes_get(t->emap));
if( !(xmin < px && xmax < px) && !(xmin > px+ow && xmax > px+ow))
{
if( !(ymin < py && ymax < py) && !(ymin > py+oh && ymax > py+oh))
{
//display the route
evas_object_move(route, xmin - px + ox, ymin - py + oy);
evas_object_resize(route, xmax - xmin, ymax - ymin);
int i = 0;
EINA_LIST_FOREACH(emap_route_nodes_get(t->emap), ln, n)
{
if (t->inbound)
{
elm_map_utils_convert_geo_into_coord(wd->obj, emap_route_node_lon_get(n), emap_route_node_lat_get(n), 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;
evas_object_raise(route);
obj_rotate_zoom(obj, route);
evas_object_show(route);
p = eina_list_nth(t->path, i);
if(!p)
{
p = evas_object_line_add(evas_object_evas_get(t->wd->obj));
evas_object_smart_member_add(p, t->wd->pan_smart);
t->path = eina_list_append(t->path, p);
}
evas_object_line_xy_set(p, t->x, t->y, x, y);
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, emap_route_node_lon_get(n), emap_route_node_lat_get(n), 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;
}
i++;
}
t->inbound = EINA_FALSE;
continue;
}
}
//the route is not display
evas_object_hide(route);
}
#endif
}
@ -2111,7 +2044,7 @@ _del_hook(Evas_Object *obj)
Ecore_Event_Handler *h;
Elm_Map_Route *r;
Elm_Map_Name *na;
Elm_Map_Track *t;
Evas_Object *route;
if (!wd) return;
EINA_LIST_FREE(wd->groups_clas, group_clas)
@ -2174,18 +2107,9 @@ _del_hook(Evas_Object *obj)
}
}
EINA_LIST_FOREACH(wd->track, l, t)
EINA_LIST_FREE(wd->track, route)
{
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);
}
evas_object_del(route);
}
if (wd->map) evas_map_free(wd->map);
@ -3363,7 +3287,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;
Evas_Object *route;
int z = 0, zoom_changed = 0, started = 0;
if ((!wd) || (!wd->src) || (wd->zoom_animator)) return;
@ -3392,15 +3316,9 @@ elm_map_zoom_set(Evas_Object *obj, int zoom)
}
}
EINA_LIST_FOREACH(wd->track, l, t)
EINA_LIST_FOREACH(wd->track, l, route)
{
if (t)
{
EINA_LIST_FOREACH(t->path, l, p)
{
evas_object_polygon_points_clear(p);
}
}
evas_object_hide(route);
}
if (wd->mode != ELM_MAP_ZOOM_MODE_MANUAL)
@ -5264,40 +5182,25 @@ elm_map_wheel_disabled_get(const Evas_Object *obj)
* @param obj The map object
* @param emap the emap object
*
* @return The Track object
* @return The Route object. This is a elm object of type Elm_Route
*
* @ingroup Map
*/
EAPI Elm_Map_Track *
EAPI Evas_Object *
elm_map_track_add(Evas_Object *obj, EMap_Route *emap)
{
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->emap = emap;
Evas_Object *route = elm_route_add(obj);
elm_route_emap_set(route, emap);
wd->track = eina_list_append(wd->track, route);
wd->track = eina_list_append(wd->track, track);
return track;
return route;
}
EMap_Route
*elm_map_track_emap_get(Elm_Map_Track *track)
{
return track->emap;
}
#endif
/**
@ -5309,67 +5212,15 @@ EMap_Route
*/
EAPI void
elm_map_track_remove(Elm_Map_Track *track)
elm_map_track_remove(Evas_Object *obj, Evas_Object *route)
{
EINA_SAFETY_ON_NULL_RETURN(track);
ELM_CHECK_WIDTYPE(obj, widtype) ;
Widget_Data *wd = elm_widget_data_get(obj);
Path_Node *n;
Evas_Object *p;
if (!wd) return ;
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;
wd->track = eina_list_remove(wd->track, route);
evas_object_del(route);
}
static char *
@ -5377,7 +5228,7 @@ _mapnik_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom)
{
char buf[PATH_MAX];
snprintf(buf, sizeof(buf), "http://tile.openstreetmap.org/%d/%d/%d.png",
zoom, x, y);
zoom, x, y);
return strdup(buf);
}

View File

@ -0,0 +1,298 @@
#include <Elementary.h>
#include "elm_priv.h"
/**
* @defgroup Route MapRoute
*
* For displaying a route on the map widget
*
*/
typedef struct _Widget_Data Widget_Data;
typedef struct Segment Segment;
struct _Widget_Data
{
Evas_Object *obj;
#ifdef ELM_EMAP
EMap_Route *emap;
#endif
double lon_min, lon_max;
double lat_min, lat_max;
Eina_List *segments; //list of *Segment
Eina_Bool must_calc_segments :1;
};
struct Segment
{
Evas_Object *obj;
#ifdef ELM_EMAP
EMap_Route_Node *node_start;
EMap_Route_Node *node_end;
#endif
double start_x, start_y;
double end_x, end_y;
Eina_Bool must_calc :1;
};
static const char *widtype = NULL;
static void _del_hook(Evas_Object *obj);
static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
static void _theme_hook(Evas_Object *obj);
static void _sizing_eval(Evas_Object *obj);
static void _clear_route(Evas_Object *obj);
static void _update_lon_lat_min_max(Evas_Object *obj, double lon, double lat);
static void
_del_hook(Evas_Object *obj)
{
Evas_Object *segment;
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return;
_clear_route(obj);
free(wd);
}
static void
_resize_cb(void *data __UNUSED__ , Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
{
_sizing_eval(obj);
}
static void
_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
{
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return;
}
static void
_theme_hook(Evas_Object *obj)
{
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return;
//TODO
_sizing_eval(obj);
}
static void
_sizing_eval(Evas_Object *obj)
{
Eina_List *l;
Segment *segment;
Evas_Coord x, y, w, h;
Evas_Coord start_x, start_y, end_x, end_y;
Widget_Data *wd = elm_widget_data_get(obj);
evas_object_geometry_get(obj, &x, &y, &w, &h);
EINA_LIST_FOREACH(wd->segments, l, segment)
{
if(wd->must_calc_segments || segment->must_calc)
{
#ifdef ELM_EMAP
segment->start_x = (emap_route_node_lon_get(segment->node_start)- wd->lon_min) / (float)(wd->lon_max - wd->lon_min);
segment->start_y = 1 - (emap_route_node_lat_get(segment->node_start) - wd->lat_min) / (float)(wd->lat_max - wd->lat_min);
segment->end_x = (emap_route_node_lon_get(segment->node_end) - wd->lon_min) / (float)(wd->lon_max - wd->lon_min);
segment->end_y = 1 - (emap_route_node_lat_get(segment->node_end) - wd->lat_min) / (float)(wd->lat_max - wd->lat_min);
#endif
segment->must_calc = EINA_FALSE;
}
start_x = x+(int)(segment->start_x*w);
start_y = y+(int)(segment->start_y*h);
end_x = x+(int)(segment->end_x*w);
end_y = y+(int)(segment->end_y*h);
evas_object_line_xy_set(segment->obj, start_x, start_y, end_x, end_y);
}
wd->must_calc_segments = EINA_FALSE;
}
static void
_clear_route(Evas_Object *obj)
{
Segment *segment;
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return;
#ifdef ELM_EMAP
wd->lon_min = EMAP_LON_MAX;
wd->lon_max = EMAP_LON_MIN;
wd->lat_min = EMAP_LAT_MAX;
wd->lat_max = EMAP_LAT_MIN;
#endif
EINA_LIST_FREE(wd->segments, segment)
{
evas_object_del(segment->obj);
free(segment);
}
}
static void
_update_lon_lat_min_max(Evas_Object *obj, double lon, double lat)
{
Widget_Data *wd = elm_widget_data_get(obj);
if(wd->lon_min > lon)
{
wd->lon_min = lon;
wd->must_calc_segments = EINA_TRUE;
}
if(wd->lat_min > lat)
{
wd->lat_min = lat;
wd->must_calc_segments = EINA_TRUE;
}
if(wd->lon_max < lon)
{
wd->lon_max = lon;
wd->must_calc_segments = EINA_TRUE;
}
if(wd->lat_max < lat)
{
wd->lat_max = lat;
wd->must_calc_segments = EINA_TRUE;
}
}
/**
* Add a new route to the parent
*
* @param parent The parent object
* @return The new object or NULL if it cannot be created
*
* @ingroup Route
*/
EAPI Evas_Object *
elm_route_add(Evas_Object *parent)
{
Evas_Object *obj;
Evas *e;
Widget_Data *wd;
Evas_Object *icon;
ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
ELM_SET_WIDTYPE(widtype, "map_route");
elm_widget_type_set(obj, "map_route");
elm_widget_sub_object_add(parent, obj);
elm_widget_data_set(obj, wd);
elm_widget_del_hook_set(obj, _del_hook);
elm_widget_theme_hook_set(obj, _theme_hook);
elm_widget_can_focus_set(obj, EINA_FALSE);
evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE,
_resize_cb, obj);
evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
_resize_cb, obj);
#ifdef ELM_EMAP
wd->lon_min = EMAP_LON_MAX;
wd->lon_max = EMAP_LON_MIN;
wd->lat_min = EMAP_LAT_MAX;
wd->lat_max = EMAP_LAT_MIN;
#endif
_mirrored_set(obj, elm_widget_mirrored_get(obj));
_sizing_eval(obj);
return obj;
}
#ifdef ELM_EMAP
/**
* Set the emap object which describes the route
*
* @param obj The photo object
* @param emap the route
*
* @return (1 = success, 0 = error)
*
* @ingroup Route
*/
EAPI Eina_Bool
elm_route_emap_set(Evas_Object *obj, EMap_Route *emap)
{
EMap_Route_Node *node, *node_prev = NULL;
Evas_Object *o;
Eina_List *l;
ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
Widget_Data *wd = elm_widget_data_get(obj);
if (!wd) return EINA_FALSE;
wd->emap = emap;
_clear_route(obj);
EINA_LIST_FOREACH(emap_route_nodes_get(wd->emap), l, node)
{
if(node_prev)
{
Segment *segment = calloc(1, sizeof(Segment));
segment->node_start = node_prev;
segment->node_end = node;
o = evas_object_line_add(evas_object_evas_get(obj));
segment->obj = o;
evas_object_smart_member_add(o, obj);
evas_object_show(o);
segment->must_calc = EINA_TRUE;
_update_lon_lat_min_max(obj, emap_route_node_lon_get(node_prev), emap_route_node_lat_get(node_prev));
_update_lon_lat_min_max(obj, emap_route_node_lon_get(node), emap_route_node_lat_get(node));
wd->segments = eina_list_append(wd->segments, segment);
}
node_prev = node;
}
_sizing_eval(obj);
}
#endif
EAPI double
elm_route_lon_min_get(Evas_Object *obj)
{
ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
Widget_Data *wd = elm_widget_data_get(obj);
return wd->lon_min;
}
EAPI double
elm_route_lat_min_get(Evas_Object *obj)
{
ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
Widget_Data *wd = elm_widget_data_get(obj);
return wd->lat_min;
}
EAPI double
elm_route_lon_max_get(Evas_Object *obj)
{
ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
Widget_Data *wd = elm_widget_data_get(obj);
return wd->lon_max;
}
EAPI double
elm_route_lat_max_get(Evas_Object *obj)
{
ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
Widget_Data *wd = elm_widget_data_get(obj);
return wd->lat_max;
}
/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/