]> err.no Git - libchamplain/commitdiff
Introduce ChamplainMapSource
authorPierre-Luc Beaudoin <pierre-luc@pierlux.com>
Sat, 28 Feb 2009 17:42:22 +0000 (19:42 +0200)
committerPierre-Luc Beaudoin <pierre-luc@pierlux.com>
Wed, 4 Mar 2009 21:05:37 +0000 (23:05 +0200)
champlain/Makefile.am
champlain/champlain-map-source.c [new file with mode: 0644]
champlain/champlain-map-source.h [new file with mode: 0644]
champlain/champlain-map.c
champlain/champlain-map.h
champlain/champlain-tile.c
champlain/champlain-view.c
champlain/champlain-view.h
demos/launcher-gtk.c

index 8e44c4fbeaccd5e0015b5e519c0947fba4623cb7..133074efa3e5156233600f6b909643af1bac53b7 100644 (file)
@@ -22,7 +22,8 @@ libchamplain_headers = \
        champlain-map.h                 \
        champlain-zoom-level.h          \
        champlain-enum-types.h          \
-       champlain-tile.h
+       champlain-tile.h                \
+       champlain-map-source.h
 
 
 libchamplain_0_3_la_SOURCES = \
@@ -34,10 +35,8 @@ libchamplain_0_3_la_SOURCES = \
        champlain-marker.c              \
        champlain-map.c                 \
        champlain-zoom-level.c          \
-       champlain-tile.c                \
-       sources/oam.c                   \
-       sources/osmmapnik.c             \
-       sources/mffrelief.c
+       champlain-tile.c                \
+       champlain-map-source.c
 
 noinst_HEADERS = \
        champlain-debug.h               \
@@ -47,10 +46,8 @@ noinst_HEADERS = \
        champlain-map.h                 \
        champlain-zoom-level.h          \
        champlain-tile.h                \
-       sources/oam.h                   \
-       sources/osmmapnik.h             \
-       sources/mffrelief.h             \
-       champlain-enum-types.h
+       champlain-enum-types.h          \
+       champlain-map-source.h
 
 libchamplain_include_HEADERS = \
        champlain.h                     \
