X-Git-Url: https://git.street.me.uk/andy/viking.git/blobdiff_plain/6579ca1f1ab83925efad84c52a70b839c4a57153..778f41c5f8072cef5f865534cb75bd346f5c68f5:/src/viktrwlayer.c diff --git a/src/viktrwlayer.c b/src/viktrwlayer.c index 4a05cc18..60082ce5 100644 --- a/src/viktrwlayer.c +++ b/src/viktrwlayer.c @@ -80,7 +80,14 @@ static gboolean return_true (gpointer a, gpointer b, gpointer c) { return TRUE; static g_hash_table_remove_all (GHashTable *ght) { g_hash_table_foreach_remove ( ght, (GHRFunc) return_true, FALSE ); } #endif +#ifdef VIK_CONFIG_GOOGLE_DIRECTIONS +// This is currently broken as Google have disabled the KML output in Google Maps API v3 +// It has been ifdefed out in the hope that Route Finding functionality will be restored one day... +// Only have 'JSON' and 'XML' see: +// https://developers.google.com/maps/documentation/directions/#DirectionsResponses #define GOOGLE_DIRECTIONS_STRING "maps.google.com/maps?q=from:%s,%s+to:%s,%s&output=kml" +#endif + #define VIK_TRW_LAYER_TRACK_GC 16 #define VIK_TRW_LAYER_TRACK_GC_RATES 10 #define VIK_TRW_LAYER_TRACK_GC_MIN 0 @@ -135,6 +142,9 @@ struct _VikTrwLayer { gdouble track_draw_speed_factor; GArray *track_gc; GdkGC *current_track_gc; + // Separate GC for a track's potential new point as drawn via separate method + // (compared to the actual track points drawn in the main trw_layer_draw_track function) + GdkGC *current_track_newpoint_gc; GdkGC *track_bg_gc; GdkGC *waypoint_gc; GdkGC *waypoint_text_gc; @@ -142,8 +152,8 @@ struct _VikTrwLayer { GdkFont *waypoint_font; VikTrack *current_track; guint16 ct_x1, ct_y1, ct_x2, ct_y2; - gboolean ct_sync_done; - + gboolean draw_sync_done; + gboolean draw_sync_do; VikCoordMode coord_mode; @@ -231,6 +241,7 @@ static void trw_layer_goto_track_max_speed ( gpointer pass_along[6] ); static void trw_layer_goto_track_max_alt ( gpointer pass_along[6] ); static void trw_layer_goto_track_min_alt ( gpointer pass_along[6] ); static void trw_layer_goto_track_center ( gpointer pass_along[6] ); +static void trw_layer_merge_by_segment ( gpointer pass_along[6] ); static void trw_layer_merge_by_timestamp ( gpointer pass_along[6] ); static void trw_layer_merge_with_other ( gpointer pass_along[6] ); static void trw_layer_append_track ( gpointer pass_along[6] ); @@ -305,12 +316,14 @@ static gboolean tool_begin_track_click ( VikTrwLayer *vtl, GdkEventButton *event static gpointer tool_new_track_create ( VikWindow *vw, VikViewport *vvp); static gboolean tool_new_track_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ); static VikLayerToolFuncStatus tool_new_track_move ( VikTrwLayer *vtl, GdkEventMotion *event, VikViewport *vvp ); +static void tool_new_track_release ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ); static gboolean tool_new_track_key_press ( VikTrwLayer *vtl, GdkEventKey *event, VikViewport *vvp ); static gpointer tool_new_waypoint_create ( VikWindow *vw, VikViewport *vvp); static gboolean tool_new_waypoint_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ); +#ifdef VIK_CONFIG_GOOGLE_DIRECTIONS static gpointer tool_route_finder_create ( VikWindow *vw, VikViewport *vvp); static gboolean tool_route_finder_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ); - +#endif static void cached_pixbuf_free ( CachedPixbuf *cp ); static gint cached_pixbuf_cmp ( CachedPixbuf *cp, const gchar *name ); @@ -335,36 +348,54 @@ static void highest_wp_number_remove_wp(VikTrwLayer *vtl, const gchar *old_wp_na static VikToolInterface trw_layer_tools[] = { { { "CreateWaypoint", "vik-icon-Create Waypoint", N_("Create _Waypoint"), "W", N_("Create Waypoint"), 0 }, (VikToolConstructorFunc) tool_new_waypoint_create, NULL, NULL, NULL, - (VikToolMouseFunc) tool_new_waypoint_click, NULL, NULL, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_addwp_pixbuf }, + (VikToolMouseFunc) tool_new_waypoint_click, NULL, NULL, (VikToolKeyFunc) NULL, + FALSE, + GDK_CURSOR_IS_PIXMAP, &cursor_addwp_pixbuf }, { { "CreateTrack", "vik-icon-Create Track", N_("Create _Track"), "T", N_("Create Track"), 0 }, (VikToolConstructorFunc) tool_new_track_create, NULL, NULL, NULL, - (VikToolMouseFunc) tool_new_track_click, (VikToolMouseMoveFunc) tool_new_track_move, NULL, - (VikToolKeyFunc) tool_new_track_key_press, GDK_CURSOR_IS_PIXMAP, &cursor_addtr_pixbuf }, + (VikToolMouseFunc) tool_new_track_click, + (VikToolMouseMoveFunc) tool_new_track_move, + (VikToolMouseFunc) tool_new_track_release, + (VikToolKeyFunc) tool_new_track_key_press, + TRUE, // Still need to handle clicks when in PAN mode to disable the potential trackpoint drawing + GDK_CURSOR_IS_PIXMAP, &cursor_addtr_pixbuf }, { { "BeginTrack", "vik-icon-Begin Track", N_("_Begin Track"), "B", N_("Begin Track"), 0 }, (VikToolConstructorFunc) tool_begin_track_create, NULL, NULL, NULL, - (VikToolMouseFunc) tool_begin_track_click, NULL, NULL, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_begintr_pixbuf }, + (VikToolMouseFunc) tool_begin_track_click, NULL, NULL, (VikToolKeyFunc) NULL, + FALSE, + GDK_CURSOR_IS_PIXMAP, &cursor_begintr_pixbuf }, { { "EditWaypoint", "vik-icon-Edit Waypoint", N_("_Edit Waypoint"), "E", N_("Edit Waypoint"), 0 }, (VikToolConstructorFunc) tool_edit_waypoint_create, NULL, NULL, NULL, (VikToolMouseFunc) tool_edit_waypoint_click, (VikToolMouseMoveFunc) tool_edit_waypoint_move, - (VikToolMouseFunc) tool_edit_waypoint_release, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_edwp_pixbuf }, + (VikToolMouseFunc) tool_edit_waypoint_release, (VikToolKeyFunc) NULL, + FALSE, + GDK_CURSOR_IS_PIXMAP, &cursor_edwp_pixbuf }, { { "EditTrackpoint", "vik-icon-Edit Trackpoint", N_("Edit Trac_kpoint"), "K", N_("Edit Trackpoint"), 0 }, (VikToolConstructorFunc) tool_edit_trackpoint_create, NULL, NULL, NULL, (VikToolMouseFunc) tool_edit_trackpoint_click, (VikToolMouseMoveFunc) tool_edit_trackpoint_move, - (VikToolMouseFunc) tool_edit_trackpoint_release, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_edtr_pixbuf }, + (VikToolMouseFunc) tool_edit_trackpoint_release, (VikToolKeyFunc) NULL, + FALSE, + GDK_CURSOR_IS_PIXMAP, &cursor_edtr_pixbuf }, { { "ShowPicture", "vik-icon-Show Picture", N_("Show P_icture"), "I", N_("Show Picture"), 0 }, (VikToolConstructorFunc) tool_show_picture_create, NULL, NULL, NULL, - (VikToolMouseFunc) tool_show_picture_click, NULL, NULL, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_showpic_pixbuf }, + (VikToolMouseFunc) tool_show_picture_click, NULL, NULL, (VikToolKeyFunc) NULL, + FALSE, + GDK_CURSOR_IS_PIXMAP, &cursor_showpic_pixbuf }, +#ifdef VIK_CONFIG_GOOGLE_DIRECTIONS { { "RouteFinder", "vik-icon-Route Finder", N_("Route _Finder"), "F", N_("Route Finder"), 0 }, (VikToolConstructorFunc) tool_route_finder_create, NULL, NULL, NULL, - (VikToolMouseFunc) tool_route_finder_click, NULL, NULL, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_route_finder_pixbuf }, + (VikToolMouseFunc) tool_route_finder_click, NULL, NULL, (VikToolKeyFunc) NULL, + FALSE, + GDK_CURSOR_IS_PIXMAP, &cursor_route_finder_pixbuf }, +#endif }; enum { TOOL_CREATE_WAYPOINT=0, TOOL_CREATE_TRACK, TOOL_BEGIN_TRACK, TOOL_EDIT_WAYPOINT, TOOL_EDIT_TRACKPOINT, TOOL_SHOW_PICTURE, NUM_TOOLS }; @@ -945,7 +976,8 @@ static VikTrwLayer* trw_layer_new ( gint drawmode ) rv->moving_tp = FALSE; rv->moving_wp = FALSE; - rv->ct_sync_done = TRUE; + rv->draw_sync_done = TRUE; + rv->draw_sync_do = TRUE; rv->route_finder_started = FALSE; rv->route_finder_check_added_track = FALSE; @@ -1505,6 +1537,11 @@ static void trw_layer_free_track_gcs ( VikTrwLayer *vtl ) g_object_unref ( vtl->current_track_gc ); vtl->current_track_gc = NULL; } + if ( vtl->current_track_newpoint_gc ) + { + g_object_unref ( vtl->current_track_newpoint_gc ); + vtl->current_track_newpoint_gc = NULL; + } if ( ! vtl->track_gc ) return; @@ -1531,6 +1568,12 @@ static void trw_layer_new_track_gcs ( VikTrwLayer *vtl, VikViewport *vp ) vtl->current_track_gc = vik_viewport_new_gc ( vp, "#FF0000", 2 ); gdk_gc_set_line_attributes ( vtl->current_track_gc, 2, GDK_LINE_ON_OFF_DASH, GDK_CAP_ROUND, GDK_JOIN_ROUND ); + // 'newpoint' gc is exactly the same as the current track gc + if ( vtl->current_track_newpoint_gc ) + g_object_unref ( vtl->current_track_newpoint_gc ); + vtl->current_track_newpoint_gc = vik_viewport_new_gc ( vp, "#FF0000", 2 ); + gdk_gc_set_line_attributes ( vtl->current_track_newpoint_gc, 2, GDK_LINE_ON_OFF_DASH, GDK_CAP_ROUND, GDK_JOIN_ROUND ); + vtl->track_gc = g_array_sized_new ( FALSE, FALSE, sizeof ( GdkGC * ), VIK_TRW_LAYER_TRACK_GC ); gc[0] = vik_viewport_new_gc ( vp, "#2d870a", width ); /* below range */ @@ -3433,6 +3476,7 @@ static void trw_layer_extend_track_end ( gpointer pass_along[6] ) goto_coord ( pass_along[1], pass_along[0], pass_along[5], &(((VikTrackpoint *)g_list_last(track->trackpoints)->data)->coord) ); } +#ifdef VIK_CONFIG_GOOGLE_DIRECTIONS /** * extend a track using route finder */ @@ -3451,6 +3495,7 @@ static void trw_layer_extend_track_end_route_finder ( gpointer pass_along[6] ) goto_coord ( pass_along[1], pass_along[0], pass_along[5], &last_coord) ; } +#endif static void trw_layer_apply_dem_data ( gpointer pass_along[6] ) { @@ -3788,6 +3833,20 @@ static void trw_layer_append_track ( gpointer pass_along[6] ) } } +/* merge by segments */ +static void trw_layer_merge_by_segment ( gpointer pass_along[6] ) +{ + VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0]; + VikTrack *trk = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] ); + guint segments = vik_track_merge_segments ( trk ); + // NB currently no need to redraw as segments not actually shown on the display + // However inform the user of what happened: + gchar str[64]; + const gchar *tmp_str = ngettext("%d segment merged", "%d segments merged", segments); + g_snprintf(str, 64, tmp_str, segments); + a_dialog_info_msg (VIK_GTK_WINDOW_FROM_LAYER(vtl), str ); +} + /* merge by time routine */ static void trw_layer_merge_by_timestamp ( gpointer pass_along[6] ) { @@ -4952,6 +5011,11 @@ static gboolean trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *men gtk_menu_shell_append ( GTK_MENU_SHELL(combine_submenu), item ); gtk_widget_show ( item ); + item = gtk_menu_item_new_with_mnemonic ( _("Merge _Segments") ); + g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_merge_by_segment), pass_along ); + gtk_menu_shell_append ( GTK_MENU_SHELL(combine_submenu), item ); + gtk_widget_show ( item ); + item = gtk_menu_item_new_with_mnemonic ( _("_Append Track...") ); g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_append_track), pass_along ); gtk_menu_shell_append ( GTK_MENU_SHELL(combine_submenu), item ); @@ -5039,11 +5103,13 @@ static gboolean trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *men gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); gtk_widget_show ( item ); +#ifdef VIK_CONFIG_GOOGLE_DIRECTIONS item = gtk_image_menu_item_new_with_mnemonic ( _("Extend _Using Route Finder") ); gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock ("Route Finder", GTK_ICON_SIZE_MENU) ); // Own icon - see stock_icons in vikwindow.c g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_extend_track_end_route_finder), pass_along ); gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); gtk_widget_show ( item ); +#endif #ifdef VIK_CONFIG_OPENSTREETMAP item = gtk_image_menu_item_new_with_mnemonic ( _("Upload to _OSM...") ); @@ -5203,27 +5269,30 @@ static void trw_layer_tpwin_response ( VikTrwLayer *vtl, gint response ) GList *new_tpl; + // Find available adjacent trackpoint if ( (new_tpl = vtl->current_tpl->next) || (new_tpl = vtl->current_tpl->prev) ) { if ( VIK_TRACKPOINT(vtl->current_tpl->data)->newsegment && vtl->current_tpl->next ) VIK_TRACKPOINT(vtl->current_tpl->next->data)->newsegment = TRUE; /* don't concat segments on del */ - tr->trackpoints = g_list_remove_link ( tr->trackpoints, vtl->current_tpl ); /* this nulls current_tpl->prev and next */ + // Delete current trackpoint + vik_trackpoint_free ( vtl->current_tpl->data ); + tr->trackpoints = g_list_delete_link ( tr->trackpoints, vtl->current_tpl ); + + // Set to current to the available adjacent trackpoint + vtl->current_tpl = new_tpl; - /* at this point the old trackpoint exists, but the list links are correct (new), so it is safe to do this. */ + // Reset dialog with the available adjacent trackpoint if ( vtl->current_tp_track ) vik_trw_layer_tpwin_set_tp ( vtl->tpwin, new_tpl, vtl->current_tp_track->name ); - g_free ( vtl->current_tpl->data ); /* TODO: vik_trackpoint_free() */ - g_list_free_1 ( vtl->current_tpl ); - vtl->current_tpl = new_tpl; vik_layer_emit_update(VIK_LAYER(vtl), FALSE); } else { - tr->trackpoints = g_list_remove_link ( tr->trackpoints, vtl->current_tpl ); - g_free ( vtl->current_tpl->data ); /* TODO longone: vik_trackpoint_new() and vik_trackpoint_free() */ - g_list_free_1 ( vtl->current_tpl ); + // Delete current trackpoint + vik_trackpoint_free ( vtl->current_tpl->data ); + tr->trackpoints = g_list_delete_link ( tr->trackpoints, vtl->current_tpl ); trw_layer_cancel_current_tp ( vtl, FALSE ); } } @@ -5588,20 +5657,31 @@ static gboolean trw_layer_show_selected_viewport_menu ( VikTrwLayer *vtl, GdkEve VikTrack *track = (VikTrack*)vik_window_get_selected_track ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(vtl) ); if ( track && track->visible ) { - if ( vik_window_get_selected_name ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(vtl) ) ) { + if ( track->name ) { if ( vtl->track_right_click_menu ) - gtk_object_sink ( GTK_OBJECT(vtl->track_right_click_menu) ); + gtk_object_sink ( GTK_OBJECT(vtl->track_right_click_menu) ); vtl->track_right_click_menu = GTK_MENU ( gtk_menu_new () ); - trw_layer_sublayer_add_menu_items ( vtl, - vtl->track_right_click_menu, - NULL, - VIK_TRW_LAYER_SUBLAYER_TRACK, - vik_window_get_selected_name ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(vtl) ), - g_hash_table_lookup ( vtl->tracks_iters, vik_window_get_selected_name ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(vtl) ) ), - vvp); + trku_udata udataU; + udataU.trk = track; + udataU.uuid = NULL; + + gpointer *trkf = g_hash_table_find ( vtl->tracks, (GHRFunc) trw_layer_track_find_uuid, &udataU ); + + if ( trkf && udataU.uuid ) { + + GtkTreeIter *iter = g_hash_table_lookup ( vtl->tracks_iters, udataU.uuid ); + + trw_layer_sublayer_add_menu_items ( vtl, + vtl->track_right_click_menu, + NULL, + VIK_TRW_LAYER_SUBLAYER_TRACK, + udataU.uuid, + iter, + vvp ); + } gtk_menu_popup ( vtl->track_right_click_menu, NULL, NULL, NULL, NULL, event->button, gtk_get_current_event_time() ); @@ -5612,19 +5692,30 @@ static gboolean trw_layer_show_selected_viewport_menu ( VikTrwLayer *vtl, GdkEve /* See if a waypoint is selected */ VikWaypoint *waypoint = (VikWaypoint*)vik_window_get_selected_waypoint ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(vtl) ); if ( waypoint && waypoint->visible ) { - if ( vik_window_get_selected_name ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(vtl) ) ) { + if ( waypoint->name ) { if ( vtl->wp_right_click_menu ) - gtk_object_sink ( GTK_OBJECT(vtl->wp_right_click_menu) ); + gtk_object_sink ( GTK_OBJECT(vtl->wp_right_click_menu) ); vtl->wp_right_click_menu = GTK_MENU ( gtk_menu_new () ); - trw_layer_sublayer_add_menu_items ( vtl, - vtl->wp_right_click_menu, - NULL, - VIK_TRW_LAYER_SUBLAYER_WAYPOINT, - vik_window_get_selected_name ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(vtl) ), - g_hash_table_lookup ( vtl->waypoints_iters, vik_window_get_selected_name ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(vtl) ) ), - vvp); + + wpu_udata udata; + udata.wp = waypoint; + udata.uuid = NULL; + + gpointer *wpf = g_hash_table_find ( vtl->waypoints, (GHRFunc) trw_layer_waypoint_find_uuid, (gpointer) &udata ); + + if ( wpf && udata.uuid ) { + GtkTreeIter *iter = g_hash_table_lookup ( vtl->waypoints_iters, udata.uuid ); + + trw_layer_sublayer_add_menu_items ( vtl, + vtl->wp_right_click_menu, + NULL, + VIK_TRW_LAYER_SUBLAYER_WAYPOINT, + udata.uuid, + iter, + vvp ); + } gtk_menu_popup ( vtl->wp_right_click_menu, NULL, NULL, NULL, NULL, event->button, gtk_get_current_event_time() ); return TRUE; @@ -5871,25 +5962,29 @@ static gpointer tool_new_track_create ( VikWindow *vw, VikViewport *vvp) typedef struct { VikTrwLayer *vtl; - VikViewport *vvp; - gint x1,y1,x2,y2,x3,y3; - const gchar* str; -} new_track_move_passalong_t; - -/* sync and undraw, but only when we have time */ -static gboolean ct_sync ( gpointer passalong ) -{ - new_track_move_passalong_t *p = (new_track_move_passalong_t *) passalong; + GdkDrawable *drawable; + GdkGC *gc; + GdkPixmap *pixmap; +} draw_sync_t; - vik_viewport_sync ( p->vvp ); - gdk_gc_set_function ( p->vtl->current_track_gc, GDK_INVERT ); - vik_viewport_draw_line ( p->vvp, p->vtl->current_track_gc, p->x1, p->y1, p->x2, p->y2 ); - vik_viewport_draw_string (p->vvp, gdk_font_from_description (pango_font_description_from_string ("Sans 8")), p->vtl->current_track_gc, p->x3, p->y3, p->str); - gdk_gc_set_function ( p->vtl->current_track_gc, GDK_COPY ); - - g_free ( (gpointer) p->str ) ; - p->vtl->ct_sync_done = TRUE; - g_free ( p ); +/* + * Draw specified pixmap + */ +static gboolean draw_sync ( gpointer data ) +{ + draw_sync_t *ds = (draw_sync_t*) data; + // Sometimes don't want to draw + // normally because another update has taken precedent such as panning the display + // which means this pixmap is no longer valid + if ( ds->vtl->draw_sync_do ) { + gdk_threads_enter(); + gdk_draw_drawable (ds->drawable, + ds->gc, + ds->pixmap, + 0, 0, 0, 0, -1, -1); + ds->vtl->draw_sync_done = TRUE; + gdk_threads_leave(); + } return FALSE; } @@ -5967,16 +6062,41 @@ static void update_statusbar ( VikTrwLayer *vtl ) static VikLayerToolFuncStatus tool_new_track_move ( VikTrwLayer *vtl, GdkEventMotion *event, VikViewport *vvp ) { /* if we haven't sync'ed yet, we don't have time to do more. */ - if ( vtl->ct_sync_done && vtl->current_track && vtl->current_track->trackpoints ) { - GList *iter = vtl->current_track->trackpoints; - new_track_move_passalong_t *passalong; + if ( vtl->draw_sync_done && vtl->current_track && vtl->current_track->trackpoints ) { + GList *iter = g_list_last ( vtl->current_track->trackpoints ); + + static GdkPixmap *pixmap = NULL; + int w1, h1, w2, h2; + // Need to check in case window has been resized + w1 = vik_viewport_get_width(vvp); + h1 = vik_viewport_get_height(vvp); + if (!pixmap) { + pixmap = gdk_pixmap_new ( GTK_WIDGET(vvp)->window, w1, h1, -1 ); + } + gdk_drawable_get_size (pixmap, &w2, &h2); + if (w1 != w2 || h1 != h2) { + g_object_unref ( G_OBJECT ( pixmap ) ); + pixmap = gdk_pixmap_new ( GTK_WIDGET(vvp)->window, w1, h1, -1 ); + } + + // Reset to background + gdk_draw_drawable (pixmap, + vtl->current_track_newpoint_gc, + vik_viewport_get_pixmap(vvp), + 0, 0, 0, 0, -1, -1); + + draw_sync_t *passalong; gint x1, y1; - while ( iter->next ) - iter = iter->next; - gdk_gc_set_function ( vtl->current_track_gc, GDK_INVERT ); vik_viewport_coord_to_screen ( vvp, &(VIK_TRACKPOINT(iter->data)->coord), &x1, &y1 ); - vik_viewport_draw_line ( vvp, vtl->current_track_gc, x1, y1, event->x, event->y ); + + // FOR SCREEN OVERLAYS WE MUST DRAW INTO THIS PIXMAP (when using the reset method) + // otherwise using vik_viewport_draw_* functions puts the data into the base pixmap, + // thus when we come to reset to the background it would include what we have already drawn!! + gdk_draw_line ( pixmap, + vtl->current_track_newpoint_gc, + x1, y1, event->x, event->y ); + // Using this reset method is more reliable than trying to undraw previous efforts via the GDK_INVERT method /* Find out actual distance of current track */ gdouble distance = vik_track_get_length (vtl->current_track); @@ -6012,28 +6132,38 @@ static VikLayerToolFuncStatus tool_new_track_move ( VikTrwLayer *vtl, GdkEventMo /* offset from cursor a bit */ xd = event->x + 10; yd = event->y - 10; - /* note attempted setting text using pango layouts - but the 'undraw' technique didn't work */ - vik_viewport_draw_string (vvp, gdk_font_from_description (pango_font_description_from_string ("Sans 8")), vtl->current_track_gc, xd, yd, str); - gdk_gc_set_function ( vtl->current_track_gc, GDK_COPY ); + PangoLayout *pl = gtk_widget_create_pango_layout (GTK_WIDGET(vvp), NULL); + PangoFontDescription *pfd = pango_font_description_from_string ("Sans 8"); // FIXME: settable option? global variable? + pango_layout_set_font_description (pl, pfd); + pango_font_description_free (pfd); + + pango_layout_set_text (pl, str, -1); + gint wd, hd; + pango_layout_get_pixel_size ( pl, &wd, &hd ); - passalong = g_new(new_track_move_passalong_t,1); /* freed by sync */ + // Create a background block to make the text easier to read over the background map + GdkGC *background_block_gc = vik_viewport_new_gc ( vvp, "#cccccc", 1); + gdk_draw_rectangle (pixmap, background_block_gc, TRUE, xd-2, yd-2, wd+4, hd+2); + gdk_draw_layout (pixmap, vtl->current_track_newpoint_gc, xd, yd, pl); + + g_object_unref ( G_OBJECT ( pl ) ); + g_object_unref ( G_OBJECT ( background_block_gc ) ); + + passalong = g_new(draw_sync_t,1); // freed by draw_sync() passalong->vtl = vtl; - passalong->vvp = vvp; - passalong->x1 = x1; - passalong->y1 = y1; - passalong->x2 = event->x; - passalong->y2 = event->y; - passalong->x3 = xd; - passalong->y3 = yd; - passalong->str = str; + passalong->pixmap = pixmap; + passalong->drawable = GTK_WIDGET(vvp)->window; + passalong->gc = vtl->current_track_newpoint_gc; // Update statusbar with full gain/loss information statusbar_write (str, elev_gain, elev_loss, vtl); - /* this will sync and undraw when we have time to */ - g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, ct_sync, passalong, NULL); - vtl->ct_sync_done = FALSE; + g_free ((gpointer)str); + + // draw pixmap when we have time to + g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, draw_sync, passalong, NULL); + vtl->draw_sync_done = FALSE; return VIK_LAYER_TOOL_ACK_GRAB_FOCUS; } return VIK_LAYER_TOOL_ACK; @@ -6069,6 +6199,13 @@ static gboolean tool_new_track_click ( VikTrwLayer *vtl, GdkEventButton *event, if (!vtl || vtl->vl.type != VIK_LAYER_TRW) return FALSE; + if ( event->button == 2 ) { + // As the display is panning, the new track pixmap is now invalid so don't draw it + // otherwise this drawing done results in flickering back to an old image + vtl->draw_sync_do = FALSE; + return FALSE; + } + if ( event->button == 3 && vtl->current_track ) { /* undo */ @@ -6141,6 +6278,15 @@ static gboolean tool_new_track_click ( VikTrwLayer *vtl, GdkEventButton *event, return TRUE; } +static void tool_new_track_release ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ) +{ + if ( event->button == 2 ) { + // Pan moving ended - enable potential point drawing again + vtl->draw_sync_do = TRUE; + vtl->draw_sync_done = TRUE; + } +} + /*** New waypoint ****/ static gpointer tool_new_waypoint_create ( VikWindow *vw, VikViewport *vvp) @@ -6304,6 +6450,7 @@ static gboolean tool_edit_trackpoint_release ( VikTrwLayer *vtl, GdkEventButton } +#ifdef VIK_CONFIG_GOOGLE_DIRECTIONS /*** Route Finder ***/ static gpointer tool_route_finder_create ( VikWindow *vw, VikViewport *vvp) { @@ -6379,6 +6526,7 @@ static gboolean tool_route_finder_click ( VikTrwLayer *vtl, GdkEventButton *even } return TRUE; } +#endif /*** Show picture ****/