--- trunk/src/osm-gps-map-osd-classic.c 2009/08/20 19:17:23 70 +++ trunk/src/osm-gps-map-osd-classic.c 2009/08/21 13:20:40 71 @@ -1,3 +1,5 @@ +/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */ +/* vim:set et sw=4 ts=4 cino=t0,(0: */ /* * Copyright (C) Till Harbaum 2009 * @@ -17,27 +19,68 @@ #include "config.h" -#ifdef USE_CAIRO -#include +/* parameters that can be overwritten from the config file: */ +/* OSM_GPS_MAP_OSD_DIAMETER */ + +#ifndef USE_CAIRO +#error "OSD control display lacks a non-cairo implementation!" #endif +#include + +#include "osm-gps-map.h" + //the osd controls typedef struct { GdkPixmap *backup; - cairo_surface_t *overlay; gint backup_x, backup_y; + + cairo_surface_t *overlay; + OsmGpsMapOsdGpsCallback cb; gpointer data; } osd_priv_t; +/* the osd structure mainly contains various callbacks */ +/* required to draw and update the OSD */ typedef struct { - - + void(enable_gps)(OsmGpsMap *, OsmGpsMapOsdGpsCallback, gpointer); + void(restore)(OsmGpsMap*); + void(draw)(OsmGpsMap *, gint, gint); + void(render)(OsmGpsMapPrivate *); + osd_button_t(*check)(gint, gint); /* check if x/y lies within OSD */ + void(free)(gpointer); gpointer priv; } osm_gps_map_osd_t; +static osm_gps_map_osd_t osd_classic = { + .restore = osm_gps_map_osd_restore, + .draw = osm_gps_map_osd_draw_controls, + .check = osm_gps_map_osd_check, + .render = osm_gps_map_osd_render, + .enable_gps = osm_gps_map_osd_enable_gps, + .free = osm_gps_map_osd_free, + .priv = NULL; +} + +/* this is the only function that's externally visible */ +osm_gps_map_osd_t * +osm_gps_map_osd_classic_init(void) +{ + return osd_classic; +} + +static void +osm_gps_map_osd_free(gpointer priv_ptr) +{ + osd_priv_t *priv = (osd_priv_t *)priv_ptr; + + + g_free(priv); +} + /* position and extent of bounding box */ #define OSD_X (10) #define OSD_Y (10) @@ -74,9 +117,11 @@ #define Z_LEFT (Z_RAD) #define Z_RIGHT (2 * D_RAD - Z_RAD) + /* create the cairo shape used for the zoom buttons */ static void -osm_gps_map_osd_zoom_shape(cairo_t *cr, gint x, gint y) { +osm_gps_map_osd_zoom_shape(cairo_t *cr, gint x, gint y) +{ cairo_move_to (cr, x+Z_LEFT, y+Z_TOP); cairo_line_to (cr, x+Z_RIGHT, y+Z_TOP); cairo_arc (cr, x+Z_RIGHT, y+Z_MID, Z_RAD, -M_PI/2, M_PI/2); @@ -86,22 +131,11 @@ /* create the cairo shape used for the dpad */ static void -osm_gps_map_osd_dpad_shape(cairo_t *cr, gint x, gint y) { +osm_gps_map_osd_dpad_shape(cairo_t *cr, gint x, gint y) +{ cairo_arc (cr, x+D_RAD, y+D_RAD, D_RAD, 0, 2 * M_PI); } -typedef enum { - OSD_NONE = 0, - OSD_BG, - OSD_UP, - OSD_DOWN, - OSD_LEFT, - OSD_RIGHT, - OSD_IN, - OSD_OUT, - OSD_GPS -} osd_button_t; - static gboolean osm_gps_map_in_circle(gint x, gint y, gint cx, gint cy, gint rad) { @@ -340,8 +374,6 @@ priv->osd.backup_x = x-1; priv->osd.backup_y = y-1; - -#ifdef USE_CAIRO /* OSD itself uses some off-screen rendering, so check if the */ /* offscreen buffer is present and create it if not */ if(!priv->osd.overlay) { @@ -357,10 +389,6 @@ cairo_set_source_surface(cr, priv->osd.overlay, x, y); cairo_paint(cr); cairo_destroy(cr); - -#else -#warning "OSD control display lacks a non-cairo implementation!" -#endif } static void @@ -378,1556 +406,14 @@ } } -#endif - -static gboolean -osm_gps_map_map_redraw (OsmGpsMap *map) -{ - OsmGpsMapPrivate *priv = map->priv; - - priv->idle_map_redraw = 0; - - /* the motion_notify handler uses priv->pixmap to redraw the area; if we - * change it while we are dragging, we will end up showing it in the wrong - * place. This could be fixed by carefully recompute the coordinates, but - * for now it's easier just to disable redrawing the map while dragging */ - if (priv->dragging) - return FALSE; - - priv->redraw_cycle++; - - /* draw white background to initialise pixmap */ - gdk_draw_rectangle ( - priv->pixmap, - GTK_WIDGET(map)->style->white_gc, - TRUE, - 0, 0, - GTK_WIDGET(map)->allocation.width + EXTRA_BORDER * 2, - GTK_WIDGET(map)->allocation.height + EXTRA_BORDER * 2); - - osm_gps_map_fill_tiles_pixel(map); - - osm_gps_map_print_tracks(map); - osm_gps_map_draw_gps_point(map); - osm_gps_map_print_images(map); -#ifdef ENABLE_BALLOON - osm_gps_map_draw_balloon_int(map); -#endif -#ifdef ENABLE_OSD - osm_gps_map_osd_draw_controls(map, 0, 0); -#endif - - //osm_gps_map_osd_speed(map, 1.5); - osm_gps_map_purge_cache(map); - gtk_widget_queue_draw (GTK_WIDGET (map)); - - return FALSE; -} - -static void -osm_gps_map_map_redraw_idle (OsmGpsMap *map) -{ - OsmGpsMapPrivate *priv = map->priv; - - if (priv->idle_map_redraw == 0) - priv->idle_map_redraw = g_idle_add ((GSourceFunc)osm_gps_map_map_redraw, map); -} - -static void -osm_gps_map_init (OsmGpsMap *object) -{ - OsmGpsMapPrivate *priv; - - priv = G_TYPE_INSTANCE_GET_PRIVATE (object, OSM_TYPE_GPS_MAP, OsmGpsMapPrivate); - object->priv = priv; - - priv->pixmap = NULL; - - priv->trip_history = NULL; - priv->gps = g_new0(coord_t, 1); - priv->gps_valid = FALSE; - -#ifdef ENABLE_BALLOON - priv->balloon.coo = g_new0(coord_t, 1); - priv->balloon.valid = FALSE; - priv->balloon.cb = NULL; -#endif - -#ifdef ENABLE_OSD - priv->osd.backup = NULL; - priv->osd.overlay = NULL; - priv->osd.cb = NULL; -#endif - - priv->tracks = NULL; - priv->images = NULL; - - priv->drag_counter = 0; - priv->drag_mouse_dx = 0; - priv->drag_mouse_dy = 0; - priv->drag_start_mouse_x = 0; - priv->drag_start_mouse_y = 0; - - priv->uri_format = 0; - priv->the_google = FALSE; - - priv->map_source = -1; - -#ifndef LIBSOUP22 - //Change naumber of concurrent connections option? - priv->soup_session = soup_session_async_new_with_options( - SOUP_SESSION_USER_AGENT, - "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11", - NULL); -#else - /* libsoup-2.2 seems not to be able to set the user agent */ - priv->soup_session = soup_session_async_new(); -#endif - - //Hash table which maps tile d/l URIs to SoupMessage requests - priv->tile_queue = g_hash_table_new (g_str_hash, g_str_equal); - - //Some mapping providers (Google) have varying degrees of tiles at multiple - //zoom levels - priv->missing_tiles = g_hash_table_new (g_str_hash, g_str_equal); - - /* memory cache for most recently used tiles */ - priv->tile_cache = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, (GDestroyNotify)cached_tile_free); - priv->max_tile_cache_size = 20; - - gtk_widget_add_events (GTK_WIDGET (object), - GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | - GDK_POINTER_MOTION_MASK | - GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK); - GTK_WIDGET_SET_FLAGS (object, GTK_CAN_FOCUS); - - g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MASK, my_log_handler, NULL); -} - -#ifndef G_CHECKSUM_MD5 -/* simple hash algorithm hack if md5 is not present */ -static char *simple_hash(char *str) { - union { - char str[4]; - gulong val; - } hash = { .val = 0x55555555 }; - - while(*str) { - hash.str[(int)str & 3] ^= *str; - str++; - } - return g_strdup_printf("%08lX", hash.val); -} -#endif - -static GObject * -osm_gps_map_constructor (GType gtype, guint n_properties, GObjectConstructParam *properties) -{ - GObject *object; - OsmGpsMapPrivate *priv; - OsmGpsMap *map; - const char *uri; - - //Always chain up to the parent constructor - object = G_OBJECT_CLASS(osm_gps_map_parent_class)->constructor(gtype, n_properties, properties); - map = OSM_GPS_MAP(object); - priv = OSM_GPS_MAP_PRIVATE(object); - - //user can specify a map source ID, or a repo URI as the map source - uri = osm_gps_map_source_get_repo_uri(OSM_GPS_MAP_SOURCE_NULL); - if ( (priv->map_source == 0) || (strcmp(priv->repo_uri, uri) == 0) ) { - g_debug("Using null source"); - priv->map_source = OSM_GPS_MAP_SOURCE_NULL; - - priv->null_tile = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, 256, 256); - gdk_pixbuf_fill(priv->null_tile, 0xcccccc00); - } - else if (priv->map_source >= 0) { - //check if the source given is valid - uri = osm_gps_map_source_get_repo_uri(priv->map_source); - if (uri) { - g_debug("Setting map source from ID"); - g_free(priv->repo_uri); - - priv->repo_uri = g_strdup(uri); - priv->image_format = g_strdup( - osm_gps_map_source_get_image_format(priv->map_source)); - priv->max_zoom = osm_gps_map_source_get_max_zoom(priv->map_source); - priv->min_zoom = osm_gps_map_source_get_min_zoom(priv->map_source); - } - } - - if (!priv->cache_dir_is_full_path) { -#ifdef G_CHECKSUM_MD5 - char *md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, priv->repo_uri, -1); -#else - char *md5 = simple_hash(priv->repo_uri); -#endif - - if (priv->cache_dir) { - char *old = priv->cache_dir; - //the new cachedir is the given cache dir + the md5 of the repo_uri - priv->cache_dir = g_strdup_printf("%s%c%s", old, G_DIR_SEPARATOR, md5); - g_debug("Adjusting cache dir %s -> %s", old, priv->cache_dir); - g_free(old); - } else { - //the new cachedir is the current dir + the md5 of the repo_uri - priv->cache_dir = g_strdup(md5); - } - - g_free(md5); - } - - inspect_map_uri(map); - - return object; -} - -static void -osm_gps_map_dispose (GObject *object) -{ - OsmGpsMap *map = OSM_GPS_MAP(object); - OsmGpsMapPrivate *priv = map->priv; - - if (priv->is_disposed) - return; - - priv->is_disposed = TRUE; - - soup_session_abort(priv->soup_session); - g_object_unref(priv->soup_session); - - g_hash_table_destroy(priv->tile_queue); - g_hash_table_destroy(priv->missing_tiles); - g_hash_table_destroy(priv->tile_cache); - - osm_gps_map_free_images(map); - - if(priv->pixmap) - g_object_unref (priv->pixmap); - - if (priv->null_tile) - g_object_unref (priv->null_tile); - - if(priv->gc_map) - g_object_unref(priv->gc_map); - - if (priv->idle_map_redraw != 0) - g_source_remove (priv->idle_map_redraw); - - g_free(priv->gps); - -#ifdef ENABLE_BALLOON - g_free(priv->balloon.coo); -#endif - -#ifdef ENABLE_OSD - if (priv->osd.backup) - g_object_unref(priv->osd.backup); - - if (priv->osd.overlay) - cairo_surface_destroy(priv->osd.overlay); -#endif - - G_OBJECT_CLASS (osm_gps_map_parent_class)->dispose (object); -} - -static void -osm_gps_map_finalize (GObject *object) -{ - OsmGpsMap *map = OSM_GPS_MAP(object); - OsmGpsMapPrivate *priv = map->priv; - - g_free(priv->cache_dir); - g_free(priv->repo_uri); - g_free(priv->image_format); - - osm_gps_map_free_trip(map); - osm_gps_map_free_tracks(map); - - G_OBJECT_CLASS (osm_gps_map_parent_class)->finalize (object); -} - -static void -osm_gps_map_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - g_return_if_fail (OSM_IS_GPS_MAP (object)); - OsmGpsMap *map = OSM_GPS_MAP(object); - OsmGpsMapPrivate *priv = map->priv; - - switch (prop_id) - { - case PROP_AUTO_CENTER: - priv->map_auto_center = g_value_get_boolean (value); - break; - case PROP_RECORD_TRIP_HISTORY: - priv->record_trip_history = g_value_get_boolean (value); - break; - case PROP_SHOW_TRIP_HISTORY: - priv->show_trip_history = g_value_get_boolean (value); - break; - case PROP_AUTO_DOWNLOAD: - priv->map_auto_download = g_value_get_boolean (value); - break; - case PROP_REPO_URI: - priv->repo_uri = g_value_dup_string (value); - break; - case PROP_PROXY_URI: - if ( g_value_get_string(value) ) { - priv->proxy_uri = g_value_dup_string (value); - g_debug("Setting proxy server: %s", priv->proxy_uri); - -#ifndef LIBSOUP22 - GValue val = {0}; - - SoupURI* uri = soup_uri_new(priv->proxy_uri); - g_value_init(&val, SOUP_TYPE_URI); - g_value_take_boxed(&val, uri); - - g_object_set_property(G_OBJECT(priv->soup_session),SOUP_SESSION_PROXY_URI,&val); -#else - SoupUri* uri = soup_uri_new(priv->proxy_uri); - g_object_set(G_OBJECT(priv->soup_session), SOUP_SESSION_PROXY_URI, uri, NULL); -#endif - } else - priv->proxy_uri = NULL; - - break; - case PROP_TILE_CACHE_DIR: - if ( g_value_get_string(value) ) - priv->cache_dir = g_value_dup_string (value); - break; - case PROP_TILE_CACHE_DIR_IS_FULL_PATH: - priv->cache_dir_is_full_path = g_value_get_boolean (value); - break; - case PROP_ZOOM: - priv->map_zoom = g_value_get_int (value); - break; - case PROP_MAX_ZOOM: - priv->max_zoom = g_value_get_int (value); - break; - case PROP_MIN_ZOOM: - priv->min_zoom = g_value_get_int (value); - break; - case PROP_MAP_X: - priv->map_x = g_value_get_int (value); - priv->center_coord_set = FALSE; - break; - case PROP_MAP_Y: - priv->map_y = g_value_get_int (value); - priv->center_coord_set = FALSE; - break; - case PROP_GPS_TRACK_WIDTH: - priv->ui_gps_track_width = g_value_get_int (value); - break; - case PROP_GPS_POINT_R1: - priv->ui_gps_point_inner_radius = g_value_get_int (value); - break; - case PROP_GPS_POINT_R2: - priv->ui_gps_point_outer_radius = g_value_get_int (value); - break; - case PROP_MAP_SOURCE: - priv->map_source = g_value_get_int (value); - break; - case PROP_IMAGE_FORMAT: - priv->image_format = g_value_dup_string (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -osm_gps_map_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - g_return_if_fail (OSM_IS_GPS_MAP (object)); - float lat,lon; - OsmGpsMap *map = OSM_GPS_MAP(object); - OsmGpsMapPrivate *priv = map->priv; - - switch (prop_id) - { - case PROP_AUTO_CENTER: - g_value_set_boolean(value, priv->map_auto_center); - break; - case PROP_RECORD_TRIP_HISTORY: - g_value_set_boolean(value, priv->record_trip_history); - break; - case PROP_SHOW_TRIP_HISTORY: - g_value_set_boolean(value, priv->show_trip_history); - break; - case PROP_AUTO_DOWNLOAD: - g_value_set_boolean(value, priv->map_auto_download); - break; - case PROP_REPO_URI: - g_value_set_string(value, priv->repo_uri); - break; - case PROP_PROXY_URI: - g_value_set_string(value, priv->proxy_uri); - break; - case PROP_TILE_CACHE_DIR: - g_value_set_string(value, priv->cache_dir); - break; - case PROP_TILE_CACHE_DIR_IS_FULL_PATH: - g_value_set_boolean(value, priv->cache_dir_is_full_path); - break; - case PROP_ZOOM: - g_value_set_int(value, priv->map_zoom); - break; - case PROP_MAX_ZOOM: - g_value_set_int(value, priv->max_zoom); - break; - case PROP_MIN_ZOOM: - g_value_set_int(value, priv->min_zoom); - break; - case PROP_LATITUDE: - lat = pixel2lat(priv->map_zoom, - priv->map_y + (GTK_WIDGET(map)->allocation.height / 2)); - g_value_set_float(value, rad2deg(lat)); - break; - case PROP_LONGITUDE: - lon = pixel2lon(priv->map_zoom, - priv->map_x + (GTK_WIDGET(map)->allocation.width / 2)); - g_value_set_float(value, rad2deg(lon)); - break; - case PROP_MAP_X: - g_value_set_int(value, priv->map_x); - break; - case PROP_MAP_Y: - g_value_set_int(value, priv->map_y); - break; - case PROP_TILES_QUEUED: - g_value_set_int(value, g_hash_table_size(priv->tile_queue)); - break; - case PROP_GPS_TRACK_WIDTH: - g_value_set_int(value, priv->ui_gps_track_width); - break; - case PROP_GPS_POINT_R1: - g_value_set_int(value, priv->ui_gps_point_inner_radius); - break; - case PROP_GPS_POINT_R2: - g_value_set_int(value, priv->ui_gps_point_outer_radius); - break; - case PROP_MAP_SOURCE: - g_value_set_int(value, priv->map_source); - break; - case PROP_IMAGE_FORMAT: - g_value_set_string(value, priv->image_format); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static gboolean -osm_gps_map_scroll_event (GtkWidget *widget, GdkEventScroll *event) -{ - OsmGpsMap *map = OSM_GPS_MAP(widget); - OsmGpsMapPrivate *priv = map->priv; - - if (event->direction == GDK_SCROLL_UP) - { - osm_gps_map_set_zoom(map, priv->map_zoom+1); - } - else - { - osm_gps_map_set_zoom(map, priv->map_zoom-1); - } - - return FALSE; -} - -static gboolean -osm_gps_map_button_press (GtkWidget *widget, GdkEventButton *event) -{ - OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget); - -#ifdef ENABLE_BALLOON - /* don't drag if the user clicked within the balloon */ - if (osm_gps_map_in_balloon(priv, - event->x + EXTRA_BORDER, - event->y + EXTRA_BORDER)) - { - priv->drag_counter = -1; - return FALSE; - } -#endif - -#ifdef ENABLE_OSD - #define SCROLL_STEP 10 - - /* pressed inside OSD control? */ - osd_button_t but = osm_gps_map_osd_check(event->x, event->y); - if(but != OSD_NONE) - { - priv->drag_counter = -1; - - switch(but) { - case OSD_GPS: - priv->osd.cb(priv->osd.data); - break; - - case OSD_UP: - priv->map_y -= GTK_WIDGET(widget)->allocation.height/SCROLL_STEP; - priv->center_coord_set = FALSE; - break; - - case OSD_DOWN: - priv->map_y += GTK_WIDGET(widget)->allocation.height/SCROLL_STEP; - priv->center_coord_set = FALSE; - break; - - case OSD_LEFT: - priv->map_x -= GTK_WIDGET(widget)->allocation.width/SCROLL_STEP; - priv->center_coord_set = FALSE; - break; - - case OSD_RIGHT: - priv->map_x += GTK_WIDGET(widget)->allocation.width/SCROLL_STEP; - priv->center_coord_set = FALSE; - break; - - case OSD_IN: - osm_gps_map_set_zoom(OSM_GPS_MAP(widget), priv->map_zoom+1); - break; - - case OSD_OUT: - osm_gps_map_set_zoom(OSM_GPS_MAP(widget), priv->map_zoom-1); - break; - - default: - break; - } - - osm_gps_map_map_redraw_idle(OSM_GPS_MAP(widget)); - - return FALSE; - } -#endif - - priv->drag_counter = 0; - priv->drag_start_mouse_x = (int) event->x; - priv->drag_start_mouse_y = (int) event->y; - priv->drag_start_map_x = priv->map_x; - priv->drag_start_map_y = priv->map_y; - - return FALSE; -} - -static gboolean -osm_gps_map_button_release (GtkWidget *widget, GdkEventButton *event) -{ - OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget); - -#ifdef ENABLE_BALLOON - /* released inside the balloon? */ - if (osm_gps_map_in_balloon(priv, - event->x + EXTRA_BORDER, - event->y + EXTRA_BORDER)) - { - osm_gps_map_handle_balloon_click(OSM_GPS_MAP(widget), - event->x - priv->balloon.rect.x + EXTRA_BORDER, - event->y - priv->balloon.rect.y + EXTRA_BORDER); - } -#endif - - if (priv->dragging) - { - priv->dragging = FALSE; - - priv->map_x = priv->drag_start_map_x; - priv->map_y = priv->drag_start_map_y; - - priv->map_x += (priv->drag_start_mouse_x - (int) event->x); - priv->map_y += (priv->drag_start_mouse_y - (int) event->y); - - priv->center_coord_set = FALSE; - - osm_gps_map_map_redraw_idle(OSM_GPS_MAP(widget)); - } - - priv->drag_mouse_dx = 0; - priv->drag_mouse_dy = 0; - priv->drag_counter = -1; - - return FALSE; -} - -static gboolean -osm_gps_map_expose (GtkWidget *widget, GdkEventExpose *event); - -static gboolean -osm_gps_map_motion_notify (GtkWidget *widget, GdkEventMotion *event) -{ - int x, y; - GdkModifierType state; - OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget); - - if (event->is_hint) - gdk_window_get_pointer (event->window, &x, &y, &state); - else - { - x = event->x; - y = event->y; - state = event->state; - } - - // are we being dragged - if (!(state & GDK_BUTTON1_MASK)) - return FALSE; - - if (priv->drag_counter < 0) - return FALSE; - - priv->drag_counter++; - - // we havent dragged more than 6 pixels - if (priv->drag_counter < 6) - return FALSE; - -#ifdef USE_MAEMO - /* reduce update frequency on maemo to keep screen update fluid */ - static guint32 last_time = 0; - - if(event->time - last_time < 100) return FALSE; - last_time = event->time; -#endif - - priv->dragging = TRUE; - - if (priv->map_auto_center) - g_object_set(G_OBJECT(widget), "auto-center", FALSE, NULL); - - priv->drag_mouse_dx = x - priv->drag_start_mouse_x; - priv->drag_mouse_dy = y - priv->drag_start_mouse_y; - -#ifdef ENABLE_OSD - /* undo OSD */ - osm_gps_map_osd_restore (OSM_GPS_MAP(widget)); - - /* draw new OSD */ - osm_gps_map_osd_draw_controls (OSM_GPS_MAP(widget), - -priv->drag_mouse_dx, - -priv->drag_mouse_dy); -#endif - - osm_gps_map_expose (widget, NULL); - - - return FALSE; -} - -static gboolean -osm_gps_map_configure (GtkWidget *widget, GdkEventConfigure *event) -{ - OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget); - - /* create pixmap */ - if (priv->pixmap) - g_object_unref (priv->pixmap); - - priv->pixmap = gdk_pixmap_new ( - widget->window, - widget->allocation.width + EXTRA_BORDER * 2, - widget->allocation.height + EXTRA_BORDER * 2, - -1); - - /* and gc, used for clipping (I think......) */ - if(priv->gc_map) - g_object_unref(priv->gc_map); - - priv->gc_map = gdk_gc_new(priv->pixmap); - - osm_gps_map_map_redraw(OSM_GPS_MAP(widget)); - - return FALSE; -} - -static gboolean -osm_gps_map_expose (GtkWidget *widget, GdkEventExpose *event) -{ - OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget); - - gdk_draw_drawable ( - widget->window, - widget->style->fg_gc[GTK_WIDGET_STATE (widget)], - priv->pixmap, - 0,0, - priv->drag_mouse_dx - EXTRA_BORDER, - priv->drag_mouse_dy - EXTRA_BORDER, - -1,-1); - - //Paint white outside of the map if dragging. Its less - //ugly than painting the corrupted map - if(priv->drag_mouse_dx>EXTRA_BORDER) { - gdk_draw_rectangle ( - widget->window, - widget->style->white_gc, - TRUE, - 0, 0, - priv->drag_mouse_dx - EXTRA_BORDER, - widget->allocation.height); - } - else if (-priv->drag_mouse_dx > EXTRA_BORDER) - { - gdk_draw_rectangle ( - widget->window, - widget->style->white_gc, - TRUE, - priv->drag_mouse_dx + widget->allocation.width + EXTRA_BORDER, 0, - -priv->drag_mouse_dx - EXTRA_BORDER, - widget->allocation.height); - } - - if (priv->drag_mouse_dy>EXTRA_BORDER) { - gdk_draw_rectangle ( - widget->window, - widget->style->white_gc, - TRUE, - 0, 0, - widget->allocation.width, - priv->drag_mouse_dy - EXTRA_BORDER); - } - else if (-priv->drag_mouse_dy > EXTRA_BORDER) - { - gdk_draw_rectangle ( - widget->window, - widget->style->white_gc, - TRUE, - 0, priv->drag_mouse_dy + widget->allocation.height + EXTRA_BORDER, - widget->allocation.width, - -priv->drag_mouse_dy - EXTRA_BORDER); - } -#if 0 - if(!priv->dragging) - gdk_draw_drawable ( - widget->window, - widget->style->fg_gc[GTK_WIDGET_STATE (widget)], - priv->pixmap, - event->area.x + EXTRA_BORDER, - event->area.y + EXTRA_BORDER, - event->area.x, event->area.y, - event->area.width, event->area.height); -#endif - return FALSE; -} - -static void -osm_gps_map_class_init (OsmGpsMapClass *klass) -{ - GObjectClass* object_class = G_OBJECT_CLASS (klass); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); - - g_type_class_add_private (klass, sizeof (OsmGpsMapPrivate)); - - object_class->dispose = osm_gps_map_dispose; - object_class->finalize = osm_gps_map_finalize; - object_class->constructor = osm_gps_map_constructor; - object_class->set_property = osm_gps_map_set_property; - object_class->get_property = osm_gps_map_get_property; - - widget_class->expose_event = osm_gps_map_expose; - widget_class->configure_event = osm_gps_map_configure; - widget_class->button_press_event = osm_gps_map_button_press; - widget_class->button_release_event = osm_gps_map_button_release; - widget_class->motion_notify_event = osm_gps_map_motion_notify; - widget_class->scroll_event = osm_gps_map_scroll_event; - - g_object_class_install_property (object_class, - PROP_AUTO_CENTER, - g_param_spec_boolean ("auto-center", - "auto center", - "map auto center", - TRUE, - G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_RECORD_TRIP_HISTORY, - g_param_spec_boolean ("record-trip-history", - "record trip history", - "should all gps points be recorded in a trip history", - TRUE, - G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_SHOW_TRIP_HISTORY, - g_param_spec_boolean ("show-trip-history", - "show trip history", - "should the recorded trip history be shown on the map", - TRUE, - G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_AUTO_DOWNLOAD, - g_param_spec_boolean ("auto-download", - "auto download", - "map auto download", - TRUE, - G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_REPO_URI, - g_param_spec_string ("repo-uri", - "repo uri", - "map source tile repository uri", - OSM_REPO_URI, - G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property (object_class, - PROP_PROXY_URI, - g_param_spec_string ("proxy-uri", - "proxy uri", - "http proxy uri on NULL", - NULL, - G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property (object_class, - PROP_TILE_CACHE_DIR, - g_param_spec_string ("tile-cache", - "tile cache", - "osm local tile cache dir", - NULL, - G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property (object_class, - PROP_TILE_CACHE_DIR_IS_FULL_PATH, - g_param_spec_boolean ("tile-cache-is-full-path", - "tile cache is full path", - "if true, the path passed to tile-cache is interpreted as the full cache path", - FALSE, - G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property (object_class, - PROP_ZOOM, - g_param_spec_int ("zoom", - "zoom", - "zoom level", - MIN_ZOOM, /* minimum property value */ - MAX_ZOOM, /* maximum property value */ - 3, - G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property (object_class, - PROP_MAX_ZOOM, - g_param_spec_int ("max-zoom", - "max zoom", - "maximum zoom level", - MIN_ZOOM, /* minimum property value */ - MAX_ZOOM, /* maximum property value */ - OSM_MAX_ZOOM, - G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property (object_class, - PROP_MIN_ZOOM, - g_param_spec_int ("min-zoom", - "min zoom", - "minimum zoom level", - MIN_ZOOM, /* minimum property value */ - MAX_ZOOM, /* maximum property value */ - OSM_MIN_ZOOM, - G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property (object_class, - PROP_LATITUDE, - g_param_spec_float ("latitude", - "latitude", - "latitude in degrees", - -90.0, /* minimum property value */ - 90.0, /* maximum property value */ - 0, - G_PARAM_READABLE)); - - g_object_class_install_property (object_class, - PROP_LONGITUDE, - g_param_spec_float ("longitude", - "longitude", - "longitude in degrees", - -180.0, /* minimum property value */ - 180.0, /* maximum property value */ - 0, - G_PARAM_READABLE)); - - g_object_class_install_property (object_class, - PROP_MAP_X, - g_param_spec_int ("map-x", - "map-x", - "initial map x location", - G_MININT, /* minimum property value */ - G_MAXINT, /* maximum property value */ - 890, - G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property (object_class, - PROP_MAP_Y, - g_param_spec_int ("map-y", - "map-y", - "initial map y location", - G_MININT, /* minimum property value */ - G_MAXINT, /* maximum property value */ - 515, - G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property (object_class, - PROP_TILES_QUEUED, - g_param_spec_int ("tiles-queued", - "tiles-queued", - "number of tiles currently waiting to download", - G_MININT, /* minimum property value */ - G_MAXINT, /* maximum property value */ - 0, - G_PARAM_READABLE)); - - g_object_class_install_property (object_class, - PROP_GPS_TRACK_WIDTH, - g_param_spec_int ("gps-track-width", - "gps-track-width", - "width of the lines drawn for the gps track", - 1, /* minimum property value */ - G_MAXINT, /* maximum property value */ - 4, - G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_GPS_POINT_R1, - g_param_spec_int ("gps-track-point-radius", - "gps-track-point-radius", - "radius of the gps point inner circle", - 0, /* minimum property value */ - G_MAXINT, /* maximum property value */ - 10, - G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_GPS_POINT_R2, - g_param_spec_int ("gps-track-highlight-radius", - "gps-track-highlight-radius", - "radius of the gps point highlight circle", - 0, /* minimum property value */ - G_MAXINT, /* maximum property value */ - 20, - G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); - - g_object_class_install_property (object_class, - PROP_MAP_SOURCE, - g_param_spec_int ("map-source", - "map source", - "map source ID", - -1, /* minimum property value */ - G_MAXINT, /* maximum property value */ - -1, - G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property (object_class, - PROP_IMAGE_FORMAT, - g_param_spec_string ("image-format", - "image format", - "map source tile repository image format (jpg, png)", - OSM_IMAGE_FORMAT, - G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); -} - -const char* -osm_gps_map_source_get_friendly_name(OsmGpsMapSource_t source) -{ - switch(source) - { - case OSM_GPS_MAP_SOURCE_NULL: - return "None"; - case OSM_GPS_MAP_SOURCE_OPENSTREETMAP: - return "OpenStreetMap"; - case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER: - return "OpenStreetMap Renderer"; - case OSM_GPS_MAP_SOURCE_OPENAERIALMAP: - return "OpenAerialMap"; - case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE: - return "Maps-For-Free"; - case OSM_GPS_MAP_SOURCE_GOOGLE_STREET: - return "Google Maps"; - case OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE: - return "Google Satellite"; - case OSM_GPS_MAP_SOURCE_GOOGLE_HYBRID: - return "Google Hybrid"; - case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_STREET: - return "Virtual Earth"; - case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_SATELLITE: - return "Virtual Earth Satellite"; - case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_HYBRID: - return "Virtual Earth Hybrid"; - case OSM_GPS_MAP_SOURCE_YAHOO_STREET: - return "Yahoo Maps"; - case OSM_GPS_MAP_SOURCE_YAHOO_SATELLITE: - return "Yahoo Satellite"; - case OSM_GPS_MAP_SOURCE_YAHOO_HYBRID: - return "Yahoo Hybrid"; - default: - return NULL; - } - return NULL; -} - -//http://www.internettablettalk.com/forums/showthread.php?t=5209 -//https://garage.maemo.org/plugins/scmsvn/viewcvs.php/trunk/src/maps.c?root=maemo-mapper&view=markup -//http://www.ponies.me.uk/maps/GoogleTileUtils.java -//http://www.mgmaps.com/cache/MapTileCacher.perl -const char* -osm_gps_map_source_get_repo_uri(OsmGpsMapSource_t source) -{ - switch(source) - { - case OSM_GPS_MAP_SOURCE_NULL: - return "none://"; - case OSM_GPS_MAP_SOURCE_OPENSTREETMAP: - return OSM_REPO_URI; - case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER: - return "http://tah.openstreetmap.org/Tiles/tile/#Z/#X/#Y.png"; - case OSM_GPS_MAP_SOURCE_OPENAERIALMAP: - return "http://tile.openaerialmap.org/tiles/1.0.0/openaerialmap-900913/#Z/#X/#Y.jpg"; - case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE: - return "http://maps-for-free.com/layer/relief/z#Z/row#Y/#Z_#X-#Y.jpg"; - case OSM_GPS_MAP_SOURCE_GOOGLE_STREET: - return "http://mt#R.google.com/vt/v=w2.97&x=#X&y=#Y&z=#Z"; - case OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE: - return "http://khm#R.google.com/kh?n=404&v=3&t=#Q"; - case OSM_GPS_MAP_SOURCE_GOOGLE_HYBRID: - return NULL; /* No longer working "http://mt#R.google.com/mt?n=404&v=w2t.99&x=#X&y=#Y&zoom=#S" */ - case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_STREET: - return "http://a#R.ortho.tiles.virtualearth.net/tiles/r#W.jpeg?g=50"; - case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_SATELLITE: - return "http://a#R.ortho.tiles.virtualearth.net/tiles/a#W.jpeg?g=50"; - case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_HYBRID: - return "http://a#R.ortho.tiles.virtualearth.net/tiles/h#W.jpeg?g=50"; - case OSM_GPS_MAP_SOURCE_YAHOO_STREET: - case OSM_GPS_MAP_SOURCE_YAHOO_SATELLITE: - case OSM_GPS_MAP_SOURCE_YAHOO_HYBRID: - /* TODO: Implement signed Y, aka U - * http://us.maps3.yimg.com/aerial.maps.yimg.com/ximg?v=1.7&t=a&s=256&x=%d&y=%-d&z=%d - * x = tilex, - * y = (1 << (MAX_ZOOM - zoom)) - tiley - 1, - * z = zoom - (MAX_ZOOM - 17)); - */ - return NULL; - default: - return NULL; - } - return NULL; -} - -const char * -osm_gps_map_source_get_image_format(OsmGpsMapSource_t source) -{ - switch(source) { - case OSM_GPS_MAP_SOURCE_NULL: - case OSM_GPS_MAP_SOURCE_OPENSTREETMAP: - case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER: - return "png"; - case OSM_GPS_MAP_SOURCE_OPENAERIALMAP: - case OSM_GPS_MAP_SOURCE_GOOGLE_STREET: - case OSM_GPS_MAP_SOURCE_GOOGLE_HYBRID: - case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_STREET: - case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_SATELLITE: - case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_HYBRID: - case OSM_GPS_MAP_SOURCE_YAHOO_STREET: - case OSM_GPS_MAP_SOURCE_YAHOO_SATELLITE: - case OSM_GPS_MAP_SOURCE_YAHOO_HYBRID: - case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE: - case OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE: - return "jpg"; - default: - return "bin"; - } - return "bin"; -} - - -int -osm_gps_map_source_get_min_zoom(OsmGpsMapSource_t source) -{ - return 1; -} - -int -osm_gps_map_source_get_max_zoom(OsmGpsMapSource_t source) -{ - switch(source) { - case OSM_GPS_MAP_SOURCE_NULL: - return 18; - case OSM_GPS_MAP_SOURCE_OPENSTREETMAP: - return OSM_MAX_ZOOM; - case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER: - case OSM_GPS_MAP_SOURCE_OPENAERIALMAP: - case OSM_GPS_MAP_SOURCE_GOOGLE_STREET: - case OSM_GPS_MAP_SOURCE_GOOGLE_HYBRID: - case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_STREET: - case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_SATELLITE: - case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_HYBRID: - case OSM_GPS_MAP_SOURCE_YAHOO_STREET: - case OSM_GPS_MAP_SOURCE_YAHOO_SATELLITE: - case OSM_GPS_MAP_SOURCE_YAHOO_HYBRID: - return 17; - case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE: - return 11; - case OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE: - return 18; - default: - return 17; - } - return 17; -} - -void -osm_gps_map_download_maps (OsmGpsMap *map, coord_t *pt1, coord_t *pt2, int zoom_start, int zoom_end) -{ - int i,j,zoom,num_tiles; - OsmGpsMapPrivate *priv = map->priv; - - if (pt1 && pt2) - { - gchar *filename; - num_tiles = 0; - zoom_end = CLAMP(zoom_end, priv->min_zoom, priv->max_zoom); - g_debug("Download maps: z:%d->%d",zoom_start, zoom_end); - - for(zoom=zoom_start; zoom<=zoom_end; zoom++) - { - int x1,y1,x2,y2; - - x1 = (int)floor((float)lon2pixel(zoom, pt1->rlon) / (float)TILESIZE); - y1 = (int)floor((float)lat2pixel(zoom, pt1->rlat) / (float)TILESIZE); - - x2 = (int)floor((float)lon2pixel(zoom, pt2->rlon) / (float)TILESIZE); - y2 = (int)floor((float)lat2pixel(zoom, pt2->rlat) / (float)TILESIZE); - - // loop x1-x2 - for(i=x1; i<=x2; i++) - { - // loop y1 - y2 - for(j=y1; j<=y2; j++) - { - // x = i, y = j - filename = g_strdup_printf("%s%c%d%c%d%c%d.%s", - priv->cache_dir, G_DIR_SEPARATOR, - zoom, G_DIR_SEPARATOR, - i, G_DIR_SEPARATOR, - j, - priv->image_format); - if (!g_file_test(filename, G_FILE_TEST_EXISTS)) - { - osm_gps_map_download_tile(map, zoom, i, j, FALSE); - num_tiles++; - } - g_free(filename); - } - } - g_debug("DL @Z:%d = %d tiles",zoom,num_tiles); - } - } -} - -void -osm_gps_map_get_bbox (OsmGpsMap *map, coord_t *pt1, coord_t *pt2) -{ - OsmGpsMapPrivate *priv = map->priv; - - if (pt1 && pt2) { - pt1->rlat = pixel2lat(priv->map_zoom, priv->map_y); - pt1->rlon = pixel2lon(priv->map_zoom, priv->map_x); - pt2->rlat = pixel2lat(priv->map_zoom, priv->map_y + GTK_WIDGET(map)->allocation.height); - pt2->rlon = pixel2lon(priv->map_zoom, priv->map_x + GTK_WIDGET(map)->allocation.width); - - g_debug("BBOX: %f %f %f %f", pt1->rlat, pt1->rlon, pt2->rlat, pt2->rlon); - } -} - -void -osm_gps_map_set_mapcenter (OsmGpsMap *map, float latitude, float longitude, int zoom) -{ - osm_gps_map_set_center (map, latitude, longitude); - osm_gps_map_set_zoom (map, zoom); -} - -void -osm_gps_map_set_center (OsmGpsMap *map, float latitude, float longitude) -{ - int pixel_x, pixel_y; - OsmGpsMapPrivate *priv; - - g_return_if_fail (OSM_IS_GPS_MAP (map)); - priv = map->priv; - - priv->center_rlat = deg2rad(latitude); - priv->center_rlon = deg2rad(longitude); - priv->center_coord_set = TRUE; - - // pixel_x,y, offsets - pixel_x = lon2pixel(priv->map_zoom, priv->center_rlon); - pixel_y = lat2pixel(priv->map_zoom, priv->center_rlat); - - priv->map_x = pixel_x - GTK_WIDGET(map)->allocation.width/2; - priv->map_y = pixel_y - GTK_WIDGET(map)->allocation.height/2; - - osm_gps_map_map_redraw_idle(map); -} - -int -osm_gps_map_set_zoom (OsmGpsMap *map, int zoom) -{ - int zoom_old; - double factor = 0.0; - int width_center, height_center; - OsmGpsMapPrivate *priv; - - g_return_val_if_fail (OSM_IS_GPS_MAP (map), 0); - priv = map->priv; - - if (zoom != priv->map_zoom) - { - width_center = GTK_WIDGET(map)->allocation.width / 2; - height_center = GTK_WIDGET(map)->allocation.height / 2; - - zoom_old = priv->map_zoom; - //constrain zoom min_zoom -> max_zoom - priv->map_zoom = CLAMP(zoom, priv->min_zoom, priv->max_zoom); - - if (priv->center_coord_set) - { - priv->map_x = lon2pixel(priv->map_zoom, priv->center_rlon) - width_center; - priv->map_y = lat2pixel(priv->map_zoom, priv->center_rlat) - height_center; - } - else - { - factor = exp(priv->map_zoom * M_LN2)/exp(zoom_old * M_LN2); - priv->map_x = ((priv->map_x + width_center) * factor) - width_center; - priv->map_y = ((priv->map_y + height_center) * factor) - height_center; - } - - g_debug("Zoom changed from %d to %d factor:%f x:%d", - zoom_old, priv->map_zoom, factor, priv->map_x); - - osm_gps_map_map_redraw_idle(map); - } - return priv->map_zoom; -} - -void -osm_gps_map_add_track (OsmGpsMap *map, GSList *track) -{ - OsmGpsMapPrivate *priv; - - g_return_if_fail (OSM_IS_GPS_MAP (map)); - priv = map->priv; - - if (track) { - priv->tracks = g_slist_append(priv->tracks, track); - osm_gps_map_map_redraw_idle(map); - } -} - -void -osm_gps_map_clear_tracks (OsmGpsMap *map) -{ - g_return_if_fail (OSM_IS_GPS_MAP (map)); - - osm_gps_map_free_tracks(map); - osm_gps_map_map_redraw_idle(map); -} - -void -osm_gps_map_add_image (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image) -{ - g_return_if_fail (OSM_IS_GPS_MAP (map)); - - if (image) { - OsmGpsMapPrivate *priv = map->priv; - image_t *im; - - //cache w/h for speed, and add image to list - im = g_new0(image_t,1); - im->w = gdk_pixbuf_get_width(image); - im->h = gdk_pixbuf_get_height(image); - im->pt.rlat = deg2rad(latitude); - im->pt.rlon = deg2rad(longitude); - - g_object_ref(image); - im->image = image; - - priv->images = g_slist_append(priv->images, im); - - osm_gps_map_map_redraw_idle(map); - } -} - -gboolean -osm_gps_map_remove_image (OsmGpsMap *map, GdkPixbuf *image) -{ - OsmGpsMapPrivate *priv = map->priv; - if (priv->images) { - GSList *list; - for(list = priv->images; list != NULL; list = list->next) - { - image_t *im = list->data; - if (im->image == image) - { - priv->images = g_slist_remove_link(priv->images, list); - g_object_unref(im->image); - g_free(im); - osm_gps_map_map_redraw_idle(map); - return TRUE; - } - } - } - return FALSE; -} - -void -osm_gps_map_clear_images (OsmGpsMap *map) -{ - g_return_if_fail (OSM_IS_GPS_MAP (map)); - - osm_gps_map_free_images(map); - osm_gps_map_map_redraw_idle(map); -} - -void -osm_gps_map_osd_speed (OsmGpsMap *map, float speed) -{ - OsmGpsMapPrivate *priv; - - PangoContext *context = NULL; - PangoLayout *layout = NULL; - PangoFontDescription *desc = NULL; - - GdkColor color; - GdkGC *gc; - - gchar *buffer; - //static int x = 10, y = 10; - static int width = 0, height = 0; - - g_return_if_fail (OSM_IS_GPS_MAP (map)); - priv = map->priv; - - buffer = g_strdup_printf("%.0f", speed); - - /* pango initialisation */ - context = gtk_widget_get_pango_context (GTK_WIDGET(map)); - layout = pango_layout_new (context); - desc = pango_font_description_new(); - - pango_font_description_set_size (desc, 40 * PANGO_SCALE); - pango_layout_set_font_description (layout, desc); - pango_layout_set_text (layout, buffer, strlen(buffer)); - - gc = gdk_gc_new (GTK_WIDGET(map)->window); - - color.red = (0 > 50) ? 0xffff : 0; - color.green = 0; - color.blue = 0; - - gdk_gc_set_rgb_fg_color (gc, &color); - - /* faster / less flicker alternative:*/ - gdk_draw_drawable ( - GTK_WIDGET(map)->window, - GTK_WIDGET(map)->style->fg_gc[GTK_WIDGET_STATE(map)], - priv->pixmap, - 0,0, - 0,0, - width+10,width+10); - - gdk_draw_layout(GTK_WIDGET(map)->window, - gc, - 0, 0, - layout); - - /* set width and height */ - pango_layout_get_pixel_size(layout, &width, &height); - - g_free(buffer); - pango_font_description_free (desc); - g_object_unref (layout); - g_object_unref (gc); -} - -void -osm_gps_map_draw_gps (OsmGpsMap *map, float latitude, float longitude, float heading) -{ - int pixel_x, pixel_y; - OsmGpsMapPrivate *priv; - - g_return_if_fail (OSM_IS_GPS_MAP (map)); - priv = map->priv; - - priv->gps->rlat = deg2rad(latitude); - priv->gps->rlon = deg2rad(longitude); - priv->gps_valid = TRUE; - - // pixel_x,y, offsets - pixel_x = lon2pixel(priv->map_zoom, priv->gps->rlon); - pixel_y = lat2pixel(priv->map_zoom, priv->gps->rlat); - - //If trip marker add to list of gps points. - if (priv->record_trip_history) { - coord_t *tp = g_new0(coord_t,1); - tp->rlat = priv->gps->rlat; - tp->rlon = priv->gps->rlon; - priv->trip_history = g_slist_append(priv->trip_history, tp); - } - - // dont draw anything if we are dragging - if (priv->dragging) { - g_debug("Dragging"); - return; - } - - //Automatically center the map if the track approaches the edge - if(priv->map_auto_center) { - int x = pixel_x - priv->map_x; - int y = pixel_y - priv->map_y; - int width = GTK_WIDGET(map)->allocation.width; - int height = GTK_WIDGET(map)->allocation.height; - if( x < (width/2 - width/8) || x > (width/2 + width/8) || - y < (height/2 - height/8) || y > (height/2 + height/8)) { - - priv->map_x = pixel_x - GTK_WIDGET(map)->allocation.width/2; - priv->map_y = pixel_y - GTK_WIDGET(map)->allocation.height/2; - priv->center_coord_set = FALSE; - } - } - - // this redraws the map (including the gps track, and adjusts the - // map center if it was changed - osm_gps_map_map_redraw_idle(map); -} - -void -osm_gps_map_clear_gps (OsmGpsMap *map) -{ - osm_gps_map_free_trip(map); - osm_gps_map_map_redraw_idle(map); -} - -coord_t -osm_gps_map_get_co_ordinates (OsmGpsMap *map, int pixel_x, int pixel_y) -{ - coord_t coord; - OsmGpsMapPrivate *priv = map->priv; - - coord.rlat = pixel2lat(priv->map_zoom, priv->map_y + pixel_y); - coord.rlon = pixel2lon(priv->map_zoom, priv->map_x + pixel_x); - return coord; -} - -GtkWidget * -osm_gps_map_new (void) -{ - return g_object_new (OSM_TYPE_GPS_MAP, NULL); -} - -void -osm_gps_map_screen_to_geographic (OsmGpsMap *map, gint pixel_x, gint pixel_y, - gfloat *latitude, gfloat *longitude) -{ - OsmGpsMapPrivate *priv; - - g_return_if_fail (OSM_IS_GPS_MAP (map)); - priv = map->priv; - - if (latitude) - *latitude = rad2deg(pixel2lat(priv->map_zoom, priv->map_y + pixel_y)); - if (longitude) - *longitude = rad2deg(pixel2lon(priv->map_zoom, priv->map_x + pixel_x)); -} - -void -osm_gps_map_geographic_to_screen (OsmGpsMap *map, - gfloat latitude, gfloat longitude, - gint *pixel_x, gint *pixel_y) -{ - OsmGpsMapPrivate *priv; - - g_return_if_fail (OSM_IS_GPS_MAP (map)); - priv = map->priv; - - if (pixel_x) - *pixel_x = lon2pixel(priv->map_zoom, deg2rad(longitude)) - priv->map_x; - if (pixel_y) - *pixel_y = lat2pixel(priv->map_zoom, deg2rad(latitude)) - priv->map_y; -} - -void -osm_gps_map_scroll (OsmGpsMap *map, gint dx, gint dy) -{ - OsmGpsMapPrivate *priv; - - g_return_if_fail (OSM_IS_GPS_MAP (map)); - priv = map->priv; - - priv->center_coord_set = FALSE; - priv->map_x += dx; - priv->map_y += dy; - - osm_gps_map_map_redraw_idle (map); -} - -float -osm_gps_map_get_scale(OsmGpsMap *map) -{ - OsmGpsMapPrivate *priv; - - g_return_val_if_fail (OSM_IS_GPS_MAP (map), OSM_NAN); - priv = map->priv; - - return osm_gps_map_get_scale_at_point(priv->map_zoom, priv->center_rlat, priv->center_rlon); -} - -#ifdef ENABLE_BALLOON -void -osm_gps_map_draw_balloon (OsmGpsMap *map, float latitude, float longitude, - OsmGpsMapBalloonCallback cb, gpointer data) -{ - OsmGpsMapPrivate *priv; - - /* remove and previously installed balloon */ - osm_gps_map_clear_balloon (map); - - g_return_if_fail (OSM_IS_GPS_MAP (map)); - priv = map->priv; - - priv->balloon.coo->rlat = deg2rad(latitude); - priv->balloon.coo->rlon = deg2rad(longitude); - priv->balloon.valid = TRUE; - - priv->balloon.cb = cb; - priv->balloon.data = data; - - // this redraws the map - osm_gps_map_map_redraw_idle(map); -} - -void -osm_gps_map_clear_balloon (OsmGpsMap *map) +static void +osm_gps_map_osd_enable_gps (OsmGpsMap *map, OsmGpsMapOsdGpsCallback cb, gpointer data) { OsmGpsMapPrivate *priv; g_return_if_fail (OSM_IS_GPS_MAP (map)); priv = map->priv; - priv->balloon.valid = FALSE; - - osm_gps_map_map_redraw_idle(map); -} -#endif - -#ifdef ENABLE_OSD -void osm_gps_map_osd_enable_gps (OsmGpsMap *map, OsmGpsMapOsdGpsCallback cb, gpointer data) { - OsmGpsMapPrivate *priv; - - g_return_if_fail (OSM_IS_GPS_MAP (map)); - priv = map->priv; - priv->osd.cb = cb; priv->osd.data = data; @@ -1937,4 +423,3 @@ osm_gps_map_map_redraw_idle(map); } -#endif