X-Git-Url: https://git.street.me.uk/andy/viking.git/blobdiff_plain/3cc574137b278895d6604df2413563539d8ce514..ba048e02a8b0c1563afe35591409dd21260b3b91:/src/viktrwlayer.c?ds=sidebyside diff --git a/src/viktrwlayer.c b/src/viktrwlayer.c index 9080b4c1..f6bc0838 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 @@ -34,6 +35,7 @@ #include "vikgpslayer.h" #include "viktrwlayer_tpwin.h" #include "viktrwlayer_propwin.h" +#include "viktrwlayer_analysis.h" #ifdef VIK_CONFIG_GEOTAG #include "viktrwlayer_geotag.h" #include "geotag_exif.h" @@ -52,8 +54,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,21 +78,18 @@ #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 5 +#define VIK_TRW_LAYER_TRACK_GC 6 #define VIK_TRW_LAYER_TRACK_GCS 10 #define VIK_TRW_LAYER_TRACK_GC_BLACK 0 #define VIK_TRW_LAYER_TRACK_GC_SLOW 1 #define VIK_TRW_LAYER_TRACK_GC_AVER 2 #define VIK_TRW_LAYER_TRACK_GC_FAST 3 #define VIK_TRW_LAYER_TRACK_GC_STOP 4 +#define VIK_TRW_LAYER_TRACK_GC_SINGLE 5 #define DRAWMODE_BY_TRACK 0 #define DRAWMODE_BY_SPEED 1 -#define DRAWMODE_ALL_BLACK 2 +#define DRAWMODE_ALL_SAME_COLOR 2 // Note using DRAWMODE_BY_SPEED may be slow especially for vast numbers of trackpoints // as we are (re)calculating the colour for every point @@ -127,6 +129,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; @@ -139,23 +143,28 @@ 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; GdkGC *track_1color_gc; + GdkColor track_color; GdkGC *current_track_gc; // Separate GC for a track's potential new point as drawn via separate method // (compared to the actual track points drawn in the main trw_layer_draw_track function) GdkGC *current_track_newpoint_gc; - GdkGC *track_bg_gc; - GdkGC *waypoint_gc; - GdkGC *waypoint_text_gc; - 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; @@ -206,6 +215,9 @@ struct _VikTrwLayer { VikStdLayerMenuItem menu_selection; gint highest_wp_number; + + // One per layer + GtkWidget *tracks_analysis_dialog; }; /* A caached waypoint image. */ @@ -225,6 +237,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 ); @@ -233,7 +246,6 @@ static void trw_layer_delete_item ( gpointer pass_along[6] ); static void trw_layer_copy_item_cb ( gpointer pass_along[6] ); static void trw_layer_cut_item_cb ( gpointer pass_along[6] ); -static void trw_layer_find_maxmin_waypoints ( const gpointer id, const VikWaypoint *w, struct LatLon maxmin[2] ); static void trw_layer_find_maxmin_tracks ( const gpointer id, const VikTrack *trk, struct LatLon maxmin[2] ); static void trw_layer_find_maxmin (VikTrwLayer *vtl, struct LatLon maxmin[2]); @@ -243,6 +255,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] ); @@ -289,9 +303,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] ); @@ -328,12 +340,14 @@ static void trw_layer_tpwin_response ( VikTrwLayer *vtl, gint response ); static void trw_layer_tpwin_init ( VikTrwLayer *vtl ); static gpointer tool_edit_trackpoint_create ( VikWindow *vw, VikViewport *vvp); +static void tool_edit_trackpoint_destroy ( tool_ed_t *t ); static gboolean tool_edit_trackpoint_click ( VikTrwLayer *vtl, GdkEventButton *event, gpointer data ); static gboolean tool_edit_trackpoint_move ( VikTrwLayer *vtl, GdkEventMotion *event, gpointer data ); static gboolean tool_edit_trackpoint_release ( VikTrwLayer *vtl, GdkEventButton *event, gpointer data ); static gpointer tool_show_picture_create ( VikWindow *vw, VikViewport *vvp); static gboolean tool_show_picture_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ); static gpointer tool_edit_waypoint_create ( VikWindow *vw, VikViewport *vvp); +static void tool_edit_waypoint_destroy ( tool_ed_t *t ); static gboolean tool_edit_waypoint_click ( VikTrwLayer *vtl, GdkEventButton *event, gpointer data ); static gboolean tool_edit_waypoint_move ( VikTrwLayer *vtl, GdkEventMotion *event, gpointer data ); static gboolean tool_edit_waypoint_release ( VikTrwLayer *vtl, GdkEventButton *event, gpointer data ); @@ -346,10 +360,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 ); @@ -397,7 +409,9 @@ static VikToolInterface trw_layer_tools[] = { GDK_CURSOR_IS_PIXMAP, &cursor_new_route_pixbuf }, { { "EditWaypoint", "vik-icon-Edit Waypoint", N_("_Edit Waypoint"), "E", N_("Edit Waypoint"), 0 }, - (VikToolConstructorFunc) tool_edit_waypoint_create, NULL, NULL, NULL, + (VikToolConstructorFunc) tool_edit_waypoint_create, + (VikToolDestructorFunc) tool_edit_waypoint_destroy, + NULL, NULL, (VikToolMouseFunc) tool_edit_waypoint_click, (VikToolMouseMoveFunc) tool_edit_waypoint_move, (VikToolMouseFunc) tool_edit_waypoint_release, (VikToolKeyFunc) NULL, @@ -405,7 +419,9 @@ static VikToolInterface trw_layer_tools[] = { GDK_CURSOR_IS_PIXMAP, &cursor_edwp_pixbuf }, { { "EditTrackpoint", "vik-icon-Edit Trackpoint", N_("Edit Trac_kpoint"), "K", N_("Edit Trackpoint"), 0 }, - (VikToolConstructorFunc) tool_edit_trackpoint_create, NULL, NULL, NULL, + (VikToolConstructorFunc) tool_edit_trackpoint_create, + (VikToolDestructorFunc) tool_edit_trackpoint_destroy, + NULL, NULL, (VikToolMouseFunc) tool_edit_trackpoint_click, (VikToolMouseMoveFunc) tool_edit_trackpoint_move, (VikToolMouseFunc) tool_edit_trackpoint_release, (VikToolKeyFunc) NULL, @@ -418,13 +434,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 { @@ -434,9 +448,7 @@ enum { TOOL_EDIT_WAYPOINT, TOOL_EDIT_TRACKPOINT, TOOL_SHOW_PICTURE, -#ifdef VIK_CONFIG_GOOGLE TOOL_ROUTE_FINDER, -#endif NUM_TOOLS }; @@ -445,7 +457,7 @@ enum { static gchar *params_groups[] = { N_("Waypoints"), N_("Tracks"), N_("Waypoint Images") }; enum { GROUP_WAYPOINTS, GROUP_TRACKS, GROUP_IMAGES }; -static gchar *params_drawmodes[] = { N_("Draw by Track"), N_("Draw by Speed"), N_("All Tracks Black"), 0 }; +static gchar *params_drawmodes[] = { N_("Draw by Track"), N_("Draw by Speed"), N_("All Tracks Same Color"), NULL }; static gchar *params_wpsymbols[] = { N_("Filled Square"), N_("Square"), N_("Circle"), N_("X"), 0 }; #define MIN_POINT_SIZE 2 @@ -481,44 +493,88 @@ 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 }, - { "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, NULL, NULL }, + { VIK_LAYER_TRW, "waypoints_visible", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL, NULL, vik_lpd_true_default, NULL, NULL }, + { VIK_LAYER_TRW, "routes_visible", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL, NULL, vik_lpd_true_default, NULL, NULL }, + + { VIK_LAYER_TRW, "drawmode", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Track Drawing Mode:"), VIK_LAYER_WIDGET_COMBOBOX, params_drawmodes, NULL, NULL, drawmode_default, NULL, NULL }, + { 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, NULL, NULL }, + { 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, NULL, NULL }, + { 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, NULL, NULL }, + { 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, NULL, NULL }, + { VIK_LAYER_TRW, "trkdirectionsize", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Direction Size:"), VIK_LAYER_WIDGET_SPINBUTTON, ¶ms_scales[11], NULL, NULL, trkdirectionsize_default, NULL, NULL }, + { VIK_LAYER_TRW, "drawpoints", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, N_("Draw Trackpoints"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL, vik_lpd_true_default, NULL, NULL }, + { VIK_LAYER_TRW, "trkpointsize", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Trackpoint Size:"), VIK_LAYER_WIDGET_SPINBUTTON, ¶ms_scales[10], NULL, NULL, trkpointsize_default, NULL, NULL }, + { VIK_LAYER_TRW, "drawelevation", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, N_("Draw Elevation"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL, vik_lpd_false_default, NULL, NULL }, + { 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, NULL, NULL }, + + { 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, NULL, NULL }, + { 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, NULL, NULL }, + + { 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, NULL, NULL }, + { VIK_LAYER_TRW, "trackbgcolor", VIK_LAYER_PARAM_COLOR, GROUP_TRACKS, N_("Track Background Color"), VIK_LAYER_WIDGET_COLOR, NULL, NULL, NULL, trackbgcolor_default, NULL, NULL }, + { 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, NULL, NULL }, + + { 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, NULL, NULL }, + + { VIK_LAYER_TRW, "drawlabels", VIK_LAYER_PARAM_BOOLEAN, GROUP_WAYPOINTS, N_("Draw Labels"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL, vik_lpd_true_default, NULL, NULL }, + { 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, NULL, NULL }, + { VIK_LAYER_TRW, "wpcolor", VIK_LAYER_PARAM_COLOR, GROUP_WAYPOINTS, N_("Waypoint Color:"), VIK_LAYER_WIDGET_COLOR, NULL, NULL, NULL, black_color_default, NULL, NULL }, + { VIK_LAYER_TRW, "wptextcolor", VIK_LAYER_PARAM_COLOR, GROUP_WAYPOINTS, N_("Waypoint Text:"), VIK_LAYER_WIDGET_COLOR, NULL, NULL, NULL, wptextcolor_default, NULL, NULL }, + { VIK_LAYER_TRW, "wpbgcolor", VIK_LAYER_PARAM_COLOR, GROUP_WAYPOINTS, N_("Background:"), VIK_LAYER_WIDGET_COLOR, NULL, NULL, NULL, wpbgcolor_default, NULL, NULL }, + { 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, NULL, NULL }, + { VIK_LAYER_TRW, "wpsymbol", VIK_LAYER_PARAM_UINT, GROUP_WAYPOINTS, N_("Waypoint marker:"), VIK_LAYER_WIDGET_COMBOBOX, params_wpsymbols, NULL, NULL, wpsymbol_default, NULL, NULL }, + { VIK_LAYER_TRW, "wpsize", VIK_LAYER_PARAM_UINT, GROUP_WAYPOINTS, N_("Waypoint size:"), VIK_LAYER_WIDGET_SPINBUTTON, ¶ms_scales[7], NULL, NULL, wpsize_default, NULL, NULL }, + { 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, NULL, NULL }, + { 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, NULL, NULL }, + + { 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, NULL, NULL }, + { 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, NULL, NULL }, + { 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, NULL, NULL }, + { 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, NULL, NULL }, }; // ENUMERATION MUST BE IN THE SAME ORDER AS THE NAMED PARAMS ABOVE @@ -529,6 +585,7 @@ enum { PARAM_RV, // Tracks PARAM_DM, + PARAM_TC, PARAM_DL, PARAM_LT, PARAM_DD, @@ -542,6 +599,7 @@ enum { PARAM_BLT, PARAM_TBGC, PARAM_TDSF, + PARAM_TSO, // Waypoints PARAM_DLA, PARAM_WPFONTSIZE, @@ -552,6 +610,7 @@ enum { PARAM_WPSYM, PARAM_WPSIZE, PARAM_WPSYMS, + PARAM_WPSO, // WP images PARAM_DI, PARAM_IS, @@ -567,11 +626,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 ); @@ -815,6 +873,9 @@ static gboolean trw_layer_paste_item ( VikTrwLayer *vtl, gint subtype, guint8 *i name = trw_layer_new_unique_sublayer_name(vtl, VIK_TRW_LAYER_SUBLAYER_WAYPOINT, w->name); vik_trw_layer_add_waypoint ( vtl, name, w ); waypoint_convert (NULL, w, &vtl->coord_mode); + g_free ( name ); + + trw_layer_calculate_bounds_waypoints ( vtl ); // Consider if redraw necessary for the new item if ( vtl->vl.visible && vtl->waypoints_visible && w->visible ) @@ -830,6 +891,7 @@ static gboolean trw_layer_paste_item ( VikTrwLayer *vtl, gint subtype, guint8 *i name = trw_layer_new_unique_sublayer_name(vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, t->name); vik_trw_layer_add_track ( vtl, name, t ); vik_track_convert (t, vtl->coord_mode); + g_free ( name ); // Consider if redraw necessary for the new item if ( vtl->vl.visible && vtl->tracks_visible && t->visible ) @@ -845,6 +907,7 @@ static gboolean trw_layer_paste_item ( VikTrwLayer *vtl, gint subtype, guint8 *i name = trw_layer_new_unique_sublayer_name(vtl, VIK_TRW_LAYER_SUBLAYER_ROUTE, t->name); vik_trw_layer_add_route ( vtl, name, t ); vik_track_convert (t, vtl->coord_mode); + g_free ( name ); // Consider if redraw necessary for the new item if ( vtl->vl.visible && vtl->routes_visible && t->visible ) @@ -869,6 +932,10 @@ static gboolean trw_layer_set_param ( VikTrwLayer *vtl, guint16 id, VikLayerPara case PARAM_WV: vtl->waypoints_visible = data.b; break; case PARAM_RV: vtl->routes_visible = data.b; break; case PARAM_DM: vtl->drawmode = data.u; break; + case PARAM_TC: + vtl->track_color = data.c; + if ( vp ) trw_layer_new_track_gcs ( vtl, vp ); + break; case PARAM_DP: vtl->drawpoints = data.b; break; case PARAM_DPS: if ( data.u >= MIN_POINT_SIZE && data.u <= MAX_POINT_SIZE ) @@ -891,17 +958,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 >= 0 && data.u <= 8 && data.u != vtl->bg_line_thickness ) + 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 ) @@ -917,14 +989,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; } @@ -938,6 +1041,7 @@ static VikLayerParamData trw_layer_get_param ( VikTrwLayer *vtl, guint16 id, gbo case PARAM_WV: rv.b = vtl->waypoints_visible; break; case PARAM_RV: rv.b = vtl->routes_visible; break; case PARAM_DM: rv.u = vtl->drawmode; break; + case PARAM_TC: rv.c = vtl->track_color; break; case PARAM_DP: rv.b = vtl->drawpoints; break; case PARAM_DPS: rv.u = vtl->drawpoints_size; break; case PARAM_DE: rv.b = vtl->drawelevation; break; @@ -951,19 +1055,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; } @@ -1090,6 +1196,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; } @@ -1118,7 +1227,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 ); @@ -1142,27 +1253,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; @@ -1172,7 +1272,11 @@ static VikTrwLayer* trw_layer_new ( gint drawmode ) static void trw_layer_free ( VikTrwLayer *trwlayer ) { g_hash_table_destroy(trwlayer->waypoints); + g_hash_table_destroy(trwlayer->waypoints_iters); g_hash_table_destroy(trwlayer->tracks); + g_hash_table_destroy(trwlayer->tracks_iters); + g_hash_table_destroy(trwlayer->routes); + g_hash_table_destroy(trwlayer->routes_iters); /* ODC: replace with GArray */ trw_layer_free_track_gcs ( trwlayer ); @@ -1181,7 +1285,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 ) ); @@ -1195,9 +1299,14 @@ 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) ); + if ( trwlayer->tracks_analysis_dialog != NULL ) + gtk_widget_destroy ( GTK_WIDGET(trwlayer->tracks_analysis_dialog) ); + g_list_foreach ( trwlayer->image_cache->head, (GFunc) cached_pixbuf_free, NULL ); g_queue_free ( trwlayer->image_cache ); } @@ -1240,6 +1349,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) ); } /* @@ -1276,6 +1387,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; @@ -1297,9 +1411,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 ); @@ -1339,9 +1450,9 @@ static void trw_layer_draw_track ( const gpointer id, VikTrack *track, struct Dr main_gc = dp->vtl->track_1color_gc; break; default: - // Mostly for DRAWMODE_ALL_BLACK + // Mostly for DRAWMODE_ALL_SAME_COLOR // but includes DRAWMODE_BY_SPEED, main_gc is set later on as necessary - main_gc = g_array_index(dp->vtl->track_gc, GdkGC *, VIK_TRW_LAYER_TRACK_GC_BLACK); + main_gc = g_array_index(dp->vtl->track_gc, GdkGC *, VIK_TRW_LAYER_TRACK_GC_SINGLE); break; } } @@ -1466,9 +1577,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)); @@ -1538,10 +1649,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 ) @@ -1563,7 +1675,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 */ @@ -1647,9 +1758,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 ) { @@ -1678,18 +1789,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 ); @@ -1698,12 +1798,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; @@ -1724,6 +1823,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; @@ -1738,7 +1844,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 ) @@ -1783,7 +1889,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 @@ -1809,34 +1915,30 @@ static void trw_layer_new_track_gcs ( VikTrwLayer *vtl, VikViewport *vp ) gc[VIK_TRW_LAYER_TRACK_GC_AVER] = vik_viewport_new_gc ( vp, "#D2CD26", width ); // yellow-ish gc[VIK_TRW_LAYER_TRACK_GC_FAST] = vik_viewport_new_gc ( vp, "#2B8700", width ); // green-ish + gc[VIK_TRW_LAYER_TRACK_GC_SINGLE] = vik_viewport_new_gc_from_color ( vp, &(vtl->track_color), width ); + g_array_append_vals ( vtl->track_gc, gc, VIK_TRW_LAYER_TRACK_GC ); } 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); + 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 ); @@ -1877,11 +1979,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); @@ -1900,11 +1998,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 ); @@ -1915,29 +2009,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 ) @@ -1947,13 +2029,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 ); + 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); @@ -2232,8 +2314,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; @@ -2432,6 +2518,28 @@ 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 ) ); +} + +gboolean vik_trw_layer_get_tracks_visibility ( VikTrwLayer *vtl ) +{ + return vtl->tracks_visible; +} + +gboolean vik_trw_layer_get_routes_visibility ( VikTrwLayer *vtl ) +{ + return vtl->routes_visible; +} + +gboolean vik_trw_layer_get_waypoints_visibility ( VikTrwLayer *vtl ) +{ + return vtl->waypoints_visible; +} + /* * ATM use a case sensitive find * Finds the first one @@ -2483,44 +2591,26 @@ VikTrack *vik_trw_layer_get_route ( VikTrwLayer *vtl, const gchar *name ) return g_hash_table_find ( vtl->routes, (GHRFunc) trw_layer_track_find, (gpointer) name ); } -static void trw_layer_find_maxmin_waypoints ( const gpointer id, const VikWaypoint *w, struct LatLon maxmin[2] ) -{ - static VikCoord fixme; - vik_coord_copy_convert ( &(w->coord), VIK_COORD_LATLON, &fixme ); - if ( VIK_LATLON(&fixme)->lat > maxmin[0].lat || maxmin[0].lat == 0.0 ) - maxmin[0].lat = VIK_LATLON(&fixme)->lat; - if ( VIK_LATLON(&fixme)->lat < maxmin[1].lat || maxmin[1].lat == 0.0 ) - maxmin[1].lat = VIK_LATLON(&fixme)->lat; - if ( VIK_LATLON(&fixme)->lon > maxmin[0].lon || maxmin[0].lon == 0.0 ) - maxmin[0].lon = VIK_LATLON(&fixme)->lon; - if ( VIK_LATLON(&fixme)->lon < maxmin[1].lon || maxmin[1].lon == 0.0 ) - maxmin[1].lon = VIK_LATLON(&fixme)->lon; -} - static void trw_layer_find_maxmin_tracks ( const gpointer id, const VikTrack *trk, struct LatLon maxmin[2] ) { - GList *tr = trk->trackpoints; - static VikCoord fixme; - - while ( tr ) - { - vik_coord_copy_convert ( &(VIK_TRACKPOINT(tr->data)->coord), VIK_COORD_LATLON, &fixme ); - if ( VIK_LATLON(&fixme)->lat > maxmin[0].lat || maxmin[0].lat == 0.0 ) - maxmin[0].lat = VIK_LATLON(&fixme)->lat; - if ( VIK_LATLON(&fixme)->lat < maxmin[1].lat || maxmin[1].lat == 0.0 ) - maxmin[1].lat = VIK_LATLON(&fixme)->lat; - if ( VIK_LATLON(&fixme)->lon > maxmin[0].lon || maxmin[0].lon == 0.0 ) - maxmin[0].lon = VIK_LATLON(&fixme)->lon; - if ( VIK_LATLON(&fixme)->lon < maxmin[1].lon || maxmin[1].lon == 0.0 ) - maxmin[1].lon = VIK_LATLON(&fixme)->lon; - tr = tr->next; - } + if ( trk->bbox.north > maxmin[0].lat || maxmin[0].lat == 0.0 ) + maxmin[0].lat = trk->bbox.north; + if ( trk->bbox.south < maxmin[1].lat || maxmin[1].lat == 0.0 ) + maxmin[1].lat = trk->bbox.south; + if ( trk->bbox.east > maxmin[0].lon || maxmin[0].lon == 0.0 ) + maxmin[0].lon = trk->bbox.east; + if ( trk->bbox.west < maxmin[1].lon || maxmin[1].lon == 0.0 ) + maxmin[1].lon = trk->bbox.west; } static void trw_layer_find_maxmin (VikTrwLayer *vtl, struct LatLon maxmin[2]) { // Continually reuse maxmin to find the latest maximum and minimum values - g_hash_table_foreach ( vtl->waypoints, (GHFunc) trw_layer_find_maxmin_waypoints, maxmin ); + // First set to waypoints bounds + maxmin[0].lat = vtl->waypoints_bbox.north; + maxmin[1].lat = vtl->waypoints_bbox.south; + maxmin[0].lon = vtl->waypoints_bbox.east; + maxmin[1].lon = vtl->waypoints_bbox.west; g_hash_table_foreach ( vtl->tracks, (GHFunc) trw_layer_find_maxmin_tracks, maxmin ); g_hash_table_foreach ( vtl->routes, (GHFunc) trw_layer_find_maxmin_tracks, maxmin ); } @@ -2631,6 +2721,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 ) @@ -2639,7 +2735,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 @@ -2647,7 +2745,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; } } @@ -2701,7 +2801,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.") ); } @@ -2791,8 +2893,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 ); @@ -2846,7 +2948,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 ) { @@ -2872,6 +2974,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 ); } @@ -2883,6 +2986,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 ); } @@ -2945,23 +3049,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 /* @@ -2974,7 +3076,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 ); } /** @@ -2987,7 +3089,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 @@ -3002,7 +3104,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 @@ -3018,7 +3120,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; @@ -3144,7 +3246,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] ) @@ -3153,8 +3255,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] ) @@ -3163,9 +3280,8 @@ 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 ); + g_free ( name ); vik_window_enable_layer_tool ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), VIK_LAYER_TRW, TOOL_CREATE_TRACK ); } @@ -3189,6 +3305,7 @@ static void trw_layer_new_route ( gpointer lav[2] ) if ( ! vtl->current_track ) { gchar *name = trw_layer_new_unique_sublayer_name ( vtl, VIK_TRW_LAYER_SUBLAYER_ROUTE, _("Route")) ; new_route_create_common ( vtl, name ); + g_free ( name ); vik_window_enable_layer_tool ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), VIK_LAYER_TRW, TOOL_CREATE_ROUTE ); } } @@ -3247,7 +3364,10 @@ static void trw_layer_auto_waypoints_view ( gpointer lav[2] ) else if ( g_hash_table_size (vtl->waypoints) > 1 ) { struct LatLon maxmin[2] = { {0,0}, {0,0} }; - g_hash_table_foreach ( vtl->waypoints, (GHFunc) trw_layer_find_maxmin_waypoints, maxmin ); + maxmin[0].lat = vtl->waypoints_bbox.north; + maxmin[1].lat = vtl->waypoints_bbox.south; + maxmin[0].lon = vtl->waypoints_bbox.east; + maxmin[1].lon = vtl->waypoints_bbox.west; trw_layer_zoom_to_show_latlons ( vtl, vik_layers_panel_get_viewport (vlp), maxmin ); } @@ -3410,12 +3530,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...") ); @@ -3469,6 +3588,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) ); @@ -3567,15 +3688,15 @@ 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 ); g_hash_table_insert ( vtl->waypoints_iters, GUINT_TO_POINTER(wp_uuid), iter ); + + // Sort now as post_read is not called on a realized waypoint + vik_treeview_sort_children ( VIK_LAYER(vtl)->vt, &(vtl->waypoints_iter), vtl->wp_sort_order ); } highest_wp_number_add_wp(vtl, name); @@ -3601,15 +3722,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 ); @@ -3634,16 +3755,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 ); @@ -3658,6 +3778,32 @@ 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 ); + } + } +} + +/** + * trw_layer_new_unique_sublayer_name: + * + * Allocates a unique new name + */ gchar *trw_layer_new_unique_sublayer_name (VikTrwLayer *vtl, gint sublayer_type, const gchar *name) { gint i = 2; @@ -3728,34 +3874,58 @@ 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 ); + g_free ( newname ); vik_trw_layer_delete_track ( vtl_src, trk ); } 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 ); + g_free ( newname ); vik_trw_layer_delete_route ( vtl_src, trk ); } 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 ); + g_free ( newname ); 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 ); } } @@ -3782,8 +3952,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); @@ -4173,6 +4342,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] ) { @@ -4184,9 +4377,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 ) @@ -4375,7 +4570,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 */ @@ -4396,7 +4590,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] ) { @@ -4491,7 +4684,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] ); @@ -4502,11 +4695,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) ); } } @@ -4720,8 +4913,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 @@ -4729,10 +4921,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) ); } } @@ -4809,8 +5001,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 @@ -4820,6 +5011,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) ); } } @@ -4903,8 +5095,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 ) @@ -5016,8 +5207,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 @@ -5030,6 +5220,7 @@ static void trw_layer_merge_by_timestamp ( gpointer pass_along[6] ) } g_list_free(nearby_tracks); + vik_layer_emit_update( VIK_LAYER(vtl) ); } @@ -5054,6 +5245,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; @@ -5062,6 +5256,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; @@ -5080,6 +5277,7 @@ static void trw_layer_split_at_selected_trackpoint ( VikTrwLayer *vtl, gint subt vik_layer_emit_update(VIK_LAYER(vtl)); } + g_free ( name ); } } @@ -5112,10 +5310,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)); @@ -5146,7 +5353,8 @@ 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);*/ - + g_free ( new_tr_name ); + vik_track_calculate_bounds ( tr ); iter = g_list_next(iter); } // Remove original track and then update the display @@ -5232,6 +5440,9 @@ 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); } + g_free ( new_tr_name ); + vik_track_calculate_bounds ( tr ); + iter = g_list_next(iter); } // Remove original track and then update the display @@ -5275,6 +5486,7 @@ static void trw_layer_split_segments ( gpointer pass_along[6] ) if ( tracks[i] ) { new_tr_name = trw_layer_new_unique_sublayer_name ( vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, trk->name); vik_trw_layer_add_track ( vtl, new_tr_name, tracks[i] ); + g_free ( new_tr_name ); } } if ( tracks ) { @@ -5364,11 +5576,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]) ); @@ -5528,9 +5735,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 ); } } @@ -5549,6 +5757,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 ); +} + /** * */ @@ -5739,26 +5993,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; @@ -5819,11 +6055,249 @@ 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) ); +} + +/** + * trw_layer_analyse_close: + * + * Stuff to do on dialog closure + */ +static void trw_layer_analyse_close ( GtkWidget *dialog, gint resp, VikLayer* vl ) +{ + VikTrwLayer *vtl = VIK_TRW_LAYER(vl); + gtk_widget_destroy ( dialog ); + vtl->tracks_analysis_dialog = NULL; +} + +/** + * trw_layer_analyse_create_list: + * + * Create the latest list of tracks with the associated layer(s) + * Although this will always be from a single layer here + */ +static GList* trw_layer_analyse_create_list ( VikLayer *vl, gpointer user_data ) +{ + VikTrwLayer *vtl = VIK_TRW_LAYER(vl); + GList *tracks = NULL; + if ( GPOINTER_TO_INT(user_data) == VIK_TRW_LAYER_SUBLAYER_TRACKS ) + tracks = g_hash_table_get_values ( vik_trw_layer_get_tracks(vtl) ); + else + tracks = g_hash_table_get_values ( vik_trw_layer_get_routes(vtl) ); + + GList *tracks_and_layers = NULL; + // build tracks_and_layers list + tracks = g_list_first ( tracks ); + while ( tracks ) { + vik_trw_track_list_t *vtdl = g_malloc (sizeof(vik_trw_track_list_t)); + vtdl->trk = VIK_TRACK(tracks->data); + vtdl->vtl = vtl; + tracks_and_layers = g_list_prepend ( tracks_and_layers, vtdl ); + tracks = g_list_next ( tracks ); + } + + return tracks_and_layers; +} + +static void trw_layer_tracks_stats ( gpointer lav[2] ) +{ + VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]); + // There can only be one! + if ( vtl->tracks_analysis_dialog ) + return; + + vtl->tracks_analysis_dialog = vik_trw_layer_analyse_this ( VIK_GTK_WINDOW_FROM_LAYER(vtl), + VIK_LAYER(vtl)->name, + VIK_LAYER(vtl), + GINT_TO_POINTER(VIK_TRW_LAYER_SUBLAYER_TRACKS), + trw_layer_analyse_create_list, + trw_layer_analyse_close ); +} + +/** + * + */ +static void trw_layer_routes_stats ( gpointer lav[2] ) +{ + VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]); + // There can only be one! + if ( vtl->tracks_analysis_dialog ) + return; + + vtl->tracks_analysis_dialog = vik_trw_layer_analyse_this ( VIK_GTK_WINDOW_FROM_LAYER(vtl), + VIK_LAYER(vtl)->name, + VIK_LAYER(vtl), + GINT_TO_POINTER(VIK_TRW_LAYER_SUBLAYER_ROUTES), + trw_layer_analyse_create_list, + trw_layer_analyse_close ); +} + 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] ); @@ -5860,8 +6334,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 ); @@ -5876,9 +6351,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) ); @@ -5890,8 +6364,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 ); @@ -5913,9 +6388,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) ); @@ -5927,8 +6401,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 ); @@ -5950,9 +6425,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) ); @@ -6096,7 +6570,7 @@ static gboolean trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *men pass_along[5] = wp->image; item = gtk_image_menu_item_new_with_mnemonic ( _("_Show Picture...") ); - gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock ("Show Picture", GTK_ICON_SIZE_MENU) ); // Own icon - see stock_icons in vikwindow.c + gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock ("vik-icon-Show Picture", GTK_ICON_SIZE_MENU) ); // Own icon - see stock_icons in vikwindow.c g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_show_picture), pass_along ); gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); gtk_widget_show ( item ); @@ -6188,6 +6662,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 ) @@ -6230,6 +6728,35 @@ 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 ); + + item = gtk_menu_item_new_with_mnemonic ( _("_Statistics") ); + g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_tracks_stats), pass_along ); + gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); + gtk_widget_show ( item ); } if ( subtype == VIK_TRW_LAYER_SUBLAYER_ROUTES ) @@ -6273,6 +6800,57 @@ 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 ); + + item = gtk_menu_item_new_with_mnemonic ( _("_Statistics") ); + g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_routes_stats), pass_along ); + gtk_menu_shell_append ( GTK_MENU_SHELL(menu), 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 (); @@ -6463,14 +7041,14 @@ static gboolean trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *men item = gtk_image_menu_item_new_with_mnemonic ( _("Down_load Maps Along Track...") ); else item = gtk_image_menu_item_new_with_mnemonic ( _("Down_load Maps Along Route...") ); - gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock ("Maps Download", GTK_ICON_SIZE_MENU) ); // Own icon - see stock_icons in vikwindow.c + gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock ("vik-icon-Maps Download", GTK_ICON_SIZE_MENU) ); // Own icon - see stock_icons in vikwindow.c g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_download_map_along_track_cb), pass_along ); gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); gtk_widget_show ( item ); } item = gtk_image_menu_item_new_with_mnemonic ( _("_Apply DEM Data") ); - gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock ("DEM Download/Import", GTK_ICON_SIZE_MENU) ); // Own icon - see stock_icons in vikwindow.c + gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock ("vik-icon-DEM Download", GTK_ICON_SIZE_MENU) ); // Own icon - see stock_icons in vikwindow.c g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_apply_dem_data), pass_along ); gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); gtk_widget_show ( item ); @@ -6502,15 +7080,13 @@ static gboolean trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *men gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); gtk_widget_show ( item ); -#ifdef VIK_CONFIG_GOOGLE 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 + gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock ("vik-icon-Route Finder", GTK_ICON_SIZE_MENU) ); // Own icon - see stock_icons in vikwindow.c g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_extend_track_end_route_finder), pass_along ); gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); gtk_widget_show ( item ); } -#endif // ATM can't upload a single waypoint but can do waypoints to a GPS if ( subtype != VIK_TRW_LAYER_SUBLAYER_WAYPOINT ) { @@ -6635,7 +7211,7 @@ static void trw_layer_insert_tp_after_current_tp ( VikTrwLayer *vtl ) if courses in degrees are 350 + 020, the mid course more likely to be 005 (not 185) [similar applies if value is in radians] */ if (tp_current->course != NAN && tp_next->course != NAN) - tp_new->speed = (tp_current->course + tp_next->course)/2; + tp_new->course = (tp_current->course + tp_next->course)/2; /* DOP / sat values remain at defaults as not they do not seem applicable to a dreamt up point */ @@ -6649,6 +7225,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 ); } } @@ -6713,8 +7290,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)); } @@ -6747,6 +7326,99 @@ 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 + + // Attempt force dialog to be shown so we can find out where it is more reliably... + while ( gtk_events_pending() ) + gtk_main_iteration (); + + // 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 ) @@ -6755,8 +7427,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 ); @@ -6772,6 +7454,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; @@ -6784,6 +7467,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 ) @@ -6795,7 +7479,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; @@ -6827,6 +7511,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; @@ -6858,6 +7545,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; } @@ -6868,6 +7556,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); @@ -6943,12 +7632,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 ); @@ -6982,13 +7676,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; @@ -7027,6 +7725,8 @@ 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.closest_tpl = NULL; + tp_params.bbox = bbox; if (vtl->tracks_visible) { g_hash_table_foreach ( vtl->tracks, (GHFunc) track_search_closest_tp, &tp_params); @@ -7128,7 +7828,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 () ); @@ -7171,7 +7871,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 () ); @@ -7256,6 +7956,11 @@ static gpointer tool_edit_waypoint_create ( VikWindow *vw, VikViewport *vvp) return t; } +static void tool_edit_waypoint_destroy ( tool_ed_t *t ) +{ + g_free ( t ); +} + static gboolean tool_edit_waypoint_click ( VikTrwLayer *vtl, GdkEventButton *event, gpointer data ) { WPSearchParams params; @@ -7293,6 +7998,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; @@ -7399,6 +8105,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; } @@ -7449,6 +8157,7 @@ static gboolean draw_sync ( gpointer data ) ds->vtl->draw_sync_done = TRUE; gdk_threads_leave(); } + g_free ( ds ); return FALSE; } @@ -7545,12 +8254,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 @@ -7601,33 +8310,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() ) { - pango_layout_set_text (pl, str, -1); - gint wd, hd; - pango_layout_get_pixel_size ( pl, &wd, &hd ); + gchar *str = distance_string (distance); - gint xd,yd; - // offset from cursor a bit depending on font size - xd = event->x + 10; - yd = event->y - 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 ); - // 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); + gint xd,yd; + // offset from cursor a bit depending on font size + xd = event->x + 10; + yd = event->y - hd; - g_object_unref ( G_OBJECT ( pl ) ); - g_object_unref ( G_OBJECT ( background_block_gc ) ); + // 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_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; @@ -7637,8 +8352,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; @@ -7701,6 +8414,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) ); @@ -7738,7 +8452,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 ); } @@ -7760,9 +8474,8 @@ 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 ); + g_free ( name ); } else return TRUE; @@ -7792,8 +8505,10 @@ static gboolean tool_new_route_click ( VikTrwLayer *vtl, GdkEventButton *event, if ( event->button == 1 && ( ! vtl->current_track || (vtl->current_track && !vtl->current_track->is_route ) ) ) { gchar *name = trw_layer_new_unique_sublayer_name(vtl, VIK_TRW_LAYER_SUBLAYER_ROUTE, _("Route")); - if ( ( name = a_dialog_new_track ( VIK_GTK_WINDOW_FROM_LAYER(vtl), vtl->routes, name, TRUE ) ) ) + if ( ( name = a_dialog_new_track ( VIK_GTK_WINDOW_FROM_LAYER(vtl), vtl->routes, name, TRUE ) ) ) { new_route_create_common ( vtl, name ); + g_free ( name ); + } else return TRUE; } @@ -7813,8 +8528,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; } @@ -7829,6 +8546,11 @@ static gpointer tool_edit_trackpoint_create ( VikWindow *vw, VikViewport *vvp) return t; } +static void tool_edit_trackpoint_destroy ( tool_ed_t *t ) +{ + g_free ( t ); +} + static gboolean tool_edit_trackpoint_click ( VikTrwLayer *vtl, GdkEventButton *event, gpointer data ) { tool_ed_t *t = data; @@ -7846,6 +8568,8 @@ 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; + params.closest_tpl = 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; @@ -7965,6 +8689,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 ); @@ -7979,7 +8705,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) { @@ -8011,9 +8736,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 ); @@ -8027,14 +8749,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 ) { @@ -8044,6 +8759,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; @@ -8056,7 +8775,6 @@ static gboolean tool_route_finder_click ( VikTrwLayer *vtl, GdkEventButton *even } return TRUE; } -#endif /*** Show picture ****/ @@ -8226,7 +8944,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; } @@ -8258,10 +8980,89 @@ 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 ) +{ + if ( ! VIK_LAYER(vtl)->vt ) + return; + + // 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 ) @@ -8453,7 +9254,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) {