[libchamplain] ChamplainView: add support for overlay sources



commit 801b23da32e51c0f146329efa199a8488db2236d
Author: Giovanni Campagna <gcampagna src gnome org>
Date:   Sun Jul 21 19:30:07 2013 +0200

    ChamplainView: add support for overlay sources
    
    OWM are layers to be rendered on top of an existing map, and
    the simplest way to achieve that is to have ChamplainView render
    maps from a list of sources.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=704645

 champlain/champlain-map-source-factory.c |   32 ++++++++
 champlain/champlain-map-source-factory.h |    2 +
 champlain/champlain-view.c               |  119 ++++++++++++++++++++++++------
 champlain/champlain-view.h               |    6 ++
 4 files changed, 136 insertions(+), 23 deletions(-)
---
diff --git a/champlain/champlain-map-source-factory.c b/champlain/champlain-map-source-factory.c
index 5289e8d..8832d81 100644
--- a/champlain/champlain-map-source-factory.c
+++ b/champlain/champlain-map-source-factory.c
@@ -482,6 +482,38 @@ champlain_map_source_factory_create_cached_source (ChamplainMapSourceFactory *fa
   return CHAMPLAIN_MAP_SOURCE (source_chain);
 }
 
+/**
+ * champlain_map_source_factory_create_memcached_source:
+ * @factory: the Factory
+ * @id: the wanted map source id
+ *
+ * Creates a memory cached map source.
+ *
+ * Returns: (transfer none): a ready to use #ChamplainMapSourceChain consisting of
+ * #ChamplainMemoryCache and #ChamplainMapSource matching the given name
+ *
+ * Since: 0.6
+ */
+ChamplainMapSource *
+champlain_map_source_factory_create_memcached_source (ChamplainMapSourceFactory *factory,
+    const gchar *id)
+{
+  ChamplainMapSourceChain *source_chain;
+  ChamplainMapSource *tile_source;
+  ChamplainMapSource *memory_cache;
+  ChamplainRenderer *renderer;
+
+  tile_source = champlain_map_source_factory_create (factory, id);
+
+  renderer = CHAMPLAIN_RENDERER (champlain_image_renderer_new ());
+  memory_cache = CHAMPLAIN_MAP_SOURCE (champlain_memory_cache_new_full (100, renderer));
+
+  source_chain = champlain_map_source_chain_new ();
+  champlain_map_source_chain_push (source_chain, tile_source);
+  champlain_map_source_chain_push (source_chain, memory_cache);
+
+  return CHAMPLAIN_MAP_SOURCE (source_chain);
+}
 
 /**
  * champlain_map_source_factory_create_error_source:
diff --git a/champlain/champlain-map-source-factory.h b/champlain/champlain-map-source-factory.h
index 4d6527f..01de1b9 100644
--- a/champlain/champlain-map-source-factory.h
+++ b/champlain/champlain-map-source-factory.h
@@ -82,6 +82,8 @@ ChamplainMapSource *champlain_map_source_factory_create (ChamplainMapSourceFacto
     const gchar *id);
 ChamplainMapSource *champlain_map_source_factory_create_cached_source (ChamplainMapSourceFactory *factory,
     const gchar *id);
+ChamplainMapSource *champlain_map_source_factory_create_memcached_source (ChamplainMapSourceFactory *factory,
+    const gchar *id);
 ChamplainMapSource *champlain_map_source_factory_create_error_source (ChamplainMapSourceFactory *factory,
     guint tile_size);
 
diff --git a/champlain/champlain-view.c b/champlain/champlain-view.c
index 9186f84..75b90a1 100644
--- a/champlain/champlain-view.c
+++ b/champlain/champlain-view.c
@@ -133,7 +133,6 @@ typedef struct
 typedef struct
 {
   ChamplainView *view;
-  ChamplainMapSource *map_source;
   gint x;
   gint y;
   gint zoom_level;
@@ -162,6 +161,7 @@ struct _ChamplainViewPrivate
   gint viewport_height;
 
   ChamplainMapSource *map_source; /* Current map tile source */
+  GList *all_sources;
 
   guint zoom_level; /* Holds the current zoom level number */
   guint min_zoom_level; /* Lowest allowed zoom level */
@@ -606,6 +606,9 @@ champlain_view_dispose (GObject *object)
       priv->map_source = NULL;
     }
 
+  g_list_free_full (priv->all_sources, g_object_unref);
+  priv->all_sources = NULL;
+
   if (priv->background_content)
     {
       g_object_unref (priv->background_content);
@@ -1875,7 +1878,6 @@ fill_background_tiles (ChamplainView *view)
     }
 }
 
