From 314fc83f49ca06a33f9de6d63c944dd2a6ee8180 Mon Sep 17 00:00:00 2001 From: Pierre-Luc Beaudoin Date: Sat, 28 Feb 2009 19:42:22 +0200 Subject: [PATCH] Introduce ChamplainMapSource --- champlain/Makefile.am | 15 +- champlain/champlain-map-source.c | 658 +++++++++++++++++++++++++++++++ champlain/champlain-map-source.h | 110 ++++++ champlain/champlain-map.c | 64 ++- champlain/champlain-map.h | 30 +- champlain/champlain-tile.c | 194 --------- champlain/champlain-view.c | 117 ++++-- champlain/champlain-view.h | 21 +- demos/launcher-gtk.c | 6 +- 9 files changed, 886 insertions(+), 329 deletions(-) create mode 100644 champlain/champlain-map-source.c create mode 100644 champlain/champlain-map-source.h diff --git a/champlain/Makefile.am b/champlain/Makefile.am index 8e44c4f..133074e 100644 --- a/champlain/Makefile.am +++ b/champlain/Makefile.am @@ -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 index 0000000..d22894c --- /dev/null +++ b/champlain/champlain-map-source.c @@ -0,0 +1,658 @@ +/* + * Copyright (C) 2008 Pierre-Luc Beaudoin + * + * 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 +#include +#include +#include +#include +#include +#include + +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 index 0000000..0c30cc1 --- /dev/null +++ b/champlain/champlain-map-source.h @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2008-2009 Pierre-Luc Beaudoin + * + * 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 can be included directly." +#endif + +#ifndef CHAMPLAIN_MAP_SOURCE_H +#define CHAMPLAIN_MAP_SOURCE_H + +#include +#include +#include + +#include + +#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 diff --git a/champlain/champlain-map.c b/champlain/champlain-map.c index ca99e81..cc9b3da 100644 --- a/champlain/champlain-map.c +++ b/champlain/champlain-map.c @@ -21,34 +21,14 @@ #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 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; diff --git a/champlain/champlain-map.h b/champlain/champlain-map.h index d8451e3..011e0b8 100644 --- a/champlain/champlain-map.h +++ b/champlain/champlain-map.h @@ -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" @@ -30,39 +31,22 @@ 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 diff --git a/champlain/champlain-tile.c b/champlain/champlain-tile.c index b948eac..aa52322 100644 --- a/champlain/champlain-tile.c +++ b/champlain/champlain-tile.c @@ -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; -} diff --git a/champlain/champlain-view.c b/champlain/champlain-view.c index 4572f7f..26b5d2d 100644 --- a/champlain/champlain-view.c +++ b/champlain/champlain-view.c @@ -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); +} diff --git a/champlain/champlain-view.h b/champlain/champlain-view.h index 80421c9..dc09bf5 100644 --- a/champlain/champlain-view.h +++ b/champlain/champlain-view.h @@ -24,29 +24,12 @@ #define CHAMPLAIN_VIEW_H #include +#include #include #include #include -/** - * 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 diff --git a/demos/launcher-gtk.c b/demos/launcher-gtk.c index 12f6b06..1fb658d 100644 --- a/demos/launcher-gtk.c +++ b/demos/launcher-gtk.c @@ -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); } } -- 2.39.5