* 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);
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);
+}
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);
#include <champlain/champlain.h>
#define PADDING 10
+ChamplainMarker *markers [4];
static gboolean
map_view_button_release_cb (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)
{
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);
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;
}
{
ClutterActor* actor, *stage, *buttons, *button;
ChamplainLayer *layer;
- guint width;
+ guint width, total_width = 0;;
g_thread_init (NULL);
clutter_init (&argc, &argv);
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);
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 */