From: Pierre-Luc Beaudoin Date: Mon, 23 Mar 2009 20:53:37 +0000 (+0200) Subject: Fix Bug 574809: Provide a way to make visible a bunch of markers X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=12db909f23912c6751ff27c3ef4444ad66047eeb;p=libchamplain Fix Bug 574809: Provide a way to make visible a bunch of markers and make the go_to animation more sensible --- diff --git a/champlain/champlain-view.c b/champlain/champlain-view.c index 84d71eb..5ff0bc5 100644 --- a/champlain/champlain-view.c +++ b/champlain/champlain-view.c @@ -1139,8 +1139,7 @@ champlain_view_go_to (ChamplainView *view, * To have a nice animation, the duration should be longer if the zoom level * is higher and if the points are far away */ - duration = 100 * priv->zoom_level * - sqrt (pow (latitude - priv->latitude, 2) + pow (longitude - priv->longitude, 2)); + duration = 500 * priv->zoom_level / 2.0; ctx->timeline = clutter_timeline_new_for_duration (duration); ctx->alpha = clutter_alpha_new_full (ctx->timeline, CLUTTER_ALPHA_SINE_INC, NULL, NULL); @@ -1610,3 +1609,117 @@ champlain_view_set_zoom_on_double_click (ChamplainView *view, priv->zoom_on_double_click = value; } + +/** + * champlain_view_ensure_visible: + * @view: a #ChamplainView + * @min_lat: the minimum latitude + * @min_lon: the minimum longitude + * @max_lat: the maximum latitude + * @max_lon: the maximum longitude + * + * Changes the map's zoom level and center to make sure the given zone is + * visible. + * + * Since: 0.4 + */ +void +champlain_view_ensure_visible (ChamplainView *view, + gdouble min_lat, + gdouble min_lon, + gdouble max_lat, + gdouble max_lon, + gboolean animate) +{ + ChamplainViewPrivate *priv = GET_PRIVATE (view); + gint zoom_level = priv->zoom_level; + gdouble width, height; + gboolean good_size = FALSE; + + width = max_lon - min_lon; + height = max_lat - min_lat; + width *= 1.1; + height *= 1.1; + + DEBUG("Zone to expose (%f, %f) to (%f, %f)", min_lat, min_lon, max_lat, max_lon); + do + { + gint min_x, min_y, max_x, max_y; + min_x = champlain_map_source_get_x (priv->map_source, zoom_level, min_lon); + min_y = champlain_map_source_get_y (priv->map_source, zoom_level, min_lat); + + max_x = champlain_map_source_get_x (priv->map_source, zoom_level, max_lon); + max_y = champlain_map_source_get_y (priv->map_source, zoom_level, max_lat); + + if (min_y - max_y <= priv->viewport_size.height && + max_x - min_x <= priv->viewport_size.width) + good_size = TRUE; + else + zoom_level--; + + if (zoom_level <= 0) + break; + } + while (good_size == FALSE); + + if (good_size == FALSE) + { + zoom_level = 0; + min_lat = min_lon = width = height = 0; + } + + DEBUG ("Ideal zoom level is %d", zoom_level); + champlain_view_set_zoom_level (view, zoom_level); + if (animate) + champlain_view_go_to (view, min_lat + height / 2.0, min_lon + width / 2.0); + else + champlain_view_center_on (view, min_lat + height / 2.0, min_lon + width / 2.0); +} + +/** + * champlain_view_ensure_markers_visible: + * @view: a #ChamplainView + * @markers: a NULL terminated array of #ChamplainMarkers + * + * Changes the map's zoom level and center to make sure those markers are + * visible. + * + * FIXME: This doesn't take into account the marker's actor size yet + * + * Since: 0.4 + */ +void +champlain_view_ensure_markers_visible (ChamplainView *view, + ChamplainMarker *markers[], + gboolean animate) +{ + gdouble min_lat, min_lon, max_lat, max_lon; + ChamplainMarker *marker = NULL; + gint i = 0; + + min_lat = min_lon = 200; + max_lat = max_lon = -200; + + marker = markers[i]; + while (marker != NULL) + { + gdouble lat, lon; + g_object_get (G_OBJECT (marker), "latitude", &lat, "longitude", &lon, + NULL); + + if (lon < min_lon) + min_lon = lon; + + if (lat < min_lat) + min_lat = lat; + + if (lon > max_lon) + max_lon = lon; + + if (lat > max_lat) + max_lat = lat; + + marker = markers[i++]; + } + champlain_view_ensure_visible (view, min_lat, min_lon, max_lat, max_lon, animate); +} diff --git a/champlain/champlain-view.h b/champlain/champlain-view.h index 8704b36..0cb3e30 100644 --- a/champlain/champlain-view.h +++ b/champlain/champlain-view.h @@ -75,11 +75,15 @@ void champlain_view_go_to (ChamplainView *view, gdouble latitude, gdouble longit void champlain_view_stop_go_to (ChamplainView *view); void champlain_view_zoom_in (ChamplainView *champlainView); - void champlain_view_zoom_out (ChamplainView *champlainView); - void champlain_view_set_zoom_level (ChamplainView *champlainView, gint zoom_level); + +void champlain_view_ensure_visible (ChamplainView *view, gdouble min_lat, + gdouble min_lon, gdouble max_lat, gdouble max_lon, gboolean animate); +void champlain_view_ensure_markers_visible (ChamplainView *view, + ChamplainMarker *markers[], gboolean animate); + void champlain_view_set_map_source (ChamplainView *champlainView, ChamplainMapSource *map_source); void champlain_view_set_size (ChamplainView *view, guint width, guint height); diff --git a/demos/launcher.c b/demos/launcher.c index d8e76aa..259751f 100644 --- a/demos/launcher.c +++ b/demos/launcher.c @@ -19,6 +19,7 @@ #include #define PADDING 10 +ChamplainMarker *markers [4]; static gboolean map_view_button_release_cb (ClutterActor *actor, @@ -69,6 +70,15 @@ zoom_out (ClutterActor *actor, return TRUE; } +static gboolean +center (ClutterActor *actor, + ClutterButtonEvent *event, + ChamplainView * view) +{ + champlain_view_ensure_markers_visible (view, markers, TRUE); + return TRUE; +} + static ChamplainLayer * create_marker_layer (ChamplainView *view) { @@ -81,6 +91,7 @@ create_marker_layer (ChamplainView *view) marker = champlain_marker_new_with_label ("Montréal", "Airmole 14", NULL, NULL); + markers[0] = CHAMPLAIN_MARKER (marker); champlain_marker_set_position (CHAMPLAIN_MARKER (marker), 45.528178, -73.563788); clutter_container_add (CLUTTER_CONTAINER (layer), marker, NULL); @@ -90,15 +101,19 @@ create_marker_layer (ChamplainView *view) marker = champlain_marker_new_with_label ("New York", "Sans 25", &white, NULL); + markers[1] = CHAMPLAIN_MARKER (marker); champlain_marker_set_position (CHAMPLAIN_MARKER (marker), 40.77, -73.98); clutter_container_add (CLUTTER_CONTAINER (layer), marker, NULL); marker = champlain_marker_new_with_label ("Saint-Tite-des-Caps", "Serif 12", NULL, &orange); + markers[2] = CHAMPLAIN_MARKER (marker); champlain_marker_set_position (CHAMPLAIN_MARKER (marker), 47.130885, -70.764141); clutter_container_add (CLUTTER_CONTAINER (layer), marker, NULL); + markers[3] = NULL; + clutter_actor_show (CLUTTER_ACTOR (layer)); return layer; } @@ -134,7 +149,7 @@ main (int argc, { ClutterActor* actor, *stage, *buttons, *button; ChamplainLayer *layer; - guint width; + guint width, total_width = 0;; g_thread_init (NULL); clutter_init (&argc, &argv); @@ -155,6 +170,7 @@ main (int argc, clutter_container_add_actor (CLUTTER_CONTAINER (buttons), button); clutter_actor_set_reactive (button, TRUE); clutter_actor_get_size (button, &width, NULL); + total_width += width + PADDING; g_signal_connect (button, "button-release-event", G_CALLBACK (zoom_in), actor); @@ -162,11 +178,23 @@ main (int argc, button = make_button ("Zoom out"); clutter_container_add_actor (CLUTTER_CONTAINER (buttons), button); clutter_actor_set_reactive (button, TRUE); - clutter_actor_set_position (button, width + PADDING, 0); + clutter_actor_set_position (button, total_width, 0); + clutter_actor_get_size (button, &width, NULL); + total_width += width + PADDING; g_signal_connect (button, "button-release-event", G_CALLBACK (zoom_out), actor); + button = make_button ("Center on markers"); + clutter_container_add_actor (CLUTTER_CONTAINER (buttons), button); + clutter_actor_set_reactive (button, TRUE); + clutter_actor_set_position (button, total_width, 0); + clutter_actor_get_size (button, &width, NULL); + total_width += width + PADDING; + g_signal_connect (button, "button-release-event", + G_CALLBACK (center), + actor); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), buttons); /* Create the markers and marker layer */