{
double lon, lat;
double flon, flat, tlon, tlat;
- Evas_Coord ox, oy, x, y, w, h;
+ Evas_Coord ox, oy, x, y, w, h, rx, ry, tx, ty;
+ double d;
int zoom;
+ Evas_Coord size;
Evas_Event_Mouse_Down *down = (Evas_Event_Mouse_Down *)event_info;
if (!down) return;
evas_object_geometry_get(data, &ox, &oy, &w, &h);
zoom = elm_map_zoom_get(data);
if (zoom<5) return;
+ size = pow(2.0, zoom) * 256;
elm_map_geo_region_get(obj, &lon, &lat);
- elm_map_utils_convert_geo_into_coord(obj, lon, lat, pow(2.0, zoom)*256, &x, &y);
- x += down->output.x - (w / 2) - ox;
- y += down->output.y - (h / 2) - oy;
- elm_map_utils_convert_coord_into_geo(obj, x, y, pow(2.0, zoom)*256, &lon, &lat);
+ elm_map_utils_convert_geo_into_coord(obj, lon, lat, size, &x, &y);
+
+ rx = x;
+ ry = y;
+ x += down->output.x - ((float)w * 0.5) - ox;
+ y += down->output.y - ((float)h * 0.5) - oy;
+ elm_map_rotate_get(data, &d, NULL, NULL);
+ elm_map_utils_rotate_coord(data, x, y, rx, ry, -d, &tx, &ty);
+ elm_map_utils_convert_coord_into_geo(obj, tx, ty, size, &lon, &lat);
itc1 = elm_map_marker_class_new(data);
if (route_from && route_to)
{
elm_map_marker_remove(route_from);
- route_from = NULL;
+ route_from = NULL;
elm_map_marker_remove(route_to);
- route_to = NULL;
+ route_to = NULL;
elm_map_route_remove(route);
}
}
static void
+my_bt_rotate_cw(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+ double d;
+ Evas_Coord x, y, w, h;
+ float half_w, half_h;
+ evas_object_geometry_get(data, &x, &y, &w, &h);
+ half_w = (float)w * 0.5;
+ half_h = (float)h * 0.5;
+
+ elm_map_rotate_get(data, &d, NULL, NULL);
+ d += 15.0;
+ elm_map_rotate_set(data, d, x + half_w, y + half_h);
+}
+
+static void
+my_bt_rotate_ccw(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
+{
+ double d;
+ Evas_Coord x, y, w, h;
+ float half_w, half_h;
+ evas_object_geometry_get(data, &x, &y, &w, &h);
+ half_w = (float)w * 0.5;
+ half_h = (float)h * 0.5;
+
+ elm_map_rotate_get(data, &d, NULL, NULL);
+ d -= 15.0;
+ elm_map_rotate_set(data, d, x + half_w, y + half_h);
+}
+
+static void
my_bt_zoom_out(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
{
double zoom;
style = rand() % 2;
if (!style) g_clas = itc_group1;
- else g_clas = itc_group2;
+ else g_clas = itc_group2;
markers[i] = elm_map_marker_add(data, r1/100., r2/100., m_clas, g_clas, d);
}
evas_object_size_hint_align_set(bt, 0.1, 0.9);
evas_object_show(bt);
elm_box_pack_end(bx, bt);
+
+ bt = elm_button_add(win);
+ elm_button_label_set(bt, "R +");
+ evas_object_smart_callback_add(bt, "clicked", my_bt_rotate_cw, map);
+ evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(bt, 0.1, 0.9);
+ evas_object_show(bt);
+ elm_box_pack_end(bx, bt);
+
+ bt = elm_button_add(win);
+ elm_button_label_set(bt, "R -");
+ evas_object_smart_callback_add(bt, "clicked", my_bt_rotate_ccw, map);
+ evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(bt, 0.1, 0.9);
+ evas_object_show(bt);
+ elm_box_pack_end(bx, bt);
//
//
#define NOMINATIM_ATTR_LON "lon"
#define NOMINATIM_ATTR_LAT "lat"
+#define PINCH_ZOOM_MIN 0.25
+#define PINCH_ZOOM_MAX 3.0
+
// Map sources
// Currently the size of a tile must be 256*256
// and the size of the map must be pow(2.0, z)*tile_size
Eina_Bool on_hold : 1;
Eina_Bool paused : 1;
Eina_Bool paused_markers : 1;
- Eina_Bool pinch_zoom : 1;
struct {
Eina_Bool enabled;
Eina_List *route;
Evas_Event_Mouse_Down ev;
Eina_List *names;
+ int multi_count;
+
+ struct {
+ Evas_Coord cx, cy;
+ double level, diff;
+ } pinch;
+
+ struct {
+ Evas_Coord cx, cy;
+ double a, d;
+ } rotate;
+
+ struct {
+ Evas_Coord cx, cy;
+ double level;
+ } pinch_zoom;
+
};
struct _Mod_Api
struct {
Evas_Coord x, y;
+ } start;
+
+ struct {
+ Evas_Coord x, y;
} prev;
Evas_Coord x, y, w, h;
Evas_Object *object;
Ecore_Timer *hold_timer;
+ int pinch_start_dis;
int pinch_dis;
};
NAME_XML_LAST
} Name_Xml_Attibute;
-static int dis_old = 0;
static const char *widtype = NULL;
static const char SIG_CHANGED[] = "changed";
_elm_module_del(wd->m);
wd->m = NULL;
}
-
+
p = _elm_config->modules;
pe = p;
for (;;)
if (n)
{
char *nn;
-
+
strncpy(n, p, pe - p);
n[pe - p] = 0;
nn = strchr(n, '>');
}
static void
+obj_rotate_zoom(void *data, Evas_Object *obj)
+{
+ ELM_CHECK_WIDTYPE(data, widtype);
+ Widget_Data *wd = elm_widget_data_get(data);
+ if ((!wd->pinch.cx) && (!wd->pinch.cy))
+ {
+ wd->pinch.cx = wd->rotate.cx;
+ wd->pinch.cy = wd->rotate.cy;
+ }
+
+ Evas_Map *map = evas_map_new(4);
+ if (!map) return;
+
+ evas_map_util_points_populate_from_object_full(map, obj, 0);
+ evas_map_util_zoom(map, wd->pinch.level, wd->pinch.level, wd->pinch.cx, wd->pinch.cy);
+ evas_map_util_rotate(map, wd->rotate.d, wd->rotate.cx, wd->rotate.cy);
+ evas_object_map_enable_set(obj, EINA_TRUE);
+ evas_object_map_set(obj, map);
+ evas_map_free(map);
+}
+
+static void
route_place(Evas_Object *obj, Grid *g __UNUSED__, Evas_Coord px, Evas_Coord py, Evas_Coord ox __UNUSED__, Evas_Coord oy __UNUSED__, Evas_Coord ow, Evas_Coord oh)
{
ELM_CHECK_WIDTYPE(obj, widtype);
evas_object_line_xy_set(p, r->x, r->y, x, y);
evas_object_color_set(p, r->color.r, r->color.g, r->color.b, r->color.a);
evas_object_raise(p);
+ obj_rotate_zoom(obj, p);
evas_object_show(p);
r->x = x;
r->y = y;
{
group->update_resize = EINA_FALSE;
evas_object_resize(group->obj, ww, hh);
+ obj_rotate_zoom(obj, group->obj);
}
if (group->update_raise)
{
group->update_raise = EINA_FALSE;
evas_object_raise(group->obj);
+ obj_rotate_zoom(obj, group->obj);
evas_object_show(group->obj);
}
if (group->bubble) _group_bubble_place(group);
evas_object_resize(gi->img, ww, hh);
+ obj_rotate_zoom(obj, gi->img);
/*evas_object_move(gi->txt,
xx - px + ax + ox,
yy - py + ay + oy);
if (evas_object_image_load_error_get(gi->img) != EVAS_LOAD_ERROR_NONE)
ecore_file_remove(gi->file);
+ obj_rotate_zoom(gi->wd->obj, gi->img);
evas_object_show(gi->img);
//evas_object_text_text_set(gi->txt, gi->file);
if (source) free(source);
}
else if (gi->have)
- evas_object_show(gi->img);
+ {
+ obj_rotate_zoom(obj, gi->img);
+ evas_object_show(gi->img);
+ }
}
}
}
static void
_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info)
{
+ ELM_CHECK_WIDTYPE(data, widtype);
Widget_Data *wd = elm_widget_data_get(data);
Evas_Event_Mouse_Down *ev = event_info;
Event *ev0;
static void
_mouse_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
{
- Widget_Data *wd = elm_widget_data_get(data);
Evas_Event_Mouse_Move *move = event_info;
Event *ev0;
- if (wd->pinch_zoom) return;
ev0 = get_event_object(data, 0);
if (!ev0) return;
ev0->prev.x = move->cur.output.x;
static void
_mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
{
+ ELM_CHECK_WIDTYPE(data, widtype);
Widget_Data *wd = elm_widget_data_get(data);
Evas_Event_Mouse_Up *ev = event_info;
int mdevice;
}
elm_smart_scroller_hold_set(wd->scr, 0);
elm_smart_scroller_freeze_set(wd->scr, 0);
- wd->pinch_zoom = EINA_FALSE;
}
else
{
static void
_mouse_multi_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info)
{
+ ELM_CHECK_WIDTYPE(data, widtype);
Widget_Data *wd = elm_widget_data_get(data);
Event *ev;
Evas_Event_Multi_Down *down = event_info;
elm_smart_scroller_hold_set(wd->scr, 1);
elm_smart_scroller_freeze_set(wd->scr, 1);
- ev = get_event_object(data, down->device);
- if (ev) goto done;
+ if ((wd->multi_count + 1) > 1) goto done;
+ else wd->multi_count++;
ev = create_event_object(data, obj, down->device);
if (!ev)
goto done;
}
- wd->pinch_zoom = EINA_FALSE;
-
ev->hold_timer = NULL;
- ev->prev.x = down->output.x;
- ev->prev.y = down->output.y;
+ ev->start.x = ev->prev.x = down->output.x;
+ ev->start.y = ev->prev.y = down->output.y;
+ ev->pinch_start_dis = 0;
+ wd->pinch.level = 1.0;
+ wd->pinch.diff = 1.0;
done:
+ if (wd->long_timer)
+ {
+ ecore_timer_del(wd->long_timer);
+ wd->long_timer = NULL;
+ }
return;
}
static void
_mouse_multi_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
{
+ ELM_CHECK_WIDTYPE(data, widtype);
Widget_Data *wd = elm_widget_data_get(data);
Evas_Event_Multi_Move *move = event_info;
- int dis_new, zoom;
+ int dis_new;
+ double t, tt, a, a_diff;
Event *ev0;
Event *ev;
- if (wd->pinch_zoom) return;
ev = get_event_object(data, move->device);
if (!ev) return;
- ev->prev.x = move->cur.output.x;
- ev->prev.y = move->cur.output.y;
-
ev0 = get_event_object(data, 0);
if (!ev0) return;
- dis_new = get_distance(ev0->prev.x, ev0->prev.y, ev->prev.x, ev->prev.y);
- zoom = wd->zoom;
-
- if (dis_old)
+ if (wd->multi_count == 1)
{
- if (((dis_old - dis_new) > 0) &&
- (ev->pinch_dis > elm_finger_size_get()))
- {
- wd->pinch_zoom = EINA_TRUE;
- zoom--;
- elm_map_zoom_set(data, zoom);
- ev->pinch_dis = 0;
- }
- else if (((dis_old - dis_new) < 0) &&
- (ev->pinch_dis < -elm_finger_size_get()))
+ Evas_Coord x, y, w, h;
+ float half_w, half_h;
+
+ evas_object_geometry_get(data, &x, &y, &w, &h);
+ half_w = (float)w * 0.5;
+ half_h = (float)h * 0.5;
+ dis_new = get_distance(ev0->prev.x, ev0->prev.y, ev->prev.x, ev->prev.y);
+
+ if (!ev->pinch_start_dis) ev->pinch_start_dis = dis_new;
+ else
{
- wd->pinch_zoom = EINA_TRUE;
- zoom++;
- elm_map_zoom_set(data, zoom);
- ev->pinch_dis = 0;
+ ev->pinch_dis = dis_new;
+ tt = wd->pinch.diff;
+ wd->pinch.diff = (double)(ev->pinch_dis - ev->pinch_start_dis);
+ t = (wd->pinch.diff * 0.01) + 1.0;
+ if ((!wd->zoom) || ((wd->zoom + (int)t - 1) <= map_sources_tab[wd->source].zoom_min) ||
+ ((wd->zoom + (int)t - 1) >= map_sources_tab[wd->source].zoom_max) ||
+ (t > PINCH_ZOOM_MAX) || (t < PINCH_ZOOM_MIN))
+ {
+ wd->pinch.diff = tt;
+ goto do_nothing;
+ }
+ else
+ {
+ wd->pinch.level = (wd->pinch.diff * 0.01) + 1.0;
+ wd->pinch.cx = x + half_w;
+ wd->pinch.cy = y + half_h;
+ }
+
+ a = (double)(ev->prev.y - ev0->prev.y) / (double)(ev->prev.x - ev0->prev.x);
+ if (!wd->rotate.a) wd->rotate.a = a;
+ else
+ {
+
+ a_diff = wd->rotate.a - a;
+ if (a_diff > 0) wd->rotate.d -= 1.0;
+ else if (a_diff < 0) wd->rotate.d += 1.0;
+ wd->rotate.a = a;
+ wd->rotate.cx = x + half_w;
+ wd->rotate.cy = y + half_h;
+ }
+
+ if (wd->calc_job) ecore_job_del(wd->calc_job);
+ wd->calc_job = ecore_job_add(_calc_job, wd);
}
- ev->pinch_dis += (dis_old - dis_new);
}
- dis_old = dis_new;
+do_nothing:
+ ev->prev.x = move->cur.output.x;
+ ev->prev.y = move->cur.output.y;
}
static void
_mouse_multi_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
{
+ ELM_CHECK_WIDTYPE(data, widtype);
+ Widget_Data *wd = elm_widget_data_get(data);
Evas_Event_Multi_Up *up = event_info;
Event *ev0;
Event *ev;
+ Eina_Bool tp;
+ double t = 0.0;
+
+ wd->multi_count--;
+ if (wd->calc_job) ecore_job_del(wd->calc_job);
+ if (wd->zoom_animator)
+ {
+ ecore_animator_del(wd->zoom_animator);
+ wd->zoom_animator = NULL;
+ }
+ tp = wd->paused;
+ wd->paused = EINA_TRUE;
+ if (wd->pinch.diff >= 0.0) t = wd->pinch.diff * 0.01;
+ else if (wd->pinch.diff < 0.0) t = -1.0 / ((wd->pinch.diff * 0.01) + 1.0);
+ elm_map_zoom_set(data, wd->zoom + (int)ceil(t));
+ wd->pinch.level = 1.0;
+ wd->paused = tp;
+ wd->rotate.a = 0.0;
ev = get_event_object(data, up->device);
if (!ev)
DBG("Cannot get multi device");
return;
}
- dis_old = 0;
ev0 = get_event_object(data, 0);
if (ev0)
rect_place(sd->wd->obj, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh);
EINA_LIST_FOREACH(sd->wd->grids, l, g)
{
- grid_load(sd->wd->obj, g);
+ if (sd->wd->pinch.level == 1.0) grid_load(sd->wd->obj, g);
grid_place(sd->wd->obj, g, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh);
marker_place(sd->wd->obj, g, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh);
if (!sd->wd->zoom_animator) route_place(sd->wd->obj, g, sd->wd->pan_x, sd->wd->pan_y, ox, oy, ow, oh);
evas_object_move(group->bubble, xx, yy);
evas_object_resize(group->bubble, ww, hh);
+ obj_rotate_zoom(group->wd, group->bubble);
evas_object_show(group->bubble);
evas_object_move(group->rect, xx, yy);
evas_object_resize(group->rect, ww, hh);
+ obj_rotate_zoom(group->wd, group->rect);
evas_object_show(group->rect);
}
wd->markers_max_num = 30;
wd->source = ELM_MAP_SOURCE_MAPNIK;
+ wd->pinch.level = 1.0;
evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
zoom = map_sources_tab[wd->source].zoom_max;
if (zoom < map_sources_tab[wd->source].zoom_min)
zoom = map_sources_tab[wd->source].zoom_min;
- if (zoom == wd->zoom) return;
wd->zoom = zoom;
wd->size.ow = wd->size.w;
}
/**
+ * Convert a pixel coordinate into a roated pixcel coordinate.
+ *
+ * @param obj The map object
+ * @param x x to rotate.
+ * @param y y to rotate.
+ * @param cx rotation's center horizontal position.
+ * @param cy rotation's center vertical position.
+ * @param degree amount of degrees from 0.0 to 360.0 to rotate arount Z axis.
+ * @param xx rotated x.
+ * @param yy rotated y.
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_utils_rotate_coord(const Evas_Object *obj __UNUSED__, const Evas_Coord x, const Evas_Coord y, const Evas_Coord cx, const Evas_Coord cy, const double degree, Evas_Coord *xx, Evas_Coord *yy)
+{
+ if ((!xx) || (!yy)) return;
+
+ double r = (degree * M_PI) / 180.0;
+ double tx, ty, ttx, tty;
+
+ tx = x - cx;
+ ty = y - cy;
+
+ ttx = tx * cos(r);
+ tty = tx * sin(r);
+ tx = ttx + (ty * cos(r + M_PI_2));
+ ty = tty + (ty * sin(r + M_PI_2));
+
+ *xx = tx + cx;
+ *yy = ty + cy;
+}
+
+/**
* Add a marker on the map
*
* @param obj The map object
* @param lon the longitude
* @param lat the latitude
* @param clas the class to use
+ * @param clas_group the class group
* @param data the data passed to the callbacks
*
* @return The marker object
elm_map_route_color_get(Elm_Map_Route *route, int *r, int *g , int *b, int *a)
{
EINA_SAFETY_ON_NULL_RETURN(route);
- if (*r) *r = route->color.r;
- if (*g) *g = route->color.g;
- if (*b) *b = route->color.b;
- if (*a) *a = route->color.a;
+ if (r) *r = route->color.r;
+ if (g) *g = route->color.g;
+ if (b) *b = route->color.b;
+ if (a) *a = route->color.a;
}
/**
return route->info.waypoints;
}
-
+/**
+ * Get the information of address
+ *
+ * @param name the name object
+ * @return Returns the address of name
+ *
+ * @ingroup Map
+ */
EAPI const char *
elm_map_name_address_get(Elm_Map_Name *name)
{
return name->address;
}
+/**
+ * Get the current coordinates of the name.
+ *
+ * This gets the current coordinates of the name object.
+ *
+ * @param obj The name object
+ * @param lat The latitude.
+ * @param lon The longitude.
+ *
+ * @ingroup Map
+ */
EAPI void
elm_map_name_region_get(Elm_Map_Name *name, double *lon, double *lat)
{
EINA_SAFETY_ON_NULL_RETURN(name);
- if (*lon) *lon = name->lon;
- if (*lat) *lat = name->lat;
+ if (lon) *lon = name->lon;
+ if (lat) *lat = name->lat;
}
+/**
+ * Remove a name from the map
+ *
+ * @param name The name to remove
+ *
+ * @ingroup Map
+ */
EAPI void
elm_map_name_remove(Elm_Map_Name *name)
{
}
}
+/**
+ * Set the rotate degree of the map
+ *
+ * @param obj The map object
+ * @param angle amount of degrees from 0.0 to 360.0 to rotate arount Z axis.
+ * @param cx rotation's center horizontal position.
+ * @param cy rotation's center vertical position.
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_rotate_set(Evas_Object *obj, double degree, Evas_Coord cx, Evas_Coord cy)
+{
+ ELM_CHECK_WIDTYPE(obj, widtype);
+ Widget_Data *wd = elm_widget_data_get(obj);
+
+ wd->rotate.d = degree;
+ wd->rotate.cx = cx;
+ wd->rotate.cy = cy;
+ wd->calc_job = ecore_job_add(_calc_job, wd);
+}
+
+/**
+ * Get the rotate degree of the map
+ *
+ * @param obj The map object
+ * @return amount of degrees from 0.0 to 360.0 to rotate arount Z axis.
+ * @param cx rotation's center horizontal position.
+ * @param cy rotation's center vertical position.
+ *
+ * @ingroup Map
+ */
+EAPI void
+elm_map_rotate_get(const Evas_Object *obj, double *degree, Evas_Coord *cx, Evas_Coord *cy)
+{
+ ELM_CHECK_WIDTYPE(obj, widtype);
+ Widget_Data *wd = elm_widget_data_get(obj);
+
+ if (degree) *degree = wd->rotate.d;
+ if (cx) *cx = wd->rotate.cx;
+ if (cy) *cy = wd->rotate.cy;
+}
static char *
_mapnik_url_cb(Evas_Object *obj __UNUSED__, int x, int y, int zoom)