-
 static void 
 tile_map_set (ChamplainView *view, gint tile_x, gint tile_y, gboolean value)
 {
@@ -1899,6 +1901,38 @@ tile_in_tile_map (ChamplainView *view, gint tile_x, gint tile_y)
   return GPOINTER_TO_INT (g_hash_table_lookup (priv->tile_map, &key));
 }
 
+static void
+load_tile_for_source (ChamplainView      *view,
+                      ChamplainMapSource *source,
+                      int                 opacity,
+                      int                 size,
+                      int                 x,
+                      int                 y)
+{
+  ChamplainViewPrivate *priv = view->priv;
+  ChamplainTile *tile = champlain_tile_new ();
+
+  DEBUG ("Loading tile %d, %d, %d", priv->zoom_level, x, y);
+
+  champlain_tile_set_x (tile, x);
+  champlain_tile_set_y (tile, y);
+  champlain_tile_set_zoom_level (tile, priv->zoom_level);
+  champlain_tile_set_size (tile, size);
+  clutter_actor_set_opacity (CLUTTER_ACTOR (tile), opacity);
+
+  g_signal_connect (tile, "notify::state", G_CALLBACK (tile_state_notify), view);
+  clutter_actor_add_child (priv->map_layer, CLUTTER_ACTOR (tile));
+  champlain_viewport_set_actor_position (CHAMPLAIN_VIEWPORT (priv->viewport), CLUTTER_ACTOR (tile), x * 
size, y * size);
+
+  /* updates champlain_view state automatically as
+     notify::state signal is connected  */
+  champlain_tile_set_state (tile, CHAMPLAIN_STATE_LOADING);
+
+  champlain_map_source_fill_tile (source, tile);
+
+  if (source != priv->map_source)
+    g_object_set_data (G_OBJECT (tile), "overlay", GINT_TO_POINTER (TRUE));
+}
 
 static gboolean
 fill_tile_cb (FillTileCallbackData *data)
@@ -1907,31 +1941,23 @@ fill_tile_cb (FillTileCallbackData *data)
   
   ChamplainView *view = data->view;
   ChamplainViewPrivate *priv = view->priv;
-  ChamplainMapSource *map_source = data->map_source;
   gint x = data->x;
   gint y = data->y;
   gint size = data->size;
   gint zoom_level = data->zoom_level;
 
-  if (!tile_in_tile_map (view, x, y) && zoom_level == priv->zoom_level && map_source == priv->map_source &&
+  if (!tile_in_tile_map (view, x, y) && zoom_level == priv->zoom_level &&
       y >= priv->tile_y_first && y < priv->tile_y_last && x >= priv->tile_x_first && x < priv->tile_x_last)
     {
-      ChamplainTile *tile = champlain_tile_new ();
-
-      champlain_tile_set_x (tile, x);
-      champlain_tile_set_y (tile, y);
-      champlain_tile_set_zoom_level (tile, zoom_level);
-      champlain_tile_set_size (tile, size);
-
-      g_signal_connect (tile, "notify::state", G_CALLBACK (tile_state_notify), view);
-      clutter_actor_add_child (priv->map_layer, CLUTTER_ACTOR (tile));
-      champlain_viewport_set_actor_position (CHAMPLAIN_VIEWPORT (priv->viewport), CLUTTER_ACTOR (tile), x * 
size, y * size);
+      GList *iter;
 
-      /* updates champlain_view state automatically as
-         notify::state signal is connected  */
-      champlain_tile_set_state (tile, CHAMPLAIN_STATE_LOADING);
+      load_tile_for_source (view, priv->map_source, 255, size, x, y);
+      for (iter = priv->all_sources; iter; iter = iter->next)
+        load_tile_for_source (view, iter->data,
+                              GPOINTER_TO_INT (g_object_get_data (G_OBJECT (iter->data),
+                                                                  "opacity")),
+                              size, x, y);
 
-      champlain_map_source_fill_tile (priv->map_source, tile);
       tile_map_set (view, x, y, TRUE);
     }
 
@@ -1941,7 +1967,6 @@ fill_tile_cb (FillTileCallbackData *data)
   return FALSE;
 }
 
-
 static void
 load_visible_tiles (ChamplainView *view,
     gboolean relocate)
