X-Git-Url: https://git.street.me.uk/andy/viking.git/blobdiff_plain/074b10677af25dfda93469ca855dcee96cfc22e8..6339640601c48c559aed48a573946fc25785a6e9:/src/viktrwlayer.c diff --git a/src/viktrwlayer.c b/src/viktrwlayer.c index 6982bb03..6cdd217c 100644 --- a/src/viktrwlayer.c +++ b/src/viktrwlayer.c @@ -6,6 +6,7 @@ * Copyright (C) 2007, Quy Tonthat * Copyright (C) 2009, Hein Ragas * Copyright (c) 2012, Rob Norris + * Copyright (c) 2012-2013, Guilhem Bonnefille * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -52,8 +53,11 @@ #include "acquire.h" #include "datasources.h" #include "datasource_gps.h" +#include "vikexttool_datasources.h" #include "util.h" +#include "vikrouting.h" + #include "icons/icons.h" #ifdef HAVE_MATH_H @@ -73,10 +77,6 @@ #include #include -#ifdef VIK_CONFIG_GOOGLE -#define GOOGLE_DIRECTIONS_STRING "maps.google.com/maps?q=from:%s,%s+to:%s,%s&output=js" -#endif - #define VIK_TRW_LAYER_TRACK_GC 6 #define VIK_TRW_LAYER_TRACK_GCS 10 #define VIK_TRW_LAYER_TRACK_GC_BLACK 0 @@ -128,6 +128,8 @@ struct _VikTrwLayer { GHashTable *waypoints; GtkTreeIter tracks_iter, routes_iter, waypoints_iter; gboolean tracks_visible, routes_visible, waypoints_visible; + LatLonBBox waypoints_bbox; + guint8 drawmode; guint8 drawpoints; guint8 drawpoints_size; @@ -140,11 +142,14 @@ struct _VikTrwLayer { guint8 drawdirections_size; guint8 line_thickness; guint8 bg_line_thickness; + vik_layer_sort_order_t track_sort_order; guint8 wp_symbol; guint8 wp_size; gboolean wp_draw_symbols; font_size_t wp_font_size; + gchar *wp_fsize_str; + vik_layer_sort_order_t wp_sort_order; gdouble track_draw_speed_factor; GArray *track_gc; @@ -154,10 +159,11 @@ struct _VikTrwLayer { // 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; - GdkGC *waypoint_bg_gc; + GdkGC *track_bg_gc; GdkColor track_bg_color; + GdkGC *waypoint_gc; GdkColor waypoint_color; + GdkGC *waypoint_text_gc; GdkColor waypoint_text_color; + GdkGC *waypoint_bg_gc; GdkColor waypoint_bg_color; + gboolean wpbgand; GdkFont *waypoint_font; VikTrack *current_track; // ATM shared between new tracks and new routes guint16 ct_x1, ct_y1, ct_x2, ct_y2; @@ -227,6 +233,7 @@ struct DrawingParams { const VikCoord *center; gboolean one_zone, lat_lon; gdouble ce1, ce2, cn1, cn2; + LatLonBBox bbox; }; static gboolean trw_layer_delete_waypoint ( VikTrwLayer *vtl, VikWaypoint *wp ); @@ -245,6 +252,8 @@ static void trw_layer_free_track_gcs ( VikTrwLayer *vtl ); static void trw_layer_draw_track_cb ( const gpointer id, VikTrack *track, struct DrawingParams *dp ); static void trw_layer_draw_waypoint ( const gpointer id, VikWaypoint *wp, struct DrawingParams *dp ); +static void trw_layer_calculate_bounds_waypoints ( VikTrwLayer *vtl ); + static void goto_coord ( gpointer *vlp, gpointer vvp, gpointer vl, const VikCoord *coord ); static void trw_layer_goto_track_startpoint ( gpointer pass_along[6] ); static void trw_layer_goto_track_endpoint ( gpointer pass_along[6] ); @@ -291,9 +300,7 @@ static void trw_layer_geotagging_track ( gpointer pass_along[6] ); static void trw_layer_geotagging ( gpointer lav[2] ); #endif static void trw_layer_acquire_gps_cb ( gpointer lav[2] ); -#ifdef VIK_CONFIG_GOOGLE -static void trw_layer_acquire_google_cb ( gpointer lav[2] ); -#endif +static void trw_layer_acquire_routing_cb ( gpointer lav[2] ); #ifdef VIK_CONFIG_OPENSTREETMAP static void trw_layer_acquire_osm_cb ( gpointer lav[2] ); static void trw_layer_acquire_osm_my_traces_cb ( gpointer lav[2] ); @@ -348,10 +355,8 @@ static void tool_new_track_release ( VikTrwLayer *vtl, GdkEventButton *event, Vi 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 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 ); @@ -420,13 +425,11 @@ static VikToolInterface trw_layer_tools[] = { FALSE, GDK_CURSOR_IS_PIXMAP, &cursor_showpic_pixbuf }, -#ifdef VIK_CONFIG_GOOGLE { { "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, FALSE, GDK_CURSOR_IS_PIXMAP, &cursor_route_finder_pixbuf }, -#endif }; enum { @@ -436,9 +439,7 @@ enum { TOOL_EDIT_WAYPOINT, TOOL_EDIT_TRACKPOINT, TOOL_SHOW_PICTURE, -#ifdef VIK_CONFIG_GOOGLE TOOL_ROUTE_FINDER, -#endif NUM_TOOLS }; @@ -483,46 +484,89 @@ static gchar* params_font_sizes[] = { N_("Extra Extra Large"), NULL }; +// Needs to align with vik_layer_sort_order_t +static gchar* params_sort_order[] = { + N_("None"), + N_("Name Ascending"), + N_("Name Descending"), + NULL +}; + +static VikLayerParamData black_color_default ( void ) { + VikLayerParamData data; gdk_color_parse ( "#000000", &data.c ); return data; // Black +} +static VikLayerParamData drawmode_default ( void ) { return VIK_LPD_UINT ( DRAWMODE_BY_TRACK ); } +static VikLayerParamData line_thickness_default ( void ) { return VIK_LPD_UINT ( 1 ); } +static VikLayerParamData trkpointsize_default ( void ) { return VIK_LPD_UINT ( MIN_POINT_SIZE ); } +static VikLayerParamData trkdirectionsize_default ( void ) { return VIK_LPD_UINT ( 5 ); } +static VikLayerParamData bg_line_thickness_default ( void ) { return VIK_LPD_UINT ( 0 ); } +static VikLayerParamData trackbgcolor_default ( void ) { + VikLayerParamData data; gdk_color_parse ( "#FFFFFF", &data.c ); return data; // White +} +static VikLayerParamData elevation_factor_default ( void ) { return VIK_LPD_UINT ( 30 ); } +static VikLayerParamData stop_length_default ( void ) { return VIK_LPD_UINT ( 60 ); } +static VikLayerParamData speed_factor_default ( void ) { return VIK_LPD_DOUBLE ( 30.0 ); } + +static VikLayerParamData wpfontsize_default ( void ) { return VIK_LPD_UINT ( FS_MEDIUM ); } +static VikLayerParamData wptextcolor_default ( void ) { + VikLayerParamData data; gdk_color_parse ( "#FFFFFF", &data.c ); return data; // White +} +static VikLayerParamData wpbgcolor_default ( void ) { + VikLayerParamData data; gdk_color_parse ( "#8383C4", &data.c ); return data; // Kind of Blue +} +static VikLayerParamData wpsize_default ( void ) { return VIK_LPD_UINT ( 4 ); } +static VikLayerParamData wpsymbol_default ( void ) { return VIK_LPD_UINT ( WP_SYMBOL_FILLED_SQUARE ); } + +static VikLayerParamData image_size_default ( void ) { return VIK_LPD_UINT ( 64 ); } +static VikLayerParamData image_alpha_default ( void ) { return VIK_LPD_UINT ( 255 ); } +static VikLayerParamData image_cache_size_default ( void ) { return VIK_LPD_UINT ( 300 ); } + +static VikLayerParamData sort_order_default ( void ) { return VIK_LPD_UINT ( 0 ); } + VikLayerParam trw_layer_params[] = { - { "tracks_visible", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL }, - { "waypoints_visible", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL }, - { "routes_visible", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL }, - - { "drawmode", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Track Drawing Mode:"), VIK_LAYER_WIDGET_COMBOBOX, params_drawmodes, NULL, NULL }, - { "trackcolor", VIK_LAYER_PARAM_COLOR, GROUP_TRACKS, N_("All Tracks Color:"), VIK_LAYER_WIDGET_COLOR, NULL, NULL, - N_("The color used when 'All Tracks Same Color' drawing mode is selected") }, - { "drawlines", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, N_("Draw Track Lines"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL }, - { "line_thickness", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Track Thickness:"), VIK_LAYER_WIDGET_SPINBUTTON, ¶ms_scales[0], NULL, NULL }, - { "drawdirections", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, N_("Draw Track Direction"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL }, - { "trkdirectionsize", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Direction Size:"), VIK_LAYER_WIDGET_SPINBUTTON, ¶ms_scales[11], NULL, NULL }, - { "drawpoints", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, N_("Draw Trackpoints"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL }, - { "trkpointsize", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Trackpoint Size:"), VIK_LAYER_WIDGET_SPINBUTTON, ¶ms_scales[10], NULL, NULL }, - { "drawelevation", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, N_("Draw Elevation"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL }, - { "elevation_factor", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Draw Elevation Height %:"), VIK_LAYER_WIDGET_HSCALE, ¶ms_scales[9], NULL, NULL }, - - { "drawstops", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, N_("Draw Stops"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, - N_("Whether to draw a marker when trackpoints are at the same position but over the minimum stop length apart in time") }, - { "stop_length", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Min Stop Length (seconds):"), VIK_LAYER_WIDGET_SPINBUTTON, ¶ms_scales[8], NULL, NULL }, - - { "bg_line_thickness", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Track BG Thickness:"), VIK_LAYER_WIDGET_SPINBUTTON, ¶ms_scales[6], NULL, NULL}, - { "trackbgcolor", VIK_LAYER_PARAM_COLOR, GROUP_TRACKS, N_("Track Background Color"), VIK_LAYER_WIDGET_COLOR, NULL, NULL, NULL }, - { "speed_factor", VIK_LAYER_PARAM_DOUBLE, GROUP_TRACKS, N_("Draw by Speed Factor (%):"), VIK_LAYER_WIDGET_HSCALE, ¶ms_scales[1], NULL, - N_("The percentage factor away from the average speed determining the color used") }, - - { "drawlabels", VIK_LAYER_PARAM_BOOLEAN, GROUP_WAYPOINTS, N_("Draw Labels"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL }, - { "wpfontsize", VIK_LAYER_PARAM_UINT, GROUP_WAYPOINTS, N_("Waypoint Font Size:"), VIK_LAYER_WIDGET_COMBOBOX, params_font_sizes, NULL, NULL }, - { "wpcolor", VIK_LAYER_PARAM_COLOR, GROUP_WAYPOINTS, N_("Waypoint Color:"), VIK_LAYER_WIDGET_COLOR, NULL, NULL, NULL }, - { "wptextcolor", VIK_LAYER_PARAM_COLOR, GROUP_WAYPOINTS, N_("Waypoint Text:"), VIK_LAYER_WIDGET_COLOR, NULL, NULL, NULL }, - { "wpbgcolor", VIK_LAYER_PARAM_COLOR, GROUP_WAYPOINTS, N_("Background:"), VIK_LAYER_WIDGET_COLOR, NULL, NULL, NULL }, - { "wpbgand", VIK_LAYER_PARAM_BOOLEAN, GROUP_WAYPOINTS, N_("Fake BG Color Translucency:"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL }, - { "wpsymbol", VIK_LAYER_PARAM_UINT, GROUP_WAYPOINTS, N_("Waypoint marker:"), VIK_LAYER_WIDGET_COMBOBOX, params_wpsymbols, NULL, NULL }, - { "wpsize", VIK_LAYER_PARAM_UINT, GROUP_WAYPOINTS, N_("Waypoint size:"), VIK_LAYER_WIDGET_SPINBUTTON, ¶ms_scales[7], NULL, NULL }, - { "wpsyms", VIK_LAYER_PARAM_BOOLEAN, GROUP_WAYPOINTS, N_("Draw Waypoint Symbols:"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL }, - - { "drawimages", VIK_LAYER_PARAM_BOOLEAN, GROUP_IMAGES, N_("Draw Waypoint Images"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL }, - { "image_size", VIK_LAYER_PARAM_UINT, GROUP_IMAGES, N_("Image Size (pixels):"), VIK_LAYER_WIDGET_HSCALE, ¶ms_scales[3], NULL, NULL }, - { "image_alpha", VIK_LAYER_PARAM_UINT, GROUP_IMAGES, N_("Image Alpha:"), VIK_LAYER_WIDGET_HSCALE, ¶ms_scales[4], NULL, NULL }, - { "image_cache_size", VIK_LAYER_PARAM_UINT, GROUP_IMAGES, N_("Image Memory Cache Size:"), VIK_LAYER_WIDGET_HSCALE, ¶ms_scales[5], NULL, NULL }, + { VIK_LAYER_TRW, "tracks_visible", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL, NULL, vik_lpd_true_default }, + { VIK_LAYER_TRW, "waypoints_visible", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL, NULL, vik_lpd_true_default }, + { VIK_LAYER_TRW, "routes_visible", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL, NULL, vik_lpd_true_default }, + + { VIK_LAYER_TRW, "drawmode", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Track Drawing Mode:"), VIK_LAYER_WIDGET_COMBOBOX, params_drawmodes, NULL, NULL, drawmode_default }, + { VIK_LAYER_TRW, "trackcolor", VIK_LAYER_PARAM_COLOR, GROUP_TRACKS, N_("All Tracks Color:"), VIK_LAYER_WIDGET_COLOR, NULL, NULL, + N_("The color used when 'All Tracks Same Color' drawing mode is selected"), black_color_default }, + { VIK_LAYER_TRW, "drawlines", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, N_("Draw Track Lines"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL, vik_lpd_true_default }, + { VIK_LAYER_TRW, "line_thickness", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Track Thickness:"), VIK_LAYER_WIDGET_SPINBUTTON, ¶ms_scales[0], NULL, NULL, line_thickness_default }, + { VIK_LAYER_TRW, "drawdirections", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, N_("Draw Track Direction"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL, vik_lpd_false_default }, + { VIK_LAYER_TRW, "trkdirectionsize", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Direction Size:"), VIK_LAYER_WIDGET_SPINBUTTON, ¶ms_scales[11], NULL, NULL, trkdirectionsize_default }, + { VIK_LAYER_TRW, "drawpoints", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, N_("Draw Trackpoints"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL, vik_lpd_true_default }, + { VIK_LAYER_TRW, "trkpointsize", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Trackpoint Size:"), VIK_LAYER_WIDGET_SPINBUTTON, ¶ms_scales[10], NULL, NULL, trkpointsize_default }, + { VIK_LAYER_TRW, "drawelevation", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, N_("Draw Elevation"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL, vik_lpd_false_default }, + { VIK_LAYER_TRW, "elevation_factor", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Draw Elevation Height %:"), VIK_LAYER_WIDGET_HSCALE, ¶ms_scales[9], NULL, NULL, elevation_factor_default }, + + { VIK_LAYER_TRW, "drawstops", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, N_("Draw Stops"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, + N_("Whether to draw a marker when trackpoints are at the same position but over the minimum stop length apart in time"), vik_lpd_false_default }, + { VIK_LAYER_TRW, "stop_length", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Min Stop Length (seconds):"), VIK_LAYER_WIDGET_SPINBUTTON, ¶ms_scales[8], NULL, NULL, stop_length_default }, + + { VIK_LAYER_TRW, "bg_line_thickness", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Track BG Thickness:"), VIK_LAYER_WIDGET_SPINBUTTON, ¶ms_scales[6], NULL, NULL, bg_line_thickness_default }, + { VIK_LAYER_TRW, "trackbgcolor", VIK_LAYER_PARAM_COLOR, GROUP_TRACKS, N_("Track Background Color"), VIK_LAYER_WIDGET_COLOR, NULL, NULL, NULL, trackbgcolor_default }, + { VIK_LAYER_TRW, "speed_factor", VIK_LAYER_PARAM_DOUBLE, GROUP_TRACKS, N_("Draw by Speed Factor (%):"), VIK_LAYER_WIDGET_HSCALE, ¶ms_scales[1], NULL, + N_("The percentage factor away from the average speed determining the color used"), speed_factor_default }, + + { VIK_LAYER_TRW, "tracksortorder", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Track Sort Order:"), VIK_LAYER_WIDGET_COMBOBOX, params_sort_order, NULL, NULL, sort_order_default }, + + // Waypoint Options: + { VIK_LAYER_TRW, "drawlabels", VIK_LAYER_PARAM_BOOLEAN, GROUP_WAYPOINTS, N_("Draw Labels"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL, vik_lpd_true_default }, + { VIK_LAYER_TRW, "wpfontsize", VIK_LAYER_PARAM_UINT, GROUP_WAYPOINTS, N_("Waypoint Font Size:"), VIK_LAYER_WIDGET_COMBOBOX, params_font_sizes, NULL, NULL, wpfontsize_default }, + { VIK_LAYER_TRW, "wpcolor", VIK_LAYER_PARAM_COLOR, GROUP_WAYPOINTS, N_("Waypoint Color:"), VIK_LAYER_WIDGET_COLOR, NULL, NULL, NULL, black_color_default }, + { VIK_LAYER_TRW, "wptextcolor", VIK_LAYER_PARAM_COLOR, GROUP_WAYPOINTS, N_("Waypoint Text:"), VIK_LAYER_WIDGET_COLOR, NULL, NULL, NULL, wptextcolor_default }, + { VIK_LAYER_TRW, "wpbgcolor", VIK_LAYER_PARAM_COLOR, GROUP_WAYPOINTS, N_("Background:"), VIK_LAYER_WIDGET_COLOR, NULL, NULL, NULL, wpbgcolor_default }, + { VIK_LAYER_TRW, "wpbgand", VIK_LAYER_PARAM_BOOLEAN, GROUP_WAYPOINTS, N_("Fake BG Color Translucency:"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL, vik_lpd_false_default }, + { VIK_LAYER_TRW, "wpsymbol", VIK_LAYER_PARAM_UINT, GROUP_WAYPOINTS, N_("Waypoint marker:"), VIK_LAYER_WIDGET_COMBOBOX, params_wpsymbols, NULL, NULL, wpsymbol_default }, + { VIK_LAYER_TRW, "wpsize", VIK_LAYER_PARAM_UINT, GROUP_WAYPOINTS, N_("Waypoint size:"), VIK_LAYER_WIDGET_SPINBUTTON, ¶ms_scales[7], NULL, NULL, wpsize_default }, + { VIK_LAYER_TRW, "wpsyms", VIK_LAYER_PARAM_BOOLEAN, GROUP_WAYPOINTS, N_("Draw Waypoint Symbols:"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL, vik_lpd_true_default }, + { VIK_LAYER_TRW, "wpsortorder", VIK_LAYER_PARAM_UINT, GROUP_WAYPOINTS, N_("Waypoint Sort Order:"), VIK_LAYER_WIDGET_COMBOBOX, params_sort_order, NULL, NULL, sort_order_default }, + + { VIK_LAYER_TRW, "drawimages", VIK_LAYER_PARAM_BOOLEAN, GROUP_IMAGES, N_("Draw Waypoint Images"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL, vik_lpd_true_default }, + { VIK_LAYER_TRW, "image_size", VIK_LAYER_PARAM_UINT, GROUP_IMAGES, N_("Image Size (pixels):"), VIK_LAYER_WIDGET_HSCALE, ¶ms_scales[3], NULL, NULL, image_size_default }, + { VIK_LAYER_TRW, "image_alpha", VIK_LAYER_PARAM_UINT, GROUP_IMAGES, N_("Image Alpha:"), VIK_LAYER_WIDGET_HSCALE, ¶ms_scales[4], NULL, NULL, image_alpha_default }, + { VIK_LAYER_TRW, "image_cache_size", VIK_LAYER_PARAM_UINT, GROUP_IMAGES, N_("Image Memory Cache Size:"), VIK_LAYER_WIDGET_HSCALE, ¶ms_scales[5], NULL, NULL, image_cache_size_default }, }; // ENUMERATION MUST BE IN THE SAME ORDER AS THE NAMED PARAMS ABOVE @@ -547,6 +591,7 @@ enum { PARAM_BLT, PARAM_TBGC, PARAM_TDSF, + PARAM_TSO, // Waypoints PARAM_DLA, PARAM_WPFONTSIZE, @@ -557,6 +602,7 @@ enum { PARAM_WPSYM, PARAM_WPSIZE, PARAM_WPSYMS, + PARAM_WPSO, // WP images PARAM_DI, PARAM_IS, @@ -572,11 +618,10 @@ enum { /****** END PARAMETERS ******/ -static VikTrwLayer* trw_layer_new ( gint drawmode ); /* Layer Interface function definitions */ static VikTrwLayer* trw_layer_create ( VikViewport *vp ); static void trw_layer_realize ( VikTrwLayer *vtl, VikTreeview *vt, GtkTreeIter *layer_iter ); -static void trw_layer_post_read ( VikTrwLayer *vtl, GtkWidget *vvp ); +static void trw_layer_post_read ( VikTrwLayer *vtl, GtkWidget *vvp, gboolean from_file ); static void trw_layer_free ( VikTrwLayer *trwlayer ); static void trw_layer_draw ( VikTrwLayer *l, gpointer data ); static void trw_layer_change_coord_mode ( VikTrwLayer *vtl, VikCoordMode dest_mode ); @@ -821,6 +866,8 @@ static gboolean trw_layer_paste_item ( VikTrwLayer *vtl, gint subtype, guint8 *i vik_trw_layer_add_waypoint ( vtl, name, w ); waypoint_convert (NULL, w, &vtl->coord_mode); + trw_layer_calculate_bounds_waypoints ( vtl ); + // Consider if redraw necessary for the new item if ( vtl->vl.visible && vtl->waypoints_visible && w->visible ) vik_layer_emit_update ( VIK_LAYER(vtl) ); @@ -876,7 +923,7 @@ static gboolean trw_layer_set_param ( VikTrwLayer *vtl, guint16 id, VikLayerPara case PARAM_DM: vtl->drawmode = data.u; break; case PARAM_TC: vtl->track_color = data.c; - trw_layer_new_track_gcs ( vtl, vp ); + if ( vp ) trw_layer_new_track_gcs ( vtl, vp ); break; case PARAM_DP: vtl->drawpoints = data.b; break; case PARAM_DPS: @@ -900,17 +947,22 @@ static gboolean trw_layer_set_param ( VikTrwLayer *vtl, guint16 id, VikLayerPara case PARAM_LT: if ( data.u > 0 && data.u < 15 && data.u != vtl->line_thickness ) { vtl->line_thickness = data.u; - trw_layer_new_track_gcs ( vtl, vp ); + if ( vp ) trw_layer_new_track_gcs ( vtl, vp ); } break; case PARAM_BLT: if ( data.u <= 8 && data.u != vtl->bg_line_thickness ) { vtl->bg_line_thickness = data.u; - trw_layer_new_track_gcs ( vtl, vp ); + if ( vp ) trw_layer_new_track_gcs ( vtl, vp ); } break; - case PARAM_TBGC: gdk_gc_set_rgb_fg_color(vtl->track_bg_gc, &(data.c)); break; + case PARAM_TBGC: + vtl->track_bg_color = data.c; + if ( vtl->track_bg_gc ) + gdk_gc_set_rgb_fg_color(vtl->track_bg_gc, &(vtl->track_bg_color)); + break; case PARAM_TDSF: vtl->track_draw_speed_factor = data.d; break; + case PARAM_TSO: if ( data.u < VL_SO_LAST ) vtl->track_sort_order = data.u; break; case PARAM_DLA: vtl->drawlabels = data.b; break; case PARAM_DI: vtl->drawimages = data.b; break; case PARAM_IS: if ( data.u != vtl->image_size ) @@ -926,14 +978,45 @@ static gboolean trw_layer_set_param ( VikTrwLayer *vtl, guint16 id, VikLayerPara while ( vtl->image_cache->length > vtl->image_cache_size ) /* if shrinking cache_size, free pixbuf ASAP */ cached_pixbuf_free ( g_queue_pop_tail ( vtl->image_cache ) ); break; - case PARAM_WPC: gdk_gc_set_rgb_fg_color(vtl->waypoint_gc, &(data.c)); break; - case PARAM_WPTC: gdk_gc_set_rgb_fg_color(vtl->waypoint_text_gc, &(data.c)); break; - case PARAM_WPBC: gdk_gc_set_rgb_fg_color(vtl->waypoint_bg_gc, &(data.c)); break; - case PARAM_WPBA: gdk_gc_set_function(vtl->waypoint_bg_gc, data.b ? GDK_AND : GDK_COPY ); break; + case PARAM_WPC: + vtl->waypoint_color = data.c; + if ( vtl->waypoint_gc ) + gdk_gc_set_rgb_fg_color(vtl->waypoint_gc, &(vtl->waypoint_color)); + break; + case PARAM_WPTC: + vtl->waypoint_text_color = data.c; + if ( vtl->waypoint_text_gc ) + gdk_gc_set_rgb_fg_color(vtl->waypoint_text_gc, &(vtl->waypoint_text_color)); + break; + case PARAM_WPBC: + vtl->waypoint_bg_color = data.c; + if ( vtl->waypoint_bg_gc ) + gdk_gc_set_rgb_fg_color(vtl->waypoint_bg_gc, &(vtl->waypoint_bg_color)); + break; + case PARAM_WPBA: + vtl->wpbgand = data.b; + if ( vtl->waypoint_bg_gc ) + gdk_gc_set_function(vtl->waypoint_bg_gc, data.b ? GDK_AND : GDK_COPY ); + break; case PARAM_WPSYM: if ( data.u < WP_NUM_SYMBOLS ) vtl->wp_symbol = data.u; break; case PARAM_WPSIZE: if ( data.u > 0 && data.u <= 64 ) vtl->wp_size = data.u; break; case PARAM_WPSYMS: vtl->wp_draw_symbols = data.b; break; - case PARAM_WPFONTSIZE: if ( data.u < FS_NUM_SIZES ) vtl->wp_font_size = data.u; break; + case PARAM_WPFONTSIZE: + if ( data.u < FS_NUM_SIZES ) { + vtl->wp_font_size = data.u; + g_free ( vtl->wp_fsize_str ); + switch ( vtl->wp_font_size ) { + case FS_XX_SMALL: vtl->wp_fsize_str = g_strdup ( "xx-small" ); break; + case FS_X_SMALL: vtl->wp_fsize_str = g_strdup ( "x-small" ); break; + case FS_SMALL: vtl->wp_fsize_str = g_strdup ( "small" ); break; + case FS_LARGE: vtl->wp_fsize_str = g_strdup ( "large" ); break; + case FS_X_LARGE: vtl->wp_fsize_str = g_strdup ( "x-large" ); break; + case FS_XX_LARGE: vtl->wp_fsize_str = g_strdup ( "xx-large" ); break; + default: vtl->wp_fsize_str = g_strdup ( "medium" ); break; + } + } + break; + case PARAM_WPSO: if ( data.u < VL_SO_LAST ) vtl->wp_sort_order = data.u; break; } return TRUE; } @@ -961,19 +1044,21 @@ static VikLayerParamData trw_layer_get_param ( VikTrwLayer *vtl, guint16 id, gbo case PARAM_BLT: rv.u = vtl->bg_line_thickness; break; case PARAM_DLA: rv.b = vtl->drawlabels; break; case PARAM_DI: rv.b = vtl->drawimages; break; - case PARAM_TBGC: vik_gc_get_fg_color(vtl->track_bg_gc, &(rv.c)); break; + case PARAM_TBGC: rv.c = vtl->track_bg_color; break; case PARAM_TDSF: rv.d = vtl->track_draw_speed_factor; break; + case PARAM_TSO: rv.u = vtl->track_sort_order; break; case PARAM_IS: rv.u = vtl->image_size; break; case PARAM_IA: rv.u = vtl->image_alpha; break; case PARAM_ICS: rv.u = vtl->image_cache_size; break; - case PARAM_WPC: vik_gc_get_fg_color(vtl->waypoint_gc, &(rv.c)); break; - case PARAM_WPTC: vik_gc_get_fg_color(vtl->waypoint_text_gc, &(rv.c)); break; - case PARAM_WPBC: vik_gc_get_fg_color(vtl->waypoint_bg_gc, &(rv.c)); break; - case PARAM_WPBA: rv.b = (vik_gc_get_function(vtl->waypoint_bg_gc)==GDK_AND); break; + case PARAM_WPC: rv.c = vtl->waypoint_color; break; + case PARAM_WPTC: rv.c = vtl->waypoint_text_color; break; + case PARAM_WPBC: rv.c = vtl->waypoint_bg_color; break; + case PARAM_WPBA: rv.b = vtl->wpbgand; break; case PARAM_WPSYM: rv.u = vtl->wp_symbol; break; case PARAM_WPSIZE: rv.u = vtl->wp_size; break; case PARAM_WPSYMS: rv.b = vtl->wp_draw_symbols; break; case PARAM_WPFONTSIZE: rv.u = vtl->wp_font_size; break; + case PARAM_WPSO: rv.u = vtl->wp_sort_order; break; } return rv; } @@ -1100,6 +1185,9 @@ static VikTrwLayer *trw_layer_unmarshall( guint8 *data, gint len, VikViewport *v } //g_debug ("consumed_length %d vs len %d", consumed_length, len); + // Not stored anywhere else so need to regenerate + trw_layer_calculate_bounds_waypoints ( vtl ); + return vtl; } @@ -1128,7 +1216,9 @@ static guint strcase_hash(gconstpointer v) } */ -static VikTrwLayer* trw_layer_new ( gint drawmode ) +// Stick a 1 at the end of the function name to make it more unique +// thus more easily searchable in a simple text editor +static VikTrwLayer* trw_layer_new1 ( VikViewport *vvp ) { VikTrwLayer *rv = VIK_TRW_LAYER ( g_object_new ( VIK_TRW_LAYER_TYPE, NULL ) ); vik_layer_set_type ( VIK_LAYER(rv), VIK_LAYER_TRW ); @@ -1152,27 +1242,16 @@ static VikTrwLayer* trw_layer_new ( gint drawmode ) rv->routes = g_hash_table_new_full ( g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) vik_track_free ); rv->routes_iters = g_hash_table_new_full ( g_direct_hash, g_direct_equal, NULL, g_free ); - // Default values + rv->image_cache = g_queue_new(); // Must be performed before set_params via set_defaults + + vik_layer_set_defaults ( VIK_LAYER(rv), vvp ); + + // Param settings that are not available via the GUI + // Force to on after processing params (which defaults them to off with a zero value) rv->waypoints_visible = rv->tracks_visible = rv->routes_visible = TRUE; - rv->drawmode = drawmode; - rv->drawpoints = TRUE; - rv->drawpoints_size = MIN_POINT_SIZE; - rv->drawdirections_size = 5; - rv->elevation_factor = 30; - rv->stop_length = 60; - rv->drawlines = TRUE; - rv->track_draw_speed_factor = 30.0; - rv->line_thickness = 1; rv->draw_sync_done = TRUE; rv->draw_sync_do = TRUE; - - rv->image_cache = g_queue_new(); - rv->image_size = 64; - rv->image_alpha = 255; - rv->image_cache_size = 300; - rv->drawimages = TRUE; - rv->drawlabels = TRUE; // Everything else is 0, FALSE or NULL return rv; @@ -1191,7 +1270,7 @@ static void trw_layer_free ( VikTrwLayer *trwlayer ) g_object_ref_sink ( G_OBJECT(trwlayer->wp_right_click_menu) ); if ( trwlayer->track_right_click_menu ) - gtk_object_sink ( GTK_OBJECT(trwlayer->track_right_click_menu) ); + g_object_ref_sink ( G_OBJECT(trwlayer->track_right_click_menu) ); if ( trwlayer->wplabellayout != NULL) g_object_unref ( G_OBJECT ( trwlayer->wplabellayout ) ); @@ -1205,6 +1284,8 @@ static void trw_layer_free ( VikTrwLayer *trwlayer ) if ( trwlayer->waypoint_bg_gc != NULL ) g_object_unref ( G_OBJECT ( trwlayer->waypoint_bg_gc ) ); + g_free ( trwlayer->wp_fsize_str ); + if ( trwlayer->tpwin != NULL ) gtk_widget_destroy ( GTK_WIDGET(trwlayer->tpwin) ); @@ -1250,6 +1331,8 @@ static void init_drawing_params ( struct DrawingParams *dp, VikTrwLayer *vtl, Vi dp->cn1 = bottomright.north_south; dp->cn2 = upperleft.north_south; } + + vik_viewport_get_min_max_lat_lon ( vp, &(dp->bbox.south), &(dp->bbox.north), &(dp->bbox.west), &(dp->bbox.east) ); } /* @@ -1286,6 +1369,9 @@ static void draw_utm_skip_insignia ( VikViewport *vvp, GdkGC *gc, gint x, gint y static void trw_layer_draw_track ( const gpointer id, VikTrack *track, struct DrawingParams *dp, gboolean draw_track_outline ) { + if ( ! track->visible ) + return; + /* TODO: this function is a mess, get rid of any redundancy */ GList *list = track->trackpoints; GdkGC *main_gc; @@ -1307,9 +1393,6 @@ static void trw_layer_draw_track ( const gpointer id, VikTrack *track, struct Dr alt_diff = max_alt - min_alt; } - if ( ! track->visible ) - return; - /* admittedly this is not an efficient way to do it because we go through the whole GC thing all over... */ if ( dp->vtl->bg_line_thickness && !draw_track_outline ) trw_layer_draw_track ( id, track, dp, TRUE ); @@ -1476,9 +1559,9 @@ static void trw_layer_draw_track ( const gpointer id, VikTrack *track, struct Dr GdkGC *tmp_gc; if ( ((oldx - x) > 0 && (oldy - y) > 0) || ((oldx - x) < 0 && (oldy - y) < 0)) - tmp_gc = GTK_WIDGET(dp->vp)->style->light_gc[3]; + tmp_gc = gtk_widget_get_style(GTK_WIDGET(dp->vp))->light_gc[3]; else - tmp_gc = GTK_WIDGET(dp->vp)->style->dark_gc[0]; + tmp_gc = gtk_widget_get_style(GTK_WIDGET(dp->vp))->dark_gc[0]; vik_viewport_draw_polygon ( dp->vp, tmp_gc, TRUE, tmp, 4); vik_viewport_draw_line ( dp->vp, main_gc, oldx, oldy-FIXALTITUDE(list->data), x, y-FIXALTITUDE(list->next->data)); @@ -1548,10 +1631,11 @@ static void trw_layer_draw_track ( const gpointer id, VikTrack *track, struct Dr } } -/* the only reason this exists is so that trw_layer_draw_track can first call itself to draw the white track background */ static void trw_layer_draw_track_cb ( const gpointer id, VikTrack *track, struct DrawingParams *dp ) { - trw_layer_draw_track ( id, track, dp, FALSE ); + if ( BBOX_INTERSECT ( track->bbox, dp->bbox ) ) { + trw_layer_draw_track ( id, track, dp, FALSE ); + } } static void cached_pixbuf_free ( CachedPixbuf *cp ) @@ -1573,7 +1657,6 @@ static void trw_layer_draw_waypoint ( const gpointer id, VikWaypoint *wp, struct wp->coord.north_south > dp->cn1 && wp->coord.north_south < dp->cn2 ) ) { gint x, y; - GdkPixbuf *sym = NULL; vik_viewport_coord_to_screen ( dp->vp, &(wp->coord), &x, &y ); /* if in shrunken_cache, get that. If not, get and add to shrunken_cache */ @@ -1657,9 +1740,9 @@ static void trw_layer_draw_waypoint ( const gpointer id, VikWaypoint *wp, struct } } - /* DRAW ACTUAL DOT */ - if ( dp->vtl->wp_draw_symbols && wp->symbol && (sym = a_get_wp_sym(wp->symbol)) ) { - vik_viewport_draw_pixbuf ( dp->vp, sym, 0, 0, x - gdk_pixbuf_get_width(sym)/2, y - gdk_pixbuf_get_height(sym)/2, -1, -1 ); + // Draw appropriate symbol - either symbol image or simple types + if ( dp->vtl->wp_draw_symbols && wp->symbol && wp->symbol_pixbuf ) { + vik_viewport_draw_pixbuf ( dp->vp, wp->symbol_pixbuf, 0, 0, x - gdk_pixbuf_get_width(wp->symbol_pixbuf)/2, y - gdk_pixbuf_get_height(wp->symbol_pixbuf)/2, -1, -1 ); } else if ( wp == dp->vtl->current_wp ) { switch ( dp->vtl->wp_symbol ) { @@ -1688,18 +1771,7 @@ static void trw_layer_draw_waypoint ( const gpointer id, VikWaypoint *wp, struct // Hopefully name won't break the markup (may need to sanitize - g_markup_escape_text()) // Could this stored in the waypoint rather than recreating each pass? - gchar *fsize = NULL; - switch (dp->vtl->wp_font_size) { - case FS_XX_SMALL: fsize = g_strdup ( "xx-small" ); break; - case FS_X_SMALL: fsize = g_strdup ( "x-small" ); break; - case FS_SMALL: fsize = g_strdup ( "small" ); break; - case FS_LARGE: fsize = g_strdup ( "large" ); break; - case FS_X_LARGE: fsize = g_strdup ( "x-large" ); break; - case FS_XX_LARGE: fsize = g_strdup ( "xx-large" ); break; - default: fsize = g_strdup ( "medium" ); break; - } - - gchar *wp_label_markup = g_strdup_printf ( "%s", fsize, wp->name ); + gchar *wp_label_markup = g_strdup_printf ( "%s", dp->vtl->wp_fsize_str, wp->name ); if ( pango_parse_markup ( wp_label_markup, -1, 0, NULL, NULL, NULL, NULL ) ) pango_layout_set_markup ( dp->vtl->wplabellayout, wp_label_markup, -1 ); @@ -1708,12 +1780,11 @@ static void trw_layer_draw_waypoint ( const gpointer id, VikWaypoint *wp, struct pango_layout_set_text ( dp->vtl->wplabellayout, wp->name, -1 ); g_free ( wp_label_markup ); - g_free ( fsize ); pango_layout_get_pixel_size ( dp->vtl->wplabellayout, &width, &height ); label_x = x - width/2; - if (sym) - label_y = y - height - 2 - gdk_pixbuf_get_height(sym)/2; + if ( wp->symbol_pixbuf ) + label_y = y - height - 2 - gdk_pixbuf_get_height(wp->symbol_pixbuf)/2; else label_y = y - dp->vtl->wp_size - height - 2; @@ -1734,6 +1805,13 @@ static void trw_layer_draw_waypoint ( const gpointer id, VikWaypoint *wp, struct } } +static void trw_layer_draw_waypoint_cb ( gpointer id, VikWaypoint *wp, struct DrawingParams *dp ) +{ + if ( BBOX_INTERSECT ( dp->vtl->waypoints_bbox, dp->bbox ) ) { + trw_layer_draw_waypoint ( id, wp, dp ); + } +} + static void trw_layer_draw ( VikTrwLayer *l, gpointer data ) { static struct DrawingParams dp; @@ -1748,7 +1826,7 @@ static void trw_layer_draw ( VikTrwLayer *l, gpointer data ) g_hash_table_foreach ( l->routes, (GHFunc) trw_layer_draw_track_cb, &dp ); if (l->waypoints_visible) - g_hash_table_foreach ( l->waypoints, (GHFunc) trw_layer_draw_waypoint, &dp ); + g_hash_table_foreach ( l->waypoints, (GHFunc) trw_layer_draw_waypoint_cb, &dp ); } static void trw_layer_free_track_gcs ( VikTrwLayer *vtl ) @@ -1793,7 +1871,7 @@ static void trw_layer_new_track_gcs ( VikTrwLayer *vtl, VikViewport *vp ) if ( vtl->track_bg_gc ) g_object_unref ( vtl->track_bg_gc ); - vtl->track_bg_gc = vik_viewport_new_gc ( vp, "#FFFFFF", width + vtl->bg_line_thickness ); + vtl->track_bg_gc = vik_viewport_new_gc_from_color ( vp, &(vtl->track_bg_color), width + vtl->bg_line_thickness ); // Ensure new track drawing heeds line thickness setting // however always have a minium of 2, as 1 pixel is really narrow @@ -1826,31 +1904,23 @@ static void trw_layer_new_track_gcs ( VikTrwLayer *vtl, VikViewport *vp ) static VikTrwLayer* trw_layer_create ( VikViewport *vp ) { - VikTrwLayer *rv = trw_layer_new ( DRAWMODE_BY_TRACK ); + VikTrwLayer *rv = trw_layer_new1 ( vp ); vik_layer_rename ( VIK_LAYER(rv), vik_trw_layer_interface.name ); - if ( vp == NULL || GTK_WIDGET(vp)->window == NULL ) { + if ( vp == NULL || gtk_widget_get_window(GTK_WIDGET(vp)) == NULL ) { /* early exit, as the rest is GUI related */ return rv; } rv->wplabellayout = gtk_widget_create_pango_layout (GTK_WIDGET(vp), NULL); - pango_layout_set_font_description (rv->wplabellayout, GTK_WIDGET(vp)->style->font_desc); - - gdk_color_parse ( "#000000", &(rv->track_color) ); // Black + pango_layout_set_font_description (rv->wplabellayout, gtk_widget_get_style(GTK_WIDGET(vp))->font_desc); trw_layer_new_track_gcs ( rv, vp ); - rv->waypoint_gc = vik_viewport_new_gc ( vp, "#000000", 2 ); - rv->waypoint_text_gc = vik_viewport_new_gc ( vp, "#FFFFFF", 1 ); - rv->waypoint_bg_gc = vik_viewport_new_gc ( vp, "#8383C4", 1 ); - gdk_gc_set_function ( rv->waypoint_bg_gc, GDK_AND ); - - rv->has_verified_thumbnails = FALSE; - rv->wp_symbol = WP_SYMBOL_FILLED_SQUARE; - rv->wp_size = 4; - rv->wp_draw_symbols = TRUE; - rv->wp_font_size = FS_MEDIUM; + rv->waypoint_gc = vik_viewport_new_gc_from_color ( vp, &(rv->waypoint_color), 2 ); + rv->waypoint_text_gc = vik_viewport_new_gc_from_color ( vp, &(rv->waypoint_text_color), 1 ); + rv->waypoint_bg_gc = vik_viewport_new_gc_from_color ( vp, &(rv->waypoint_bg_color), 1 ); + gdk_gc_set_function ( rv->waypoint_bg_gc, rv->wpbgand ); rv->coord_mode = vik_viewport_get_coord_mode ( vp ); @@ -1891,11 +1961,7 @@ static void trw_layer_realize_track ( gpointer id, VikTrack *track, gpointer pas gdk_pixbuf_fill ( pixbuf, pixel ); } -#ifdef VIK_CONFIG_ALPHABETIZED_TRW - vik_treeview_add_sublayer_alphabetized ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[0], (GtkTreeIter *) pass_along[1], track->name, pass_along[2], id, GPOINTER_TO_INT (pass_along[4]), pixbuf, TRUE, TRUE ); -#else vik_treeview_add_sublayer ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[0], (GtkTreeIter *) pass_along[1], track->name, pass_along[2], id, GPOINTER_TO_INT (pass_along[4]), pixbuf, TRUE, TRUE ); -#endif if ( pixbuf ) g_object_unref (pixbuf); @@ -1914,11 +1980,7 @@ static void trw_layer_realize_waypoint ( gpointer id, VikWaypoint *wp, gpointer { GtkTreeIter *new_iter = g_malloc(sizeof(GtkTreeIter)); -#ifdef VIK_CONFIG_ALPHABETIZED_TRW - vik_treeview_add_sublayer_alphabetized ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[0], (GtkTreeIter *) pass_along[1], wp->name, pass_along[2], id, GPOINTER_TO_INT (pass_along[4]), get_wp_sym_small (wp->symbol), TRUE, TRUE ); -#else vik_treeview_add_sublayer ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[0], (GtkTreeIter *) pass_along[1], wp->name, pass_along[2], id, GPOINTER_TO_UINT (pass_along[4]), get_wp_sym_small (wp->symbol), TRUE, TRUE ); -#endif *new_iter = *((GtkTreeIter *) pass_along[1]); g_hash_table_insert ( VIK_TRW_LAYER(pass_along[2])->waypoints_iters, id, new_iter ); @@ -1929,29 +1991,17 @@ static void trw_layer_realize_waypoint ( gpointer id, VikWaypoint *wp, gpointer static void trw_layer_add_sublayer_tracks ( VikTrwLayer *vtl, VikTreeview *vt, GtkTreeIter *layer_iter ) { -#ifdef VIK_CONFIG_ALPHABETIZED_TRW - vik_treeview_add_sublayer_alphabetized ( (VikTreeview *) vt, layer_iter, &(vtl->tracks_iter), _("Tracks"), vtl, NULL, VIK_TRW_LAYER_SUBLAYER_TRACKS, NULL, TRUE, FALSE ); -#else vik_treeview_add_sublayer ( (VikTreeview *) vt, layer_iter, &(vtl->tracks_iter), _("Tracks"), vtl, NULL, VIK_TRW_LAYER_SUBLAYER_TRACKS, NULL, TRUE, FALSE ); -#endif } static void trw_layer_add_sublayer_waypoints ( VikTrwLayer *vtl, VikTreeview *vt, GtkTreeIter *layer_iter ) { -#ifdef VIK_CONFIG_ALPHABETIZED_TRW - vik_treeview_add_sublayer_alphabetized ( (VikTreeview *) vt, layer_iter, &(vtl->waypoints_iter), _("Waypoints"), vtl, NULL, VIK_TRW_LAYER_SUBLAYER_WAYPOINTS, NULL, TRUE, FALSE ); -#else vik_treeview_add_sublayer ( (VikTreeview *) vt, layer_iter, &(vtl->waypoints_iter), _("Waypoints"), vtl, NULL, VIK_TRW_LAYER_SUBLAYER_WAYPOINTS, NULL, TRUE, FALSE ); -#endif } static void trw_layer_add_sublayer_routes ( VikTrwLayer *vtl, VikTreeview *vt, GtkTreeIter *layer_iter ) { -#ifdef VIK_CONFIG_ALPHABETIZED_TRW - vik_treeview_add_sublayer_alphabetized ( (VikTreeview *) vt, layer_iter, &(vtl->routes_iter), _("Routes"), vtl, NULL, VIK_TRW_LAYER_SUBLAYER_ROUTES, NULL, TRUE, FALSE ); -#else vik_treeview_add_sublayer ( (VikTreeview *) vt, layer_iter, &(vtl->routes_iter), _("Routes"), vtl, NULL, VIK_TRW_LAYER_SUBLAYER_ROUTES, NULL, TRUE, FALSE ); -#endif } static void trw_layer_realize ( VikTrwLayer *vtl, VikTreeview *vt, GtkTreeIter *layer_iter ) @@ -1961,13 +2011,13 @@ static void trw_layer_realize ( VikTrwLayer *vtl, VikTreeview *vt, GtkTreeIter * if ( g_hash_table_size (vtl->tracks) > 0 ) { trw_layer_add_sublayer_tracks ( vtl, vt , layer_iter ); + pass_along[5] = GINT_TO_POINTER(g_hash_table_size (vtl->tracks)); g_hash_table_foreach ( vtl->tracks, (GHFunc) trw_layer_realize_track, pass_along ); - vik_treeview_item_set_visible ( (VikTreeview *) vt, &(vtl->tracks_iter), vtl->tracks_visible ); + vik_treeview_item_set_visible ( vt, &(vtl->tracks_iter), vtl->tracks_visible ); } if ( g_hash_table_size (vtl->routes) > 0 ) { - trw_layer_add_sublayer_routes ( vtl, vt, layer_iter ); pass_along[0] = &(vtl->routes_iter); @@ -2246,8 +2296,12 @@ static const gchar* trw_layer_sublayer_tooltip ( VikTrwLayer *l, gint subtype, g { VikWaypoint *w = g_hash_table_lookup ( l->waypoints, sublayer ); // NB It's OK to return NULL - if ( w ) - return w->comment; + if ( w ) { + if ( w->comment ) + return w->comment; + else + return w->description; + } } break; default: break; @@ -2446,6 +2500,13 @@ GHashTable *vik_trw_layer_get_waypoints ( VikTrwLayer *l ) return l->waypoints; } +gboolean vik_trw_layer_is_empty ( VikTrwLayer *vtl ) +{ + return ! ( g_hash_table_size ( vtl->tracks ) || + g_hash_table_size ( vtl->routes ) || + g_hash_table_size ( vtl->waypoints ) ); +} + /* * ATM use a case sensitive find * Finds the first one @@ -2645,6 +2706,12 @@ static void trw_layer_export ( gpointer layer_and_vlp[2], const gchar *title, co GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); + gchar *cwd = g_get_current_dir(); + if ( cwd ) { + gtk_file_chooser_set_current_folder ( GTK_FILE_CHOOSER(file_selector), cwd ); + g_free ( cwd ); + } + gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER(file_selector), default_name); while ( gtk_dialog_run ( GTK_DIALOG(file_selector) ) == GTK_RESPONSE_ACCEPT ) @@ -2653,7 +2720,9 @@ static void trw_layer_export ( gpointer layer_and_vlp[2], const gchar *title, co if ( g_file_test ( fn, G_FILE_TEST_EXISTS ) == FALSE ) { gtk_widget_hide ( file_selector ); + vik_window_set_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0])) ); failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), fn, file_type, trk, TRUE ); + vik_window_clear_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0])) ); break; } else @@ -2661,7 +2730,9 @@ static void trw_layer_export ( gpointer layer_and_vlp[2], const gchar *title, co if ( a_dialog_yes_or_no ( GTK_WINDOW(file_selector), _("The file \"%s\" exists, do you wish to overwrite it?"), a_file_basename ( fn ) ) ) { gtk_widget_hide ( file_selector ); + vik_window_set_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0])) ); failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), fn, file_type, trk, TRUE ); + vik_window_clear_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0])) ); break; } } @@ -2715,7 +2786,9 @@ static void trw_layer_export_external_gpx ( gpointer layer_and_vlp[2], const gch int fd; if ((fd = g_file_open_tmp("tmp-viking.XXXXXX.gpx", &name_used, NULL)) >= 0) { + vik_window_set_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0])) ); gboolean failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), name_used, FILE_TYPE_GPX, NULL, TRUE); + vik_window_clear_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0])) ); if (failed) { a_dialog_error_msg (VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0]), _("Could not create temporary file for export.") ); } @@ -2805,8 +2878,8 @@ static void trw_layer_goto_wp ( gpointer layer_and_vlp[2] ) label = gtk_label_new(_("Waypoint Name:")); entry = gtk_entry_new(); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dia)->vbox), label, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dia)->vbox), entry, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dia))), label, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dia))), entry, FALSE, FALSE, 0); gtk_widget_show_all ( label ); gtk_widget_show_all ( entry ); @@ -2860,7 +2933,7 @@ gboolean vik_trw_layer_new_waypoint ( VikTrwLayer *vtl, GtkWindow *w, const VikC if ( elev != VIK_DEM_INVALID_ELEVATION ) wp->altitude = (gdouble)elev; - returned_name = a_dialog_waypoint ( w, default_name, wp, vtl->coord_mode, TRUE, &updated ); + returned_name = a_dialog_waypoint ( w, default_name, vtl, wp, vtl->coord_mode, TRUE, &updated ); if ( returned_name ) { @@ -2886,6 +2959,7 @@ static void trw_layer_new_wikipedia_wp_viewport ( gpointer lav[2] ) // Note the order is max part first then min part - thus reverse order of use in min_max function: vik_viewport_get_min_max_lat_lon ( vvp, &maxmin[1].lat, &maxmin[0].lat, &maxmin[1].lon, &maxmin[0].lon ); a_geonames_wikipedia_box((VikWindow *)(VIK_GTK_WINDOW_FROM_LAYER(vtl)), vtl, maxmin); + trw_layer_calculate_bounds_waypoints ( vtl ); vik_layers_panel_emit_update ( vlp ); } @@ -2897,6 +2971,7 @@ static void trw_layer_new_wikipedia_wp_layer ( gpointer lav[2] ) trw_layer_find_maxmin (vtl, maxmin); a_geonames_wikipedia_box((VikWindow *)(VIK_GTK_WINDOW_FROM_LAYER(vtl)), vtl, maxmin); + trw_layer_calculate_bounds_waypoints ( vtl ); vik_layers_panel_emit_update ( vlp ); } @@ -2959,23 +3034,21 @@ static void trw_layer_acquire_gps_cb ( gpointer lav[2] ) VikViewport *vvp = vik_window_viewport(vw); vik_datasource_gps_interface.mode = VIK_DATASOURCE_ADDTOLAYER; - a_acquire ( vw, vlp, vvp, &vik_datasource_gps_interface ); + a_acquire ( vw, vlp, vvp, &vik_datasource_gps_interface, NULL, NULL ); } -#ifdef VIK_CONFIG_GOOGLE /* - * Acquire into this TRW Layer from Google Directions + * Acquire into this TRW Layer from Directions */ -static void trw_layer_acquire_google_cb ( gpointer lav[2] ) +static void trw_layer_acquire_routing_cb ( gpointer lav[2] ) { VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]); VikLayersPanel *vlp = VIK_LAYERS_PANEL(lav[1]); VikWindow *vw = (VikWindow *)(VIK_GTK_WINDOW_FROM_LAYER(vtl)); VikViewport *vvp = vik_window_viewport(vw); - a_acquire ( vw, vlp, vvp, &vik_datasource_google_interface ); + a_acquire ( vw, vlp, vvp, &vik_datasource_routing_interface, NULL, NULL ); } -#endif #ifdef VIK_CONFIG_OPENSTREETMAP /* @@ -2988,7 +3061,7 @@ static void trw_layer_acquire_osm_cb ( gpointer lav[2] ) VikWindow *vw = (VikWindow *)(VIK_GTK_WINDOW_FROM_LAYER(vtl)); VikViewport *vvp = vik_window_viewport(vw); - a_acquire ( vw, vlp, vvp, &vik_datasource_osm_interface ); + a_acquire ( vw, vlp, vvp, &vik_datasource_osm_interface, NULL, NULL ); } /** @@ -3001,7 +3074,7 @@ static void trw_layer_acquire_osm_my_traces_cb ( gpointer lav[2] ) VikWindow *vw = (VikWindow *)(VIK_GTK_WINDOW_FROM_LAYER(vtl)); VikViewport *vvp = vik_window_viewport(vw); - a_acquire ( vw, vlp, vvp, &vik_datasource_osm_my_traces_interface ); + a_acquire ( vw, vlp, vvp, &vik_datasource_osm_my_traces_interface, NULL, NULL ); } #endif @@ -3016,7 +3089,7 @@ static void trw_layer_acquire_geocache_cb ( gpointer lav[2] ) VikWindow *vw = (VikWindow *)(VIK_GTK_WINDOW_FROM_LAYER(vtl)); VikViewport *vvp = vik_window_viewport(vw); - a_acquire ( vw, vlp, vvp, &vik_datasource_gc_interface ); + a_acquire ( vw, vlp, vvp, &vik_datasource_gc_interface, NULL, NULL ); } #endif @@ -3032,7 +3105,7 @@ static void trw_layer_acquire_geotagged_cb ( gpointer lav[2] ) VikViewport *vvp = vik_window_viewport(vw); vik_datasource_geotag_interface.mode = VIK_DATASOURCE_ADDTOLAYER; - a_acquire ( vw, vlp, vvp, &vik_datasource_geotag_interface ); + a_acquire ( vw, vlp, vvp, &vik_datasource_geotag_interface, NULL, NULL ); // Reverify thumbnails as they may have changed vtl->has_verified_thumbnails = FALSE; @@ -3158,7 +3231,7 @@ static void trw_layer_acquire_file_cb ( gpointer lav[2] ) VikWindow *vw = (VikWindow *)(VIK_GTK_WINDOW_FROM_LAYER(vtl)); VikViewport *vvp = vik_window_viewport(vw); - a_acquire ( vw, vlp, vvp, &vik_datasource_file_interface ); + a_acquire ( vw, vlp, vvp, &vik_datasource_file_interface, NULL, NULL ); } static void trw_layer_new_wp ( gpointer lav[2] ) @@ -3167,8 +3240,23 @@ static void trw_layer_new_wp ( gpointer lav[2] ) VikLayersPanel *vlp = VIK_LAYERS_PANEL(lav[1]); /* TODO longone: okay, if layer above (aggregate) is invisible but vtl->visible is true, this redraws for no reason. instead return true if you want to update. */ - if ( vik_trw_layer_new_waypoint ( vtl, VIK_GTK_WINDOW_FROM_LAYER(vtl), vik_viewport_get_center(vik_layers_panel_get_viewport(vlp))) && VIK_LAYER(vtl)->visible ) + if ( vik_trw_layer_new_waypoint ( vtl, VIK_GTK_WINDOW_FROM_LAYER(vtl), vik_viewport_get_center(vik_layers_panel_get_viewport(vlp))) && VIK_LAYER(vtl)->visible ) { + trw_layer_calculate_bounds_waypoints ( vtl ); vik_layers_panel_emit_update ( vlp ); + } +} + +static void new_track_create_common ( VikTrwLayer *vtl, gchar *name ) +{ + vtl->current_track = vik_track_new(); + vtl->current_track->visible = TRUE; + if ( vtl->drawmode == DRAWMODE_ALL_SAME_COLOR ) + // Create track with the preferred colour from the layer properties + vtl->current_track->color = vtl->track_color; + else + gdk_color_parse ( "#000000", &(vtl->current_track->color) ); + vtl->current_track->has_color = TRUE; + vik_trw_layer_add_track ( vtl, name, vtl->current_track ); } static void trw_layer_new_track ( gpointer lav[2] ) @@ -3177,9 +3265,7 @@ static void trw_layer_new_track ( gpointer lav[2] ) if ( ! vtl->current_track ) { gchar *name = trw_layer_new_unique_sublayer_name ( vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, _("Track")) ; - vtl->current_track = vik_track_new(); - vtl->current_track->visible = TRUE; - vik_trw_layer_add_track ( vtl, name, vtl->current_track ); + new_track_create_common ( vtl, name ); vik_window_enable_layer_tool ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), VIK_LAYER_TRW, TOOL_CREATE_TRACK ); } @@ -3424,12 +3510,11 @@ static void trw_layer_add_menu_items ( VikTrwLayer *vtl, GtkMenu *menu, gpointer gtk_menu_shell_append (GTK_MENU_SHELL (acquire_submenu), item); gtk_widget_show ( item ); -#ifdef VIK_CONFIG_GOOGLE - item = gtk_menu_item_new_with_mnemonic ( _("From Google _Directions...") ); - g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_acquire_google_cb), pass_along ); + /* FIXME: only add menu when at least a routing engine has support for Directions */ + item = gtk_menu_item_new_with_mnemonic ( _("From _Directions...") ); + g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_acquire_routing_cb), pass_along ); gtk_menu_shell_append (GTK_MENU_SHELL (acquire_submenu), item); gtk_widget_show ( item ); -#endif #ifdef VIK_CONFIG_OPENSTREETMAP item = gtk_menu_item_new_with_mnemonic ( _("From _OSM Traces...") ); @@ -3483,6 +3568,8 @@ static void trw_layer_add_menu_items ( VikTrwLayer *vtl, GtkMenu *menu, gpointer gtk_menu_shell_append (GTK_MENU_SHELL (acquire_submenu), item); gtk_widget_show ( item ); + vik_ext_tool_datasources_add_menu_items_to_menu ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), GTK_MENU (acquire_submenu) ); + GtkWidget *upload_submenu = gtk_menu_new (); item = gtk_image_menu_item_new_with_mnemonic ( _("_Upload") ); gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_GO_UP, GTK_ICON_SIZE_MENU) ); @@ -3581,11 +3668,8 @@ void vik_trw_layer_add_waypoint ( VikTrwLayer *vtl, gchar *name, VikWaypoint *wp GtkTreeIter *iter = g_malloc(sizeof(GtkTreeIter)); // Visibility column always needed for waypoints -#ifdef VIK_CONFIG_ALPHABETIZED_TRW - vik_treeview_add_sublayer_alphabetized ( VIK_LAYER(vtl)->vt, &(vtl->waypoints_iter), iter, name, vtl, GUINT_TO_POINTER(wp_uuid), VIK_TRW_LAYER_SUBLAYER_WAYPOINT, get_wp_sym_small (wp->symbol), TRUE, TRUE ); -#else vik_treeview_add_sublayer ( VIK_LAYER(vtl)->vt, &(vtl->waypoints_iter), iter, name, vtl, GUINT_TO_POINTER(wp_uuid), VIK_TRW_LAYER_SUBLAYER_WAYPOINT, get_wp_sym_small (wp->symbol), TRUE, TRUE ); -#endif + // Actual setting of visibility dependent on the waypoint vik_treeview_item_set_visible ( VIK_LAYER(vtl)->vt, iter, wp->visible ); @@ -3615,15 +3699,15 @@ void vik_trw_layer_add_track ( VikTrwLayer *vtl, gchar *name, VikTrack *t ) GtkTreeIter *iter = g_malloc(sizeof(GtkTreeIter)); // Visibility column always needed for tracks -#ifdef VIK_CONFIG_ALPHABETIZED_TRW - vik_treeview_add_sublayer_alphabetized ( VIK_LAYER(vtl)->vt, &(vtl->tracks_iter), iter, name, vtl, GUINT_TO_POINTER(tr_uuid), VIK_TRW_LAYER_SUBLAYER_TRACK, NULL, TRUE, TRUE ); -#else vik_treeview_add_sublayer ( VIK_LAYER(vtl)->vt, &(vtl->tracks_iter), iter, name, vtl, GUINT_TO_POINTER(tr_uuid), VIK_TRW_LAYER_SUBLAYER_TRACK, NULL, TRUE, TRUE ); -#endif + // Actual setting of visibility dependent on the track vik_treeview_item_set_visible ( VIK_LAYER(vtl)->vt, iter, t->visible ); g_hash_table_insert ( vtl->tracks_iters, GUINT_TO_POINTER(tr_uuid), iter ); + + // Sort now as post_read is not called on a realized track + vik_treeview_sort_children ( VIK_LAYER(vtl)->vt, &(vtl->tracks_iter), vtl->track_sort_order ); } g_hash_table_insert ( vtl->tracks, GUINT_TO_POINTER(tr_uuid), t ); @@ -3648,16 +3732,15 @@ void vik_trw_layer_add_route ( VikTrwLayer *vtl, gchar *name, VikTrack *t ) } GtkTreeIter *iter = g_malloc(sizeof(GtkTreeIter)); - // Visibility column always needed for tracks -#ifdef VIK_CONFIG_ALPHABETIZED_TRW - vik_treeview_add_sublayer_alphabetized ( VIK_LAYER(vtl)->vt, &(vtl->routes_iter), iter, name, vtl, GUINT_TO_POINTER(rt_uuid), VIK_TRW_LAYER_SUBLAYER_ROUTE, NULL, TRUE, TRUE ); -#else + // Visibility column always needed for routes vik_treeview_add_sublayer ( VIK_LAYER(vtl)->vt, &(vtl->routes_iter), iter, name, vtl, GUINT_TO_POINTER(rt_uuid), VIK_TRW_LAYER_SUBLAYER_ROUTE, NULL, TRUE, TRUE ); -#endif - // Actual setting of visibility dependent on the track + // Actual setting of visibility dependent on the route vik_treeview_item_set_visible ( VIK_LAYER(vtl)->vt, iter, t->visible ); g_hash_table_insert ( vtl->routes_iters, GUINT_TO_POINTER(rt_uuid), iter ); + + // Sort now as post_read is not called on a realized route + vik_treeview_sort_children ( VIK_LAYER(vtl)->vt, &(vtl->routes_iter), vtl->track_sort_order ); } g_hash_table_insert ( vtl->routes, GUINT_TO_POINTER(rt_uuid), t ); @@ -3672,6 +3755,27 @@ void trw_layer_cancel_tps_of_track ( VikTrwLayer *vtl, VikTrack *trk ) trw_layer_cancel_current_tp ( vtl, FALSE ); } +/** + * Normally this is done to due the waypoint size preference having changed + */ +void vik_trw_layer_reset_waypoints ( VikTrwLayer *vtl ) +{ + GHashTableIter iter; + gpointer key, value; + + // Foreach waypoint + g_hash_table_iter_init ( &iter, vtl->waypoints ); + while ( g_hash_table_iter_next ( &iter, &key, &value ) ) { + VikWaypoint *wp = VIK_WAYPOINT(value); + if ( wp->symbol ) { + // Reapply symbol setting to update the pixbuf + gchar *tmp_symbol = g_strdup ( wp->symbol ); + vik_waypoint_set_symbol ( wp, tmp_symbol ); + g_free ( tmp_symbol ); + } + } +} + gchar *trw_layer_new_unique_sublayer_name (VikTrwLayer *vtl, gint sublayer_type, const gchar *name) { gint i = 2; @@ -3742,10 +3846,19 @@ static void trw_layer_enum_item ( gpointer id, GList **tr, GList **l ) */ static void trw_layer_move_item ( VikTrwLayer *vtl_src, VikTrwLayer *vtl_dest, gpointer id, gint type ) { + // TODO reconsider strategy when moving within layer (if anything...) + gboolean rename = ( vtl_src != vtl_dest ); + if ( ! rename ) + return; + if (type == VIK_TRW_LAYER_SUBLAYER_TRACK) { VikTrack *trk = g_hash_table_lookup ( vtl_src->tracks, id ); - gchar *newname = trw_layer_new_unique_sublayer_name(vtl_dest, type, trk->name); + gchar *newname; + if ( rename ) + newname = trw_layer_new_unique_sublayer_name ( vtl_dest, type, trk->name ); + else + newname = g_strdup ( trk->name ); VikTrack *trk2 = vik_track_copy ( trk, TRUE ); vik_trw_layer_add_track ( vtl_dest, newname, trk2 ); @@ -3755,7 +3868,11 @@ static void trw_layer_move_item ( VikTrwLayer *vtl_src, VikTrwLayer *vtl_dest, g if (type == VIK_TRW_LAYER_SUBLAYER_ROUTE) { VikTrack *trk = g_hash_table_lookup ( vtl_src->routes, id ); - gchar *newname = trw_layer_new_unique_sublayer_name(vtl_dest, type, trk->name); + gchar *newname; + if ( rename ) + newname = trw_layer_new_unique_sublayer_name ( vtl_dest, type, trk->name ); + else + newname = g_strdup ( trk->name ); VikTrack *trk2 = vik_track_copy ( trk, TRUE ); vik_trw_layer_add_route ( vtl_dest, newname, trk2 ); @@ -3765,11 +3882,19 @@ static void trw_layer_move_item ( VikTrwLayer *vtl_src, VikTrwLayer *vtl_dest, g if (type == VIK_TRW_LAYER_SUBLAYER_WAYPOINT) { VikWaypoint *wp = g_hash_table_lookup ( vtl_src->waypoints, id ); - gchar *newname = trw_layer_new_unique_sublayer_name(vtl_dest, type, wp->name); + gchar *newname; + if ( rename ) + newname = trw_layer_new_unique_sublayer_name ( vtl_dest, type, wp->name ); + else + newname = g_strdup ( wp->name ); VikWaypoint *wp2 = vik_waypoint_copy ( wp ); vik_trw_layer_add_waypoint ( vtl_dest, newname, wp2 ); trw_layer_delete_waypoint ( vtl_src, wp ); + + // Recalculate bounds even if not renamed as maybe dragged between layers + trw_layer_calculate_bounds_waypoints ( vtl_dest ); + trw_layer_calculate_bounds_waypoints ( vtl_src ); } } @@ -3796,8 +3921,7 @@ static void trw_layer_drag_drop_request ( VikTrwLayer *vtl_src, VikTrwLayer *vtl while (iter) { if (type==VIK_TRW_LAYER_SUBLAYER_TRACKS) { trw_layer_move_item ( vtl_src, vtl_dest, iter->data, VIK_TRW_LAYER_SUBLAYER_TRACK); - } - else if (type==VIK_TRW_LAYER_SUBLAYER_ROUTES) { + } else if (type==VIK_TRW_LAYER_SUBLAYER_ROUTES) { trw_layer_move_item ( vtl_src, vtl_dest, iter->data, VIK_TRW_LAYER_SUBLAYER_ROUTE); } else { trw_layer_move_item ( vtl_src, vtl_dest, iter->data, VIK_TRW_LAYER_SUBLAYER_WAYPOINT); @@ -4187,6 +4311,30 @@ static void trw_layer_delete_item ( gpointer pass_along[6] ) vik_layer_emit_update ( VIK_LAYER(vtl) ); } +/** + * Rename waypoint and maintain corresponding name of waypoint in the treeview + */ +static void trw_layer_waypoint_rename ( VikTrwLayer *vtl, VikWaypoint *wp, const gchar *new_name ) +{ + vik_waypoint_set_name ( wp, new_name ); + + // Now update the treeview as well + wpu_udata udataU; + udataU.wp = wp; + udataU.uuid = NULL; + + // Need key of it for treeview update + gpointer *wpf = g_hash_table_find ( vtl->waypoints, (GHRFunc) trw_layer_waypoint_find_uuid, &udataU ); + + if ( wpf && udataU.uuid ) { + GtkTreeIter *it = g_hash_table_lookup ( vtl->waypoints_iters, udataU.uuid ); + + if ( it ) { + vik_treeview_item_set_name ( VIK_LAYER(vtl)->vt, it, new_name ); + vik_treeview_sort_children ( VIK_LAYER(vtl)->vt, &(vtl->waypoints_iter), vtl->wp_sort_order ); + } + } +} static void trw_layer_properties_item ( gpointer pass_along[7] ) { @@ -4198,9 +4346,11 @@ static void trw_layer_properties_item ( gpointer pass_along[7] ) if ( wp && wp->name ) { gboolean updated = FALSE; - a_dialog_waypoint ( VIK_GTK_WINDOW_FROM_LAYER(vtl), wp->name, wp, vtl->coord_mode, FALSE, &updated ); + gchar *new_name = a_dialog_waypoint ( VIK_GTK_WINDOW_FROM_LAYER(vtl), wp->name, vtl, wp, vtl->coord_mode, FALSE, &updated ); + if ( new_name ) + trw_layer_waypoint_rename ( vtl, wp, new_name ); - if ( updated && wp->symbol && pass_along[6] ) + if ( updated && pass_along[6] ) vik_treeview_item_set_icon ( VIK_LAYER(vtl)->vt, pass_along[6], get_wp_sym_small (wp->symbol) ); if ( updated && VIK_LAYER(vtl)->visible ) @@ -4389,7 +4539,6 @@ 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 /** * extend a track using route finder */ @@ -4410,7 +4559,6 @@ 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] ) { @@ -4505,7 +4653,7 @@ static void trw_layer_goto_track_min_alt ( gpointer pass_along[6] ) */ static void trw_layer_auto_track_view ( gpointer pass_along[6] ) { - VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0]; + VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]); VikTrack *trk; if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE ) trk = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] ); @@ -4516,11 +4664,11 @@ static void trw_layer_auto_track_view ( gpointer pass_along[6] ) { struct LatLon maxmin[2] = { {0,0}, {0,0} }; trw_layer_find_maxmin_tracks ( NULL, trk, maxmin ); - trw_layer_zoom_to_show_latlons ( VIK_TRW_LAYER(pass_along[0]), pass_along[5], maxmin ); + trw_layer_zoom_to_show_latlons ( vtl, pass_along[5], maxmin ); if ( pass_along[1] ) vik_layers_panel_emit_update ( VIK_LAYERS_PANEL(pass_along[1]) ); else - vik_layer_emit_update ( VIK_LAYER(pass_along[0]) ); + vik_layer_emit_update ( VIK_LAYER(vtl) ); } } @@ -4734,8 +4882,7 @@ static void trw_layer_merge_with_other ( gpointer pass_along[6] ) merge_track = vik_trw_layer_get_track ( vtl, l->data ); if (merge_track) { - track->trackpoints = g_list_concat(track->trackpoints, merge_track->trackpoints); - merge_track->trackpoints = NULL; + vik_track_steal_and_append_trackpoints ( track, merge_track ); if ( track->is_route ) vik_trw_layer_delete_route (vtl, merge_track); else @@ -4743,10 +4890,10 @@ static void trw_layer_merge_with_other ( gpointer pass_along[6] ) track->trackpoints = g_list_sort(track->trackpoints, trackpoint_compare); } } - /* TODO: free data before free merge_list */ for (l = merge_list; l != NULL; l = g_list_next(l)) g_free(l->data); g_list_free(merge_list); + vik_layer_emit_update( VIK_LAYER(vtl) ); } } @@ -4823,8 +4970,7 @@ static void trw_layer_append_track ( gpointer pass_along[6] ) append_track = vik_trw_layer_get_track ( vtl, l->data ); if ( append_track ) { - trk->trackpoints = g_list_concat(trk->trackpoints, append_track->trackpoints); - append_track->trackpoints = NULL; + vik_track_steal_and_append_trackpoints ( trk, append_track ); if ( trk->is_route ) vik_trw_layer_delete_route (vtl, append_track); else @@ -4834,6 +4980,7 @@ static void trw_layer_append_track ( gpointer pass_along[6] ) for (l = append_list; l != NULL; l = g_list_next(l)) g_free(l->data); g_list_free(append_list); + vik_layer_emit_update( VIK_LAYER(vtl) ); } } @@ -4917,8 +5064,7 @@ static void trw_layer_append_other ( gpointer pass_along[6] ) } } - trk->trackpoints = g_list_concat(trk->trackpoints, append_track->trackpoints); - append_track->trackpoints = NULL; + vik_track_steal_and_append_trackpoints ( trk, append_track ); // Delete copied which is FROM THE OTHER TYPE list if ( trk->is_route ) @@ -5030,8 +5176,7 @@ static void trw_layer_merge_by_timestamp ( gpointer pass_along[6] ) */ /* remove trackpoints from merged track, delete track */ - orig_trk->trackpoints = g_list_concat(orig_trk->trackpoints, VIK_TRACK(l->data)->trackpoints); - VIK_TRACK(l->data)->trackpoints = NULL; + vik_track_steal_and_append_trackpoints ( orig_trk, VIK_TRACK(l->data) ); vik_trw_layer_delete_track (vtl, VIK_TRACK(l->data)); // Tracks have changed, therefore retry again against all the remaining tracks @@ -5044,6 +5189,7 @@ static void trw_layer_merge_by_timestamp ( gpointer pass_along[6] ) } g_list_free(nearby_tracks); + vik_layer_emit_update( VIK_LAYER(vtl) ); } @@ -5068,6 +5214,9 @@ static void trw_layer_split_at_selected_trackpoint ( VikTrwLayer *vtl, gint subt vtl->current_tpl->next->prev = newglist; /* end old track here */ vtl->current_tpl->next = NULL; + // Bounds of the selected track changed due to the split + vik_track_calculate_bounds ( vtl->current_tp_track ); + vtl->current_tpl = newglist; /* change tp to first of new track. */ vtl->current_tp_track = tr; @@ -5076,6 +5225,9 @@ static void trw_layer_split_at_selected_trackpoint ( VikTrwLayer *vtl, gint subt else vik_trw_layer_add_track ( vtl, name, tr ); + // Bounds of the new track created by the split + vik_track_calculate_bounds ( tr ); + trku_udata udata; udata.trk = tr; udata.uuid = NULL; @@ -5126,10 +5278,19 @@ static void trw_layer_split_by_timestamp ( gpointer pass_along[6] ) while (iter) { ts = VIK_TRACKPOINT(iter->data)->timestamp; + + // Check for unordered time points - this is quite a rare occurence - unless one has reversed a track. if (ts < prev_ts) { - g_print("panic: ts < prev_ts: this should never happen!\n"); + gchar tmp_str[64]; + strftime ( tmp_str, sizeof(tmp_str), "%c", localtime(&ts) ); + if ( a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(vtl), + _("Can not split track due to trackpoints not ordered in time - such as at %s.\n\nGoto this trackpoint?"), + tmp_str ) ) { + goto_coord ( pass_along[1], vtl, pass_along[5], &(VIK_TRACKPOINT(iter->data)->coord) ); + } return; } + if (ts - prev_ts > thr*60) { /* flush accumulated trackpoints into new list */ newlists = g_list_append(newlists, g_list_reverse(newtps)); @@ -5160,6 +5321,7 @@ static void trw_layer_split_by_timestamp ( gpointer pass_along[6] ) vik_trw_layer_add_track(vtl, new_tr_name, tr); /* g_print("adding track %s, times %d - %d\n", new_tr_name, VIK_TRACKPOINT(tr->trackpoints->data)->timestamp, VIK_TRACKPOINT(g_list_last(tr->trackpoints)->data)->timestamp);*/ + vik_track_calculate_bounds ( tr ); iter = g_list_next(iter); } @@ -5246,6 +5408,8 @@ static void trw_layer_split_by_n_points ( gpointer pass_along[6] ) new_tr_name = trw_layer_new_unique_sublayer_name ( vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, track->name); vik_trw_layer_add_track(vtl, new_tr_name, tr); } + vik_track_calculate_bounds ( tr ); + iter = g_list_next(iter); } // Remove original track and then update the display @@ -5378,11 +5542,6 @@ static void trw_layer_reverse ( gpointer pass_along[6] ) if ( ! track ) return; - // Check valid track - GList *trps = track->trackpoints; - if ( !trps ) - return; - vik_track_reverse ( track ); vik_layer_emit_update ( VIK_LAYER(pass_along[0]) ); @@ -5542,9 +5701,10 @@ static void vik_trw_layer_uniquify_tracks ( VikTrwLayer *vtl, VikLayersPanel *vl if ( it ) { vik_treeview_item_set_name ( VIK_LAYER(vtl)->vt, it, newname ); -#ifdef VIK_CONFIG_ALPHABETIZED_TRW - vik_treeview_sublayer_realphabetize ( VIK_LAYER(vtl)->vt, it, newname ); -#endif + if ( ontrack ) + vik_treeview_sort_children ( VIK_LAYER(vtl)->vt, &(vtl->tracks_iter), vtl->wp_sort_order ); + else + vik_treeview_sort_children ( VIK_LAYER(vtl)->vt, &(vtl->routes_iter), vtl->wp_sort_order ); } } @@ -5563,6 +5723,52 @@ static void vik_trw_layer_uniquify_tracks ( VikTrwLayer *vtl, VikLayersPanel *vl vik_layers_panel_emit_update ( vlp ); } +static void trw_layer_sort_order_a2z ( gpointer pass_along[6] ) +{ + VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]); + GtkTreeIter *iter; + + switch (GPOINTER_TO_INT (pass_along[2])) { + case VIK_TRW_LAYER_SUBLAYER_TRACKS: + iter = &(vtl->tracks_iter); + vtl->track_sort_order = VL_SO_ALPHABETICAL_ASCENDING; + break; + case VIK_TRW_LAYER_SUBLAYER_ROUTES: + iter = &(vtl->routes_iter); + vtl->track_sort_order = VL_SO_ALPHABETICAL_ASCENDING; + break; + default: // VIK_TRW_LAYER_SUBLAYER_WAYPOINTS: + iter = &(vtl->waypoints_iter); + vtl->wp_sort_order = VL_SO_ALPHABETICAL_ASCENDING; + break; + } + + vik_treeview_sort_children ( VIK_LAYER(vtl)->vt, iter, VL_SO_ALPHABETICAL_ASCENDING ); +} + +static void trw_layer_sort_order_z2a ( gpointer pass_along[6] ) +{ + VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]); + GtkTreeIter *iter; + + switch (GPOINTER_TO_INT (pass_along[2])) { + case VIK_TRW_LAYER_SUBLAYER_TRACKS: + iter = &(vtl->tracks_iter); + vtl->track_sort_order = VL_SO_ALPHABETICAL_DESCENDING; + break; + case VIK_TRW_LAYER_SUBLAYER_ROUTES: + iter = &(vtl->routes_iter); + vtl->track_sort_order = VL_SO_ALPHABETICAL_DESCENDING; + break; + default: // VIK_TRW_LAYER_SUBLAYER_WAYPOINTS: + iter = &(vtl->waypoints_iter); + vtl->wp_sort_order = VL_SO_ALPHABETICAL_DESCENDING; + break; + } + + vik_treeview_sort_children ( VIK_LAYER(vtl)->vt, iter, VL_SO_ALPHABETICAL_DESCENDING ); +} + /** * */ @@ -5753,26 +5959,8 @@ static void vik_trw_layer_uniquify_waypoints ( VikTrwLayer *vtl, VikLayersPanel // Rename it gchar *newname = trw_layer_new_unique_sublayer_name ( vtl, VIK_TRW_LAYER_SUBLAYER_WAYPOINT, udata.same_waypoint_name ); - vik_waypoint_set_name ( waypoint, newname ); - wpu_udata udataU; - udataU.wp = waypoint; - udataU.uuid = NULL; - - // Need want key of it for treeview update - gpointer *wpf = g_hash_table_find ( vtl->waypoints, (GHRFunc) trw_layer_waypoint_find_uuid, &udataU ); - - if ( wpf && udataU.uuid ) { - - GtkTreeIter *it = g_hash_table_lookup ( vtl->waypoints_iters, udataU.uuid ); - - if ( it ) { - vik_treeview_item_set_name ( VIK_LAYER(vtl)->vt, it, newname ); -#ifdef VIK_CONFIG_ALPHABETIZED_TRW - vik_treeview_sublayer_realphabetize ( VIK_LAYER(vtl)->vt, it, newname ); -#endif - } - } + trw_layer_waypoint_rename ( vtl, waypoint, newname ); // Start trying to find same names again... waypoint_names = NULL; @@ -5833,11 +6021,175 @@ static void trw_layer_delete_waypoints_from_selection ( gpointer lav[2] ) trw_layer_delete_waypoint_by_name (vtl, l->data); } g_list_free(delete_list); + + trw_layer_calculate_bounds_waypoints ( vtl ); vik_layer_emit_update( VIK_LAYER(vtl) ); } } +/** + * + */ +static void trw_layer_iter_visibility_toggle ( gpointer id, GtkTreeIter *it, VikTreeview *vt ) +{ + vik_treeview_item_toggle_visible ( vt, it ); +} + +/** + * + */ +static void trw_layer_iter_visibility ( gpointer id, GtkTreeIter *it, gpointer vis_data[2] ) +{ + vik_treeview_item_set_visible ( (VikTreeview*)vis_data[0], it, GPOINTER_TO_INT (vis_data[1]) ); +} + +/** + * + */ +static void trw_layer_waypoints_visibility ( gpointer id, VikWaypoint *wp, gpointer on_off ) +{ + wp->visible = GPOINTER_TO_INT (on_off); +} + +/** + * + */ +static void trw_layer_waypoints_toggle_visibility ( gpointer id, VikWaypoint *wp ) +{ + wp->visible = !wp->visible; +} + +/** + * + */ +static void trw_layer_waypoints_visibility_off ( gpointer lav[2] ) +{ + VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]); + gpointer vis_data[2] = { VIK_LAYER(vtl)->vt, GINT_TO_POINTER(FALSE) }; + g_hash_table_foreach ( vtl->waypoints_iters, (GHFunc) trw_layer_iter_visibility, vis_data ); + g_hash_table_foreach ( vtl->waypoints, (GHFunc) trw_layer_waypoints_visibility, vis_data[1] ); + // Redraw + vik_layer_emit_update ( VIK_LAYER(vtl) ); +} + +/** + * + */ +static void trw_layer_waypoints_visibility_on ( gpointer lav[2] ) +{ + VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]); + gpointer vis_data[2] = { VIK_LAYER(vtl)->vt, GINT_TO_POINTER(TRUE) }; + g_hash_table_foreach ( vtl->waypoints_iters, (GHFunc) trw_layer_iter_visibility, vis_data ); + g_hash_table_foreach ( vtl->waypoints, (GHFunc) trw_layer_waypoints_visibility, vis_data[1] ); + // Redraw + vik_layer_emit_update ( VIK_LAYER(vtl) ); +} + +/** + * + */ +static void trw_layer_waypoints_visibility_toggle ( gpointer lav[2] ) +{ + VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]); + g_hash_table_foreach ( vtl->waypoints_iters, (GHFunc) trw_layer_iter_visibility_toggle, VIK_LAYER(vtl)->vt ); + g_hash_table_foreach ( vtl->waypoints, (GHFunc) trw_layer_waypoints_toggle_visibility, NULL ); + // Redraw + vik_layer_emit_update ( VIK_LAYER(vtl) ); +} + +/** + * + */ +static void trw_layer_tracks_visibility ( gpointer id, VikTrack *trk, gpointer on_off ) +{ + trk->visible = GPOINTER_TO_INT (on_off); +} + +/** + * + */ +static void trw_layer_tracks_toggle_visibility ( gpointer id, VikTrack *trk ) +{ + trk->visible = !trk->visible; +} + +/** + * + */ +static void trw_layer_tracks_visibility_off ( gpointer lav[2] ) +{ + VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]); + gpointer vis_data[2] = { VIK_LAYER(vtl)->vt, GINT_TO_POINTER(FALSE) }; + g_hash_table_foreach ( vtl->tracks_iters, (GHFunc) trw_layer_iter_visibility, vis_data ); + g_hash_table_foreach ( vtl->tracks, (GHFunc) trw_layer_tracks_visibility, vis_data[1] ); + // Redraw + vik_layer_emit_update ( VIK_LAYER(vtl) ); +} + +/** + * + */ +static void trw_layer_tracks_visibility_on ( gpointer lav[2] ) +{ + VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]); + gpointer vis_data[2] = { VIK_LAYER(vtl)->vt, GINT_TO_POINTER(TRUE) }; + g_hash_table_foreach ( vtl->tracks_iters, (GHFunc) trw_layer_iter_visibility, vis_data ); + g_hash_table_foreach ( vtl->tracks, (GHFunc) trw_layer_tracks_visibility, vis_data[1] ); + // Redraw + vik_layer_emit_update ( VIK_LAYER(vtl) ); +} + +/** + * + */ +static void trw_layer_tracks_visibility_toggle ( gpointer lav[2] ) +{ + VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]); + g_hash_table_foreach ( vtl->tracks_iters, (GHFunc) trw_layer_iter_visibility_toggle, VIK_LAYER(vtl)->vt ); + g_hash_table_foreach ( vtl->tracks, (GHFunc) trw_layer_tracks_toggle_visibility, NULL ); + // Redraw + vik_layer_emit_update ( VIK_LAYER(vtl) ); +} + +/** + * + */ +static void trw_layer_routes_visibility_off ( gpointer lav[2] ) +{ + VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]); + gpointer vis_data[2] = { VIK_LAYER(vtl)->vt, GINT_TO_POINTER(FALSE) }; + g_hash_table_foreach ( vtl->routes_iters, (GHFunc) trw_layer_iter_visibility, vis_data ); + g_hash_table_foreach ( vtl->routes, (GHFunc) trw_layer_tracks_visibility, vis_data[1] ); + // Redraw + vik_layer_emit_update ( VIK_LAYER(vtl) ); +} + +/** + * + */ +static void trw_layer_routes_visibility_on ( gpointer lav[2] ) +{ + VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]); + gpointer vis_data[2] = { VIK_LAYER(vtl)->vt, GINT_TO_POINTER(TRUE) }; + g_hash_table_foreach ( vtl->routes_iters, (GHFunc) trw_layer_iter_visibility, vis_data ); + g_hash_table_foreach ( vtl->routes, (GHFunc) trw_layer_tracks_visibility, vis_data[1] ); + // Redraw + vik_layer_emit_update ( VIK_LAYER(vtl) ); +} + +/** + * + */ +static void trw_layer_routes_visibility_toggle ( gpointer lav[2] ) +{ + VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]); + g_hash_table_foreach ( vtl->routes_iters, (GHFunc) trw_layer_iter_visibility_toggle, VIK_LAYER(vtl)->vt ); + g_hash_table_foreach ( vtl->routes, (GHFunc) trw_layer_tracks_toggle_visibility, NULL ); + // Redraw + vik_layer_emit_update ( VIK_LAYER(vtl) ); +} + static void trw_layer_goto_waypoint ( gpointer pass_along[6] ) { VikWaypoint *wp = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->waypoints, pass_along[3] ); @@ -5874,8 +6226,9 @@ static const gchar* trw_layer_sublayer_rename_request ( VikTrwLayer *l, const gc VikWaypoint *wp = g_hash_table_lookup ( l->waypoints, sublayer ); // No actual change to the name supplied - if (strcmp(newname, wp->name) == 0 ) - return NULL; + if ( wp->name ) + if (strcmp(newname, wp->name) == 0 ) + return NULL; VikWaypoint *wpf = vik_trw_layer_get_waypoint ( l, newname ); @@ -5890,9 +6243,8 @@ static const gchar* trw_layer_sublayer_rename_request ( VikTrwLayer *l, const gc // Update WP name and refresh the treeview vik_waypoint_set_name (wp, newname); -#ifdef VIK_CONFIG_ALPHABETIZED_TRW - vik_treeview_sublayer_realphabetize ( VIK_LAYER(l)->vt, iter, newname ); -#endif + vik_treeview_item_set_name ( VIK_LAYER(l)->vt, iter, newname ); + vik_treeview_sort_children ( VIK_LAYER(l)->vt, &(l->waypoints_iter), l->wp_sort_order ); vik_layers_panel_emit_update ( VIK_LAYERS_PANEL(vlp) ); @@ -5904,8 +6256,9 @@ static const gchar* trw_layer_sublayer_rename_request ( VikTrwLayer *l, const gc VikTrack *trk = g_hash_table_lookup ( l->tracks, sublayer ); // No actual change to the name supplied - if (strcmp(newname, trk->name) == 0) - return NULL; + if ( trk->name ) + if (strcmp(newname, trk->name) == 0) + return NULL; VikTrack *trkf = vik_trw_layer_get_track ( l, (gpointer) newname ); @@ -5927,9 +6280,8 @@ static const gchar* trw_layer_sublayer_rename_request ( VikTrwLayer *l, const gc // Property Dialog of the track vik_trw_layer_propwin_update ( trk ); -#ifdef VIK_CONFIG_ALPHABETIZED_TRW - vik_treeview_sublayer_realphabetize ( VIK_LAYER(l)->vt, iter, newname ); -#endif + vik_treeview_item_set_name ( VIK_LAYER(l)->vt, iter, newname ); + vik_treeview_sort_children ( VIK_LAYER(l)->vt, &(l->tracks_iter), l->track_sort_order ); vik_layers_panel_emit_update ( VIK_LAYERS_PANEL(vlp) ); @@ -5941,8 +6293,9 @@ static const gchar* trw_layer_sublayer_rename_request ( VikTrwLayer *l, const gc VikTrack *trk = g_hash_table_lookup ( l->routes, sublayer ); // No actual change to the name supplied - if (strcmp(newname, trk->name) == 0) - return NULL; + if ( trk->name ) + if (strcmp(newname, trk->name) == 0) + return NULL; VikTrack *trkf = vik_trw_layer_get_route ( l, (gpointer) newname ); @@ -5964,9 +6317,8 @@ static const gchar* trw_layer_sublayer_rename_request ( VikTrwLayer *l, const gc // Property Dialog of the track vik_trw_layer_propwin_update ( trk ); -#ifdef VIK_CONFIG_ALPHABETIZED_TRW - vik_treeview_sublayer_realphabetize ( VIK_LAYER(l)->vt, iter, newname ); -#endif + vik_treeview_item_set_name ( VIK_LAYER(l)->vt, iter, newname ); + vik_treeview_sort_children ( VIK_LAYER(l)->vt, &(l->tracks_iter), l->track_sort_order ); vik_layers_panel_emit_update ( VIK_LAYERS_PANEL(vlp) ); @@ -6202,6 +6554,30 @@ static gboolean trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *men g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_delete_waypoints_from_selection), pass_along ); gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); gtk_widget_show ( item ); + + GtkWidget *vis_submenu = gtk_menu_new (); + item = gtk_menu_item_new_with_mnemonic ( _("_Visibility") ); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + gtk_widget_show ( item ); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), vis_submenu ); + + item = gtk_image_menu_item_new_with_mnemonic ( _("_Show All Waypoints") ); + gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_APPLY, GTK_ICON_SIZE_MENU) ); + g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_waypoints_visibility_on), pass_along ); + gtk_menu_shell_append ( GTK_MENU_SHELL(vis_submenu), item ); + gtk_widget_show ( item ); + + item = gtk_image_menu_item_new_with_mnemonic ( _("_Hide All Waypoints") ); + gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_CLEAR, GTK_ICON_SIZE_MENU) ); + g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_waypoints_visibility_off), pass_along ); + gtk_menu_shell_append ( GTK_MENU_SHELL(vis_submenu), item ); + gtk_widget_show ( item ); + + item = gtk_image_menu_item_new_with_mnemonic ( _("_Toggle") ); + gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REFRESH, GTK_ICON_SIZE_MENU) ); + g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_waypoints_visibility_toggle), pass_along ); + gtk_menu_shell_append ( GTK_MENU_SHELL(vis_submenu), item ); + gtk_widget_show ( item ); } if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACKS ) @@ -6244,6 +6620,30 @@ static gboolean trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *men g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_delete_tracks_from_selection), pass_along ); gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); gtk_widget_show ( item ); + + GtkWidget *vis_submenu = gtk_menu_new (); + item = gtk_menu_item_new_with_mnemonic ( _("_Visibility") ); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + gtk_widget_show ( item ); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), vis_submenu ); + + item = gtk_image_menu_item_new_with_mnemonic ( _("_Show All Tracks") ); + gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_APPLY, GTK_ICON_SIZE_MENU) ); + g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_tracks_visibility_on), pass_along ); + gtk_menu_shell_append ( GTK_MENU_SHELL(vis_submenu), item ); + gtk_widget_show ( item ); + + item = gtk_image_menu_item_new_with_mnemonic ( _("_Hide All Tracks") ); + gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_CLEAR, GTK_ICON_SIZE_MENU) ); + g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_tracks_visibility_off), pass_along ); + gtk_menu_shell_append ( GTK_MENU_SHELL(vis_submenu), item ); + gtk_widget_show ( item ); + + item = gtk_image_menu_item_new_with_mnemonic ( _("_Toggle") ); + gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REFRESH, GTK_ICON_SIZE_MENU) ); + g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_tracks_visibility_toggle), pass_along ); + gtk_menu_shell_append ( GTK_MENU_SHELL(vis_submenu), item ); + gtk_widget_show ( item ); } if ( subtype == VIK_TRW_LAYER_SUBLAYER_ROUTES ) @@ -6287,6 +6687,52 @@ static gboolean trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *men g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_delete_routes_from_selection), pass_along ); gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); gtk_widget_show ( item ); + + GtkWidget *vis_submenu = gtk_menu_new (); + item = gtk_menu_item_new_with_mnemonic ( _("_Visibility") ); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + gtk_widget_show ( item ); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), vis_submenu ); + + item = gtk_image_menu_item_new_with_mnemonic ( _("_Show All Routes") ); + gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_APPLY, GTK_ICON_SIZE_MENU) ); + g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_routes_visibility_on), pass_along ); + gtk_menu_shell_append ( GTK_MENU_SHELL(vis_submenu), item ); + gtk_widget_show ( item ); + + item = gtk_image_menu_item_new_with_mnemonic ( _("_Hide All Routes") ); + gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_CLEAR, GTK_ICON_SIZE_MENU) ); + g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_routes_visibility_off), pass_along ); + gtk_menu_shell_append ( GTK_MENU_SHELL(vis_submenu), item ); + gtk_widget_show ( item ); + + item = gtk_image_menu_item_new_with_mnemonic ( _("_Toggle") ); + gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REFRESH, GTK_ICON_SIZE_MENU) ); + g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_routes_visibility_toggle), pass_along ); + gtk_menu_shell_append ( GTK_MENU_SHELL(vis_submenu), item ); + gtk_widget_show ( item ); + } + + + if ( subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINTS || subtype == VIK_TRW_LAYER_SUBLAYER_TRACKS || subtype == VIK_TRW_LAYER_SUBLAYER_ROUTES ) { + GtkWidget *submenu_sort = gtk_menu_new (); + item = gtk_image_menu_item_new_with_mnemonic ( _("_Sort") ); + gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REFRESH, GTK_ICON_SIZE_MENU) ); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + gtk_widget_show ( item ); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu_sort ); + + item = gtk_image_menu_item_new_with_mnemonic ( _("Name _Ascending") ); + gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_SORT_ASCENDING, GTK_ICON_SIZE_MENU) ); + g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_sort_order_a2z), pass_along ); + gtk_menu_shell_append ( GTK_MENU_SHELL(submenu_sort), item ); + gtk_widget_show ( item ); + + item = gtk_image_menu_item_new_with_mnemonic ( _("Name _Descending") ); + gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_SORT_DESCENDING, GTK_ICON_SIZE_MENU) ); + g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_sort_order_z2a), pass_along ); + gtk_menu_shell_append ( GTK_MENU_SHELL(submenu_sort), item ); + gtk_widget_show ( item ); } GtkWidget *upload_submenu = gtk_menu_new (); @@ -6516,7 +6962,6 @@ 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 if ( subtype == VIK_TRW_LAYER_SUBLAYER_ROUTE ) { 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 @@ -6524,7 +6969,6 @@ 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 ); } -#endif // ATM can't upload a single waypoint but can do waypoints to a GPS if ( subtype != VIK_TRW_LAYER_SUBLAYER_WAYPOINT ) { @@ -6663,6 +7107,7 @@ static void trw_layer_insert_tp_after_current_tp ( VikTrwLayer *vtl ) gint index = g_list_index ( trk->trackpoints, tp_current ); if ( index > -1 ) { + // NB no recalculation of bounds since it is inserted between points trk->trackpoints = g_list_insert ( trk->trackpoints, tp_new, index+1 ); } } @@ -6727,8 +7172,10 @@ static void trw_layer_tpwin_response ( VikTrwLayer *vtl, gint response ) vtl->current_tpl = new_tpl; // Reset dialog with the available adjacent trackpoint - if ( vtl->current_tp_track ) + if ( vtl->current_tp_track ) { + vik_track_calculate_bounds ( vtl->current_tp_track ); vik_trw_layer_tpwin_set_tp ( vtl->tpwin, new_tpl, vtl->current_tp_track->name ); + } vik_layer_emit_update(VIK_LAYER(vtl)); } @@ -6761,6 +7208,95 @@ static void trw_layer_tpwin_response ( VikTrwLayer *vtl, gint response ) vik_layer_emit_update(VIK_LAYER(vtl)); } +/** + * trw_layer_dialog_shift: + * @vertical: The reposition strategy. If Vertical moves dialog vertically, otherwise moves it horizontally + * + * Try to reposition a dialog if it's over the specified coord + * so to not obscure the item of interest + */ +void trw_layer_dialog_shift ( VikTrwLayer *vtl, GtkWindow *dialog, VikCoord *coord, gboolean vertical ) +{ + GtkWindow *parent = VIK_GTK_WINDOW_FROM_LAYER(vtl); //i.e. the main window + + // get parent window position & size + gint win_pos_x, win_pos_y; + gtk_window_get_position ( parent, &win_pos_x, &win_pos_y ); + + gint win_size_x, win_size_y; + gtk_window_get_size ( parent, &win_size_x, &win_size_y ); + + // get own dialog size + gint dia_size_x, dia_size_y; + gtk_window_get_size ( dialog, &dia_size_x, &dia_size_y ); + + // get own dialog position + gint dia_pos_x, dia_pos_y; + gtk_window_get_position ( dialog, &dia_pos_x, &dia_pos_y ); + + // Dialog not 'realized'/positioned - so can't really do any repositioning logic + if ( dia_pos_x > 2 && dia_pos_y > 2 ) { + + VikViewport *vvp = vik_window_viewport ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)) ); + + gint vp_xx, vp_yy; // In viewport pixels + vik_viewport_coord_to_screen ( vvp, coord, &vp_xx, &vp_yy ); + + // Work out the 'bounding box' in pixel terms of the dialog and only move it when over the position + + gint dest_x = 0; + gint dest_y = 0; + if ( gtk_widget_translate_coordinates ( GTK_WIDGET(vvp), GTK_WIDGET(parent), 0, 0, &dest_x, &dest_y ) ) { + + // Transform Viewport pixels into absolute pixels + gint tmp_xx = vp_xx + dest_x + win_pos_x - 10; + gint tmp_yy = vp_yy + dest_y + win_pos_y - 10; + + // Is dialog over the point (to within an ^^ edge value) + if ( (tmp_xx > dia_pos_x) && (tmp_xx < (dia_pos_x + dia_size_x)) && + (tmp_yy > dia_pos_y) && (tmp_yy < (dia_pos_y + dia_size_y)) ) { + + if ( vertical ) { + // Shift up<->down + gint hh = vik_viewport_get_height ( vvp ); + + // Consider the difference in viewport to the full window + gint offset_y = dest_y; + // Add difference between dialog and window sizes + offset_y += win_pos_y + (hh/2 - dia_size_y)/2; + + if ( vp_yy > hh/2 ) { + // Point in bottom half, move window to top half + gtk_window_move ( dialog, dia_pos_x, offset_y ); + } + else { + // Point in top half, move dialog down + gtk_window_move ( dialog, dia_pos_x, hh/2 + offset_y ); + } + } + else { + // Shift left<->right + gint ww = vik_viewport_get_width ( vvp ); + + // Consider the difference in viewport to the full window + gint offset_x = dest_x; + // Add difference between dialog and window sizes + offset_x += win_pos_x + (ww/2 - dia_size_x)/2; + + if ( vp_xx > ww/2 ) { + // Point on right, move window to left + gtk_window_move ( dialog, offset_x, dia_pos_y ); + } + else { + // Point on left, move right + gtk_window_move ( dialog, ww/2 + offset_x, dia_pos_y ); + } + } + } + } + } +} + static void trw_layer_tpwin_init ( VikTrwLayer *vtl ) { if ( ! vtl->tpwin ) @@ -6769,8 +7305,18 @@ static void trw_layer_tpwin_init ( VikTrwLayer *vtl ) g_signal_connect_swapped ( GTK_DIALOG(vtl->tpwin), "response", G_CALLBACK(trw_layer_tpwin_response), vtl ); /* connect signals -- DELETE SIGNAL VERY IMPORTANT TO SET TO NULL */ g_signal_connect_swapped ( vtl->tpwin, "delete-event", G_CALLBACK(trw_layer_cancel_current_tp), vtl ); + gtk_widget_show_all ( GTK_WIDGET(vtl->tpwin) ); + + if ( vtl->current_tpl ) { + // get tp pixel position + VikTrackpoint *tp = VIK_TRACKPOINT(vtl->current_tpl->data); + + // Shift up<->down to try not to obscure the trackpoint. + trw_layer_dialog_shift ( vtl, GTK_WINDOW(vtl->tpwin), &(tp->coord), TRUE ); + } } + if ( vtl->current_tpl ) if ( vtl->current_tp_track ) vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track->name ); @@ -6786,6 +7332,7 @@ static void trw_layer_tpwin_init ( VikTrwLayer *vtl ) typedef struct { gint x, y; gint closest_x, closest_y; + gboolean draw_images; gpointer *closest_wp_id; VikWaypoint *closest_wp; VikViewport *vvp; @@ -6798,6 +7345,7 @@ typedef struct { VikTrackpoint *closest_tp; VikViewport *vvp; GList *closest_tpl; + LatLonBBox bbox; } TPSearchParams; static void waypoint_search_closest_tp ( gpointer id, VikWaypoint *wp, WPSearchParams *params ) @@ -6809,7 +7357,7 @@ static void waypoint_search_closest_tp ( gpointer id, VikWaypoint *wp, WPSearchP vik_viewport_coord_to_screen ( params->vvp, &(wp->coord), &x, &y ); // If waypoint has an image then use the image size to select - if ( wp->image ) { + if ( params->draw_images && wp->image ) { gint slackx, slacky; slackx = wp->image_width / 2; slacky = wp->image_height / 2; @@ -6841,6 +7389,9 @@ static void track_search_closest_tp ( gpointer id, VikTrack *t, TPSearchParams * if ( !t->visible ) return; + if ( ! BBOX_INTERSECT ( t->bbox, params->bbox ) ) + return; + while (tpl) { gint x, y; @@ -6872,6 +7423,7 @@ static VikTrackpoint *closest_tp_in_five_pixel_interval ( VikTrwLayer *vtl, VikV params.vvp = vvp; params.closest_track_id = NULL; params.closest_tp = NULL; + vik_viewport_get_min_max_lat_lon ( params.vvp, &(params.bbox.south), &(params.bbox.north), &(params.bbox.west), &(params.bbox.east) ); g_hash_table_foreach ( vtl->tracks, (GHFunc) track_search_closest_tp, ¶ms); return params.closest_tp; } @@ -6882,6 +7434,7 @@ static VikWaypoint *closest_wp_in_five_pixel_interval ( VikTrwLayer *vtl, VikVie params.x = x; params.y = y; params.vvp = vvp; + params.draw_images = vtl->drawimages; params.closest_wp = NULL; params.closest_wp_id = NULL; g_hash_table_foreach ( vtl->waypoints, (GHFunc) waypoint_search_closest_tp, ¶ms); @@ -6957,12 +7510,17 @@ static gboolean trw_layer_select_release ( VikTrwLayer *vtl, GdkEventButton *eve marker_end_move ( t ); // Determine if working on a waypoint or a trackpoint - if ( t->is_waypoint ) + if ( t->is_waypoint ) { vtl->current_wp->coord = new_coord; + trw_layer_calculate_bounds_waypoints ( vtl ); + } else { if ( vtl->current_tpl ) { VIK_TRACKPOINT(vtl->current_tpl->data)->coord = new_coord; - + + if ( vtl->current_tp_track ) + vik_track_calculate_bounds ( vtl->current_tp_track ); + if ( vtl->tpwin ) if ( vtl->current_tp_track ) vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track->name ); @@ -6996,13 +7554,17 @@ static gboolean trw_layer_select_click ( VikTrwLayer *vtl, GdkEventButton *event if ( !vtl->tracks_visible && !vtl->waypoints_visible && !vtl->routes_visible ) return FALSE; + LatLonBBox bbox; + vik_viewport_get_min_max_lat_lon ( vvp, &(bbox.south), &(bbox.north), &(bbox.west), &(bbox.east) ); + // Go for waypoints first as these often will be near a track, but it's likely the wp is wanted rather then the track - if (vtl->waypoints_visible) { + if ( vtl->waypoints_visible && BBOX_INTERSECT (vtl->waypoints_bbox, bbox ) ) { WPSearchParams wp_params; wp_params.vvp = vvp; wp_params.x = event->x; wp_params.y = event->y; + wp_params.draw_images = vtl->drawimages; wp_params.closest_wp_id = NULL; wp_params.closest_wp = NULL; @@ -7041,6 +7603,7 @@ static gboolean trw_layer_select_click ( VikTrwLayer *vtl, GdkEventButton *event tp_params.y = event->y; tp_params.closest_track_id = NULL; tp_params.closest_tp = NULL; + tp_params.bbox = bbox; if (vtl->tracks_visible) { g_hash_table_foreach ( vtl->tracks, (GHFunc) track_search_closest_tp, &tp_params); @@ -7142,7 +7705,7 @@ static gboolean trw_layer_show_selected_viewport_menu ( VikTrwLayer *vtl, GdkEve if ( track->name ) { if ( vtl->track_right_click_menu ) - gtk_object_sink ( GTK_OBJECT(vtl->track_right_click_menu) ); + g_object_ref_sink ( G_OBJECT(vtl->track_right_click_menu) ); vtl->track_right_click_menu = GTK_MENU ( gtk_menu_new () ); @@ -7185,7 +7748,7 @@ static gboolean trw_layer_show_selected_viewport_menu ( VikTrwLayer *vtl, GdkEve if ( waypoint->name ) { if ( vtl->wp_right_click_menu ) - gtk_object_sink ( GTK_OBJECT(vtl->wp_right_click_menu) ); + g_object_ref_sink ( G_OBJECT(vtl->wp_right_click_menu) ); vtl->wp_right_click_menu = GTK_MENU ( gtk_menu_new () ); @@ -7307,6 +7870,7 @@ static gboolean tool_edit_waypoint_click ( VikTrwLayer *vtl, GdkEventButton *eve params.vvp = vvp; params.x = event->x; params.y = event->y; + params.draw_images = vtl->drawimages; params.closest_wp_id = NULL; /* TODO: should get track listitem so we can break it up, make a new track, mess it up, all that. */ params.closest_wp = NULL; @@ -7413,6 +7977,8 @@ static gboolean tool_edit_waypoint_release ( VikTrwLayer *vtl, GdkEventButton *e marker_end_move ( t ); vtl->current_wp->coord = new_coord; + + trw_layer_calculate_bounds_waypoints ( vtl ); vik_layer_emit_update ( VIK_LAYER(vtl) ); return TRUE; } @@ -7559,12 +8125,12 @@ static VikLayerToolFuncStatus tool_new_track_move ( VikTrwLayer *vtl, GdkEventMo 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 ); + pixmap = gdk_pixmap_new ( gtk_widget_get_window(GTK_WIDGET(vvp)), 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 ); + pixmap = gdk_pixmap_new ( gtk_widget_get_window(GTK_WIDGET(vvp)), w1, h1, -1 ); } // Reset to background @@ -7615,33 +8181,39 @@ static VikLayerToolFuncStatus tool_new_track_move ( VikTrwLayer *vtl, GdkEventMo elev_loss += last_tpt->altitude - elev_new; } } - - gchar *str = distance_string (distance); - PangoLayout *pl = gtk_widget_create_pango_layout (GTK_WIDGET(vvp), NULL); - pango_layout_set_font_description (pl, GTK_WIDGET(vvp)->style->font_desc); + // + // Display of the distance 'tooltip' during track creation is controlled by a preference + // + if ( a_vik_get_create_track_tooltip() ) { + + gchar *str = distance_string (distance); - pango_layout_set_text (pl, str, -1); - gint wd, hd; - pango_layout_get_pixel_size ( pl, &wd, &hd ); + PangoLayout *pl = gtk_widget_create_pango_layout (GTK_WIDGET(vvp), NULL); + pango_layout_set_font_description (pl, gtk_widget_get_style(GTK_WIDGET(vvp))->font_desc); + pango_layout_set_text (pl, str, -1); + gint wd, hd; + pango_layout_get_pixel_size ( pl, &wd, &hd ); - gint xd,yd; - // offset from cursor a bit depending on font size - xd = event->x + 10; - yd = event->y - hd; + gint xd,yd; + // offset from cursor a bit depending on font size + xd = event->x + 10; + yd = event->y - hd; - // 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); + // 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 ) ); + g_object_unref ( G_OBJECT ( pl ) ); + g_object_unref ( G_OBJECT ( background_block_gc ) ); + g_free (str); + } passalong = g_new(draw_sync_t,1); // freed by draw_sync() passalong->vtl = vtl; passalong->pixmap = pixmap; - passalong->drawable = GTK_WIDGET(vvp)->window; + passalong->drawable = gtk_widget_get_window(GTK_WIDGET(vvp)); passalong->gc = vtl->current_track_newpoint_gc; gdouble angle; @@ -7651,8 +8223,6 @@ static VikLayerToolFuncStatus tool_new_track_move ( VikTrwLayer *vtl, GdkEventMo // Update statusbar with full gain/loss information statusbar_write (distance, elev_gain, elev_loss, last_step, angle, vtl); - g_free (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; @@ -7715,6 +8285,7 @@ static gboolean tool_new_track_or_route_click ( VikTrwLayer *vtl, GdkEventButton g_free ( last->data ); vtl->current_track->trackpoints = g_list_remove_link ( vtl->current_track->trackpoints, last ); } + vik_track_calculate_bounds ( vtl->current_track ); update_statusbar ( vtl ); vik_layer_emit_update ( VIK_LAYER(vtl) ); @@ -7752,7 +8323,7 @@ static gboolean tool_new_track_or_route_click ( VikTrwLayer *vtl, GdkEventButton tp->timestamp = 0; if ( vtl->current_track ) { - vtl->current_track->trackpoints = g_list_append ( vtl->current_track->trackpoints, tp ); + vik_track_add_trackpoint ( vtl->current_track, tp, TRUE ); // Ensure bounds is updated /* Auto attempt to get elevation from DEM data (if it's available) */ vik_track_apply_dem_data_last_trackpoint ( vtl->current_track ); } @@ -7774,9 +8345,7 @@ static gboolean tool_new_track_click ( VikTrwLayer *vtl, GdkEventButton *event, gchar *name = trw_layer_new_unique_sublayer_name(vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, _("Track")); if ( ( name = a_dialog_new_track ( VIK_GTK_WINDOW_FROM_LAYER(vtl), vtl->tracks, name, FALSE ) ) ) { - vtl->current_track = vik_track_new(); - vtl->current_track->visible = TRUE; - vik_trw_layer_add_track ( vtl, name, vtl->current_track ); + new_track_create_common ( vtl, name ); } else return TRUE; @@ -7827,8 +8396,10 @@ static gboolean tool_new_waypoint_click ( VikTrwLayer *vtl, GdkEventButton *even if (!vtl || vtl->vl.type != VIK_LAYER_TRW) return FALSE; vik_viewport_screen_to_coord ( vvp, event->x, event->y, &coord ); - if (vik_trw_layer_new_waypoint ( vtl, VIK_GTK_WINDOW_FROM_LAYER(vtl), &coord ) && VIK_LAYER(vtl)->visible) + if (vik_trw_layer_new_waypoint ( vtl, VIK_GTK_WINDOW_FROM_LAYER(vtl), &coord ) && VIK_LAYER(vtl)->visible) { + trw_layer_calculate_bounds_waypoints ( vtl ); vik_layer_emit_update ( VIK_LAYER(vtl) ); + } return TRUE; } @@ -7860,6 +8431,7 @@ static gboolean tool_edit_trackpoint_click ( VikTrwLayer *vtl, GdkEventButton *e params.closest_track_id = NULL; /* TODO: should get track listitem so we can break it up, make a new track, mess it up, all that. */ params.closest_tp = NULL; + vik_viewport_get_min_max_lat_lon ( vvp, &(params.bbox.south), &(params.bbox.north), &(params.bbox.west), &(params.bbox.east) ); if ( event->button != 1 ) return FALSE; @@ -7979,6 +8551,8 @@ static gboolean tool_edit_trackpoint_release ( VikTrwLayer *vtl, GdkEventButton } VIK_TRACKPOINT(vtl->current_tpl->data)->coord = new_coord; + if ( vtl->current_tp_track ) + vik_track_calculate_bounds ( vtl->current_tp_track ); marker_end_move ( t ); @@ -7993,7 +8567,6 @@ static gboolean tool_edit_trackpoint_release ( VikTrwLayer *vtl, GdkEventButton } -#ifdef VIK_CONFIG_GOOGLE /*** Route Finder ***/ static gpointer tool_route_finder_create ( VikWindow *vw, VikViewport *vvp) { @@ -8025,9 +8598,6 @@ static gboolean tool_route_finder_click ( VikTrwLayer *vtl, GdkEventButton *even } else if ( vtl->route_finder_started || (event->state & GDK_CONTROL_MASK && vtl->route_finder_current_track) ) { struct LatLon start, end; - gchar startlat[G_ASCII_DTOSTR_BUF_SIZE], startlon[G_ASCII_DTOSTR_BUF_SIZE]; - gchar endlat[G_ASCII_DTOSTR_BUF_SIZE], endlon[G_ASCII_DTOSTR_BUF_SIZE]; - gchar *url; vik_coord_to_latlon ( &(vtl->route_finder_coord), &start ); vik_coord_to_latlon ( &(tmp), &end ); @@ -8041,14 +8611,7 @@ static gboolean tool_route_finder_click ( VikTrwLayer *vtl, GdkEventButton *even vtl->route_finder_started = FALSE; } - url = g_strdup_printf(GOOGLE_DIRECTIONS_STRING, - g_ascii_dtostr (startlat, G_ASCII_DTOSTR_BUF_SIZE, (gdouble) start.lat), - g_ascii_dtostr (startlon, G_ASCII_DTOSTR_BUF_SIZE, (gdouble) start.lon), - g_ascii_dtostr (endlat, G_ASCII_DTOSTR_BUF_SIZE, (gdouble) end.lat), - g_ascii_dtostr (endlon, G_ASCII_DTOSTR_BUF_SIZE, (gdouble) end.lon)); - // NB normally this returns a GPX Route - so subsequent usage of it must lookup via the routes hash - a_babel_convert_from_url ( vtl, url, "google", NULL, NULL, NULL ); - g_free ( url ); + vik_routing_default_find ( vtl, start, end); /* see if anything was done -- a track was added or appended to */ if ( vtl->route_finder_check_added_track && vtl->route_finder_added_track ) { @@ -8058,6 +8621,10 @@ static gboolean tool_route_finder_click ( VikTrwLayer *vtl, GdkEventButton *even gchar *new_comment = g_strdup_printf("%s to: %f,%f", vtl->route_finder_current_track->comment, end.lat, end.lon ); vik_track_set_comment_no_copy ( vtl->route_finder_current_track, new_comment ); } + + if ( vtl->route_finder_added_track ) + vik_track_calculate_bounds ( vtl->route_finder_added_track ); + vtl->route_finder_added_track = NULL; vtl->route_finder_check_added_track = FALSE; vtl->route_finder_append = FALSE; @@ -8070,7 +8637,6 @@ static gboolean tool_route_finder_click ( VikTrwLayer *vtl, GdkEventButton *even } return TRUE; } -#endif /*** Show picture ****/ @@ -8240,7 +8806,11 @@ static void trw_layer_track_alloc_colors ( VikTrwLayer *vtl ) // Tracks get a random spread of colours if not already assigned if ( ! VIK_TRACK(value)->has_color ) { - gdk_color_parse ( my_track_colors (ii) , &(VIK_TRACK(value)->color) ); + if ( vtl->drawmode == DRAWMODE_ALL_SAME_COLOR ) + VIK_TRACK(value)->color = vtl->track_color; + else { + gdk_color_parse ( my_track_colors (ii), &(VIK_TRACK(value)->color) ); + } VIK_TRACK(value)->has_color = TRUE; } @@ -8272,10 +8842,86 @@ static void trw_layer_track_alloc_colors ( VikTrwLayer *vtl ) } } -static void trw_layer_post_read ( VikTrwLayer *vtl, GtkWidget *vp ) +/* + * (Re)Calculate the bounds of the waypoints in this layer, + * This should be called whenever waypoints are changed + */ +static void trw_layer_calculate_bounds_waypoints ( VikTrwLayer *vtl ) { - trw_layer_verify_thumbnails ( vtl, vp ); + struct LatLon topleft = { 0.0, 0.0 }; + struct LatLon bottomright = { 0.0, 0.0 }; + struct LatLon ll; + + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init ( &iter, vtl->waypoints ); + + // Set bounds to first point + if ( g_hash_table_iter_next (&iter, &key, &value) ) { + vik_coord_to_latlon ( &(VIK_WAYPOINT(value)->coord), &topleft ); + vik_coord_to_latlon ( &(VIK_WAYPOINT(value)->coord), &bottomright ); + } + + // Ensure there is another point... + if ( g_hash_table_size ( vtl->waypoints ) > 1 ) { + + while ( g_hash_table_iter_next (&iter, &key, &value) ) { + + // See if this point increases the bounds. + vik_coord_to_latlon ( &(VIK_WAYPOINT(value)->coord), &ll ); + + if ( ll.lat > topleft.lat) topleft.lat = ll.lat; + if ( ll.lon < topleft.lon) topleft.lon = ll.lon; + if ( ll.lat < bottomright.lat) bottomright.lat = ll.lat; + if ( ll.lon > bottomright.lon) bottomright.lon = ll.lon; + } + } + + vtl->waypoints_bbox.north = topleft.lat; + vtl->waypoints_bbox.east = bottomright.lon; + vtl->waypoints_bbox.south = bottomright.lat; + vtl->waypoints_bbox.west = topleft.lon; +} + +static void trw_layer_calculate_bounds_track ( gpointer id, VikTrack *trk ) +{ + vik_track_calculate_bounds ( trk ); +} + +static void trw_layer_calculate_bounds_tracks ( VikTrwLayer *vtl ) +{ + g_hash_table_foreach ( vtl->tracks, (GHFunc) trw_layer_calculate_bounds_track, NULL ); + g_hash_table_foreach ( vtl->routes, (GHFunc) trw_layer_calculate_bounds_track, NULL ); +} + +static void trw_layer_sort_all ( VikTrwLayer *vtl ) +{ + // Obviously need 2 to tango - sorting with only 1 (or less) is a lonely activity! + if ( g_hash_table_size (vtl->tracks) > 1 ) + vik_treeview_sort_children ( VIK_LAYER(vtl)->vt, &(vtl->tracks_iter), vtl->track_sort_order ); + + if ( g_hash_table_size (vtl->routes) > 1 ) + vik_treeview_sort_children ( VIK_LAYER(vtl)->vt, &(vtl->routes_iter), vtl->track_sort_order ); + + if ( g_hash_table_size (vtl->waypoints) > 1 ) + vik_treeview_sort_children ( VIK_LAYER(vtl)->vt, &(vtl->waypoints_iter), vtl->wp_sort_order ); +} + +static void trw_layer_post_read ( VikTrwLayer *vtl, GtkWidget *vvp, gboolean from_file ) +{ + trw_layer_verify_thumbnails ( vtl, vvp ); trw_layer_track_alloc_colors ( vtl ); + + trw_layer_calculate_bounds_waypoints ( vtl ); + trw_layer_calculate_bounds_tracks ( vtl ); + + // Apply treeview sort after loading all the tracks for this layer + // (rather than sorted insert on each individual track additional) + // and after subsequent changes to the properties as the specified order may have changed. + // since the sorting of a treeview section is now very quick + // NB sorting is also performed after every name change as well to maintain the list order + trw_layer_sort_all ( vtl ); } VikCoordMode vik_trw_layer_get_coord_mode ( VikTrwLayer *vtl ) @@ -8467,7 +9113,7 @@ void vik_track_download_map(VikTrack *tr, VikMapsLayer *vml, VikViewport *vvp, g } for (rect_iter = rects_to_download; rect_iter; rect_iter = rect_iter->next) { - maps_layer_download_section (vml, vvp, &(((Rect *)(rect_iter->data))->tl), &(((Rect *)(rect_iter->data))->br), zoom_level); + vik_maps_layer_download_section (vml, vvp, &(((Rect *)(rect_iter->data))->tl), &(((Rect *)(rect_iter->data))->br), zoom_level); } if (fillins) {