[access] call a callback function with information
[framework/uifw/elementary.git] / src / lib / elm_route.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include "elm_widget_route.h"
4
5 EAPI const char ELM_ROUTE_SMART_NAME[] = "elm_route";
6
7 EVAS_SMART_SUBCLASS_NEW
8   (ELM_ROUTE_SMART_NAME, _elm_route, Elm_Route_Smart_Class,
9   Elm_Widget_Smart_Class, elm_widget_smart_class_get, NULL);
10
11 static void
12 _clear_route(Evas_Object *obj)
13 {
14    Segment *segment;
15
16    ELM_ROUTE_DATA_GET(obj, sd);
17
18 #ifdef ELM_EMAP
19    sd->lon_min = EMAP_LON_MAX;
20    sd->lon_max = EMAP_LON_MIN;
21    sd->lat_min = EMAP_LAT_MAX;
22    sd->lat_max = EMAP_LAT_MIN;
23 #endif
24
25    EINA_LIST_FREE (sd->segments, segment)
26      {
27         evas_object_del(segment->obj);
28         free(segment);
29      }
30 }
31
32 static void
33 _sizing_eval(Evas_Object *obj)
34 {
35    Eina_List *l;
36    Segment *segment;
37    Evas_Coord x, y, w, h;
38    Evas_Coord start_x, start_y, end_x, end_y;
39
40    ELM_ROUTE_DATA_GET(obj, sd);
41
42    evas_object_geometry_get(obj, &x, &y, &w, &h);
43
44    EINA_LIST_FOREACH(sd->segments, l, segment)
45      {
46         if (sd->must_calc_segments || segment->must_calc)
47           {
48 #ifdef ELM_EMAP
49              segment->start_x =
50                (emap_route_node_lon_get(segment->node_start) - sd->lon_min)
51                / (float)(sd->lon_max - sd->lon_min);
52              segment->start_y =
53                1 - (emap_route_node_lat_get(segment->node_start)
54                     - sd->lat_min) / (float)(sd->lat_max - sd->lat_min);
55              segment->end_x =
56                (emap_route_node_lon_get(segment->node_end) - sd->lon_min)
57                / (float)(sd->lon_max - sd->lon_min);
58              segment->end_y =
59                1 - (emap_route_node_lat_get(segment->node_end)
60                     - sd->lat_min) / (float)(sd->lat_max - sd->lat_min);
61 #endif
62              segment->must_calc = EINA_FALSE;
63           }
64
65         start_x = x + (int)(segment->start_x * w);
66         start_y = y + (int)(segment->start_y * h);
67         end_x = x + (int)(segment->end_x * w);
68         end_y = y + (int)(segment->end_y * h);
69
70         evas_object_line_xy_set(segment->obj, start_x, start_y, end_x, end_y);
71      }
72
73    sd->must_calc_segments = EINA_FALSE;
74 }
75
76 static void
77 _move_resize_cb(void *data __UNUSED__,
78                 Evas *e __UNUSED__,
79                 Evas_Object *obj,
80                 void *event_info __UNUSED__)
81 {
82    _sizing_eval(obj);
83 }
84
85 static Eina_Bool
86 _elm_route_smart_theme(Evas_Object *obj)
87 {
88    if (!_elm_route_parent_sc->theme(obj)) return EINA_FALSE;
89
90    //TODO
91
92    _sizing_eval(obj);
93
94    return EINA_TRUE;
95 }
96
97 #ifdef ELM_EMAP
98 static void
99 _update_lon_lat_min_max(Evas_Object *obj,
100                         double lon,
101                         double lat)
102 {
103    ELM_ROUTE_DATA_GET(obj, sd);
104
105    if (sd->lon_min > lon)
106      {
107         sd->lon_min = lon;
108         sd->must_calc_segments = EINA_TRUE;
109      }
110    if (sd->lat_min > lat)
111      {
112         sd->lat_min = lat;
113         sd->must_calc_segments = EINA_TRUE;
114      }
115
116    if (sd->lon_max < lon)
117      {
118         sd->lon_max = lon;
119         sd->must_calc_segments = EINA_TRUE;
120      }
121    if (sd->lat_max < lat)
122      {
123         sd->lat_max = lat;
124         sd->must_calc_segments = EINA_TRUE;
125      }
126 }
127
128 #endif
129
130 static void
131 _elm_route_smart_add(Evas_Object *obj)
132 {
133    EVAS_SMART_DATA_ALLOC(obj, Elm_Route_Smart_Data);
134
135    _elm_route_parent_sc->base.add(obj);
136
137    elm_widget_can_focus_set(obj, EINA_FALSE);
138
139    evas_object_event_callback_add
140      (obj, EVAS_CALLBACK_MOVE, _move_resize_cb, obj);
141    evas_object_event_callback_add
142      (obj, EVAS_CALLBACK_RESIZE, _move_resize_cb, obj);
143
144 #ifdef ELM_EMAP
145    priv->lon_min = EMAP_LON_MAX;
146    priv->lon_max = EMAP_LON_MIN;
147    priv->lat_min = EMAP_LAT_MAX;
148    priv->lat_max = EMAP_LAT_MIN;
149 #endif
150
151    _sizing_eval(obj);
152 }
153
154 static void
155 _elm_route_smart_del(Evas_Object *obj)
156 {
157    _clear_route(obj);
158
159    ELM_WIDGET_CLASS(_elm_route_parent_sc)->base.del(obj);
160 }
161
162 static void
163 _elm_route_smart_set_user(Elm_Route_Smart_Class *sc)
164 {
165    ELM_WIDGET_CLASS(sc)->base.add = _elm_route_smart_add;
166    ELM_WIDGET_CLASS(sc)->base.del = _elm_route_smart_del;
167
168    ELM_WIDGET_CLASS(sc)->theme = _elm_route_smart_theme;
169 }
170
171 EAPI const Elm_Route_Smart_Class *
172 elm_route_smart_class_get(void)
173 {
174    static Elm_Route_Smart_Class _sc =
175      ELM_ROUTE_SMART_CLASS_INIT_NAME_VERSION(ELM_ROUTE_SMART_NAME);
176    static const Elm_Route_Smart_Class *class = NULL;
177
178    if (class) return class;
179
180    _elm_route_smart_set(&_sc);
181    class = &_sc;
182
183    return class;
184 }
185
186 /**
187  * Add a new route to the parent
188  *
189  * @param parent The parent object
190  * @return The new object or NULL if it cannot be created
191  *
192  * @ingroup Route
193  */
194 EAPI Evas_Object *
195 elm_route_add(Evas_Object *parent)
196 {
197    Evas_Object *obj;
198
199    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
200
201    obj = elm_widget_add(_elm_route_smart_class_new(), parent);
202    if (!obj) return NULL;
203
204    if (!elm_widget_sub_object_add(parent, obj))
205      ERR("could not add %p as sub object of %p", obj, parent);
206
207    return obj;
208 }
209
210 #ifdef ELM_EMAP
211 /**
212  * Set the emap object which describes the route
213  *
214  * @param obj The photo object
215  * @param emap the route
216  *
217  * @ingroup Route
218  */
219 EAPI void
220 elm_route_emap_set(Evas_Object *obj,
221                    EMap_Route *emap)
222 {
223    EMap_Route_Node *node, *node_prev = NULL;
224    Evas_Object *o;
225    Eina_List *l;
226
227    ELM_ROUTE_CHECK(obj);
228    ELM_ROUTE_DATA_GET(obj, sd);
229
230    sd->emap = emap;
231
232    _clear_route(obj);
233
234    EINA_LIST_FOREACH(emap_route_nodes_get(sd->emap), l, node)
235      {
236         if (node_prev)
237           {
238              Segment *segment = calloc(1, sizeof(Segment));
239
240              segment->node_start = node_prev;
241              segment->node_end = node;
242
243              o = evas_object_line_add(evas_object_evas_get(obj));
244              segment->obj = o;
245              evas_object_smart_member_add(o, obj);
246
247              segment->must_calc = EINA_TRUE;
248
249              _update_lon_lat_min_max
250                (obj, emap_route_node_lon_get(node_prev),
251                emap_route_node_lat_get(node_prev));
252              _update_lon_lat_min_max
253                (obj, emap_route_node_lon_get(node),
254                emap_route_node_lat_get(node));
255
256              sd->segments = eina_list_append(sd->segments, segment);
257           }
258
259         node_prev = node;
260      }
261
262    _sizing_eval(obj);
263 }
264
265 #endif
266
267 EAPI void
268 elm_route_longitude_min_max_get(const Evas_Object *obj,
269                                 double *min,
270                                 double *max)
271 {
272    ELM_ROUTE_CHECK(obj);
273    ELM_ROUTE_DATA_GET(obj, sd);
274
275    if (min) *min = sd->lon_min;
276    if (max) *max = sd->lon_max;
277 }
278
279 EAPI void
280 elm_route_latitude_min_max_get(const Evas_Object *obj,
281                                double *min,
282                                double *max)
283 {
284    ELM_ROUTE_CHECK(obj);
285    ELM_ROUTE_DATA_GET(obj, sd);
286
287    if (min) *min = sd->lat_min;
288    if (max) *max = sd->lat_max;
289 }