]> err.no Git - libchamplain/commitdiff
Fix Bug 574809: Provide a way to make visible a bunch of markers
authorPierre-Luc Beaudoin <pierre-luc@pierlux.com>
Mon, 23 Mar 2009 20:53:37 +0000 (22:53 +0200)
committerPierre-Luc Beaudoin <pierre-luc@pierlux.com>
Mon, 23 Mar 2009 20:53:37 +0000 (22:53 +0200)
and make the go_to animation more sensible

champlain/champlain-view.c
champlain/champlain-view.h
demos/launcher.c

index 84d71ebacc6babed5cfe3be9381bb433935df8b2..5ff0bc50903c42b5e39b5ab66845504419c7d5e3 100644 (file)
@@ -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);
+}
index 8704b36444f4efc6956f26d95701f805bf11bf17..0cb3e308a38baf6ab08a8cc6cafc32b0bdf5780b 100644 (file)
@@ -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);
index d8e76aabf1a427513e12f7c98c7e021c920e2ea8..259751f1a69b80c7ac656d371e80e9238b68335a 100644 (file)
@@ -19,6 +19,7 @@
 #include <champlain/champlain.h>
 
 #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 */