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 = \
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 \
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 \
--- /dev/null
+/*
+ * 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)));
+}
+
--- /dev/null
+/*
+ * 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
#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;
}
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),
}
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;
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);
}
}
}
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;
}
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;
#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
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;
-}
#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"
{
ClutterActor *stage;
- ChamplainMapSource map_source;
+ ChamplainMapSource *map_source;
ChamplainScrollMode scroll_mode;
gint zoom_level; /* Holds the current zoom level number */
{
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
{
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
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)
{
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),
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,
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);
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);
{
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 (
}
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);
*/
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));
/**
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;
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);
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),
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)
{
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);
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);
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
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)
{
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);
+}
#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))
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
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);
}
}