246ac3dc46ce8c1bdbf9ac2799e871c823c5026b
[platform/core/api/maps-service.git] / src / api / maps_view.cpp
1 /* Copyright (c) 2010-2014 Samsung Electronics Co., Ltd. All rights reserved.
2  *
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17
18 #include <tizen.h>
19 #include <Ecore.h>
20 #include <Evas.h>
21 #include <unistd.h>
22 #include <glib.h>
23 #include <Elementary.h>
24
25 #include "maps_view.h"
26 #include "maps_view_plugin.h"
27 #include "maps_util.h"
28 #include "module.h"
29 #include "empty_module.h"
30 #include "commands.h"
31 #include "command_queue.h"
32 #include "poly_shape_hit_test.h"
33 #include "gesture_processor.h"
34 #include "inertial_camera.h"
35 #include "inertial_gesture.h"
36 #include "gesture_detector_statemachine.h"
37 #include "maps_view_event_data.h"
38 #include "maps_condition.h"
39
40 /*
41  * The structure of callbacks info, Maps View is invoking during events
42  */
43 typedef struct _maps_view_callback_info_s {
44         maps_view_on_event_cb callback;
45         void *user_data;
46 } maps_view_callback_info_s;
47
48 /*
49  * The structure of map view idle listener callbacks info
50  */
51 typedef struct _maps_view_idle_listener_info_s {
52         void (*callback)(void *user_data);
53         void *user_data;
54 } maps_view_idle_listener_info_s;
55
56 /*
57  * The structure of Maps View internal data
58  */
59 typedef struct _maps_view_s {
60         /* Map Coordinates and Area */
61         maps_area_h area;
62         maps_coordinates_h center;
63
64         /* Run-time scale values */
65         double zoom_factor;
66         double rotation_angle; /* in graduses */
67         int zoom_level;
68
69         /* Camera inertial transition data */
70         view::inertial_camera *inertial_camera;
71         view::inertial_gesture *inertial_gesture;
72         maps_view_idle_listener_info_s idle_listener;
73
74         /* We'd better to store that values in order to easily limit zoom level
75          * and factor in the run time without accessing the plugin frequently */
76         int min_zoom_level;
77         int max_zoom_level;
78
79         /* The handle of Maps Service, used by Map View */
80         maps_service_h maps;
81
82         /* List of Visual Objects on the View */
83         maps_item_list_h view_objects;
84
85         /* Evas basis */
86         Evas *canvas;
87         Evas_Object *panel;
88         Evas_Object *parent;
89         Evas_Object *clipper;
90
91         /* Gesture Support */
92         maps_view_action_e gesture_actions[MAPS_VIEW_GESTURE_LONG_PRESS + 1];
93         bool gesture_available[MAPS_VIEW_GESTURE_LONG_PRESS + 1];
94
95         /* Continuous gesture info */
96         view::finger_event_stream *finger_stream;
97
98         /* Map View callbacks */
99         maps_view_callback_info_s event_callbacks[MAPS_VIEW_EVENT_READY + 1];
100         bool ready;
101
102         /* Evas Queue support */
103         Ecore_Idler *idler;
104         Ecore_Animator *animator;
105         volatile bool ready_to_draw;
106
107         /* Map View Preferences */
108         maps_view_type_e type;
109         char *language;
110         bool buildings_enabled;
111         bool traffic_enabled;
112         bool public_transit_enabled;
113         bool scalebar_enabled;
114
115         /* To check hit_test */
116         int screen_dpi;
117         int min_hit_area;
118
119         void *maps_plugin_view_handle;
120 } maps_view_s;
121
122
123 /* ---------------------------------------------------------------------------*/
124
125
126 const gsize _MAPS_VIEW_LANGUAGE_MAX_LENGTH = MAPS_BASE_TYPE_MAX_LEN;
127
128
129 /* ---------------------------------------------------------------------------*/
130
131 extern plugin::plugin_s *__extract_plugin(maps_service_h maps);
132 extern int _maps_view_event_data_set_type(const maps_view_event_data_h event, maps_view_event_type_e event_type);
133 extern int _maps_view_event_data_set_gesture_type(const maps_view_event_data_h event, maps_view_gesture_e gesture_type);
134 extern int _maps_view_event_data_set_action_type(const maps_view_event_data_h event, maps_view_action_e action_type);
135 extern int _maps_view_event_data_set_center(const maps_view_event_data_h event, const maps_coordinates_h center);
136 extern int _maps_view_event_data_set_delta(const maps_view_event_data_h event, int delta_x, int delta_y);
137 extern int _maps_view_event_data_set_position(const maps_view_event_data_h event, int x, int y);
138 extern int _maps_view_event_data_set_fingers(const maps_view_event_data_h event, int fingers);
139 extern int _maps_view_event_data_set_zoom_factor(const maps_view_event_data_h event, double zoom_factor);
140 extern int _maps_view_event_data_set_rotation_angle(const maps_view_event_data_h event, double rotation_angle);
141 extern int _maps_view_event_data_set_object(const maps_view_event_data_h event, const maps_view_object_h object);
142 extern int _maps_view_event_data_create(maps_view_event_data_h *event);
143 extern int _maps_view_object_set_view(const maps_view_object_h object, const maps_view_h view);
144 maps_view_event_data_h _maps_view_create_event_data(maps_view_event_type_e type);
145 void _maps_view_invoke_event_callback(const maps_view_h view, const maps_view_event_data_h event_data);
146 int _maps_view_set_inertia_enabled(const maps_view_h view, bool enabled);
147 extern bool _maps_view_object_overlay_cb(int index, int total, maps_view_object_h object, void *user_data);
148 extern int _maps_view_object_overlay_operation(maps_view_h view, maps_view_object_h object, maps_view_object_operation_e operation);
149 static int __maps_view_set_center(maps_view_h view, maps_coordinates_h coordinates, bool internal);
150 int _maps_view_move_center(maps_view_h view, const int delta_x, const int delta_y);
151 int _maps_view_get_plugin_center(const maps_view_h view, maps_coordinates_h *center);
152 int _maps_coordinates_copy(maps_coordinates_h orig, maps_coordinates_h dest);
153
154 /* ---------------------------------------------------------------------------*/
155
156
157 /* TODO: Apply this approach for other cases, particularly, in maps_service.h*/
158 const plugin::interface_s *__get_plugin_interface(maps_view_h view)
159 {
160         const plugin::plugin_s *p =
161                 __extract_plugin(((maps_view_s *)view)->maps);
162         return (p) ? (&p->interface) : plugin::get_empty_interface_ptr();
163 }
164
165
166 /* ---------------------------------------------------------------------------*/
167
168
169 static void __maps_view_on_event_empty_cb(maps_view_event_type_e type,
170         maps_view_event_data_h event_data, void *user_data)
171 {
172         /* empty */
173 }
174
175 session::command_queue *__maps_view_select_q()
176 {
177         /*
178          *  This is a draw-enforcing mode, when the rendering and drawing
179          *  of the map is happening as fast as it possible.
180          *  This mode is good when the Map View is a single active widget
181          *  of the App.
182          *  In this mode we are relying on the ecore main loop and the
183          *  assumption, that loop steps will apear continuously, not
184          *  simultaneously.
185          *  https://docs.enlightenment.org/efl/1.15.0/Ecore_Main_Loop_Page.html
186          */
187         return session::command_queue_sync::interface();
188
189         /*
190          * This is an analogy of previous mode, but with thread safety
191          * implemented
192          */
193         /*return session::command_queue_async::interface();*/
194
195         /*
196          *  This is a thread-friendly mode, when all heavy computations
197          *  are performed in the "idle" mode.
198          *  This mode is good for apps, which has other active widgets in
199          *  addition to Map View.
200          *  This approach allows compression of repeating commands as well
201          */
202         /* return session::command_queue_view::interface(); */
203 }
204
205 bool _maps_view_is_gesture_available(maps_view_h view, maps_view_gesture_e gesture)
206 {
207         if (!view)
208                 return false;
209         maps_view_s *v = (maps_view_s *)view;
210         return v->gesture_available[gesture];
211 }
212
213 maps_view_action_e _maps_view_get_gesture_action(maps_view_h view, maps_view_gesture_e gesture)
214 {
215         if (!view)
216                 return MAPS_VIEW_ACTION_NONE;
217         maps_view_s *v = (maps_view_s *)view;
218         return v->gesture_actions[gesture];
219 }
220
221 void *_maps_view_get_maps_service_ptr(maps_view_h view)
222 {
223         if (!view)
224                 return NULL;
225         maps_view_s *v = (maps_view_s *)view;
226         return v->maps;
227 }
228
229 int _maps_view_on_overlay_update_all(maps_view_h view)
230 {
231         if (!view)
232                 return MAPS_ERROR_INVALID_PARAMETER;
233
234         maps_view_s *v = (maps_view_s *)view;
235         if (!v->view_objects)
236                 return MAPS_ERROR_NOT_FOUND;
237         return maps_item_list_foreach(v->view_objects, NULL, _maps_view_object_overlay_cb, v->clipper);
238 }
239
240 int _maps_view_on_object_operation(maps_view_h view, maps_view_object_h object, maps_view_object_operation_e operation)
241 {
242         if (!view)
243                 return  MAPS_ERROR_INVALID_PARAMETER;
244
245         maps_view_object_type_e type;
246         maps_view_object_get_type(object, &type);
247         if (type == MAPS_VIEW_OBJECT_OVERLAY) {
248                 return _maps_view_object_overlay_operation(view, object, operation);
249         } else {
250                 if(!__get_plugin_interface(view)->maps_plugin_on_object)
251                         return  MAPS_ERROR_INVALID_PARAMETER;
252
253                 return __get_plugin_interface(view)->maps_plugin_on_object(view, object, operation);
254         }
255 }
256
257 static void __on_canvas_tap(void *data, Evas *e, Evas_Object *obj, void *event_info)
258 {
259         MAPS_LOGI("__on_canvas_tap");
260         if (!event_info || !data)
261                 return;
262
263         /* Extract the view ptr */
264         maps_view_s *v = (maps_view_s *)data;
265         if (!v->finger_stream)
266                 return;
267
268         /* Detect & Process the gesture */
269         v->finger_stream->tap((Evas_Event_Mouse_Down *)event_info);
270 }
271
272 static void __on_canvas_up(void *data, Evas *e, Evas_Object *obj, void *event_info)
273 {
274         MAPS_LOGI("__on_canvas_up");
275         if (!event_info || !data)
276                 return;
277
278         /* Extract the view ptr */
279         maps_view_s *v = (maps_view_s *)data;
280         if (!v->finger_stream)
281                 return;
282
283         /* Detect & Process the gesture */
284         v->finger_stream->up((Evas_Event_Mouse_Up *)event_info);
285 }
286
287 static void __on_canvas_line(void *data, Evas *e, Evas_Object *obj, void *event_info)
288 {
289         MAPS_LOGI("__on_canvas_line");
290         if (!event_info || !data)
291                 return;
292
293         /*  Extract view ptr */
294         maps_view_s *v = (maps_view_s *)data;
295         if (!v->finger_stream)
296                 return;
297
298         /* Detect & Process the gesture */
299         v->finger_stream->move((Evas_Event_Mouse_Move *)event_info);
300 }
301
302 static void __on_canvas_multi_tap(void *data, Evas *e, Evas_Object *obj, void *event_info)
303 {
304         MAPS_LOGI("__on_canvas_multi_tap");
305         if (!event_info || !data)
306                 return;
307
308         /*  Extract view ptr */
309         maps_view_s *v = (maps_view_s *)data;
310         if (!v->finger_stream)
311                 return;
312
313         /* Detect & Process the gesture */
314         v->finger_stream->multi_tap((Evas_Event_Multi_Down *)event_info);
315 }
316
317 static void __on_canvas_multi_up(void *data, Evas *e, Evas_Object *obj, void *event_info)
318 {
319         MAPS_LOGI("__on_canvas_multi_up");
320         if (!event_info || !data)
321                 return;
322
323         /*  Extract view ptr */
324         maps_view_s *v = (maps_view_s *)data;
325         if (!v->finger_stream)
326                 return;
327
328         /* Detect & Process the gesture */
329         v->finger_stream->multi_up((Evas_Event_Multi_Up *)event_info);
330 }
331
332 static void __on_canvas_multi_line(void *data, Evas *e, Evas_Object *obj, void *event_info)
333 {
334         MAPS_LOGI("__on_canvas_multi_line");
335         if (!event_info || !data)
336                 return;
337
338         /*  Extract view ptr */
339         maps_view_s *v = (maps_view_s *)data;
340         if (!v->finger_stream)
341                 return;
342
343         /* Detect & Process the gesture */
344         v->finger_stream->multi_move((Evas_Event_Multi_Move *)event_info);
345 }
346
347 static int __maps_plugin_render_map(const maps_view_h view,
348         const maps_coordinates_h coordinates, const double zoom_factor, const double rotation_angle)
349 {
350         if (!view || !coordinates)
351                 return MAPS_ERROR_INVALID_PARAMETER;
352
353         return __get_plugin_interface(view)->maps_plugin_render_map(view,
354                                                                                 coordinates, zoom_factor, rotation_angle);
355 }
356
357 void _maps_view_set_idle_listener(const maps_view_h view,
358         void (*callback)(void *user_data), void *user_data)
359 {
360         if (!view)
361                 return;
362         maps_view_s *v = (maps_view_s *)view;
363         v->idle_listener.callback = callback;
364         v->idle_listener.user_data = user_data;
365 }
366
367 void _maps_view_halt_inertial_camera(maps_view_h view)
368 {
369         maps_view_s *v = (maps_view_s *)view;
370         if (v && v->inertial_camera && v->inertial_camera->is_transiting()) {
371                 v->inertial_camera->set_transiting(false);
372                 g_usleep(0);
373         }
374 }
375
376 static Eina_Bool __maps_view_on_idle_cb(void *data)
377 {
378         if (!data)
379                 return ECORE_CALLBACK_RENEW;
380
381         maps_view_s *v = (maps_view_s *)data;
382
383         bool is_transiting = false;
384         bool is_continue = false;
385
386         view::inertial_gesture *ig = v->inertial_gesture;
387         if (ig && ig->is_transiting()) {
388                 is_transiting |= true;
389                 is_continue |= ig->next_transition_step();
390                 g_usleep(5*1000);
391         }
392
393         view::inertial_camera *ic = v->inertial_camera;
394         if (ic && ic->is_transiting()) {
395                 is_transiting |= true;
396                 is_continue |= ic->next_transition_step();
397                 __maps_plugin_render_map(v,
398                                          ic->get_cur_center(),
399                                          ic->get_cur_zoom_factor(),
400                                          ic->get_cur_rotation_angle());
401                 _maps_coordinates_copy(ic->get_cur_center(), v->center);
402
403                 _maps_view_on_overlay_update_all(v);
404                 g_usleep(10*1000);
405         }
406
407         if (is_transiting && !is_continue) {
408                 maps_view_event_data_h ed = _maps_view_create_event_data(MAPS_VIEW_EVENT_READY);
409                 if (ed) {
410                         _maps_view_invoke_event_callback(v, ed);
411                         maps_view_event_data_destroy(ed);
412                 }
413         }
414
415         return ECORE_CALLBACK_RENEW; // same as EINA_TRUE
416 }
417
418 static Eina_Bool __maps_view_animator_cb(void *data)
419 {
420         return ECORE_CALLBACK_RENEW;
421 }
422
423 void __maps_view_ready(const maps_view_h view)
424 {
425         if (!view) return;
426
427         maps_view_s *v = (maps_view_s*)view;
428         v->ready = true;
429
430         _maps_view_set_inertia_enabled(view, true);
431
432         /* Invoke user registered event callback */
433         maps_view_event_data_h ed = _maps_view_create_event_data(MAPS_VIEW_EVENT_READY);
434         if (ed) {
435                 _maps_view_invoke_event_callback(view, ed);
436                 maps_view_event_data_destroy(ed);
437         }
438 }
439
440
441 /* ----------------------CREATE AND DESTROY-----------------------------------*/
442
443 static void __maps_view_parent_resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
444 {
445         maps_view_s *v = (maps_view_s*)data;
446
447         int x, y, w, h, ox, oy, ow, oh;
448
449         /* get geometries of evas object to check how much are changed */
450         evas_object_geometry_get(v->parent, &x, &y, &w, &h);
451         evas_object_geometry_get(v->panel, &ox, &oy, &ow, &oh);
452
453         /* compensate difference of center to keep the map image not to move for eyes after ready */
454         if (v->ready)
455                 _maps_view_move_center(v, (x - ox) / 2, (y - oy) / 2);
456
457         /* set center with stored value */
458         _maps_view_get_plugin_center(v, &v->center);
459         maps_view_set_screen_location(v, x, y, w, h);
460 }
461
462 static void __maps_view_panel_resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
463 {
464         maps_view_s *v = (maps_view_s*)data;
465
466         int x, y, w, h, ox, oy, ow, oh;
467
468         /* get geometries of evas object to check how much are changed */
469         evas_object_geometry_get(v->panel, &x, &y, &w, &h);
470         evas_object_geometry_get(v->clipper, &ox, &oy, &ow, &oh);
471
472         /* compensate difference of center to keep the map image not to move for eyes after ready */
473         if (v->ready)
474                 _maps_view_move_center(v, (x - ox) / 2, (y - oy) / 2);
475
476         /* set center with stored value */
477         _maps_view_get_plugin_center(v, &v->center);
478         maps_view_set_screen_location(v, x, y, w, h);
479 }
480
481 static void __maps_view_create_panel(maps_view_h view, Evas_Object *obj)
482 {
483         if (!view || !obj)
484                 return;
485
486         maps_view_s *v = (maps_view_s*)view;
487
488         /* Initialize the panel */
489         if (!strncmp(evas_object_type_get(obj), "image", strlen("image"))) {
490                 /* if obj is Evas_Image object */
491                 MAPS_LOGD("The panel is a Evas_Image");
492                 v->parent = NULL;
493                 v->panel = obj;
494                 evas_object_event_callback_add(v->panel, EVAS_CALLBACK_RESIZE, __maps_view_panel_resize_cb, v);
495         } else {
496                 /* if obj is the other kind of (smart) objects */
497                 v->parent = obj;
498                 v->panel = evas_object_image_add(evas_object_evas_get(v->parent));
499                 evas_object_smart_member_add(v->panel, v->parent);
500                 evas_object_event_callback_add(v->parent, EVAS_CALLBACK_RESIZE, __maps_view_parent_resize_cb, v);
501
502                 if (evas_object_visible_get(v->parent))
503                         evas_object_show(v->panel);
504                 else
505                         evas_object_hide(v->panel);
506
507                 /* Equal size of a panel object and a parent object */
508                 int x, y, w, h;
509                 evas_object_geometry_get(v->parent, &x, &y, &w, &h);
510                 evas_object_move(v->panel, x, y);
511                 evas_object_resize(v->panel, w, h);
512                 evas_object_image_fill_set(v->panel, 0, 0, w, h);
513         }
514         evas_object_image_filled_set(v->panel, EINA_FALSE);
515 }
516
517 /* Create the panel and link it to the instance of Maps Service */
518 EXPORT_API int maps_view_create(maps_service_h maps, Evas_Object *obj, maps_view_h *view)
519 {
520         if (!maps_condition_check_maps_feature())
521                 return MAPS_ERROR_NOT_SUPPORTED;
522         if (!maps)
523                 return MAPS_ERROR_INVALID_PARAMETER;
524         if (!maps_condition_check_service_supported(maps, MAPS_SERVICE_VIEW))
525                 return MAPS_ERROR_NOT_SUPPORTED;
526         if (!obj || !view)
527                 return MAPS_ERROR_INVALID_PARAMETER;
528         if (!maps_condition_check_privilege())
529                 return MAPS_ERROR_PERMISSION_DENIED;
530
531         maps_view_s *v = g_slice_new0(maps_view_s);
532         if (!v) {
533                 MAPS_LOGE("OUT_OF_MEMORY(0x%08x)", MAPS_ERROR_OUT_OF_MEMORY);
534                 return MAPS_ERROR_OUT_OF_MEMORY;
535         }
536
537         /* Initialize the list with visual objects */
538         maps_item_list_create(&v->view_objects);
539
540         /* Initialize the panel */
541         __maps_view_create_panel(v, obj);
542
543         v->maps_plugin_view_handle = NULL;
544
545         /* Set up event callbacks by default */
546         const int event_callback_cnt =
547                 sizeof(v->event_callbacks) / sizeof(v->event_callbacks[0]);
548         for(int i = 0; i < event_callback_cnt; i ++) {
549                 v->event_callbacks[i].callback = __maps_view_on_event_empty_cb;
550                 v->event_callbacks[i].user_data = NULL;
551         }
552
553         /* Assign gestures to actions */
554         v->gesture_actions[MAPS_VIEW_GESTURE_SCROLL] = MAPS_VIEW_ACTION_NONE;
555         v->gesture_actions[MAPS_VIEW_GESTURE_ZOOM] = MAPS_VIEW_ACTION_ZOOM;
556         v->gesture_actions[MAPS_VIEW_GESTURE_TAP] = MAPS_VIEW_ACTION_NONE;
557         v->gesture_actions[MAPS_VIEW_GESTURE_DOUBLE_TAP] = MAPS_VIEW_ACTION_ZOOM_IN;
558         v->gesture_actions[MAPS_VIEW_GESTURE_2_FINGER_TAP] = MAPS_VIEW_ACTION_ZOOM_OUT;
559         v->gesture_actions[MAPS_VIEW_GESTURE_ROTATE] = MAPS_VIEW_ACTION_ROTATE;
560         v->gesture_actions[MAPS_VIEW_GESTURE_LONG_PRESS] = MAPS_VIEW_ACTION_NONE;
561         v->gesture_actions[MAPS_VIEW_GESTURE_NONE] = MAPS_VIEW_ACTION_NONE;
562
563         /* Set up gesture availability */
564         v->gesture_available[MAPS_VIEW_GESTURE_SCROLL] = true;
565         v->gesture_available[MAPS_VIEW_GESTURE_ZOOM] = true;
566         v->gesture_available[MAPS_VIEW_GESTURE_TAP] = true;
567         v->gesture_available[MAPS_VIEW_GESTURE_DOUBLE_TAP] = true;
568         v->gesture_available[MAPS_VIEW_GESTURE_2_FINGER_TAP] = true;
569         v->gesture_available[MAPS_VIEW_GESTURE_ROTATE] = true;
570         v->gesture_available[MAPS_VIEW_GESTURE_LONG_PRESS] = true;
571         v->gesture_available[MAPS_VIEW_GESTURE_NONE] = false;
572
573         /* Gesture Processing */
574         v->finger_stream = new view::finger_event_stream(v);
575         if (!v->finger_stream) {
576                 MAPS_LOGE("OUT_OF_MEMORY(0x%08x)", MAPS_ERROR_OUT_OF_MEMORY);
577                 return MAPS_ERROR_OUT_OF_MEMORY;
578         }
579         evas_object_event_callback_add(v->panel, EVAS_CALLBACK_MOUSE_DOWN, __on_canvas_tap, v);
580         evas_object_event_callback_add(v->panel, EVAS_CALLBACK_MOUSE_UP, __on_canvas_up, v);
581         evas_object_event_callback_add(v->panel, EVAS_CALLBACK_MOUSE_MOVE, __on_canvas_line, v);
582
583         evas_object_event_callback_add(v->panel, EVAS_CALLBACK_MULTI_DOWN, __on_canvas_multi_tap, v);
584         evas_object_event_callback_add(v->panel, EVAS_CALLBACK_MULTI_UP, __on_canvas_multi_up, v);
585         evas_object_event_callback_add(v->panel, EVAS_CALLBACK_MULTI_MOVE, __on_canvas_multi_line, v);
586
587         /* Set up canvas and Ecore */
588         v->canvas = evas_object_evas_get(v->panel);
589         /*v->ee = ecore_evas_ecore_evas_get(v->canvas);*/
590
591         v->clipper = evas_object_rectangle_add(v->canvas);
592
593         /* Link with Maps Service */
594         v->maps = maps;
595
596         /* Set up canvas and Ecore */
597         v->language = g_strdup("en-US");
598
599         /* Add an idle handler */
600         v->idler = ecore_idler_add(__maps_view_on_idle_cb, v);
601
602         /* Set up the animation frame rate */
603         /*ecore_animator_frametime_set(0.1);*/
604
605         /* Create the animator and assign the drawing task */
606         v->animator = ecore_animator_add(__maps_view_animator_cb, v);
607
608         /* Set up the output pointer to the Maps View */
609         *view = (maps_view_h) v;
610
611         if (__get_plugin_interface(v)) {
612                 /* Notify the Plugin, that the view is created */
613                 if (__get_plugin_interface(v)->maps_plugin_create_map_view)
614                         __get_plugin_interface(v)->maps_plugin_create_map_view(*view, __maps_view_ready);
615                 else
616                         MAPS_LOGE("ERROR!! maps_plugin_create_map_view function pointer is null");
617
618                 /* Set up zoom and rotation */
619                 if (__get_plugin_interface(v)->maps_plugin_get_min_zoom_level)
620                         __get_plugin_interface(v)->maps_plugin_get_min_zoom_level(v, &v->min_zoom_level);
621                 else
622                         MAPS_LOGE("ERROR!! maps_plugin_get_min_zoom_level function pointer is null");
623
624                 if (__get_plugin_interface(v)->maps_plugin_get_max_zoom_level)
625                         __get_plugin_interface(v)->maps_plugin_get_max_zoom_level(v, &v->max_zoom_level);
626                 else
627                         MAPS_LOGE("ERROR!! maps_plugin_get_max_zoom_level function pointer is null");
628         }
629
630         if (v->min_zoom_level <= 0)
631                 v->min_zoom_level = 2;
632         if (v->max_zoom_level <= 0)
633                 v->max_zoom_level = 2;
634
635         v->zoom_level = v->min_zoom_level;
636         v->zoom_factor = double(v->zoom_level);
637         v->rotation_angle = 0.;
638
639         maps_coordinates_create(.0, .0, &v->center);
640
641         v->type = MAPS_VIEW_TYPE_NORMAL;
642         v->buildings_enabled = false;
643         v->traffic_enabled = false;
644         v->public_transit_enabled = false;
645
646         /* To check hit_test */
647         maps_get_screen_dpi(&v->screen_dpi);
648         v->min_hit_area = MAX(20, v->screen_dpi / 5);
649
650         /* Update map view */
651         __maps_view_set_center(v, v->center, TRUE);
652
653         return MAPS_ERROR_NONE;
654 }
655
656 /* Destroy the panel and unlink it from the instance of Maps Service */
657 EXPORT_API int maps_view_destroy(maps_view_h view)
658 {
659         if (!maps_condition_check_maps_feature())
660                 return MAPS_ERROR_NOT_SUPPORTED;
661         if (!view)
662                 return MAPS_ERROR_INVALID_PARAMETER;
663         if (!maps_condition_check_privilege())
664                 return MAPS_ERROR_PERMISSION_DENIED;
665
666         maps_view_s *v = (maps_view_s *) view;
667
668         /* Unregister gesture processing */
669         if (v->finger_stream)
670                 delete v->finger_stream;
671         v->finger_stream = NULL;
672
673         evas_object_event_callback_del(v->panel, EVAS_CALLBACK_MOUSE_DOWN, __on_canvas_tap);
674         evas_object_event_callback_del(v->panel, EVAS_CALLBACK_MOUSE_UP, __on_canvas_up);
675         evas_object_event_callback_del(v->panel, EVAS_CALLBACK_MOUSE_MOVE, __on_canvas_line);
676
677         evas_object_event_callback_del(v->panel, EVAS_CALLBACK_MULTI_DOWN, __on_canvas_multi_tap);
678         evas_object_event_callback_del(v->panel, EVAS_CALLBACK_MULTI_UP, __on_canvas_multi_up);
679         evas_object_event_callback_del(v->panel, EVAS_CALLBACK_MULTI_MOVE, __on_canvas_multi_line);
680
681
682         /* Unregister idle handler */
683         if (v->idler)
684                 ecore_idler_del(v->idler);
685
686         view::inertial_camera *inertial_camera = v->inertial_camera;
687         v->inertial_camera = NULL;
688         v->idle_listener.callback = NULL;
689
690         /* Delete the animator */
691         if (v->animator)
692                 ecore_animator_del(v->animator);
693
694         /* Notify the Plugin, that the view is to be destroyed */
695         if (__get_plugin_interface(view)) {
696                 if (__get_plugin_interface(view)->maps_plugin_destroy_map_view)
697                         __get_plugin_interface(view)->maps_plugin_destroy_map_view(view);
698                 else
699                         MAPS_LOGE("ERROR!! maps_plugin_destroy_map_view function pointer is null");
700         }
701
702         /* Destroy a visual panel */
703         if (v->panel)
704                 evas_object_del(v->panel);
705
706         if (v->clipper)
707                 evas_object_del(v->clipper);
708
709         if (v->center)
710                 maps_coordinates_destroy(v->center);
711
712         if (v->area)
713                 maps_area_destroy(v->area);
714
715         /* Destroy the list with visual objects */
716         maps_item_list_remove_all(v->view_objects, maps_view_object_destroy);
717         maps_item_list_destroy(v->view_objects);
718
719         if (v->language)
720                 g_free(v->language);
721
722         g_slice_free(maps_view_s, v);
723
724         if (inertial_camera)
725                 delete inertial_camera;
726
727         return MAPS_ERROR_NONE;
728 }
729
730
731 int _maps_view_set_center_directly(const maps_view_h view,
732                                                                 const maps_coordinates_h coordinates)
733 {
734         if (!view || !coordinates)
735                 return MAPS_ERROR_INVALID_PARAMETER;
736
737         maps_view_s *v = (maps_view_s *) view;
738         if (v->center != coordinates) {
739                 if (v->center)
740                         maps_coordinates_destroy(v->center);
741                 maps_coordinates_clone(coordinates, &v->center);
742         }
743         return MAPS_ERROR_NONE;
744 }
745
746 int _maps_view_get_plugin_center(const maps_view_h view,
747                                                                 maps_coordinates_h *center)
748 {
749         if (!view || !center)
750                 return MAPS_ERROR_INVALID_PARAMETER;
751
752         return __get_plugin_interface(view)->maps_plugin_get_center(view, center);
753 }
754
755 /*----------------------MAP ZOOM, ROTATE, SET CENTER--------------------------*/
756
757 /* Show the map with a given position centered using current zoom level and
758  * rotation angle */
759
760 static int __maps_view_set_center(maps_view_h view, maps_coordinates_h coordinates, bool internal)
761 {
762         if (!view || !coordinates)
763                 return MAPS_ERROR_INVALID_PARAMETER;
764         double zoom_factor = 1.;
765         int error = maps_view_get_zoom_factor(view, &zoom_factor);
766         if (error != MAPS_ERROR_NONE)
767                 return error;
768
769         double rotation_angle = 0.;
770         error = maps_view_get_orientation(view, &rotation_angle);
771         if (error != MAPS_ERROR_NONE)
772                 return error;
773
774         maps_view_s *v = (maps_view_s *) view;
775
776         /* Set up the target for camera inertial movement */
777         if(v->inertial_camera && !internal)
778                 v->inertial_camera->set_targets(coordinates,
779                                                 zoom_factor,
780                                                 rotation_angle);
781         else
782                 /* Rund rendering in the plugin */
783                 error = __maps_plugin_render_map(view,
784                                                  coordinates,
785                                                  zoom_factor,
786                                                  rotation_angle);
787
788         if (v->center != coordinates) {
789                 maps_coordinates_destroy(v->center);
790                 maps_coordinates_clone(coordinates, &v->center);
791         }
792
793         _maps_view_on_overlay_update_all(view);
794
795         if (!internal) {
796                 /* Invoke user registered event callback */
797                 maps_view_event_data_h ed =
798                         _maps_view_create_event_data(MAPS_VIEW_EVENT_ACTION);
799                 if(ed) {
800                         _maps_view_event_data_set_action_type(ed, MAPS_VIEW_ACTION_SCROLL);
801                         _maps_view_event_data_set_center(ed, v->center);
802                         _maps_view_invoke_event_callback(v, ed);
803                         maps_view_event_data_destroy(ed);
804                 }
805         }
806
807         return error;
808 }
809
810 EXPORT_API int maps_view_set_center(maps_view_h view, maps_coordinates_h coordinates)
811 {
812         if (!maps_condition_check_maps_feature() || !maps_condition_check_internet_feature())
813                 return MAPS_ERROR_NOT_SUPPORTED;
814         if (!view || !coordinates)
815                 return MAPS_ERROR_INVALID_PARAMETER;
816         if (!maps_condition_check_privilege())
817                 return MAPS_ERROR_PERMISSION_DENIED;
818
819         return __maps_view_set_center(view, coordinates, FALSE);
820 }
821
822 int _maps_view_move_center(maps_view_h view, const int delta_x, const int delta_y)
823 {
824         if (!view)
825                 return MAPS_ERROR_INVALID_PARAMETER;
826
827         int error = __get_plugin_interface(view)->maps_plugin_move_center(view, delta_x, delta_y);
828
829         /* update position of overlay objects */
830         _maps_view_on_overlay_update_all(view);
831
832         /* Invoke user registered event callback */
833         maps_view_event_data_h ed =
834                 _maps_view_create_event_data(MAPS_VIEW_EVENT_ACTION);
835         if (ed) {
836                 _maps_view_event_data_set_action_type(ed, MAPS_VIEW_ACTION_SCROLL);
837                 _maps_view_event_data_set_delta(ed, delta_x, delta_y);
838                 _maps_view_invoke_event_callback(view, ed);
839                 maps_view_event_data_destroy(ed);
840         }
841
842         return error;
843 }
844
845 EXPORT_API int maps_view_set_scalebar_enabled(const maps_view_h view, bool enable)
846 {
847         if (!maps_condition_check_maps_feature() || !maps_condition_check_internet_feature())
848                 return MAPS_ERROR_NOT_SUPPORTED;
849         if (!view)
850                 return MAPS_ERROR_INVALID_PARAMETER;
851         if (!maps_condition_check_view_data_supported(view, MAPS_VIEW_SCALEBAR))
852                 return MAPS_ERROR_NOT_SUPPORTED;
853         if (!maps_condition_check_privilege())
854                 return MAPS_ERROR_PERMISSION_DENIED;
855
856         return __get_plugin_interface(view)->maps_plugin_set_scalebar(view, enable);
857 }
858
859 EXPORT_API int maps_view_get_scalebar_enabled(const maps_view_h view, bool *enabled)
860 {
861         if (!maps_condition_check_maps_feature())
862                 return MAPS_ERROR_NOT_SUPPORTED;
863         if (!view)
864                 return MAPS_ERROR_INVALID_PARAMETER;
865         if (!maps_condition_check_view_data_supported(view, MAPS_VIEW_SCALEBAR))
866                 return MAPS_ERROR_NOT_SUPPORTED;
867         if (!enabled)
868                 return MAPS_ERROR_INVALID_PARAMETER;
869
870         return __get_plugin_interface(view)->maps_plugin_get_scalebar(view, enabled);
871 }
872
873 EXPORT_API int maps_view_get_center(const maps_view_h view, maps_coordinates_h *coordinates)
874 {
875         if (!maps_condition_check_maps_feature())
876                 return MAPS_ERROR_NOT_SUPPORTED;
877         if (!view || !coordinates)
878                 return MAPS_ERROR_INVALID_PARAMETER;
879         maps_view_s *v = (maps_view_s *) view;
880         return maps_coordinates_clone(v->center, coordinates);
881 }
882
883 EXPORT_API int maps_view_set_zoom_level(maps_view_h view, int level)
884 {
885         if (!maps_condition_check_maps_feature() || !maps_condition_check_internet_feature())
886                 return MAPS_ERROR_NOT_SUPPORTED;
887         if (!view)
888                 return MAPS_ERROR_INVALID_PARAMETER;
889         if (!maps_condition_check_privilege())
890                 return MAPS_ERROR_PERMISSION_DENIED;
891
892         maps_view_s *v = (maps_view_s *) view;
893         int new_level = level;
894         if (new_level < v->min_zoom_level) new_level = v->min_zoom_level;
895         if (new_level > v->max_zoom_level) new_level = v->max_zoom_level;
896
897         /* Add inertia to the zoom process */
898         if (v->inertial_camera)
899                 v->inertial_camera->set_zoom_target(double(new_level));
900
901         v->zoom_level = new_level;
902         v->zoom_factor = double(new_level); /* Update the integer  zoom level too */
903
904         const int error = maps_view_set_center(view, v->center);
905
906         /* Invoke user registered event callback */
907         maps_view_event_data_h ed =
908                 _maps_view_create_event_data(MAPS_VIEW_EVENT_ACTION);
909         if (ed) {
910                 _maps_view_event_data_set_action_type(ed, MAPS_VIEW_ACTION_ZOOM);
911                 _maps_view_event_data_set_zoom_factor(ed, v->zoom_factor);
912                 _maps_view_invoke_event_callback(v, ed);
913                 maps_view_event_data_destroy(ed);
914         }
915
916         return error;
917 }
918
919 EXPORT_API int maps_view_get_zoom_level(const maps_view_h view, int *level)
920 {
921         if (!maps_condition_check_maps_feature())
922                 return MAPS_ERROR_NOT_SUPPORTED;
923         if (!view || !level)
924                 return MAPS_ERROR_INVALID_PARAMETER;
925         maps_view_s *v = (maps_view_s *) view;
926         *level = v->zoom_level;
927         return MAPS_ERROR_NONE;
928 }
929
930 EXPORT_API int maps_view_set_min_zoom_level(maps_view_h view, int level)
931 {
932         if (!maps_condition_check_maps_feature())
933                 return MAPS_ERROR_NOT_SUPPORTED;
934         if (!view)
935                 return MAPS_ERROR_INVALID_PARAMETER;
936         if (!maps_condition_check_privilege())
937                 return MAPS_ERROR_PERMISSION_DENIED;
938
939         maps_view_s *v = (maps_view_s *) view;
940         int min_zoom_level = -1;
941         __get_plugin_interface(v)->maps_plugin_get_min_zoom_level(view, &min_zoom_level);
942         if (min_zoom_level < 0)
943                 return MAPS_ERROR_INVALID_OPERATION;
944         if ((level < min_zoom_level) || (level > v->max_zoom_level))
945                 return MAPS_ERROR_INVALID_PARAMETER;
946         v->min_zoom_level = level;
947         if (v->min_zoom_level > v->zoom_level)
948                 maps_view_set_zoom_level(view, v->min_zoom_level);
949         return MAPS_ERROR_NONE;
950 }
951
952 EXPORT_API int maps_view_get_min_zoom_level(const maps_view_h view, int *min_zoom_level)
953 {
954         if (!maps_condition_check_maps_feature())
955                 return MAPS_ERROR_NOT_SUPPORTED;
956         if (!view || !min_zoom_level)
957                 return MAPS_ERROR_INVALID_PARAMETER;
958         maps_view_s *v = (maps_view_s *) view;
959         *min_zoom_level = v->min_zoom_level;
960         return MAPS_ERROR_NONE;
961 }
962
963 EXPORT_API int maps_view_set_max_zoom_level(maps_view_h view, int level)
964 {
965         if (!maps_condition_check_maps_feature())
966                 return MAPS_ERROR_NOT_SUPPORTED;
967         if (!view)
968                 return MAPS_ERROR_INVALID_PARAMETER;
969         if (!maps_condition_check_privilege())
970                 return MAPS_ERROR_PERMISSION_DENIED;
971
972         maps_view_s *v = (maps_view_s *) view;
973         int max_zoom_level = -1;
974         __get_plugin_interface(v)->maps_plugin_get_max_zoom_level(view, &max_zoom_level);
975         if (max_zoom_level < 0)
976                 return MAPS_ERROR_INVALID_OPERATION;
977         if ((level < v->min_zoom_level) || (level > max_zoom_level))
978                 return MAPS_ERROR_INVALID_PARAMETER;
979         v->max_zoom_level = level;
980         if (v->max_zoom_level < v->zoom_level)
981                 maps_view_set_zoom_level(view, v->max_zoom_level);
982         return MAPS_ERROR_NONE;
983 }
984
985 EXPORT_API int maps_view_get_max_zoom_level(const maps_view_h view, int *max_zoom_level)
986 {
987         if (!maps_condition_check_maps_feature())
988                 return MAPS_ERROR_NOT_SUPPORTED;
989         if (!view || !max_zoom_level)
990                 return MAPS_ERROR_INVALID_PARAMETER;
991         maps_view_s *v = (maps_view_s *) view;
992         *max_zoom_level = v->max_zoom_level;
993         return MAPS_ERROR_NONE;
994 }
995
996 int _maps_view_set_zoom_rotate(maps_view_h view,
997                                                                 const bool zoom_changed,
998                                                                 const double factor,
999                                                                 const bool rotation_changed,
1000                                                                 const double angle)
1001 {
1002         if (!view)
1003                 return MAPS_ERROR_INVALID_PARAMETER;
1004
1005         maps_view_s *v = (maps_view_s *) view;
1006
1007         /* 1. Apply new zoom and orientation values */
1008         if (zoom_changed) {
1009                 double new_factor = factor;
1010                 if (new_factor < v->min_zoom_level) new_factor = v->min_zoom_level;
1011                 if (new_factor > v->max_zoom_level) new_factor = v->max_zoom_level;
1012
1013                 /* Add inertia to the zoom process */
1014                 if (v->inertial_camera)
1015                         v->inertial_camera->set_zoom_target(new_factor);
1016
1017                 /* Update Map View zoom factor */
1018                 v->zoom_factor = new_factor;
1019
1020                 /* Update the integer zoom level too */
1021                 v->zoom_level = int(new_factor);
1022         }
1023
1024         if (rotation_changed) {
1025                 /* Add inertia to the rotation process */
1026                 if (v->inertial_camera)
1027                         v->inertial_camera->set_rotation_target(angle);
1028
1029                 /* Update Map View rotation angle */
1030                 v->rotation_angle = angle;
1031         }
1032
1033         /* 2. Send update center command to the plugin */
1034         const int error = maps_view_set_center(view, v->center);
1035
1036         /* Notify the user about changes */
1037         if (zoom_changed) {
1038                 /* Invoke user registered event callback */
1039                 maps_view_event_data_h ed =
1040                         _maps_view_create_event_data(MAPS_VIEW_EVENT_ACTION);
1041                 if (ed) {
1042                         _maps_view_event_data_set_action_type(ed, MAPS_VIEW_ACTION_ZOOM);
1043                         _maps_view_event_data_set_zoom_factor(ed, v->zoom_factor);
1044                         _maps_view_invoke_event_callback(v, ed);
1045                         maps_view_event_data_destroy(ed);
1046                 }
1047         }
1048
1049         if (rotation_changed) {
1050                 /* Invoke user registered event callback */
1051                 maps_view_event_data_h ed =
1052                         _maps_view_create_event_data(MAPS_VIEW_EVENT_ACTION);
1053                 if (ed) {
1054                         _maps_view_event_data_set_action_type(ed, MAPS_VIEW_ACTION_ROTATE);
1055                         _maps_view_event_data_set_rotation_angle(ed, v->rotation_angle);
1056                         _maps_view_invoke_event_callback(v, ed);
1057                         maps_view_event_data_destroy(ed);
1058                 }
1059         }
1060
1061         return error;
1062 }
1063
1064 EXPORT_API int maps_view_set_zoom_factor(const maps_view_h view,
1065                                         const double factor)
1066 {
1067         if (!maps_condition_check_maps_feature())
1068                 return MAPS_ERROR_NOT_SUPPORTED;
1069         if (!view)
1070                 return MAPS_ERROR_INVALID_PARAMETER;
1071
1072         maps_view_s *v = (maps_view_s *) view;
1073         double new_factor = factor;
1074         if (new_factor < v->min_zoom_level) new_factor = v->min_zoom_level;
1075         if (new_factor > v->max_zoom_level) new_factor = v->max_zoom_level;
1076
1077         return _maps_view_set_zoom_rotate(view, true, new_factor, false, .0);
1078 }
1079
1080 EXPORT_API int maps_view_get_zoom_factor(const maps_view_h view, double *factor)
1081 {
1082         if (!maps_condition_check_maps_feature())
1083                 return MAPS_ERROR_NOT_SUPPORTED;
1084         if (!view || !factor)
1085                 return MAPS_ERROR_INVALID_PARAMETER;
1086         maps_view_s *v = (maps_view_s *) view;
1087         *factor = v->zoom_factor;
1088         return MAPS_ERROR_NONE;
1089 }
1090
1091 EXPORT_API int maps_view_set_orientation(maps_view_h view, double angle)
1092 {
1093         if (!maps_condition_check_maps_feature() || !maps_condition_check_internet_feature())
1094                 return MAPS_ERROR_NOT_SUPPORTED;
1095         if (!view)
1096                 return MAPS_ERROR_INVALID_PARAMETER;
1097         if (!maps_condition_check_privilege())
1098                 return MAPS_ERROR_PERMISSION_DENIED;
1099
1100         /* Add inertia to the rotation process */
1101         maps_view_s *v = (maps_view_s *)view;
1102         if (v->inertial_camera)
1103                 v->inertial_camera->set_rotation_target(angle);
1104
1105         return _maps_view_set_zoom_rotate(view, false, .0, true, angle);
1106 }
1107
1108 EXPORT_API int maps_view_get_orientation(const maps_view_h view, double *angle)
1109 {
1110         if (!maps_condition_check_maps_feature())
1111                 return MAPS_ERROR_NOT_SUPPORTED;
1112         if (!view || !angle)
1113                 return MAPS_ERROR_INVALID_PARAMETER;
1114         maps_view_s *v = (maps_view_s *) view;
1115         *angle = v->rotation_angle;
1116         return MAPS_ERROR_NONE;
1117 }
1118
1119
1120 /*----------------------SCREEN <--> GEOGRAPHY---------------------------------*/
1121
1122
1123 /* Converting screen coordinates to geographical */
1124 EXPORT_API int maps_view_screen_to_geolocation(maps_view_h view,
1125         int x, int y, maps_coordinates_h *coordinates)
1126 {
1127         if (!maps_condition_check_maps_feature())
1128                 return MAPS_ERROR_NOT_SUPPORTED;
1129         if (!view || !coordinates)
1130                 return MAPS_ERROR_INVALID_PARAMETER;
1131         if (!maps_condition_check_privilege())
1132                 return MAPS_ERROR_PERMISSION_DENIED;
1133
1134         int posx = 0;
1135         int posy = 0;
1136         maps_view_get_screen_location(view, &posx, &posy, NULL, NULL);
1137         return __get_plugin_interface(view)->
1138                                                 maps_plugin_screen_to_geography(view, x - posx, y - posy, coordinates);
1139 }
1140
1141 EXPORT_API int maps_view_geolocation_to_screen(const maps_view_h view,
1142         const maps_coordinates_h coordinates, int *x, int *y)
1143 {
1144         if (!maps_condition_check_maps_feature())
1145                 return MAPS_ERROR_NOT_SUPPORTED;
1146         if (!view || !coordinates || !x || !y)
1147                 return MAPS_ERROR_INVALID_PARAMETER;
1148         if (!maps_condition_check_privilege())
1149                 return MAPS_ERROR_PERMISSION_DENIED;
1150
1151         int posx = 0;
1152         int posy = 0;
1153         maps_view_get_screen_location(view, &posx, &posy, NULL, NULL);
1154         const int error = __get_plugin_interface(view)->
1155                                                 maps_plugin_geography_to_screen(view, coordinates, x, y);
1156         *x += posx;
1157         *y += posy;
1158         return error;
1159 }
1160
1161
1162 /* --------------------MAPS VIEW PREFERENCES----------------------------------*/
1163
1164
1165 EXPORT_API int maps_view_set_type(maps_view_h view, maps_view_type_e type)
1166 {
1167         if (!maps_condition_check_maps_feature() || !maps_condition_check_internet_feature())
1168                 return MAPS_ERROR_NOT_SUPPORTED;
1169         if (!view)
1170                 return MAPS_ERROR_INVALID_PARAMETER;
1171         if ((type < MAPS_VIEW_TYPE_NORMAL) || (type > MAPS_VIEW_TYPE_HYBRID))
1172                 return MAPS_ERROR_INVALID_PARAMETER;
1173         if (!maps_condition_check_privilege())
1174                 return MAPS_ERROR_PERMISSION_DENIED;
1175
1176         maps_view_s *v = (maps_view_s *) view;
1177         v->type = type;
1178         return maps_view_set_center(view, v->center);
1179 }
1180
1181 EXPORT_API int maps_view_get_type(const maps_view_h view, maps_view_type_e *type)
1182 {
1183         if (!maps_condition_check_maps_feature())
1184                 return MAPS_ERROR_NOT_SUPPORTED;
1185         if (!view || !type)
1186                 return MAPS_ERROR_INVALID_PARAMETER;
1187         maps_view_s *v = (maps_view_s *) view;
1188         *type = v->type;
1189         return MAPS_ERROR_NONE;
1190 }
1191
1192 EXPORT_API int maps_view_set_buildings_enabled(maps_view_h view, bool enabled)
1193 {
1194         if (!maps_condition_check_maps_feature() || !maps_condition_check_internet_feature())
1195                 return MAPS_ERROR_NOT_SUPPORTED;
1196         if (!view)
1197                 return MAPS_ERROR_INVALID_PARAMETER;
1198         if (!maps_condition_check_view_data_supported(view, MAPS_VIEW_BUILDING))
1199                 return MAPS_ERROR_NOT_SUPPORTED;
1200         if (!maps_condition_check_privilege())
1201                 return MAPS_ERROR_PERMISSION_DENIED;
1202
1203         maps_view_s *v = (maps_view_s *) view;
1204         v->buildings_enabled = enabled;
1205         return maps_view_set_center(view, v->center);
1206 }
1207
1208 EXPORT_API int maps_view_get_buildings_enabled(const maps_view_h view, bool *enabled)
1209 {
1210         if (!maps_condition_check_maps_feature())
1211                 return MAPS_ERROR_NOT_SUPPORTED;
1212         if (!view)
1213                 return MAPS_ERROR_INVALID_PARAMETER;
1214         if (!maps_condition_check_view_data_supported(view, MAPS_VIEW_BUILDING))
1215                 return MAPS_ERROR_NOT_SUPPORTED;
1216         if (!enabled)
1217                 return MAPS_ERROR_INVALID_PARAMETER;
1218         maps_view_s *v = (maps_view_s *) view;
1219         *enabled = v->buildings_enabled;
1220         return MAPS_ERROR_NONE;
1221 }
1222
1223 EXPORT_API int maps_view_set_traffic_enabled(maps_view_h view, bool enabled)
1224 {
1225         if (!maps_condition_check_maps_feature() || !maps_condition_check_internet_feature())
1226                 return MAPS_ERROR_NOT_SUPPORTED;
1227         if (!view)
1228                 return MAPS_ERROR_INVALID_PARAMETER;
1229         if (!maps_condition_check_view_data_supported(view, MAPS_VIEW_TRAFFIC))
1230                 return MAPS_ERROR_NOT_SUPPORTED;
1231         if (!maps_condition_check_privilege())
1232                 return MAPS_ERROR_PERMISSION_DENIED;
1233
1234         maps_view_s *v = (maps_view_s *) view;
1235         v->traffic_enabled = enabled;
1236         return maps_view_set_center(view, v->center);
1237 }
1238
1239 EXPORT_API int maps_view_get_traffic_enabled(const maps_view_h view, bool *enabled)
1240 {
1241         if (!maps_condition_check_maps_feature())
1242                 return MAPS_ERROR_NOT_SUPPORTED;
1243         if (!view)
1244                 return MAPS_ERROR_INVALID_PARAMETER;
1245         if (!maps_condition_check_view_data_supported(view, MAPS_VIEW_TRAFFIC))
1246                 return MAPS_ERROR_NOT_SUPPORTED;
1247         if (!enabled)
1248                 return MAPS_ERROR_INVALID_PARAMETER;
1249         maps_view_s *v = (maps_view_s *) view;
1250         *enabled = v->traffic_enabled;
1251         return MAPS_ERROR_NONE;
1252 }
1253
1254 EXPORT_API int maps_view_set_public_transit_enabled(maps_view_h view, bool enabled)
1255 {
1256         if (!maps_condition_check_maps_feature() || !maps_condition_check_internet_feature())
1257                 return MAPS_ERROR_NOT_SUPPORTED;
1258         if (!view)
1259                 return MAPS_ERROR_INVALID_PARAMETER;
1260         if (!maps_condition_check_view_data_supported(view, MAPS_VIEW_PUBLIC_TRANSIT))
1261                 return MAPS_ERROR_NOT_SUPPORTED;
1262         if (!maps_condition_check_privilege())
1263                 return MAPS_ERROR_PERMISSION_DENIED;
1264
1265         maps_view_s *v = (maps_view_s *) view;
1266         v->public_transit_enabled = enabled;
1267         return maps_view_set_center(view, v->center);
1268 }
1269
1270 EXPORT_API int maps_view_get_public_transit_enabled(const maps_view_h view, bool *enabled)
1271 {
1272         if (!maps_condition_check_maps_feature())
1273                 return MAPS_ERROR_NOT_SUPPORTED;
1274         if (!view)
1275                 return MAPS_ERROR_INVALID_PARAMETER;
1276         if (!maps_condition_check_view_data_supported(view, MAPS_VIEW_PUBLIC_TRANSIT))
1277                 return MAPS_ERROR_NOT_SUPPORTED;
1278         if (!enabled)
1279                 return MAPS_ERROR_INVALID_PARAMETER;
1280         maps_view_s *v = (maps_view_s *) view;
1281         *enabled = v->public_transit_enabled;
1282         return MAPS_ERROR_NONE;
1283 }
1284
1285 int _maps_view_set_inertia_enabled(maps_view_h view, bool enabled)
1286 {
1287         if (!view)
1288                 return MAPS_ERROR_INVALID_PARAMETER;
1289         maps_view_s *v = (maps_view_s *) view;
1290
1291         if (enabled) {
1292                 if (!v->inertial_gesture) {
1293                         v->inertial_gesture = new view::inertial_gesture(view);
1294                         if (!v->inertial_gesture) {
1295                                 MAPS_LOGE("OUT_OF_MEMORY(0x%08x)", MAPS_ERROR_OUT_OF_MEMORY);
1296                                 return MAPS_ERROR_OUT_OF_MEMORY;
1297                         }
1298                 }
1299
1300                 if (!v->inertial_camera) {
1301                         v->inertial_camera = new view::inertial_camera(view);
1302                         if (!v->inertial_camera) {
1303                                 MAPS_LOGE("OUT_OF_MEMORY(0x%08x)", MAPS_ERROR_OUT_OF_MEMORY);
1304                                 return MAPS_ERROR_OUT_OF_MEMORY;
1305                         }
1306                 }
1307
1308                 v->finger_stream->set_gesture_detector(v->inertial_gesture);
1309         } else {
1310                 v->finger_stream->set_gesture_detector(new view::gesture_detector_statemachine(view));
1311
1312                 if (v->inertial_gesture) {
1313                         /* Unset Inertial Camera */
1314                         if (v->inertial_gesture->is_transiting()) {
1315                                 v->inertial_gesture->set_transiting(false);
1316                                 sleep(0);
1317                         }
1318                         view::inertial_gesture *inertial_gesture = v->inertial_gesture;
1319                         v->inertial_gesture = NULL;
1320                         delete inertial_gesture;
1321                 }
1322
1323                 if (v->inertial_camera) {
1324                         /* Unset Inertial Camera */
1325                         if (v->inertial_camera->is_transiting()) {
1326                                 v->inertial_camera->set_transiting(false);
1327                                 sleep(0);
1328                         }
1329                         view::inertial_camera *inertial_camera = v->inertial_camera;
1330                         v->inertial_camera = NULL;
1331                         delete inertial_camera;
1332                 }
1333         }
1334         return MAPS_ERROR_NONE;
1335 }
1336
1337 EXPORT_API int maps_view_get_inertia_enabled(maps_view_h view, bool *enabled)
1338 {
1339         if (!maps_condition_check_maps_feature())
1340                 return MAPS_ERROR_NOT_SUPPORTED;
1341         if (!view || !enabled)
1342                 return MAPS_ERROR_INVALID_PARAMETER;
1343
1344         maps_view_s *v = (maps_view_s *) view;
1345         *enabled = v->inertial_camera != NULL;
1346         return MAPS_ERROR_NONE;
1347 }
1348
1349 EXPORT_API int maps_view_set_language(maps_view_h view, const char *language)
1350 {
1351         if (!maps_condition_check_maps_feature() || !maps_condition_check_internet_feature())
1352                 return MAPS_ERROR_NOT_SUPPORTED;
1353         if (!view || !language)
1354                 return MAPS_ERROR_INVALID_PARAMETER;
1355         if (!maps_condition_check_privilege())
1356                 return MAPS_ERROR_PERMISSION_DENIED;
1357
1358         maps_view_s *v = (maps_view_s *) view;
1359         int error = maps_set_string(language, _MAPS_VIEW_LANGUAGE_MAX_LENGTH, &v->language);
1360         if (error == MAPS_ERROR_NONE)
1361                 error = maps_view_set_center(view, v->center);
1362         return error;
1363 }
1364
1365 EXPORT_API int maps_view_get_language(const maps_view_h view, char **language)
1366 {
1367         if (!maps_condition_check_maps_feature())
1368                 return MAPS_ERROR_NOT_SUPPORTED;
1369         if (!view || !language)
1370                 return MAPS_ERROR_INVALID_PARAMETER;
1371         return maps_get_string(((maps_view_s *) view)->language,
1372                 _MAPS_VIEW_LANGUAGE_MAX_LENGTH, language);
1373 }
1374
1375
1376 /* --------------------MAPS PANEL MANIPULATIONS-------------------------------*/
1377
1378 EXPORT_API int maps_view_get_viewport(const maps_view_h view, Evas_Object **viewport)
1379 {
1380         if (!maps_condition_check_maps_feature())
1381                 return MAPS_ERROR_NOT_SUPPORTED;
1382         if (!view || !viewport)
1383                 return MAPS_ERROR_INVALID_PARAMETER;
1384         maps_view_s *v = (maps_view_s *) view;
1385         *viewport = v->panel;
1386         return MAPS_ERROR_NONE;
1387 }
1388
1389 int _maps_view_get_parent(const maps_view_h view, Evas_Object **parent)
1390 {
1391         if (!view || !parent)
1392                 return MAPS_ERROR_INVALID_PARAMETER;
1393         maps_view_s *v = (maps_view_s *) view;
1394         *parent = v->parent;
1395         return MAPS_ERROR_NONE;
1396 }
1397
1398 int _maps_view_get_clipper(const maps_view_h view, Evas_Object **clipper)
1399 {
1400         if (!view || !clipper)
1401                 return MAPS_ERROR_INVALID_PARAMETER;
1402         maps_view_s *v = (maps_view_s *) view;
1403         *clipper = v->clipper;
1404         return MAPS_ERROR_NONE;
1405 }
1406
1407 EXPORT_API int maps_view_set_screen_location(maps_view_h view, int x, int y, int width, int height)
1408 {
1409         if (!maps_condition_check_maps_feature() || !maps_condition_check_internet_feature())
1410                 return MAPS_ERROR_NOT_SUPPORTED;
1411         if (!view)
1412                 return MAPS_ERROR_INVALID_PARAMETER;
1413         if (!maps_condition_check_privilege())
1414                 return MAPS_ERROR_PERMISSION_DENIED;
1415
1416         int error = maps_view_move(view, x, y);
1417         if (error == MAPS_ERROR_NONE)
1418                 error = maps_view_resize(view, width, height);
1419         return error;
1420 }
1421
1422 EXPORT_API int maps_view_get_screen_location(const maps_view_h view, int *x, int *y, int *width, int *height)
1423 {
1424         if (!maps_condition_check_maps_feature())
1425                 return MAPS_ERROR_NOT_SUPPORTED;
1426         if (!view || (!x && !y && !width && !height))
1427                 return MAPS_ERROR_INVALID_PARAMETER;
1428         maps_view_s *v = (maps_view_s *) view;
1429         evas_object_geometry_get(v->panel, x, y, width, height);
1430         return MAPS_ERROR_NONE;
1431 }
1432
1433 EXPORT_API int maps_view_move(maps_view_h view, int x, int y)
1434 {
1435         if (!maps_condition_check_maps_feature() || !maps_condition_check_internet_feature())
1436                 return MAPS_ERROR_NOT_SUPPORTED;
1437         if (!view)
1438                 return MAPS_ERROR_INVALID_PARAMETER;
1439
1440         maps_view_s *v = (maps_view_s *) view;
1441         evas_object_move(v->panel, x, y);
1442         evas_object_move(v->clipper, x, y);
1443         return MAPS_ERROR_NONE;
1444 }
1445
1446 EXPORT_API int maps_view_resize(maps_view_h view, int width, int height)
1447 {
1448         if (!maps_condition_check_maps_feature() || !maps_condition_check_internet_feature())
1449                 return MAPS_ERROR_NOT_SUPPORTED;
1450         if (!view || (width <= 0) || (height <= 0))
1451                 return MAPS_ERROR_INVALID_PARAMETER;
1452         if (!maps_condition_check_privilege())
1453                 return MAPS_ERROR_PERMISSION_DENIED;
1454
1455         maps_view_s *v = (maps_view_s *) view;
1456         evas_object_resize(v->panel, width, height);
1457         evas_object_resize(v->clipper, width, height);
1458         evas_object_image_fill_set(v->panel, 0, 0, width, height);
1459         return __maps_view_set_center(view, v->center, TRUE);
1460 }
1461
1462 EXPORT_API int maps_view_set_visibility(maps_view_h view, bool visible)
1463 {
1464         if (!maps_condition_check_maps_feature())
1465                 return MAPS_ERROR_NOT_SUPPORTED;
1466         if (!view)
1467                 return MAPS_ERROR_INVALID_PARAMETER;
1468
1469         maps_view_s *v = (maps_view_s *) view;
1470         if (visible)
1471                 evas_object_show(v->panel);
1472         else
1473                 evas_object_hide(v->panel);
1474         return MAPS_ERROR_NONE;
1475 }
1476
1477 EXPORT_API int maps_view_get_visibility(const maps_view_h view, bool *visible)
1478 {
1479         if (!maps_condition_check_maps_feature())
1480                 return MAPS_ERROR_NOT_SUPPORTED;
1481         if (!view || !visible)
1482                 return MAPS_ERROR_INVALID_PARAMETER;
1483
1484         maps_view_s *v = (maps_view_s *) view;
1485         *visible = evas_object_visible_get(v->panel) == EINA_TRUE;
1486         return MAPS_ERROR_NONE;
1487 }
1488
1489 int _maps_view_redraw(const maps_view_h view)
1490 {
1491         if (!view)
1492                 return MAPS_ERROR_INVALID_PARAMETER;
1493
1494         maps_view_s *v = (maps_view_s *) view;
1495
1496         /* Signal to the animator, that we are ready to draw */
1497         v->ready_to_draw = true;
1498
1499         return MAPS_ERROR_NONE;
1500 }
1501
1502 /* ---------------------USER CONTROL------------------------------------------*/
1503
1504
1505 EXPORT_API int maps_view_set_event_cb(maps_view_h view, maps_view_event_type_e type,
1506         maps_view_on_event_cb callback, void *user_data)
1507 {
1508         if (!maps_condition_check_maps_feature())
1509                 return MAPS_ERROR_NOT_SUPPORTED;
1510         if (!view || !callback)
1511                 return MAPS_ERROR_INVALID_PARAMETER;
1512         if ((type < MAPS_VIEW_EVENT_GESTURE) || (type > MAPS_VIEW_EVENT_READY))
1513                 return MAPS_ERROR_INVALID_PARAMETER;
1514
1515         maps_view_s *v = (maps_view_s *) view;
1516         v->event_callbacks[type].callback = callback;
1517         v->event_callbacks[type].user_data = user_data;
1518
1519         return MAPS_ERROR_NONE;
1520 }
1521
1522 EXPORT_API int maps_view_unset_event_cb(maps_view_h view, maps_view_event_type_e type)
1523 {
1524         if (!maps_condition_check_maps_feature())
1525                 return MAPS_ERROR_NOT_SUPPORTED;
1526         if (!view)
1527                 return MAPS_ERROR_INVALID_PARAMETER;
1528         if ((type < MAPS_VIEW_EVENT_GESTURE) || (type > MAPS_VIEW_EVENT_READY))
1529                 return MAPS_ERROR_INVALID_PARAMETER;
1530
1531         maps_view_s *v = (maps_view_s *) view;
1532         v->event_callbacks[type].callback = __maps_view_on_event_empty_cb;
1533         v->event_callbacks[type].user_data = NULL;
1534
1535         return MAPS_ERROR_NONE;
1536 }
1537
1538 EXPORT_API int maps_view_set_gesture_enabled(maps_view_h view, maps_view_gesture_e gesture, bool enabled)
1539 {
1540         if (!maps_condition_check_maps_feature())
1541                 return MAPS_ERROR_NOT_SUPPORTED;
1542         if (!view)
1543                 return MAPS_ERROR_INVALID_PARAMETER;
1544         if ((gesture < MAPS_VIEW_GESTURE_NONE) || (gesture > MAPS_VIEW_GESTURE_LONG_PRESS))
1545                 return MAPS_ERROR_INVALID_PARAMETER;
1546         maps_view_s *v = (maps_view_s *) view;
1547         v->gesture_available[gesture] = enabled;
1548         return MAPS_ERROR_NONE;
1549 }
1550
1551 EXPORT_API int maps_view_get_gesture_enabled(const maps_view_h view, maps_view_gesture_e gesture, bool *enabled)
1552 {
1553         if (!maps_condition_check_maps_feature())
1554                 return MAPS_ERROR_NOT_SUPPORTED;
1555         if (!view || !enabled)
1556                 return MAPS_ERROR_INVALID_PARAMETER;
1557         if ((gesture < MAPS_VIEW_GESTURE_NONE) || (gesture > MAPS_VIEW_GESTURE_LONG_PRESS))
1558                 return MAPS_ERROR_INVALID_PARAMETER;
1559         maps_view_s *v = (maps_view_s *) view;
1560         *enabled = v->gesture_available[gesture];
1561         return MAPS_ERROR_NONE;
1562 }
1563
1564
1565 /* ---------------------VISUAL OBJECTS ON THE MAP-----------------------------*/
1566
1567 EXPORT_API int maps_view_add_object(maps_view_h view, maps_view_object_h object)
1568 {
1569         if (!maps_condition_check_maps_feature())
1570                 return MAPS_ERROR_NOT_SUPPORTED;
1571         if (!view || !object)
1572                 return MAPS_ERROR_INVALID_PARAMETER;
1573         if (!maps_condition_check_privilege())
1574                 return MAPS_ERROR_PERMISSION_DENIED;
1575
1576         int error = MAPS_ERROR_NONE;
1577         do {
1578                 /* Add Visual Object to the list of View Visual Objects */
1579                 maps_view_s *v = (maps_view_s *)view;
1580                 error = maps_item_list_append(v->view_objects, object, NULL);
1581                 if (error != MAPS_ERROR_NONE)
1582                         break;
1583
1584                 /* Link the object with the View */
1585                 error = _maps_view_object_set_view(object, view);
1586                 if (error != MAPS_ERROR_NONE)
1587                         break;
1588
1589                 /* Notify the plugin about added object */
1590                 error = _maps_view_on_object_operation(view, object, MAPS_VIEW_OBJECT_ADD);
1591                 if (error != MAPS_ERROR_NONE)
1592                         break;
1593
1594                 /* Redraw the view */
1595                 error = _maps_view_redraw(v);
1596                 if (error != MAPS_ERROR_NONE)
1597                         break;
1598
1599                 return MAPS_ERROR_NONE;
1600         } while (false);
1601
1602         return error;
1603 }
1604
1605 EXPORT_API int maps_view_remove_object(maps_view_h view, maps_view_object_h object)
1606 {
1607         if (!maps_condition_check_maps_feature())
1608                 return MAPS_ERROR_NOT_SUPPORTED;
1609         if (!view || !object)
1610                 return MAPS_ERROR_INVALID_PARAMETER;
1611         if (!maps_condition_check_privilege())
1612                 return MAPS_ERROR_PERMISSION_DENIED;
1613
1614         int error = MAPS_ERROR_NONE;
1615         do {
1616                 /* Remove Visual Object from the list of View Visual Objects */
1617                 maps_view_s *v = (maps_view_s *)view;
1618                 error =  maps_item_list_remove(v->view_objects, object, maps_view_object_destroy);
1619                 if (error != MAPS_ERROR_NONE)
1620                         return error;
1621
1622                 /* Redraw the view */
1623                 error = _maps_view_redraw(v);
1624                 if (error != MAPS_ERROR_NONE)
1625                         return error;
1626
1627                 return MAPS_ERROR_NONE;
1628         } while (false);
1629
1630         return error;
1631 }
1632
1633 EXPORT_API int maps_view_remove_all_objects(maps_view_h view)
1634 {
1635         if (!maps_condition_check_maps_feature())
1636                 return MAPS_ERROR_NOT_SUPPORTED;
1637         if (!view)
1638                 return MAPS_ERROR_INVALID_PARAMETER;
1639         if (!maps_condition_check_privilege())
1640                 return MAPS_ERROR_PERMISSION_DENIED;
1641
1642         int error = MAPS_ERROR_NONE;
1643         do {
1644                 maps_view_s *v = (maps_view_s *)view;
1645                 error = maps_item_list_remove_all(v->view_objects, maps_view_object_destroy);
1646                 if (error != MAPS_ERROR_NONE)
1647                         return error;
1648
1649                 /* Redraw the view */
1650                 error = _maps_view_redraw(v);
1651                 if (error != MAPS_ERROR_NONE)
1652                         return error;
1653
1654                 return MAPS_ERROR_NONE;
1655         } while (false);
1656
1657         return error;
1658 }
1659
1660 EXPORT_API int maps_view_foreach_object(maps_view_h view, maps_view_object_cb callback, void *user_data)
1661 {
1662         if (!maps_condition_check_maps_feature())
1663                 return MAPS_ERROR_NOT_SUPPORTED;
1664         if (!view || !callback)
1665                 return MAPS_ERROR_INVALID_PARAMETER;
1666         maps_view_s *v = (maps_view_s *)view;
1667         if (!v->view_objects)
1668                 return MAPS_ERROR_NOT_FOUND;
1669         return maps_item_list_foreach(v->view_objects, NULL, callback, user_data);
1670 }
1671
1672
1673 /* ----------------------SEND MAP VIEW CALLBACK TO THE USER-------------------*/
1674
1675 /* TODO: Consider refactoring of send Map View Callbacks to the User */
1676
1677 maps_view_event_data_h _maps_view_create_event_data(maps_view_event_type_e type)
1678 {
1679         maps_view_event_data_h event_data = NULL;
1680         const int error = _maps_view_event_data_create(&event_data);
1681         if (error != MAPS_ERROR_NONE) {
1682                 maps_view_event_data_destroy(event_data);
1683                 return NULL;
1684         }
1685         if (!event_data)
1686                 return NULL;
1687         _maps_view_event_data_set_type(event_data, type);
1688         return event_data;
1689 }
1690
1691 void _maps_view_invoke_event_callback(maps_view_h view, maps_view_event_data_h event_data)
1692 {
1693         if (!view || !event_data)
1694                 return;
1695
1696         maps_view_s *v = (maps_view_s *)view;
1697
1698         maps_view_event_type_e type = MAPS_VIEW_EVENT_GESTURE;
1699         maps_view_event_data_get_type(event_data, &type);
1700
1701 #if 0 // log
1702         int maps_view_event_data_get_gesture_type(const maps_view_event_data_h event, maps_view_gesture_e *gesture_type);
1703         int maps_view_event_data_get_action_type(const maps_view_event_data_h event, maps_view_action_e *action_type);
1704         int maps_view_event_data_get_object(const maps_view_event_data_h event, maps_view_object_h *object);
1705         int maps_view_object_get_type(maps_view_object_h object, maps_view_object_type_e *type);
1706
1707         int subtype = 0;
1708         if (type == MAPS_VIEW_EVENT_GESTURE) {
1709                 maps_view_event_data_get_gesture_type(event_data, (maps_view_gesture_e*)&subtype);
1710         } else if (type == MAPS_VIEW_EVENT_ACTION) {
1711                 maps_view_event_data_get_action_type(event_data, (maps_view_action_e*)&subtype);
1712         } else if (type == MAPS_VIEW_EVENT_OBJECT) {
1713                 maps_view_object_h object;
1714                 maps_view_event_data_get_object(event_data, &object);
1715                 maps_view_object_get_type(object, (maps_view_object_type_e*)&subtype);
1716         }
1717         if (type == MAPS_VIEW_EVENT_READY)
1718                 MAPS_LOGD("[invoked event] type=%d, subtype=%d", type, subtype);
1719 #endif
1720
1721         v->event_callbacks[type].callback(type, event_data, v->event_callbacks[type].user_data);
1722 }
1723
1724 /* ----------------------HIT TEST---------------------------------------------*/
1725 /* TODO: consider refactoring of Hit Test features and separation as
1726  *  dedicated classes */
1727
1728 typedef struct _maps_view_hit_test_data_s {
1729         maps_view_s *v;
1730         int x;
1731         int y;
1732         maps_view_object_h object;
1733 } maps_view_hit_test_data_s;
1734
1735
1736 typedef struct _maps_view_collect_poly_object_point_s {
1737         maps_view_s *v;
1738         view::poly_shape_hit_test *pd;
1739 } maps_view_collect_poly_object_point_s;
1740
1741
1742 static bool __maps_view_object_poly_collect_points_cb(int index, maps_coordinates_h point, void *user_data)
1743 {
1744         if (!point || !user_data)
1745                 return false;
1746
1747         maps_view_collect_poly_object_point_s *cpop =
1748                 (maps_view_collect_poly_object_point_s *)user_data;
1749
1750         int x = 0;
1751         int y = 0;
1752         if (maps_view_geolocation_to_screen(cpop->v, point, &x, &y) == MAPS_ERROR_NONE)
1753                 cpop->pd->add_point(float(x), float(y));
1754
1755         return true;
1756 }
1757
1758 static bool __maps_view_hit_test_cb(int index, int total, maps_view_object_h object, void *user_data)
1759 {
1760         if (!object || !user_data)
1761                 return false;
1762
1763         /* If it is an unvisible object, skip this hit-testing. */
1764         bool visible = false;
1765         maps_view_object_get_visible(object, &visible);
1766         if (!visible) return true;
1767
1768         maps_view_hit_test_data_s *htd = (maps_view_hit_test_data_s *)user_data;
1769
1770         maps_view_object_type_e type;
1771         maps_view_object_get_type(object, &type);
1772         switch(type) {
1773                 case MAPS_VIEW_OBJECT_POLYLINE: {
1774                         view::poly_shape_hit_test pd;
1775                         maps_view_collect_poly_object_point_s cpop = {htd->v, &pd};
1776                         int error = maps_view_object_polyline_foreach_point(object,
1777                                 __maps_view_object_poly_collect_points_cb, &cpop);
1778                         if (error != MAPS_ERROR_NONE)
1779                                 break;
1780
1781                         int width = 0;
1782                         maps_view_object_polyline_get_width(object, &width);
1783                         if (pd.hit_test(float(htd->x), float(htd->y), false, width))
1784                                 htd->object = object;
1785
1786                         break;
1787                 }
1788
1789                 case MAPS_VIEW_OBJECT_POLYGON: {
1790                         view::poly_shape_hit_test pd;
1791                         maps_view_collect_poly_object_point_s cpop = {htd->v, &pd};
1792                         int error = maps_view_object_polygon_foreach_point(object,
1793                                 __maps_view_object_poly_collect_points_cb, &cpop);
1794                         if (error != MAPS_ERROR_NONE)
1795                                 break;
1796
1797                         if (pd.hit_test(float(htd->x), float(htd->y), true))
1798                                 htd->object = object;
1799
1800                         break;
1801                 }
1802                 case MAPS_VIEW_OBJECT_MARKER: {
1803                         maps_coordinates_h c = NULL;
1804                         maps_view_object_marker_get_coordinates(object, &c);
1805
1806                         int x = 0;
1807                         int y = 0;
1808                         maps_view_geolocation_to_screen(htd->v, c, &x, &y);
1809                         maps_coordinates_destroy(c);
1810
1811                         int w = 0;
1812                         int h = 0;
1813                         maps_view_object_marker_get_size(object, &w, &h);
1814
1815                         /* In case of PIN marker type, rearrange the hit-area. */
1816                         maps_view_marker_type_e marker_type;
1817                         maps_view_object_marker_get_type(object, &marker_type);
1818                         if (marker_type == MAPS_VIEW_MARKER_PIN)
1819                                 y -= h / 2;
1820
1821                         /* Add some margin of the hit-area. */
1822                         w = MAX(w, htd->v->min_hit_area);
1823                         h = MAX(h, htd->v->min_hit_area);
1824
1825                         /* Gets a half range to check hit-area */
1826                         int hw = (int)(w / 2. + .5);
1827                         int hh = (int)(h / 2. + .5);
1828
1829                         /* Check hit-area */
1830                         if ((x > (htd->x - hw)) && (x < (htd->x + hw))
1831                            && (y > (htd->y - hh)) && (y < (htd->y + hh))) {
1832                                 htd->object = object;
1833                         }
1834                         break;
1835                 }
1836                 default:
1837                         break;
1838         }
1839
1840         if (htd->object)
1841                 return false;
1842
1843         return true;
1844 }
1845
1846
1847 maps_view_object_h _maps_view_object_hit_test(maps_view_h view, int x, int y, maps_view_gesture_e gesture)
1848 {
1849         if (!view)
1850                 return NULL;
1851
1852         maps_view_s *v = (maps_view_s *)view;
1853
1854         /* Check if we are going to inform anyone about object events */
1855         if (v->event_callbacks[MAPS_VIEW_EVENT_OBJECT].callback
1856                 == __maps_view_on_event_empty_cb)
1857                 return NULL;
1858
1859         /* 1. Iterate through the list of object and test the hit */
1860         maps_view_hit_test_data_s htd = {v, x, y, NULL};
1861         int error = maps_view_foreach_object(view, __maps_view_hit_test_cb, &htd);
1862         if ((error != MAPS_ERROR_NONE) || !htd.object)
1863                 return NULL;
1864
1865         /*g_print("Hit Test: FOUND OBJECT: %p\n", htd.object);*/
1866
1867         /* Invoke user registered event callback */
1868         maps_view_event_data_h ed =
1869                 _maps_view_create_event_data(MAPS_VIEW_EVENT_OBJECT);
1870         if (ed) {
1871                 _maps_view_event_data_set_object(ed, htd.object);
1872                 _maps_view_event_data_set_gesture_type(ed, gesture);
1873                 _maps_view_invoke_event_callback(view, ed);
1874                 maps_view_event_data_destroy(ed);
1875         }
1876
1877         /* 2. Extract test result */
1878         return htd.object;
1879 }
1880
1881 EXPORT_API int maps_view_get_maps_plugin_view_handle(maps_view_h view, void **maps_plugin_view_handle)
1882 {
1883         if (!maps_condition_check_maps_feature())
1884                 return MAPS_ERROR_NOT_SUPPORTED;
1885         if (!view || !maps_plugin_view_handle)
1886                 return MAPS_ERROR_INVALID_PARAMETER;
1887
1888         maps_view_s *v = (maps_view_s *)view;
1889         *maps_plugin_view_handle = v->maps_plugin_view_handle;
1890         return MAPS_ERROR_NONE;
1891 }
1892
1893 EXPORT_API int maps_view_set_maps_plugin_view_handle(maps_view_h view, void *maps_plugin_view_handle)
1894 {
1895         if (!maps_condition_check_maps_feature())
1896                 return MAPS_ERROR_NOT_SUPPORTED;
1897         if (!view)
1898                 return MAPS_ERROR_INVALID_PARAMETER;
1899
1900         maps_view_s *v = (maps_view_s *)view;
1901         v->maps_plugin_view_handle = maps_plugin_view_handle;
1902         return MAPS_ERROR_NONE;
1903 }
1904
1905 EXPORT_API int maps_view_get_scale_factor(maps_view_h view, double *scale_factor)
1906 {
1907         if (!maps_condition_check_maps_feature())
1908                 return MAPS_ERROR_NOT_SUPPORTED;
1909         if (!view || !scale_factor)
1910                 return MAPS_ERROR_INVALID_PARAMETER;
1911
1912         const plugin::interface_s *plugin = __get_plugin_interface(view);
1913         if (!plugin)
1914                 return MAPS_ERROR_INVALID_PARAMETER;
1915         if (!plugin->maps_plugin_get_view_scale_factor)
1916                 return MAPS_ERROR_NOT_SUPPORTED;
1917         return plugin->maps_plugin_get_view_scale_factor(view, scale_factor);
1918 }
1919
1920 EXPORT_API int maps_view_set_scale_factor(maps_view_h view, double scale_factor)
1921 {
1922         if (!maps_condition_check_maps_feature())
1923                 return MAPS_ERROR_NOT_SUPPORTED;
1924         if (!view)
1925                 return MAPS_ERROR_INVALID_PARAMETER;
1926         if (scale_factor < 0.1 || scale_factor > 10.0)
1927                 return MAPS_ERROR_INVALID_PARAMETER;
1928
1929         const plugin::interface_s *plugin = __get_plugin_interface(view);
1930         if (!plugin)
1931                 return MAPS_ERROR_INVALID_PARAMETER;
1932         if (!plugin->maps_plugin_set_view_scale_factor)
1933                 return MAPS_ERROR_NOT_SUPPORTED;
1934
1935         return plugin->maps_plugin_set_view_scale_factor(view, scale_factor);
1936 }
1937