diff --git a/champlain/champlain-map-source.c b/champlain/champlain-map-source.c
new file mode 100644 (file)
index 0000000..d22894c
--- /dev/null
@@ -0,0 +1,658 @@
+/*
+ * Copyright (C) 2008 Pierre-Luc Beaudoin <pierre-luc@pierlux.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "config.h"
+
+#define DEBUG_FLAG CHAMPLAIN_DEBUG_LOADING
+#include "champlain-debug.h"
+
+#include "champlain.h"
+#include "champlain-defines.h"
+#include "champlain-enum-types.h"
+#include "champlain-map-source.h"
+#include "champlain-marshal.h"
+#include "champlain-private.h"
+#include "champlain-zoom-level.h"
+
+#include <errno.h>
+#include <gdk/gdk.h>
+#include <gio/gio.h>
+#include <glib.h>
+#include <glib-object.h>
+#include <libsoup/soup.h>
+#include <math.h>
+
+enum
+{
+  /* normal signals */
+  LAST_SIGNAL
+};
+
+enum
+{
+  PROP_0,
+  PROP_NAME,
+  PROP_LICENSE,
+  PROP_LICENSE_URI,
+  PROP_MAX_ZOOM_LEVEL,
+  PROP_MIN_ZOOM_LEVEL,
+  PROP_TILE_SIZE,
+  PROP_MAP_PROJECTION
+};
+
+/* static guint champlain_map_source_signals[LAST_SIGNAL] = { 0, }; */
+
+G_DEFINE_TYPE (ChamplainMapSource, champlain_map_source, G_TYPE_OBJECT);
+
+#define GET_PRIVATE(obj)    (G_TYPE_INSTANCE_GET_PRIVATE((obj), CHAMPLAIN_TYPE_MAP_SOURCE, ChamplainMapSourcePrivate))
+
+#define CACHE_SUBDIR "champlain"
+static SoupSession * soup_session;
+
+struct _ChamplainMapSourcePrivate
+{
+  gchar *name;
+  gchar *license;
+  gchar *license_uri;
+  guint max_zoom_level;
+  guint min_zoom_level;
+  guint tile_size;
+  ChamplainMapProjection map_projection;
+  gchar *tile_uri_format;
+  ChamplainMapSourceParameter first_param;
+  ChamplainMapSourceParameter second_param;
+  ChamplainMapSourceParameter third_param;
+};
+
+static void
+champlain_map_source_get_property (GObject *object,
+                                   guint prop_id,
+                                   GValue *value,
+                                   GParamSpec *pspec)
+{
+  ChamplainMapSource *map_source = CHAMPLAIN_MAP_SOURCE(object);
+  ChamplainMapSourcePrivate *priv = GET_PRIVATE (map_source);
+
+  switch(prop_id)
+    {
+      case PROP_NAME:
+        g_value_set_string (value, priv->name);
+        break;
+      case PROP_LICENSE:
+        g_value_set_string (value, priv->license);
+        break;
+      case PROP_LICENSE_URI:
+        g_value_set_string (value, priv->license_uri);
+        break;
+      case PROP_MAX_ZOOM_LEVEL:
+        g_value_set_uint (value, priv->max_zoom_level);
+        break;
+      case PROP_MIN_ZOOM_LEVEL:
+        g_value_set_uint (value, priv->min_zoom_level);
+        break;
+      case PROP_TILE_SIZE:
+        g_value_set_uint (value, priv->tile_size);
+        break;
+      case PROP_MAP_PROJECTION:
+        g_value_set_enum (value, priv->map_projection);
+        break;
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+    }
+}
+
+static void
+champlain_map_source_set_property (GObject *object,
+                                   guint prop_id,
+                                   const GValue *value,
+                                   GParamSpec *pspec)
+{
+  ChamplainMapSource *map_source = CHAMPLAIN_MAP_SOURCE(object);
+  ChamplainMapSourcePrivate *priv = GET_PRIVATE (map_source);
+
+  switch(prop_id)
+    {
+      case PROP_NAME:
+        priv->name = g_value_dup_string (value);
+        break;
+      case PROP_LICENSE:
+        priv->license = g_value_dup_string (value);
+        break;
+      case PROP_LICENSE_URI:
+        priv->license_uri = g_value_dup_string (value);
+        break;
+      case PROP_MAX_ZOOM_LEVEL:
+        priv->max_zoom_level = g_value_get_uint (value);
+        break;
+      case PROP_MIN_ZOOM_LEVEL:
+        priv->min_zoom_level = g_value_get_uint (value);
+        break;
+      case PROP_TILE_SIZE:
+        priv->tile_size = g_value_get_uint (value);
+        break;
+      case PROP_MAP_PROJECTION:
+        priv->map_projection = g_value_get_enum (value);
+        break;
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+    }
+}
+
+static void
+champlain_map_source_finalize (GObject *object)
+{
+  /* ChamplainMapSource *map_source = CHAMPLAIN_MAP_SOURCE (object);
+   * ChamplainMapSourcePrivate *priv = GET_PRIVATE (map_source);
+   */
+
+  G_OBJECT_CLASS (champlain_map_source_parent_class)->finalize (object);
+}
+
+static void
+champlain_map_source_class_init (ChamplainMapSourceClass *klass)
+{
+  GParamSpec *pspec;
+
+  g_type_class_add_private (klass, sizeof (ChamplainMapSourcePrivate));
+
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  object_class->finalize = champlain_map_source_finalize;
+  object_class->get_property = champlain_map_source_get_property;
+  object_class->set_property = champlain_map_source_set_property;
+
+  /**
+  * ChamplainMapSource:name:
+  *
+  * The name of the map source
+  *
+  * Since: 0.4
+  */
+  pspec = g_param_spec_string ("name",
+                               "Name",
+                               "The name of the map source",
+                               "",
+                               (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+  g_object_class_install_property (object_class, PROP_NAME, pspec);
+
+  /**
+  * ChamplainMapSource:license:
+  *
+  * The usage license of the map source
+  *
+  * Since: 0.4
+  */
+  pspec = g_param_spec_string ("license",
+                               "License",
+                               "The usage license of the map source",
+                               "",
+                               (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+  g_object_class_install_property (object_class, PROP_LICENSE, pspec);
+
+  /**
+  * ChamplainMapSource:license-uri:
+  *
+  * The usage license's uri for more information 
+  *
+  * Since: 0.4
+  */
+  pspec = g_param_spec_string ("license-uri",
+                               "License-uri",
+                               "The usage license's uri for more information",
+                               "",
+                               (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+  g_object_class_install_property (object_class, PROP_LICENSE_URI, pspec);
+
+  /**
+  * ChamplainMapSource:max-zoom-level:
+  *
+  * The maximum zoom level
+  *
+  * Since: 0.4
+  */
+  pspec = g_param_spec_uint ("max-zoom-level",
+                             "Maximum Zoom Level",
+                             "The maximum zoom level",
+                             0,
+                             50,
+                             18,
+                             (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+  g_object_class_install_property (object_class, PROP_MAX_ZOOM_LEVEL, pspec);
+
+  /**
+  * ChamplainMapSource:min-zoom-level:
+  *
+  * The minimum zoom level
+  *
+  * Since: 0.4
+  */
+  pspec = g_param_spec_uint ("min-zoom-level",
+                             "Minimum Zoom Level",
+                             "The minimum zoom level",
+                             0,
+                             50,
+                             0,
+                             (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+  g_object_class_install_property (object_class, PROP_MIN_ZOOM_LEVEL, pspec);
+
+  /**
+  * ChamplainMapSource:tile-size:
+  *
+  * The tile size of the map source
+  *
+  * Since: 0.4
+  */
+  pspec = g_param_spec_uint ("tile-size",
+                             "Tile Size",
+                             "The tile size",
+                             0,
+                             2048,
+                             256,
+                             (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+  g_object_class_install_property (object_class, PROP_TILE_SIZE, pspec);
+
+  /**
+  * ChamplainMapSource:map-projection
+  *
+  * The map projection of the map source
+  *
+  * Since: 0.4
+  */
+  pspec = g_param_spec_enum ("map-projection",
+                             "Map Projection",
+                             "The map projection",
+                             CHAMPLAIN_TYPE_MAP_PROJECTION,
+                             CHAMPLAIN_MAP_PROJECTION_MERCATOR,
+                             (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+  g_object_class_install_property (object_class, PROP_MAP_PROJECTION, pspec);
+
+}
+
+static void
+champlain_map_source_init (ChamplainMapSource *champlainMapSource)
+{
+  ChamplainMapSourcePrivate *priv = GET_PRIVATE (champlainMapSource);
+}
+
+gint
+champlain_map_source_get_max_zoom_level (ChamplainMapSource *map_source)
+{
+  ChamplainMapSourcePrivate *priv = GET_PRIVATE (map_source);
+  return priv->max_zoom_level;
+}
+
+gint
+champlain_map_source_get_min_zoom_level (ChamplainMapSource *map_source)
+{
+  ChamplainMapSourcePrivate *priv = GET_PRIVATE (map_source);
+  return priv->min_zoom_level;
+}
+
+guint
+champlain_map_source_get_tile_size (ChamplainMapSource *map_source)
+{
+  ChamplainMapSourcePrivate *priv = GET_PRIVATE (map_source);
+  return priv->tile_size;
+}
+
+ChamplainMapSource*
+champlain_map_source_new_network (gchar *name,
+                                  gchar *license,
+                                  gchar *license_uri,
+                                  guint min_zoom,
+                                  guint max_zoom,
+                                  guint tile_size,
+                                  ChamplainMapProjection projection,
+                                  gchar *uri_format,
+                                  ChamplainMapSourceParameter first,
+                                  ChamplainMapSourceParameter second,
+                                  ChamplainMapSourceParameter third)
+{
+
+  ChamplainMapSource * map_source;
+  map_source = g_object_new (CHAMPLAIN_TYPE_MAP_SOURCE, "name", name,
+      "license", license, "license-uri", license_uri,
+      "min-zoom-level", min_zoom, "max-zoom-level", max_zoom,
+      "tile-size", tile_size, "map-projection", projection, NULL);
+//FIXME no function call in a _new ()
+  champlain_map_source_set_tile_uri (map_source, uri_format, first, second,
+      third);
+  return map_source;
+}
+
+static
+get_value (guint x, guint y, guint z, ChamplainMapSourceParameter param)
+{
+  switch (param)
+    {
+      case CHAMPLAIN_MAP_SOURCE_PARAMETER_X:
+        return x;
+      case CHAMPLAIN_MAP_SOURCE_PARAMETER_Y:
+        return y;
+      case CHAMPLAIN_MAP_SOURCE_PARAMETER_Z:
+        return z;
+    }
+}
+
+gchar *
+champlain_map_source_get_tile_uri (ChamplainMapSource *map_source,
+                                   guint x,
+                                   guint y,
+                                   gint z)
+{
+  ChamplainMapSourcePrivate *priv = GET_PRIVATE (map_source);
+
+  guint first;
+  guint second;
+  guint third;
+
+  first = get_value (x, y, z, priv->first_param);
+  second = get_value (x, y, z, priv->second_param);
+  third = get_value (x, y, z, priv->third_param);
+
+  return g_strdup_printf (priv->tile_uri_format, first, second, third);
+
+}
+
+void
+champlain_map_source_set_tile_uri (ChamplainMapSource *map_source,
+                                   const gchar *uri_format,
+                                   ChamplainMapSourceParameter first,
+                                   ChamplainMapSourceParameter second,
+                                   ChamplainMapSourceParameter third)
+{
+  ChamplainMapSourcePrivate *priv = GET_PRIVATE (map_source);
+
+  priv->first_param = first;
+  priv->second_param = second;
+  priv->third_param = third;
+
+  priv->tile_uri_format = g_strdup (uri_format);
+
+}
+
+ChamplainMapSource *
+champlain_map_source_new_osm_mapnik ()
+{
+  champlain_map_source_new_network ("OpenStreetMap Mapnik",
+      "(CC) by contributors", "", 0, 20, 256,
+      CHAMPLAIN_MAP_PROJECTION_MERCATOR,
+      "http://tile.openstreetmap.org/%d/%d/%d.png",
+      CHAMPLAIN_MAP_SOURCE_PARAMETER_Z,
+      CHAMPLAIN_MAP_SOURCE_PARAMETER_X,
+      CHAMPLAIN_MAP_SOURCE_PARAMETER_Y);
+}
+
+guint
+champlain_map_source_get_x (ChamplainMapSource *map_source,
+                            gint zoom_level,
+                            gdouble longitude)
+{
+  ChamplainMapSourcePrivate *priv = GET_PRIVATE (map_source);
+  // FIXME: support other projections
+  return ((longitude + 180.0) / 360.0 * pow(2.0, zoom_level)) * priv->tile_size;
+}
+
+guint
+champlain_map_source_get_y (ChamplainMapSource *map_source,
+                            gint zoom_level,
+                            gdouble latitude)
+{
+  ChamplainMapSourcePrivate *priv = GET_PRIVATE (map_source);
+  // FIXME: support other projections
+  return ((1.0 - log (tan (latitude * M_PI / 180.0) + 1.0 /
+          cos (latitude * M_PI / 180.0)) /
+        M_PI) / 2.0 * pow (2.0, zoom_level)) * priv->tile_size;
+}
+
+guint
+champlain_map_source_get_row_count (ChamplainMapSource *map_source,
+                                    gint zoom_level)
+{
+  ChamplainMapSourcePrivate *priv = GET_PRIVATE (map_source);
+  // FIXME: support other projections
+  return pow (2, zoom_level);
+}
+
+guint
+champlain_map_source_get_column_count (ChamplainMapSource *map_source,
+                                       gint zoom_level)
+{
+  ChamplainMapSourcePrivate *priv = GET_PRIVATE (map_source);
+  // FIXME: support other projections
+  return pow (2, zoom_level);
+}
+
+static gchar *
+get_filename (ChamplainMapSource *map_source,
+              ChamplainZoomLevel *level,
+              ChamplainTile *tile)
+{
+  ChamplainMapSourcePrivate *priv = GET_PRIVATE (map_source);
+  return g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s" G_DIR_SEPARATOR_S
+             "%s" G_DIR_SEPARATOR_S "%d" G_DIR_SEPARATOR_S
+             "%d" G_DIR_SEPARATOR_S "%d.png", g_get_user_cache_dir (),
+             CACHE_SUBDIR, priv->name,
+             champlain_zoom_level_get_zoom_level (level),
+             champlain_tile_get_x (tile), champlain_tile_get_y (tile),
+             NULL);
+}
+
+typedef struct {
+  ChamplainView *view;
+  ChamplainZoomLevel *zoom_level;
+  ChamplainTile *tile;
+} FileLoadedCallbackContext;
+
+static void
+create_error_tile (ChamplainTile* tile)
+{
+  ClutterActor *actor;
+  actor = clutter_texture_new_from_file (DATADIR "/champlain/error.svg", NULL);
+  if (!actor)
+    return;
+
+  champlain_tile_set_actor (tile, actor);
+  clutter_actor_show (actor);
+
+  champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
+}
+
+static void
+file_loaded_cb (SoupSession *session,
+                SoupMessage *msg,
+                gpointer user_data)
+{
+  FileLoadedCallbackContext *ctx = (FileLoadedCallbackContext*) user_data;
+  GdkPixbufLoader* loader;
+  GError *error = NULL;
+  gchar* path, *filename;
+
+  if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
+    {
+      g_warning ("Unable to download tile %d, %d: %s",
+          champlain_tile_get_x (ctx->tile),
+          champlain_tile_get_y (ctx->tile),
+          soup_status_get_phrase(msg->status_code));
+      g_object_unref (ctx->tile);
+      create_error_tile (ctx->tile);
+      return;
+    }
+
+  loader = gdk_pixbuf_loader_new();
+  if (!gdk_pixbuf_loader_write (loader,
+                          (const guchar *) msg->response_body->data,
+                          msg->response_body->length,
+                          &error))
+    {
+      if (error)
+        {
+          g_warning ("Unable to load the pixbuf: %s", error->message);
+          g_error_free (error);
+          create_error_tile (ctx->tile);
+          goto finish;
+        }
+
+      g_object_unref (loader);
+    }
+
+  gdk_pixbuf_loader_close (loader, &error);
+  if (error)
+    {
+      g_warning ("Unable to close the pixbuf loader: %s", error->message);
+      g_error_free (error);
+      create_error_tile (ctx->tile);
+      goto finish;
+    }
+
+  filename = champlain_tile_get_filename (ctx->tile);
+  path = g_path_get_dirname (filename);
+
+  if (g_mkdir_with_parents (path, 0700) == -1)
+    {
+      if (errno != EEXIST)
+        {
+          g_warning ("Unable to create the image cache: %s",
+                     g_strerror (errno));
+          g_object_unref (loader);
+        }
+    }
+
+  g_file_set_contents (filename, msg->response_body->data,
+      msg->response_body->length, NULL);
+
+  /* If the tile has been marked to be deleted, don't go any further */
+  /*if (tile->to_destroy)
+    {
+      g_object_unref (loader);
+      g_free (filename);
+      g_free (map_filename);
+      g_free (tile);
+      return;
+    }
+*/
+  GdkPixbuf* pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
+  ClutterActor *actor = clutter_texture_new();
+  clutter_texture_set_from_rgb_data (CLUTTER_TEXTURE (actor),
+      gdk_pixbuf_get_pixels (pixbuf),
+      gdk_pixbuf_get_has_alpha (pixbuf),
+      gdk_pixbuf_get_width (pixbuf),
+      gdk_pixbuf_get_height (pixbuf),
+      gdk_pixbuf_get_rowstride (pixbuf),
+      3, 0, NULL);
+  champlain_tile_set_actor (ctx->tile, actor);
+  DEBUG ("Tile loaded from network");
+
+finish:
+  champlain_tile_set_state (ctx->tile, CHAMPLAIN_STATE_DONE);
+
+  g_object_unref (loader);
+  g_free (path);
+
+  champlain_view_tile_ready (ctx->view, ctx->zoom_level, ctx->tile, TRUE);
+  g_object_unref (ctx->tile);
+  g_object_unref (ctx->zoom_level);
+  g_free (ctx);
+}
+
+void
+champlain_map_source_get_tile (ChamplainMapSource *map_source,
+                               ChamplainView *view,
+                               ChamplainZoomLevel *zoom_level,
+                               ChamplainTile *tile)
+{
+  gchar* filename;
+
+  ChamplainMapSourcePrivate *priv = GET_PRIVATE (map_source);
+
+  /* Ref the tile as it may be freeing during the loading
+   * Unref when the loading is done.
+   */
+  g_object_ref (tile);
+  g_object_ref (zoom_level);
+
+  /* Try the cached version first */
+  filename = get_filename (map_source, zoom_level, tile);
+  champlain_tile_set_filename (tile, filename);
+  champlain_tile_set_size (tile, champlain_map_source_get_tile_size (map_source));
+
+  if (g_file_test (filename, G_FILE_TEST_EXISTS))
+    {
+      GError *error = NULL;
+      ClutterActor *actor;
+
+      actor = clutter_texture_new_from_file (filename, &error);
+      champlain_tile_set_actor (tile, actor);
+      clutter_actor_show (actor);
+
+      champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
+      DEBUG ("Tile loaded from cache");
+      champlain_view_tile_ready (view, zoom_level, tile, FALSE);
+      g_object_unref (tile);
+      g_object_unref (zoom_level);
+    }
+  else /* if (!offline) */
+    {
+      SoupMessage *msg;
+      const gchar *uri;
+      FileLoadedCallbackContext *ctx = g_new0 (FileLoadedCallbackContext, 1);
+      ctx->view = view;
+      ctx->zoom_level = zoom_level;
+      ctx->tile = tile;
+
+      if (!soup_session)
+        soup_session = soup_session_async_new ();
+
+      uri = champlain_map_source_get_tile_uri (map_source,
+               champlain_tile_get_x (tile), champlain_tile_get_y (tile),
+               champlain_zoom_level_get_zoom_level (zoom_level));
+      champlain_tile_set_uri (tile, uri);
+      champlain_tile_set_state (tile, CHAMPLAIN_STATE_LOADING);
+      msg = soup_message_new (SOUP_METHOD_GET, uri);
+
+      soup_session_queue_message (soup_session, msg,
+                                  file_loaded_cb,
+                                  ctx);
+    }
+  /* If a tile is neither in cache or can be fetched, do nothing, it'll show up
+   * as empty
+   */
+}
+
+gdouble
+champlain_map_source_get_longitude (ChamplainMapSource *map_source,
+                                    gint zoom_level,
+                                    guint x)
+{
+  ChamplainMapSourcePrivate *priv = GET_PRIVATE (map_source);
+  // FIXME: support other projections
+  gdouble dx = (float)x / champlain_map_source_get_tile_size (map_source);
+  return dx / pow (2.0, zoom_level) * 360.0 - 180;
+}
+
+gdouble
+champlain_map_source_get_latitude (ChamplainMapSource *map_source,
+                                   gint zoom_level,
+                                   guint y)
+{
+  ChamplainMapSourcePrivate *priv = GET_PRIVATE (map_source);
+  // FIXME: support other projections
+  gdouble dy = (float)y / champlain_map_source_get_tile_size (map_source);
+  double n = M_PI - 2.0 * M_PI * dy / pow (2.0, zoom_level);
+  return 180.0 / M_PI * atan (0.5 * (exp (n) - exp (-n)));
+}
+
diff --git a/champlain/champlain-map-source.h b/champlain/champlain-map-source.h
new file mode 100644 (file)
index 0000000..0c30cc1
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2008-2009 Pierre-Luc Beaudoin <pierre-luc@pierlux.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#if !defined (__CHAMPLAIN_CHAMPLAIN_H_INSIDE__) && !defined (CHAMPLAIN_COMPILATION)
+#error "Only <champlain/champlain.h> can be included directly."
+#endif
+
+#ifndef CHAMPLAIN_MAP_SOURCE_H
+#define CHAMPLAIN_MAP_SOURCE_H
+
+#include <champlain/champlain-defines.h>
+#include <champlain/champlain-tile.h>
+#include <champlain/champlain-zoom-level.h>
+
+#include <glib-object.h>
+
+#define CHAMPLAIN_TYPE_MAP_SOURCE     (champlain_map_source_get_type())
+#define CHAMPLAIN_MAP_SOURCE(obj)     (G_TYPE_CHECK_INSTANCE_CAST((obj), CHAMPLAIN_TYPE_MAP_SOURCE, ChamplainMapSource))
+#define CHAMPLAIN_MAP_SOURCE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass),  CHAMPLAIN_TYPE_MAP_SOURCE, ChamplainMapSourceClass))
+#define CHAMPLAIN_IS_MAP_SOURCE(obj)  (G_TYPE_CHECK_INSTANCE_TYPE((obj), CHAMPLAIN_TYPE_MAP_SOURCE))
+#define CHAMPLAIN_IS_MAP_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),  CHAMPLAIN_TYPE_MAP_SOURCE))
+#define CHAMPLAIN_MAP_SOURCE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj),  CHAMPLAIN_TYPE_MAP_SOURCE, ChamplainMapSourceClass))
+
+typedef struct _ChamplainMapSource ChamplainMapSource;
+typedef struct _ChamplainMapSourceClass ChamplainMapSourceClass;
+typedef struct _ChamplainMapSourcePrivate ChamplainMapSourcePrivate;
+
+typedef enum
+{
+  CHAMPLAIN_MAP_PROJECTION_MERCATOR
+} ChamplainMapProjection;
+
+typedef enum
+{
+  CHAMPLAIN_MAP_SOURCE_PARAMETER_X,
+  CHAMPLAIN_MAP_SOURCE_PARAMETER_Y,
+  CHAMPLAIN_MAP_SOURCE_PARAMETER_Z,
+} ChamplainMapSourceParameter;
+
+struct _ChamplainMapSource
+{
+  GObject parent;
+  ChamplainMapSourcePrivate *priv;
+};
+
+struct _ChamplainMapSourceClass
+{
+  GObjectClass parent_class;
+};
+
+GType champlain_map_source_get_type (void);
+
+ChamplainMapSource* champlain_map_source_new_network (gchar *name,
+    gchar *license, gchar *license_uri, guint min_zoom, guint map_zoom,
+    guint tile_size, ChamplainMapProjection projection, gchar *uri_format,
+    ChamplainMapSourceParameter first, ChamplainMapSourceParameter second,
+    ChamplainMapSourceParameter third);
+
+gint champlain_map_source_get_min_zoom_level (ChamplainMapSource *map_source);
+
+gint champlain_map_source_get_max_zoom_level (ChamplainMapSource *map_source);
+
+guint champlain_map_source_get_tile_size (ChamplainMapSource *map_source);
+
+gchar * champlain_map_source_get_tile_uri (ChamplainMapSource *source,
+    guint x, guint y, gint z);
+
+void champlain_map_source_set_tile_uri (ChamplainMapSource *map_source,
+    const gchar *uri_format, ChamplainMapSourceParameter first,
+    ChamplainMapSourceParameter second, ChamplainMapSourceParameter third);
+
+ChamplainMapSource * champlain_map_source_new_osm_mapnik ();
+
+guint champlain_map_source_get_x (ChamplainMapSource *map_source,
+    gint zoom_level, gdouble longitude);
+
+guint champlain_map_source_get_y (ChamplainMapSource *map_source,
+    gint zoom_level, gdouble latitude);
+
+gdouble champlain_map_source_get_longitude (ChamplainMapSource *map_source,
+    gint zoom_level, guint x);
+
+gdouble champlain_map_source_get_latitude (ChamplainMapSource *map_source,
+    gint zoom_level, guint y);
+
+guint champlain_map_source_get_row_count (ChamplainMapSource *map_source,
+    gint zoom_level);
+
+guint champlain_map_source_get_column_count (ChamplainMapSource *map_source,
+    gint zoom_level);
+/*
+void champlain_map_source_get_tile (ChamplainMapSource *map_source,
+    ChamplainEngine *engine, ChamplainZoomLevel *level, ChamplainTile *tile);
+*/
+#endif
index ca99e81e6a6ee10d7db057c5c3d9e85cd50034e8..cc9b3da912c344d3095f7b981d9201a2cf3cb9fb 100644 (file)
 #define DEBUG_FLAG CHAMPLAIN_DEBUG_LOADING
 #include "champlain-debug.h"
 #include "champlain-zoom-level.h"
-#include "sources/osmmapnik.h"
-#include "sources/mffrelief.h"
-#include "sources/oam.h"
 
 #include <math.h>
 
 Map*
-map_new (ChamplainMapSource source)
+map_new ()
 {
   Map *map = g_new0(Map, 1);
 
-  switch(source)
-    {
-      case CHAMPLAIN_MAP_SOURCE_OPENSTREETMAP:
-        osm_mapnik_init(map);
-        break;
-      case CHAMPLAIN_MAP_SOURCE_OPENARIALMAP:
-        oam_init(map);
-        break;
-      case CHAMPLAIN_MAP_SOURCE_MAPSFORFREE_RELIEF:
-        mff_relief_init(map);
-        break;
-      case CHAMPLAIN_MAP_SOURCE_COUNT:
-      default:
-        g_warning("Unsupported map source");
-        break;
-    }
-
   map->previous_level = NULL;
   map->current_level = NULL;
 
@@ -56,14 +36,14 @@ map_new (ChamplainMapSource source)
 }
 
 void
-map_load_level(Map *map, gint zoom_level)
+map_load_level(Map *map, ChamplainMapSource *map_source, gint zoom_level)
 {
   if (map->previous_level)
     g_object_unref (map->previous_level);
   map->previous_level = map->current_level;
 
-  guint row_count = map->get_row_count(map, zoom_level);
-  guint column_count = map->get_column_count(map, zoom_level);
+  guint row_count = champlain_map_source_get_row_count (map_source, zoom_level);
+  guint column_count = champlain_map_source_get_column_count (map_source, zoom_level);
 
   map->current_level = champlain_zoom_level_new ();
   g_object_set (G_OBJECT (map->current_level),
@@ -74,18 +54,22 @@ map_load_level(Map *map, gint zoom_level)
 }
 
 void
-map_load_visible_tiles (Map *map, ChamplainRectangle viewport, gboolean offline)
+map_load_visible_tiles (Map *map, ChamplainView *view, ChamplainMapSource *source, ChamplainRectangle viewport, gboolean offline)
 {
+  gint size;
+
+  size = champlain_map_source_get_tile_size (source);
+
   if (viewport.x < 0)
     viewport.x = 0;
   if (viewport.y < 0)
     viewport.y = 0;
 
-  gint x_count = ceil((float)viewport.width / map->tile_size) + 1;
-  gint y_count = ceil((float)viewport.height / map->tile_size) + 1;
+  gint x_count = ceil((float)viewport.width / size) + 1;
+  gint y_count = ceil((float)viewport.height / size) + 1;
 
-  gint x_first = viewport.x / map->tile_size;
-  gint y_first = viewport.y / map->tile_size;
+  gint x_first = viewport.x / size;
+  gint y_first = viewport.y / size;
 
   x_count += x_first;
   y_count += y_first;
@@ -130,7 +114,9 @@ map_load_visible_tiles (Map *map, ChamplainRectangle viewport, gboolean offline)
           if(!exist)
             {
               DEBUG ("Loading tile %d, %d, %d", champlain_zoom_level_get_zoom_level (map->current_level), i, j);
-              ChamplainTile *tile = tile_load (map, champlain_zoom_level_get_zoom_level (map->current_level), i, j, offline);
+              ChamplainTile *tile = champlain_tile_new ();
+              g_object_set (G_OBJECT (tile), "x", i, "y", j, NULL);
+              champlain_map_source_get_tile (source, view, map->current_level, tile);
               champlain_zoom_level_add_tile (map->current_level, tile);
             }
         }
@@ -138,24 +124,24 @@ map_load_visible_tiles (Map *map, ChamplainRectangle viewport, gboolean offline)
 }
 
 gboolean
-map_zoom_in (Map *map)
+map_zoom_in (Map *map, ChamplainMapSource *source)
 {
   guint new_level = champlain_zoom_level_get_zoom_level (map->current_level) + 1;
-  if(new_level <= map->zoom_levels)
+  if(new_level <= champlain_map_source_get_max_zoom_level (source))
     {
-      map_load_level(map, new_level);
+      map_load_level(map, source, new_level);
       return TRUE;
     }
   return FALSE;
 }
 
 gboolean
-map_zoom_out (Map *map)
+map_zoom_out (Map *map, ChamplainMapSource *source)
 {
   guint new_level = champlain_zoom_level_get_zoom_level (map->current_level) - 1;
-  if(new_level >= 0)
+  if(new_level >= champlain_map_source_get_min_zoom_level (source))
     {
-      map_load_level(map, new_level);
+      map_load_level(map, source, new_level);
       return TRUE;
     }
   return FALSE;
@@ -168,11 +154,11 @@ map_free (Map *map)
 }
 
 gboolean
-map_zoom_to (Map *map, guint zoomLevel)
+map_zoom_to (Map *map, ChamplainMapSource *source, guint zoomLevel)
 {
-  if (zoomLevel<= map->zoom_levels)
+  if (zoomLevel<= champlain_map_source_get_max_zoom_level (source))
     {
-      map_load_level(map, zoomLevel);
+      map_load_level(map, source, zoomLevel);
       return TRUE;
     }
   return FALSE;
index d8451e3ab5479d4538483e30c3390935c19611dd..011e0b820e1acee9233c59b958b59e4ce6aba806 100644 (file)
@@ -22,6 +22,7 @@
 #include "champlain.h"
 #include "champlain-private.h"
 #include "champlain-tile.h"
+#include "champlain-map-source.h"
 #include "champlain-view.h"
 #include "champlain-zoom-level.h"
 
 
 struct _Map
 {
-  guint zoom_levels;
-  const gchar *name;
-  const gchar *license;
-  const gchar *license_uri;
-  int tile_size;
-
   ChamplainZoomLevel *current_level;
   ChamplainZoomLevel *previous_level;
-
-  guint (* get_row_count) (Map *map, guint zoom_level);
-  guint (* get_column_count) (Map *map, guint zoom_level);
-
-  gint (* longitude_to_x) (Map *map, gdouble longitude, guint zoom_level);
-  gint (* latitude_to_y) (Map *map, gdouble latitude, guint zoom_level);
-  gdouble (* x_to_longitude) (Map *map, gint x, guint zoom_level);
-  gdouble (* y_to_latitude) (Map *map, gint y, guint zoom_level);
-
-  gchar *(* get_tile_filename) (Map *map, ChamplainTile *tile);
-  gchar *(* get_tile_uri) (Map *map, ChamplainTile *tile);
 };
 
-Map *map_new (ChamplainMapSource source);
+Map *map_new ();
 
-void map_load_visible_tiles (Map *map, ChamplainRectangle viewport, gboolean offline);
+void map_load_visible_tiles (Map *map, ChamplainView * view, ChamplainMapSource *source, ChamplainRectangle viewport, gboolean offline);
 
 void map_free (Map *map);
 
-gboolean map_zoom_in (Map *map);
+gboolean map_zoom_in (Map *map, ChamplainMapSource *map_source);
 
-gboolean map_zoom_out (Map *map);
+gboolean map_zoom_out (Map *map, ChamplainMapSource *map_source);
 
-gboolean map_zoom_to (Map *map, guint zoomLevel);
+gboolean map_zoom_to (Map *map, ChamplainMapSource *map_source, guint zoomLevel);
 
-void map_load_level(Map *map, gint zoom_level);
+void map_load_level(Map *map, ChamplainMapSource *map_source, gint zoom_level);
 
 #endif
index b948eac8777d92fb86cfe85f372f7ac078a2b2bc..aa523224eb5ccc0a8abe07793dbe009de25d44c5 100644 (file)
@@ -439,197 +439,3 @@ champlain_tile_set_actor (ChamplainTile *self, ClutterActor *actor)
   priv->actor = g_object_ref (actor);
   g_object_notify (G_OBJECT (self), "actor");
 }
-
-/* The code below this point is to be refactored */
-
-typedef struct {
-  Map* map;
-  ChamplainTile* tile;
-} TwoPtr;
-
-#define CACHE_DIR "champlain"
-static SoupSession * soup_session;
-
-void
-tile_setup_animation (ChamplainTile* tile)
-{
-  ClutterActor *actor = champlain_tile_get_actor (tile);
-  ClutterEffectTemplate *etemplate = clutter_effect_template_new_for_duration (250, CLUTTER_ALPHA_SINE_INC);
-  clutter_actor_set_opacity(actor, 0);
-  clutter_effect_fade (etemplate, actor, 255, NULL, NULL);
-}
-
-static void
-create_error_tile(Map* map, ChamplainTile* tile)
-{
-  ClutterActor *actor;
-  actor = clutter_texture_new_from_file (DATADIR "/champlain/error.svg", NULL);
-  if (!actor)
-    return;
-
-  champlain_tile_set_actor (tile, actor);
-  clutter_actor_show (actor);
-
-  clutter_container_add (CLUTTER_CONTAINER (champlain_zoom_level_get_actor (map->current_level)), actor, NULL);
-  clutter_actor_show (actor);
-  tile_setup_animation (tile);
-
-  champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
-}
-
-static void
-file_loaded_cb (SoupSession *session,
-                SoupMessage *msg,
-                TwoPtr* ptr)
-{
-  GdkPixbufLoader* loader;
-  GError *error = NULL;
-  gchar* path, *filename, *map_filename;
-
-  ChamplainTile* tile = ptr->tile;
-  Map* map = ptr->map;
-
-  if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
-    {
-      g_warning ("Unable to download tile %d, %d: %s",
-          champlain_tile_get_x (tile),
-          champlain_tile_get_y (tile),
-          soup_status_get_phrase (msg->status_code));
-      create_error_tile (map, tile);
-      g_object_unref (tile);
-      return;
-    }
-
-  loader = gdk_pixbuf_loader_new ();
-  if (!gdk_pixbuf_loader_write (loader,
-                          (const guchar *) msg->response_body->data,
-                          msg->response_body->length,
-                          &error))
-    {
-      if (error)
-        {
-          g_warning ("Unable to load the pixbuf: %s", error->message);
-          g_error_free (error);
-          create_error_tile (map, tile);
-          g_object_unref (tile);
-          return;
-        }
-
-      g_object_unref (loader);
-    }
-
-  gdk_pixbuf_loader_close (loader, &error);
-  if (error)
-    {
-      g_warning ("Unable to close the pixbuf loader: %s", error->message);
-      g_error_free (error);
-      g_object_unref (loader);
-      create_error_tile(map, tile);
-      g_object_unref (tile);
-      return;
-    }
-
-  path = g_build_filename (g_get_user_cache_dir (),
-                                CACHE_DIR,
-                                map->name,
-                                NULL);
-
-  if (g_mkdir_with_parents (path, 0700) == -1)
-    {
-      if (errno != EEXIST)
-        {
-          g_warning ("Unable to create the image cache: %s",
-                     g_strerror (errno));
-          g_object_unref (loader);
-        }
-    }
-
-  map_filename = map->get_tile_filename(map, tile);
-  filename = g_build_filename (g_get_user_cache_dir (),
-                                CACHE_DIR,
-                                map->name,
-                                map_filename,
-                                NULL);
-
-  g_file_set_contents (filename,
-                       msg->response_body->data,
-                       msg->response_body->length,
-                       NULL);
-
-  GdkPixbuf* pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
-
-  ClutterActor *actor = clutter_texture_new();
-  clutter_texture_set_from_rgb_data (CLUTTER_TEXTURE (actor),
-      gdk_pixbuf_get_pixels (pixbuf),
-      gdk_pixbuf_get_has_alpha (pixbuf),
-      gdk_pixbuf_get_width (pixbuf),
-      gdk_pixbuf_get_height (pixbuf),
-      gdk_pixbuf_get_rowstride (pixbuf),
-      3, 0, NULL);
-  champlain_tile_set_actor (tile, actor);
-
-  clutter_actor_set_size (actor, champlain_tile_get_size (tile), champlain_tile_get_size (tile));
-  clutter_actor_show (actor);
-
-  clutter_container_add (CLUTTER_CONTAINER (champlain_zoom_level_get_actor (map->current_level)), actor, NULL);
-  tile_setup_animation (tile);
-
-  champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
-
-  g_object_unref (tile);
-  g_object_unref (loader); /* also frees the pixbuf */
-  g_free (filename);
-  g_free (map_filename);
-  g_free (ptr);
-}
-
-ChamplainTile*
-tile_load (Map* map, gint zoom_level, gint x, gint y, gboolean offline)
-{
-  gchar* filename, *map_filename;
-  ChamplainTile* tile = champlain_tile_new ();
-  g_object_set (G_OBJECT (tile), "x", x, "y" , y, "zoom-level", zoom_level,
-      "size", map->tile_size, NULL);
-
-  TwoPtr* ptr = g_new0 (TwoPtr, 1);
-  ptr->map = map;
-  ptr->tile = tile;
-
-  // Try the cached version first
-  map_filename = map->get_tile_filename (map, tile);
-  filename = g_build_filename (g_get_user_cache_dir (),
-                                CACHE_DIR,
-                                map->name,
-                                map_filename,
-                                NULL);
-
-  if (g_file_test (filename, G_FILE_TEST_EXISTS))
-    {
-      ClutterActor *actor = clutter_texture_new_from_file (filename, NULL);
-      champlain_tile_set_actor (tile, actor);
-      clutter_actor_show (actor);
-
-      clutter_container_add (CLUTTER_CONTAINER (champlain_zoom_level_get_actor (map->current_level)), actor, NULL);
-      champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
-      // Do not animate since it is local and fast
-    }
-  else if (!offline)
-    {
-      SoupMessage *msg;
-      if (!soup_session)
-        soup_session = soup_session_async_new ();
-
-      msg = soup_message_new (SOUP_METHOD_GET, map->get_tile_uri(map, tile));
-
-      soup_session_queue_message (soup_session, msg,
-                                  file_loaded_cb,
-                                  ptr);
-      champlain_tile_set_state (tile, CHAMPLAIN_STATE_LOADING);
-      g_object_ref (tile); //Unref when loading done
-    }
-  // If a tile is neither in cache or can be fetched, do nothing, it'll show up as empty
-
-  g_free (filename);
-  g_free (map_filename);
-  return tile;
-}
index 4572f7fead37de0affd68905b32556b12d9c8330..26b5d2d4a6bca25a54e45a2550085a65dd2bcbbf 100644 (file)
@@ -55,6 +55,7 @@
 #include "champlain-enum-types.h"
 #include "champlain-map.h"
 #include "champlain-marshal.h"
+#include "champlain-map-source.h"
 #include "champlain-private.h"
 #include "champlain-tile.h"
 #include "champlain-zoom-level.h"
@@ -97,7 +98,7 @@ struct _ChamplainViewPrivate
 {
   ClutterActor *stage;
 
-  ChamplainMapSource map_source;
+  ChamplainMapSource *map_source;
   ChamplainScrollMode scroll_mode;
   gint zoom_level; /* Holds the current zoom level number */
 
@@ -164,10 +165,11 @@ viewport_get_longitude_at (ChamplainViewPrivate *priv, gint x)
 {
   gint level;
 
-  if (!priv->map)
+  if (!priv->map_source)
     return 0.0;
 
-  return priv->map->x_to_longitude (priv->map, x, priv->zoom_level);
+  return champlain_map_source_get_longitude (priv->map_source,
+      priv->zoom_level, x);
 }
 
 static gdouble
@@ -185,10 +187,11 @@ viewport_get_latitude_at (ChamplainViewPrivate *priv, gint y)
 {
   gint level;
 
-  if (!priv->map)
+  if (!priv->map_source)
     return 0.0;
 
-  return priv->map->y_to_latitude (priv->map, y, priv->zoom_level);
+  return champlain_map_source_get_latitude (priv->map_source,
+      priv->zoom_level, y);
 }
 
 static gdouble
@@ -232,9 +235,9 @@ scroll_event (ClutterActor *actor,
   y_diff = priv->viewport_size.height / 2 - rel_y;
 
   if (event->direction == CLUTTER_SCROLL_UP)
-    success = map_zoom_in (priv->map);
+    success = map_zoom_in (priv->map, priv->map_source);
   else if (event->direction == CLUTTER_SCROLL_DOWN)
-    success = map_zoom_out (priv->map);
+    success = map_zoom_out (priv->map, priv->map_source);
 
   if (success)
     {
@@ -245,12 +248,14 @@ scroll_event (ClutterActor *actor,
       new_group = champlain_zoom_level_get_actor (priv->map->current_level);
 
       /* Get the new x,y in the new zoom level */
-      x2 = priv->map->longitude_to_x (priv->map, lon, priv->zoom_level);
-      y2 = priv->map->latitude_to_y (priv->map, lat, priv->zoom_level);
+      x2 = champlain_map_source_get_x (priv->map_source, priv->zoom_level, lon);
+      y2 = champlain_map_source_get_y (priv->map_source, priv->zoom_level, lat);
       /* Get the new lon,lat of these new x,y minus the distance from the
        * viewport center */
-      lon2 = priv->map->x_to_longitude (priv->map, x2 + x_diff, priv->zoom_level);
-      lat2 = priv->map->y_to_latitude (priv->map, y2 + y_diff, priv->zoom_level);
+      lon2 = champlain_map_source_get_longitude (priv->map_source,
+          priv->zoom_level, x2 + x_diff);
+      lat2 = champlain_map_source_get_latitude (priv->map_source,
+          priv->zoom_level, y2 + y_diff);
 
       resize_viewport (view);
       clutter_container_remove_actor (CLUTTER_CONTAINER (priv->map_layer),
@@ -277,8 +282,8 @@ marker_reposition_cb (ChamplainMarker *marker,
 
   if (priv->map)
     {
-      x = priv->map->longitude_to_x (priv->map, marker_priv->lon, priv->zoom_level);
-      y = priv->map->latitude_to_y (priv->map, marker_priv->lat, priv->zoom_level);
+      x = champlain_map_source_get_x (priv->map_source, priv->zoom_level, marker_priv->lon);
+      y = champlain_map_source_get_y (priv->map_source, priv->zoom_level, marker_priv->lat);
 
       clutter_actor_set_position (CLUTTER_ACTOR (marker),
         x - priv->anchor.x,
@@ -337,8 +342,8 @@ create_initial_map (ChamplainView *view)
   ChamplainViewPrivate *priv = GET_PRIVATE (view);
   ClutterActor *group;
 
-  priv->map = map_new (priv->map_source);
-  map_load_level (priv->map, priv->zoom_level);
+  priv->map = map_new ();
+  map_load_level (priv->map, priv->map_source, priv->zoom_level);
   group = champlain_zoom_level_get_actor (priv->map->current_level);
   clutter_container_add_actor (CLUTTER_CONTAINER (priv->map_layer), group);
 
@@ -441,7 +446,7 @@ champlain_view_get_property (GObject *object,
         g_value_set_int (value, priv->zoom_level);
         break;
       case PROP_MAP_SOURCE:
-        g_value_set_int (value, priv->map_source);
+        g_value_set_object (value, priv->map_source);
         break;
       case PROP_SCROLL_MODE:
         g_value_set_enum (value, priv->scroll_mode);
@@ -497,10 +502,10 @@ champlain_view_set_property (GObject *object,
           {
             if (level != priv->zoom_level)
               {
-                priv->zoom_level = level;
                 ClutterActor *group = champlain_zoom_level_get_actor (priv->map->current_level);
-                if (map_zoom_to (priv->map, level))
+                if (map_zoom_to (priv->map, priv->map_source, level))
                   {
+                    priv->zoom_level = level;
                     ClutterActor *new_group = champlain_zoom_level_get_actor (priv->map->current_level);
                     resize_viewport (view);
                     clutter_container_remove_actor (
@@ -516,24 +521,26 @@ champlain_view_set_property (GObject *object,
       }
     case PROP_MAP_SOURCE:
       {
-        ChamplainMapSource source = g_value_get_int (value);
+        ChamplainMapSource *source = g_value_get_object (value);
+
         if (priv->map_source != source)
           {
-            priv->map_source = source;
+            g_object_unref (priv->map_source);
+            priv->map_source = g_object_ref (source);
             if (priv->map)
               {
                 ClutterActor *group;
                 map_free (priv->map);
-                priv->map = map_new (priv->map_source);
+                priv->map = map_new ();
 
                 /* Keep same zoom level if the new map supports it */
-                if (priv->zoom_level > priv->map->zoom_levels)
+                if (priv->zoom_level > champlain_map_source_get_max_zoom_level (priv->map_source))
                   {
-                    priv->zoom_level = priv->map->zoom_levels;
+                    priv->zoom_level = champlain_map_source_get_max_zoom_level (priv->map_source);
                     g_object_notify (G_OBJECT (view), "zoom-level");
                   }
 
-                map_load_level (priv->map, priv->zoom_level);
+                map_load_level (priv->map, priv->map_source, priv->zoom_level);
                 group = champlain_zoom_level_get_actor (priv->map->current_level);
 
                 view_load_visible_tiles (view);
@@ -647,10 +654,10 @@ champlain_view_class_init (ChamplainViewClass *champlainViewClass)
   */
   g_object_class_install_property (object_class,
       PROP_MAP_SOURCE,
-      g_param_spec_int ("map-source",
+      g_param_spec_object ("map-source",
            "Map source",
            "The map source being displayed",
-           0, CHAMPLAIN_MAP_SOURCE_COUNT, CHAMPLAIN_MAP_SOURCE_OPENSTREETMAP,
+           CHAMPLAIN_TYPE_MAP_SOURCE,
            CHAMPLAIN_PARAM_READWRITE));
 
   /**
@@ -735,7 +742,7 @@ champlain_view_init (ChamplainView *view)
 
   champlain_debug_set_flags (g_getenv ("CHAMPLAIN_DEBUG"));
 
-  priv->map_source = CHAMPLAIN_MAP_SOURCE_OPENSTREETMAP;
+  priv->map_source = champlain_map_source_new_osm_mapnik ();
   priv->zoom_level = 0;
   priv->offline = FALSE;
   priv->keep_center_on_resize = TRUE;
@@ -852,7 +859,7 @@ update_license (ChamplainView *view)
   if (priv->show_license)
     {
       priv->license_actor = clutter_label_new_with_text ( "sans 8",
-          priv->map->license);
+          ""); //XXX: champlain_map_source_get_license (priv->map_source));
       clutter_actor_set_opacity (priv->license_actor, 128);
       clutter_actor_show (priv->license_actor);
 
@@ -890,21 +897,23 @@ finger_scroll_button_press_cb (ClutterActor *actor,
       gint x_diff = priv->viewport_size.width / 2 - rel_x;
       gint y_diff = priv->viewport_size.height / 2 - rel_y;
 
-      if (map_zoom_in (priv->map))
+      if (map_zoom_in (priv->map, priv->map_source))
         {
+          gint x2, y2;
+          gdouble lat2, lon2;
+
           priv->zoom_level++;
           ClutterActor *new_group = champlain_zoom_level_get_actor (priv->map->current_level);
+
           /* Get the new x,y in the new zoom level */
-          gint x2 = priv->map->longitude_to_x (priv->map, lon,
-              priv->zoom_level);
-          gint y2 = priv->map->latitude_to_y (priv->map, lat,
-              priv->zoom_level);
+          x2 = champlain_map_source_get_x (priv->map_source, priv->zoom_level, lon);
+          y2 = champlain_map_source_get_y (priv->map_source, priv->zoom_level, lat);
           /* Get the new lon,lat of these new x,y minus the distance from the
            * viewport center */
-          gdouble lon2 = priv->map->x_to_longitude (priv->map, x2 + x_diff,
-              priv->zoom_level);
-          gdouble lat2 = priv->map->y_to_latitude (priv->map, y2 + y_diff,
-              priv->zoom_level);
+          lon2 = champlain_map_source_get_longitude (priv->map_source,
+              priv->zoom_level, x2 + x_diff);
+          lat2 = champlain_map_source_get_latitude (priv->map_source,
+              priv->zoom_level, y2 + y_diff);
 
           resize_viewport (view);
           clutter_container_remove_actor (CLUTTER_CONTAINER (priv->map_layer),
@@ -960,8 +969,8 @@ champlain_view_center_on (ChamplainView *view,
   if (!priv->map)
     return;
 
-  x = priv->map->longitude_to_x (priv->map, longitude, priv->zoom_level);
-  y = priv->map->latitude_to_y (priv->map, latitude, priv->zoom_level);
+  x = champlain_map_source_get_x (priv->map_source, priv->zoom_level, longitude);
+  y = champlain_map_source_get_y (priv->map_source, priv->zoom_level, latitude);
 
   if (priv->zoom_level >= 8)
     {
@@ -1020,7 +1029,7 @@ champlain_view_zoom_in (ChamplainView *view)
   ChamplainViewPrivate *priv = GET_PRIVATE (view);
   ClutterActor *group = champlain_zoom_level_get_actor (priv->map->current_level);
 
-  if (map_zoom_in (priv->map))
+  if (map_zoom_in (priv->map, priv->map_source))
     {
       priv->zoom_level++;
       resize_viewport (view);
@@ -1050,7 +1059,7 @@ champlain_view_zoom_out (ChamplainView *view)
   ChamplainViewPrivate *priv = GET_PRIVATE (view);
   ClutterActor *group = champlain_zoom_level_get_actor (priv->map->current_level);
 
-  if (map_zoom_out (priv->map))
+  if (map_zoom_out (priv->map, priv->map_source))
     {
       priv->zoom_level--;
       resize_viewport (view);
@@ -1181,7 +1190,7 @@ view_load_visible_tiles (ChamplainView *view)
   viewport.x += priv->anchor.x;
   viewport.y += priv->anchor.y;
 
-  map_load_visible_tiles (priv->map, viewport, priv->offline);
+  map_load_visible_tiles (priv->map, view, priv->map_source, viewport, priv->offline);
 }
 
 static void
@@ -1197,12 +1206,12 @@ view_position_tile (ChamplainView* view, ChamplainTile* tile)
   g_object_get (G_OBJECT (tile), "actor", &actor,
       "x", &x, "y", &y,
       "size", &size, NULL);
+
   clutter_actor_set_position (actor,
     (x * size) - priv->anchor.x,
     (y * size) - priv->anchor.y);
 }
 
-//FIXME: This isn't called  when tiles are done loading
 static void
 view_tiles_reposition (ChamplainView* view)
 {
@@ -1216,3 +1225,25 @@ view_tiles_reposition (ChamplainView* view)
         view_position_tile (view, tile);
     }
 }
+
+void
+champlain_view_tile_ready (ChamplainView *view,
+                           ChamplainZoomLevel *level,
+                           ChamplainTile *tile,
+                           gboolean animate)
+{
+  ClutterActor *actor;
+  ClutterEffectTemplate *etemplate;
+
+  actor = champlain_tile_get_actor (tile);
+  clutter_actor_show (actor);
+  if (animate)
+    {
+      etemplate = clutter_effect_template_new_for_duration (750, CLUTTER_ALPHA_SINE_INC);
+      clutter_actor_set_opacity(actor, 0);
+      clutter_effect_fade (etemplate, actor, 255, NULL, NULL);
+    }
+
+  clutter_container_add (CLUTTER_CONTAINER (champlain_zoom_level_get_actor (level)), actor, NULL);
+  view_position_tile (view, tile);
+}
index 80421c92b30abe267e419ebe0cfb3b4a153f6689..dc09bf56185aeecfa105381608f778d5ac4acd6a 100644 (file)
 #define CHAMPLAIN_VIEW_H
 
 #include <champlain/champlain-defines.h>
+#include <champlain/champlain-zoom-level.h>
 
 #include <glib.h>
 #include <glib-object.h>
 #include <clutter/clutter.h>
 
-/**
- * ChamplainMapSource:
- * @CHAMPLAIN_MAP_SOURCE_DEBUG: Debug map, untested as of 0.2
- * @CHAMPLAIN_MAP_SOURCE_OPENSTREETMAP: Open Street Map - Mapnick tiles
- * @CHAMPLAIN_MAP_SOURCE_OPENARIALMAP: Open Arial Map
- * @CHAMPLAIN_MAP_SOURCE_MAPSFORFREE_RELIEF: Maps for free - Relief tiles
- *
- * Type of scrolling.
- */
-typedef enum
-{
-  CHAMPLAIN_MAP_SOURCE_DEBUG,
-  CHAMPLAIN_MAP_SOURCE_OPENSTREETMAP,
-  CHAMPLAIN_MAP_SOURCE_OPENARIALMAP,
-  CHAMPLAIN_MAP_SOURCE_MAPSFORFREE_RELIEF,
-  CHAMPLAIN_MAP_SOURCE_COUNT
-} ChamplainMapSource;
-
 #define CHAMPLAIN_TYPE_VIEW     (champlain_view_get_type())
 #define CHAMPLAIN_VIEW(obj)     (G_TYPE_CHECK_INSTANCE_CAST((obj), CHAMPLAIN_TYPE_VIEW, ChamplainView))
 #define CHAMPLAIN_VIEW_CLASS(klass)  (G_TYPE_CHECK_CLASS_CAST((klass),  CHAMPLAIN_TYPE_VIEW, ChamplainViewClass))
@@ -97,4 +80,6 @@ void champlain_view_set_size (ChamplainView *view, guint width, guint height);
 
 gboolean champlain_view_get_coords_from_event (ChamplainView *view, ClutterEvent *event, gdouble *lat, gdouble *lon);
 
+void champlain_view_tile_ready (ChamplainView *view, ChamplainZoomLevel *level, ChamplainTile *tile, gboolean animate);
+
 #endif
index 12f6b068be12125fd955245b2b2dc28d7c47dc51..1fb658d1d699bdcee56eb4b92dbddd4fb0909cdf 100644 (file)
@@ -79,15 +79,15 @@ map_source_changed (GtkWidget *widget,
   gchar* selection = gtk_combo_box_get_active_text(GTK_COMBO_BOX(widget));
   if (g_strcmp0(selection, OSM_MAP) == 0)
     {
-      g_object_set(G_OBJECT(view), "map-source", CHAMPLAIN_MAP_SOURCE_OPENSTREETMAP, NULL);
+      //g_object_set(G_OBJECT(view), "map-source", CHAMPLAIN_MAP_SOURCE_OPENSTREETMAP, NULL);
     }
   else if (g_strcmp0(selection, OAM_MAP) == 0)
     {
-      g_object_set(G_OBJECT(view), "map-source", CHAMPLAIN_MAP_SOURCE_OPENARIALMAP, NULL);
+      //g_object_set(G_OBJECT(view), "map-source", CHAMPLAIN_MAP_SOURCE_OPENARIALMAP, NULL);
     }
   else if (g_strcmp0(selection, MFF_MAP) == 0)
     {
-      g_object_set(G_OBJECT(view), "map-source", CHAMPLAIN_MAP_SOURCE_MAPSFORFREE_RELIEF, NULL);
+      //g_object_set(G_OBJECT(view), "map-source", CHAMPLAIN_MAP_SOURCE_MAPSFORFREE_RELIEF, NULL);
     }
 }