@@ -2024,7 +2049,6 @@ load_visible_tiles (ChamplainView *view,
               data->y = y;
               data->size = size;
               data->zoom_level = priv->zoom_level;
-              data->map_source = priv->map_source;
               data->view = g_object_ref (view);
 
               g_idle_add_full (CLUTTER_PRIORITY_REDRAW, (GSourceFunc) fill_tile_cb, data, NULL);
@@ -2133,6 +2157,9 @@ tile_state_notify (ChamplainTile *tile,
  * Changes the currently used map source. #g_object_unref() will be called on
  * the previous one.
  *
+ * As a side effect, changing the primary map source will also clear all
+ * secondary map sources.
+ *
  * Since: 0.4
  */
 void
@@ -2152,6 +2179,9 @@ champlain_view_set_map_source (ChamplainView *view,
   g_object_unref (priv->map_source);
   priv->map_source = g_object_ref_sink (source);
 
+  g_list_free_full (priv->all_sources, g_object_unref);
+  priv->all_sources = NULL;
+
   priv->min_zoom_level = champlain_map_source_get_min_zoom_level (priv->map_source);
   priv->max_zoom_level = champlain_map_source_get_max_zoom_level (priv->map_source);
 
@@ -2531,17 +2561,23 @@ show_zoom_actor (ChamplainView *view,
           ChamplainTile *tile = CHAMPLAIN_TILE (child);
           gint tile_x = champlain_tile_get_x (tile);
           gint tile_y = champlain_tile_get_y (tile);
+          gboolean overlay = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (tile), "overlay"));
 
           champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
-          
+
           g_object_ref (CLUTTER_ACTOR (tile));
           clutter_actor_iter_remove (&iter);
           clutter_actor_add_child (zoom_actor, CLUTTER_ACTOR (tile));
           g_object_unref (CLUTTER_ACTOR (tile));
-          
+
+          /* We move overlay tiles to the zoom actor so they get properly reparented
+             and destroyed as needed, but we hide them for performance reasons */
+          if (overlay)
+            clutter_actor_hide (CLUTTER_ACTOR (tile));
+
           clutter_actor_set_position (CLUTTER_ACTOR (tile), (tile_x - x_first) * size, (tile_y - y_first) * 
size);
         }
-      
+
       zoom_actor_width = clutter_actor_get_width (zoom_actor);
       zoom_actor_height = clutter_actor_get_height (zoom_actor);
 
@@ -3006,3 +3042,40 @@ champlain_view_get_bounding_box (ChamplainView *view)
 
   return bbox;
 }
+
+void
+champlain_view_add_overlay_source (ChamplainView      *view,
+                                   ChamplainMapSource *source,
+                                   guint8              opacity)
+{
+  DEBUG_LOG ()
+
+  ChamplainViewPrivate *priv;
+
+  g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
+  g_return_if_fail (CHAMPLAIN_IS_MAP_SOURCE (source));
+
+  priv = view->priv;
+  priv->all_sources = g_list_append (priv->all_sources, g_object_ref (source));
+  g_object_set_data (G_OBJECT (source), "opacity", GINT_TO_POINTER (opacity));
+
+  champlain_view_reload_tiles (view);
+}
+
+void
+champlain_view_remove_overlay_source (ChamplainView      *view,
+                                      ChamplainMapSource *source)
+{
+  DEBUG_LOG ()
+
+  ChamplainViewPrivate *priv;
+
+  g_return_if_fail (CHAMPLAIN_IS_VIEW (view));
+  g_return_if_fail (CHAMPLAIN_IS_MAP_SOURCE (source));
+
+  priv = view->priv;
+  priv->all_sources = g_list_remove (priv->all_sources, source);
+  g_object_unref (source);
+
+  champlain_view_reload_tiles (view);
+}
diff --git a/champlain/champlain-view.h b/champlain/champlain-view.h
index 868b028..18fea0a 100644
--- a/champlain/champlain-view.h
+++ b/champlain/champlain-view.h
@@ -107,6 +107,12 @@ void champlain_view_ensure_layers_visible (ChamplainView *view,
 
 void champlain_view_set_map_source (ChamplainView *view,
     ChamplainMapSource *map_source);
+void champlain_view_add_overlay_source (ChamplainView *view,
+    ChamplainMapSource *map_source,
+    guint8              opacity);
+void champlain_view_remove_overlay_source (ChamplainView *view,
+    ChamplainMapSource *map_source);
+
 void champlain_view_set_deceleration (ChamplainView *view,
     gdouble rate);
 void champlain_view_set_kinetic_mode (ChamplainView *view,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]