Merge branch 'master' into svn_merge
[framework/uifw/elementary.git] / src / lib / elm_route.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 /**
5  * @defgroup Route MapRoute
6  *
7  * For displaying a route on the map widget
8  *
9  */
10
11 typedef struct _Widget_Data Widget_Data;
12 typedef struct Segment Segment;
13
14 struct _Widget_Data
15 {
16    Evas_Object *obj;
17 #ifdef ELM_EMAP
18    EMap_Route *emap;
19 #endif
20
21    double lon_min, lon_max;
22    double lat_min, lat_max;
23
24    Eina_List *segments; //list of *Segment
25
26    Eina_Bool must_calc_segments :1;
27 };
28
29 struct Segment
30 {
31    Evas_Object *obj;
32
33 #ifdef ELM_EMAP
34    EMap_Route_Node *node_start;
35    EMap_Route_Node *node_end;
36 #endif
37
38    double start_x, start_y;
39    double end_x, end_y;
40
41    Eina_Bool must_calc :1;
42 };
43
44 static const char *widtype = NULL;
45 static void _del_hook(Evas_Object *obj);
46 static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
47 static void _theme_hook(Evas_Object *obj);
48 static void _sizing_eval(Evas_Object *obj);
49 static void _clear_route(Evas_Object *obj);
50 #ifdef ELM_EMAP
51 static void _update_lon_lat_min_max(Evas_Object *obj, double lon, double lat);
52 #endif
53
54 static void
55 _del_hook(Evas_Object *obj)
56 {
57    Widget_Data *wd = elm_widget_data_get(obj);
58    if (!wd) return;
59
60    _clear_route(obj);
61
62    free(wd);
63 }
64
65 static void
66 _resize_cb(void *data __UNUSED__ , Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
67 {
68    _sizing_eval(obj);
69 }
70
71 static void
72 _mirrored_set(Evas_Object *obj, Eina_Bool rtl __UNUSED__)
73 {
74    Widget_Data *wd = elm_widget_data_get(obj);
75    if (!wd) return;
76 }
77
78 static void
79 _theme_hook(Evas_Object *obj)
80 {
81    Widget_Data *wd = elm_widget_data_get(obj);
82    if (!wd) return;
83    //TODO
84    _sizing_eval(obj);
85 }
86
87 static void
88 _sizing_eval(Evas_Object *obj)
89 {
90    Eina_List *l;
91    Segment *segment;
92    Evas_Coord x, y, w, h;
93    Evas_Coord start_x, start_y, end_x, end_y;
94
95    Widget_Data *wd = elm_widget_data_get(obj);
96    evas_object_geometry_get(obj, &x, &y, &w, &h);
97
98    EINA_LIST_FOREACH(wd->segments, l, segment)
99      {
100         if (wd->must_calc_segments || segment->must_calc)
101           {
102
103 #ifdef ELM_EMAP
104              segment->start_x = (emap_route_node_lon_get(segment->node_start)- wd->lon_min) / (float)(wd->lon_max - wd->lon_min);
105              segment->start_y = 1 - (emap_route_node_lat_get(segment->node_start) - wd->lat_min) / (float)(wd->lat_max - wd->lat_min);
106              segment->end_x = (emap_route_node_lon_get(segment->node_end) - wd->lon_min) / (float)(wd->lon_max - wd->lon_min);
107              segment->end_y = 1 - (emap_route_node_lat_get(segment->node_end) - wd->lat_min) / (float)(wd->lat_max - wd->lat_min);
108 #endif
109              segment->must_calc = EINA_FALSE;
110           }
111
112         start_x = x+(int)(segment->start_x*w);
113         start_y = y+(int)(segment->start_y*h);
114         end_x = x+(int)(segment->end_x*w);
115         end_y = y+(int)(segment->end_y*h);
116         evas_object_line_xy_set(segment->obj, start_x, start_y, end_x, end_y);
117      }
118
119    wd->must_calc_segments = EINA_FALSE;
120 }
121
122 static void
123 _clear_route(Evas_Object *obj)
124 {
125    Segment *segment;
126    Widget_Data *wd = elm_widget_data_get(obj);
127    if (!wd) return;
128
129 #ifdef ELM_EMAP
130    wd->lon_min = EMAP_LON_MAX;
131    wd->lon_max = EMAP_LON_MIN;
132    wd->lat_min = EMAP_LAT_MAX;
133    wd->lat_max = EMAP_LAT_MIN;
134 #endif
135
136    EINA_LIST_FREE(wd->segments, segment)
137      {
138         evas_object_del(segment->obj);
139         free(segment);
140      }
141 }
142
143 #ifdef ELM_EMAP
144 static void
145 _update_lon_lat_min_max(Evas_Object *obj, double lon, double lat)
146 {
147    Widget_Data *wd = elm_widget_data_get(obj);
148
149    if (wd->lon_min > lon)
150      {
151         wd->lon_min = lon;
152         wd->must_calc_segments = EINA_TRUE;
153      }
154    if (wd->lat_min > lat)
155      {
156         wd->lat_min = lat;
157         wd->must_calc_segments = EINA_TRUE;
158      }
159
160    if (wd->lon_max < lon)
161      {
162         wd->lon_max = lon;
163         wd->must_calc_segments = EINA_TRUE;
164      }
165    if (wd->lat_max < lat)
166      {
167         wd->lat_max = lat;
168         wd->must_calc_segments = EINA_TRUE;
169      }
170 }
171 #endif
172
173 /**
174  * Add a new route to the parent
175  *
176  * @param parent The parent object
177  * @return The new object or NULL if it cannot be created
178  *
179  * @ingroup Route
180  */
181 EAPI Evas_Object *
182 elm_route_add(Evas_Object *parent)
183 {
184    Evas_Object *obj;
185    Evas *e;
186    Widget_Data *wd;
187
188    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
189
190    ELM_SET_WIDTYPE(widtype, "map_route");
191    elm_widget_type_set(obj, "map_route");
192    elm_widget_sub_object_add(parent, obj);
193    elm_widget_data_set(obj, wd);
194    elm_widget_del_hook_set(obj, _del_hook);
195    elm_widget_theme_hook_set(obj, _theme_hook);
196    elm_widget_can_focus_set(obj, EINA_FALSE);
197
198    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE,
199                                   _resize_cb, obj);
200    evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
201                                   _resize_cb, obj);
202
203 #ifdef ELM_EMAP
204    wd->lon_min = EMAP_LON_MAX;
205    wd->lon_max = EMAP_LON_MIN;
206    wd->lat_min = EMAP_LAT_MAX;
207    wd->lat_max = EMAP_LAT_MIN;
208 #endif
209
210    _mirrored_set(obj, elm_widget_mirrored_get(obj));
211    _sizing_eval(obj);
212    return obj;
213 }
214
215 #ifdef ELM_EMAP
216 /**
217  * Set the emap object which describes the route
218  *
219  * @param obj The photo object
220  * @param emap the route
221  *
222  * @return (1 = success, 0 = error)
223  *
224  * @ingroup Route
225  */
226 EAPI void
227 elm_route_emap_set(Evas_Object *obj, EMap_Route *emap)
228 {
229    EMap_Route_Node *node, *node_prev = NULL;
230    Evas_Object *o;
231    Eina_List *l;
232
233    ELM_CHECK_WIDTYPE(obj, widtype);
234    Widget_Data *wd = elm_widget_data_get(obj);
235
236    if (!wd) return;
237    wd->emap = emap;
238
239    _clear_route(obj);
240
241    EINA_LIST_FOREACH(emap_route_nodes_get(wd->emap), l, node)
242      {
243         if (node_prev)
244           {
245              Segment *segment = calloc(1, sizeof(Segment));
246              segment->node_start = node_prev;
247              segment->node_end = node;
248
249              o = evas_object_line_add(evas_object_evas_get(obj));
250              segment->obj = o;
251              evas_object_smart_member_add(o, obj);
252              evas_object_show(o);
253
254              segment->must_calc = EINA_TRUE;
255
256              _update_lon_lat_min_max(obj, emap_route_node_lon_get(node_prev), emap_route_node_lat_get(node_prev));
257              _update_lon_lat_min_max(obj, emap_route_node_lon_get(node), emap_route_node_lat_get(node));
258
259              wd->segments = eina_list_append(wd->segments, segment);
260           }
261         node_prev = node;
262      }
263
264    _sizing_eval(obj);
265 }
266 #endif
267
268 EAPI double
269 elm_route_lon_min_get(Evas_Object *obj)
270 {
271    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
272    Widget_Data *wd = elm_widget_data_get(obj);
273    return wd->lon_min;
274 }
275
276 EAPI double
277 elm_route_lat_min_get(Evas_Object *obj)
278 {
279    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
280    Widget_Data *wd = elm_widget_data_get(obj);
281    return wd->lat_min;
282 }
283
284 EAPI double
285 elm_route_lon_max_get(Evas_Object *obj)
286 {
287    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
288    Widget_Data *wd = elm_widget_data_get(obj);
289    return wd->lon_max;
290 }
291
292 EAPI double
293 elm_route_lat_max_get(Evas_Object *obj)
294 {
295    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
296    Widget_Data *wd = elm_widget_data_get(obj);
297    return wd->lat_max;
298 }
299
300 /* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0 :*/