* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
-
-#define WAYPOINT_FONT "Sans 8"
-
/* WARNING: If you go beyond this point, we are NOT responsible for any ill effects on your sanity */
-/* viktrwlayer.c -- 5000+ lines can make a difference in the state of things */
+/* viktrwlayer.c -- 8000+ lines can make a difference in the state of things */
#ifdef HAVE_CONFIG_H
#include "config.h"
#include "viking.h"
#include "vikmapslayer.h"
+#include "vikgpslayer.h"
#include "viktrwlayer_tpwin.h"
#include "viktrwlayer_propwin.h"
#ifdef VIK_CONFIG_GEOTAG
#endif
#include "acquire.h"
#include "datasources.h"
+#include "datasource_gps.h"
#include "util.h"
#include "icons/icons.h"
#include <glib/gstdio.h>
#include <glib/gi18n.h>
-/* Relax some dependencies */
-#if ! GLIB_CHECK_VERSION(2,12,0)
-static gboolean return_true (gpointer a, gpointer b, gpointer c) { return TRUE; }
-static g_hash_table_remove_all (GHashTable *ght) { g_hash_table_foreach_remove ( ght, (GHRFunc) return_true, FALSE ); }
+#ifdef VIK_CONFIG_GOOGLE
+#define GOOGLE_DIRECTIONS_STRING "maps.google.com/maps?q=from:%s,%s+to:%s,%s&output=js"
#endif
-#define GOOGLE_DIRECTIONS_STRING "maps.google.com/maps?q=from:%s,%s+to:%s,%s&output=kml"
-#define VIK_TRW_LAYER_TRACK_GC 16
-#define VIK_TRW_LAYER_TRACK_GC_RATES 10
-#define VIK_TRW_LAYER_TRACK_GC_MIN 0
-#define VIK_TRW_LAYER_TRACK_GC_MAX 11
-#define VIK_TRW_LAYER_TRACK_GC_BLACK 12
-#define VIK_TRW_LAYER_TRACK_GC_SLOW 13
-#define VIK_TRW_LAYER_TRACK_GC_AVER 14
-#define VIK_TRW_LAYER_TRACK_GC_FAST 15
+#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
#define MAX_STOP_LENGTH 86400
#define DRAW_ELEVATION_FACTOR 30 /* height of elevation plotting, sort of relative to zoom level ("mpp" that isn't mpp necessarily) */
/* this is multiplied by user-inputted value from 1-100. */
-enum {
-VIK_TRW_LAYER_SUBLAYER_TRACKS,
-VIK_TRW_LAYER_SUBLAYER_WAYPOINTS,
-VIK_TRW_LAYER_SUBLAYER_TRACK,
-VIK_TRW_LAYER_SUBLAYER_WAYPOINT
-};
enum { WP_SYMBOL_FILLED_SQUARE, WP_SYMBOL_SQUARE, WP_SYMBOL_CIRCLE, WP_SYMBOL_X, WP_NUM_SYMBOLS };
+// See http://developer.gnome.org/pango/stable/PangoMarkupFormat.html
+typedef enum {
+ FS_XX_SMALL = 0, // 'xx-small'
+ FS_X_SMALL,
+ FS_SMALL,
+ FS_MEDIUM, // DEFAULT
+ FS_LARGE,
+ FS_X_LARGE,
+ FS_XX_LARGE,
+ FS_NUM_SIZES
+} font_size_t;
+
struct _VikTrwLayer {
VikLayer vl;
GHashTable *tracks;
GHashTable *tracks_iters;
+ GHashTable *routes;
+ GHashTable *routes_iters;
GHashTable *waypoints_iters;
GHashTable *waypoints;
- GtkTreeIter waypoints_iter, tracks_iter;
- gboolean tracks_visible, waypoints_visible;
+ GtkTreeIter tracks_iter, routes_iter, waypoints_iter;
+ gboolean tracks_visible, routes_visible, waypoints_visible;
guint8 drawmode;
guint8 drawpoints;
+ guint8 drawpoints_size;
guint8 drawelevation;
guint8 elevation_factor;
guint8 drawstops;
guint32 stop_length;
guint8 drawlines;
+ guint8 drawdirections;
+ guint8 drawdirections_size;
guint8 line_thickness;
guint8 bg_line_thickness;
guint8 wp_symbol;
guint8 wp_size;
gboolean wp_draw_symbols;
+ font_size_t wp_font_size;
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;
GdkFont *waypoint_font;
- VikTrack *current_track;
+ VikTrack *current_track; // ATM shared between new tracks and new routes
guint16 ct_x1, ct_y1, ct_x2, ct_y2;
- gboolean ct_sync_done;
-
+ gboolean draw_sync_done;
+ gboolean draw_sync_do;
VikCoordMode coord_mode;
gpointer current_tp_id;
VikTrwLayerTpwin *tpwin;
- /* weird hack for joining tracks */
- GList *last_tpl;
- VikTrack *last_tp_track;
-
/* track editing tool -- more specifically, moving tps */
gboolean moving_tp;
struct DrawingParams {
VikViewport *vp;
VikTrwLayer *vtl;
+ VikWindow *vw;
gdouble xmpp, ympp;
guint16 width, height;
+ gdouble cc; // Cosine factor in track directions
+ gdouble ss; // Sine factor in track directions
const VikCoord *center;
- gint track_gc_iter;
gboolean one_zone, lat_lon;
gdouble ce1, ce2, cn1, cn2;
};
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 gchar *name, const VikWaypoint *w, struct LatLon maxmin[2] );
-static void trw_layer_find_maxmin_tracks ( const gchar *name, GList **t, struct LatLon maxmin[2] );
+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]);
static void trw_layer_new_track_gcs ( VikTrwLayer *vtl, VikViewport *vp );
static void trw_layer_free_track_gcs ( VikTrwLayer *vtl );
-static void trw_layer_draw_track_cb ( const gchar *name, VikTrack *track, struct DrawingParams *dp );
-static void trw_layer_draw_waypoint ( const gchar *name, VikWaypoint *wp, struct DrawingParams *dp );
+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 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_max_alt ( gpointer pass_along[6] );
static void trw_layer_goto_track_min_alt ( gpointer pass_along[6] );
static void trw_layer_goto_track_center ( gpointer pass_along[6] );
+static void trw_layer_merge_by_segment ( gpointer pass_along[6] );
static void trw_layer_merge_by_timestamp ( gpointer pass_along[6] );
static void trw_layer_merge_with_other ( gpointer pass_along[6] );
+static void trw_layer_append_track ( gpointer pass_along[6] );
static void trw_layer_split_by_timestamp ( gpointer pass_along[6] );
static void trw_layer_split_by_n_points ( gpointer pass_along[6] );
static void trw_layer_split_at_trackpoint ( gpointer pass_along[6] );
+static void trw_layer_split_segments ( gpointer pass_along[6] );
+static void trw_layer_delete_points_same_position ( gpointer pass_along[6] );
+static void trw_layer_delete_points_same_time ( gpointer pass_along[6] );
static void trw_layer_reverse ( gpointer pass_along[6] );
static void trw_layer_download_map_along_track_cb ( gpointer pass_along[6] );
static void trw_layer_edit_trackpoint ( gpointer pass_along[6] );
static void trw_layer_show_picture ( gpointer pass_along[6] );
+static void trw_layer_gps_upload_any ( gpointer pass_along[6] );
static void trw_layer_centerize ( gpointer layer_and_vlp[2] );
static void trw_layer_auto_view ( gpointer layer_and_vlp[2] );
static void trw_layer_export ( gpointer layer_and_vlp[2], const gchar* title, const gchar* default_name, VikTrack* trk, guint file_type );
static void trw_layer_goto_wp ( gpointer layer_and_vlp[2] );
static void trw_layer_new_wp ( gpointer lav[2] );
+static void trw_layer_new_track ( gpointer lav[2] );
+static void trw_layer_new_route ( gpointer lav[2] );
+static void trw_layer_finish_track ( gpointer lav[2] );
static void trw_layer_auto_waypoints_view ( gpointer lav[2] );
static void trw_layer_auto_tracks_view ( gpointer lav[2] );
static void trw_layer_delete_all_tracks ( gpointer lav[2] );
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
#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] );
#endif
#ifdef VIK_CONFIG_GEOCACHES
static void trw_layer_acquire_geocache_cb ( gpointer lav[2] );
#ifdef VIK_CONFIG_GEOTAG
static void trw_layer_acquire_geotagged_cb ( gpointer lav[2] );
#endif
+static void trw_layer_acquire_file_cb ( gpointer lav[2] );
+static void trw_layer_gps_upload ( gpointer lav[2] );
+
+// Specific route versions:
+// Most track handling functions can handle operating on the route list
+// However these ones are easier in separate functions
+static void trw_layer_auto_routes_view ( gpointer lav[2] );
+static void trw_layer_delete_all_routes ( gpointer lav[2] );
+static void trw_layer_delete_routes_from_selection ( gpointer lav[2] );
/* pop-up items */
static void trw_layer_properties_item ( gpointer pass_along[7] );
static void trw_layer_goto_waypoint ( gpointer pass_along[6] );
static void trw_layer_waypoint_gc_webpage ( gpointer pass_along[6] );
+static void trw_layer_waypoint_webpage ( gpointer pass_along[6] );
static void trw_layer_realize_waypoint ( gpointer id, VikWaypoint *wp, gpointer pass_along[5] );
static void trw_layer_realize_track ( gpointer id, VikTrack *track, gpointer pass_along[5] );
-static void init_drawing_params ( struct DrawingParams *dp, VikViewport *vp );
+static void init_drawing_params ( struct DrawingParams *dp, VikTrwLayer *vtl, VikViewport *vp );
static void trw_layer_insert_tp_after_current_tp ( VikTrwLayer *vtl );
-static void trw_layer_cancel_last_tp ( VikTrwLayer *vtl );
static void trw_layer_cancel_current_tp ( VikTrwLayer *vtl, gboolean destroy );
static void trw_layer_tpwin_response ( VikTrwLayer *vtl, gint response );
static void trw_layer_tpwin_init ( VikTrwLayer *vtl );
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 );
-static gpointer tool_begin_track_create ( VikWindow *vw, VikViewport *vvp);
-static gboolean tool_begin_track_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp );
+static gpointer tool_new_route_create ( VikWindow *vw, VikViewport *vvp);
+static gboolean tool_new_route_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp );
static gpointer tool_new_track_create ( VikWindow *vw, VikViewport *vvp);
static gboolean tool_new_track_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp );
static VikLayerToolFuncStatus tool_new_track_move ( VikTrwLayer *vtl, GdkEventMotion *event, VikViewport *vvp );
+static void tool_new_track_release ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp );
static gboolean tool_new_track_key_press ( VikTrwLayer *vtl, GdkEventKey *event, VikViewport *vvp );
static gpointer tool_new_waypoint_create ( VikWindow *vw, VikViewport *vvp);
static gboolean tool_new_waypoint_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp );
+#ifdef VIK_CONFIG_GOOGLE
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 );
static VikTrackpoint *closest_tp_in_five_pixel_interval ( VikTrwLayer *vtl, VikViewport *vvp, gint x, gint y );
static VikWaypoint *closest_wp_in_five_pixel_interval ( VikTrwLayer *vtl, VikViewport *vvp, gint x, gint y );
-static gchar *get_new_unique_sublayer_name (VikTrwLayer *vtl, gint sublayer_type, const gchar *name);
static void waypoint_convert ( const gpointer id, VikWaypoint *wp, VikCoordMode *dest_mode );
-static void track_convert ( const gchar *name, VikTrack *tr, VikCoordMode *dest_mode );
+static void track_convert ( const gpointer id, VikTrack *tr, VikCoordMode *dest_mode );
static gchar *highest_wp_number_get(VikTrwLayer *vtl);
static void highest_wp_number_reset(VikTrwLayer *vtl);
static VikToolInterface trw_layer_tools[] = {
{ { "CreateWaypoint", "vik-icon-Create Waypoint", N_("Create _Waypoint"), "<control><shift>W", N_("Create Waypoint"), 0 },
(VikToolConstructorFunc) tool_new_waypoint_create, NULL, NULL, NULL,
- (VikToolMouseFunc) tool_new_waypoint_click, NULL, NULL, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_addwp_pixbuf },
+ (VikToolMouseFunc) tool_new_waypoint_click, NULL, NULL, (VikToolKeyFunc) NULL,
+ FALSE,
+ GDK_CURSOR_IS_PIXMAP, &cursor_addwp_pixbuf },
{ { "CreateTrack", "vik-icon-Create Track", N_("Create _Track"), "<control><shift>T", N_("Create Track"), 0 },
(VikToolConstructorFunc) tool_new_track_create, NULL, NULL, NULL,
- (VikToolMouseFunc) tool_new_track_click, (VikToolMouseMoveFunc) tool_new_track_move, NULL,
- (VikToolKeyFunc) tool_new_track_key_press, GDK_CURSOR_IS_PIXMAP, &cursor_addtr_pixbuf },
-
- { { "BeginTrack", "vik-icon-Begin Track", N_("_Begin Track"), "<control><shift>B", N_("Begin Track"), 0 },
- (VikToolConstructorFunc) tool_begin_track_create, NULL, NULL, NULL,
- (VikToolMouseFunc) tool_begin_track_click, NULL, NULL, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_begintr_pixbuf },
+ (VikToolMouseFunc) tool_new_track_click,
+ (VikToolMouseMoveFunc) tool_new_track_move,
+ (VikToolMouseFunc) tool_new_track_release,
+ (VikToolKeyFunc) tool_new_track_key_press,
+ TRUE, // Still need to handle clicks when in PAN mode to disable the potential trackpoint drawing
+ GDK_CURSOR_IS_PIXMAP, &cursor_addtr_pixbuf },
+
+ { { "CreateRoute", "vik-icon-Create Route", N_("Create _Route"), "<control><shift>B", N_("Create Route"), 0 },
+ (VikToolConstructorFunc) tool_new_route_create, NULL, NULL, NULL,
+ (VikToolMouseFunc) tool_new_route_click,
+ (VikToolMouseMoveFunc) tool_new_track_move, // -\#
+ (VikToolMouseFunc) tool_new_track_release, // -> Reuse these track methods on a route
+ (VikToolKeyFunc) tool_new_track_key_press, // -/#
+ TRUE, // Still need to handle clicks when in PAN mode to disable the potential trackpoint drawing
+ GDK_CURSOR_IS_PIXMAP, &cursor_new_route_pixbuf },
{ { "EditWaypoint", "vik-icon-Edit Waypoint", N_("_Edit Waypoint"), "<control><shift>E", N_("Edit Waypoint"), 0 },
(VikToolConstructorFunc) tool_edit_waypoint_create, NULL, NULL, NULL,
(VikToolMouseFunc) tool_edit_waypoint_click,
(VikToolMouseMoveFunc) tool_edit_waypoint_move,
- (VikToolMouseFunc) tool_edit_waypoint_release, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_edwp_pixbuf },
+ (VikToolMouseFunc) tool_edit_waypoint_release, (VikToolKeyFunc) NULL,
+ FALSE,
+ GDK_CURSOR_IS_PIXMAP, &cursor_edwp_pixbuf },
{ { "EditTrackpoint", "vik-icon-Edit Trackpoint", N_("Edit Trac_kpoint"), "<control><shift>K", N_("Edit Trackpoint"), 0 },
(VikToolConstructorFunc) tool_edit_trackpoint_create, NULL, NULL, NULL,
(VikToolMouseFunc) tool_edit_trackpoint_click,
(VikToolMouseMoveFunc) tool_edit_trackpoint_move,
- (VikToolMouseFunc) tool_edit_trackpoint_release, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_edtr_pixbuf },
+ (VikToolMouseFunc) tool_edit_trackpoint_release, (VikToolKeyFunc) NULL,
+ FALSE,
+ GDK_CURSOR_IS_PIXMAP, &cursor_edtr_pixbuf },
{ { "ShowPicture", "vik-icon-Show Picture", N_("Show P_icture"), "<control><shift>I", N_("Show Picture"), 0 },
(VikToolConstructorFunc) tool_show_picture_create, NULL, NULL, NULL,
- (VikToolMouseFunc) tool_show_picture_click, NULL, NULL, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_showpic_pixbuf },
+ (VikToolMouseFunc) tool_show_picture_click, NULL, NULL, (VikToolKeyFunc) NULL,
+ FALSE,
+ GDK_CURSOR_IS_PIXMAP, &cursor_showpic_pixbuf },
+#ifdef VIK_CONFIG_GOOGLE
{ { "RouteFinder", "vik-icon-Route Finder", N_("Route _Finder"), "<control><shift>F", N_("Route Finder"), 0 },
(VikToolConstructorFunc) tool_route_finder_create, NULL, NULL, NULL,
- (VikToolMouseFunc) tool_route_finder_click, NULL, NULL, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_route_finder_pixbuf },
+ (VikToolMouseFunc) tool_route_finder_click, NULL, NULL, (VikToolKeyFunc) NULL,
+ FALSE,
+ GDK_CURSOR_IS_PIXMAP, &cursor_route_finder_pixbuf },
+#endif
+};
+
+enum {
+ TOOL_CREATE_WAYPOINT=0,
+ TOOL_CREATE_TRACK,
+ TOOL_CREATE_ROUTE,
+ TOOL_EDIT_WAYPOINT,
+ TOOL_EDIT_TRACKPOINT,
+ TOOL_SHOW_PICTURE,
+#ifdef VIK_CONFIG_GOOGLE
+ TOOL_ROUTE_FINDER,
+#endif
+ NUM_TOOLS
};
-enum { TOOL_CREATE_WAYPOINT=0, TOOL_CREATE_TRACK, TOOL_BEGIN_TRACK, TOOL_EDIT_WAYPOINT, TOOL_EDIT_TRACKPOINT, TOOL_SHOW_PICTURE, NUM_TOOLS };
/****** PARAMETERS ******/
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
+#define MAX_POINT_SIZE 10
+
+#define MIN_ARROW_SIZE 3
+#define MAX_ARROW_SIZE 20
static VikLayerParamScale params_scales[] = {
/* min max step digits */
{ 0, 100, 1, 0 }, /* track draw speed factor */
{ 1.0, 100.0, 1.0, 2 }, /* UNUSED */
/* 5 * step == how much to turn */
- { 16, 128, 3.2, 0 }, /* image_size */
- { 0, 255, 5, 0 }, /* image alpha */
- { 5, 500, 5, 0 }, /* image cache_size */
- { 0, 8, 1, 0 }, /* image cache_size */
+ { 16, 128, 4, 0 }, // 3: image_size - NB step size ignored when an HSCALE used
+ { 0, 255, 5, 0 }, // 4: image alpha - " " " "
+ { 5, 500, 5, 0 }, // 5: image cache_size - " "
+ { 0, 8, 1, 0 }, // 6: Background line thickness
{ 1, 64, 1, 0 }, /* wpsize */
{ MIN_STOP_LENGTH, MAX_STOP_LENGTH, 1, 0 }, /* stop_length */
- { 1, 100, 1, 0 }, /* stop_length */
+ { 1, 100, 1, 0 }, // 9: elevation factor
+ { MIN_POINT_SIZE, MAX_POINT_SIZE, 1, 0 }, // 10: track point size
+ { MIN_ARROW_SIZE, MAX_ARROW_SIZE, 1, 0 }, // 11: direction arrow size
};
+static gchar* params_font_sizes[] = {
+ N_("Extra Extra Small"),
+ N_("Extra Small"),
+ N_("Small"),
+ N_("Medium"),
+ N_("Large"),
+ N_("Extra Large"),
+ N_("Extra Extra Large"),
+ NULL };
+
VikLayerParam trw_layer_params[] = {
- { "tracks_visible", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_NOT_IN_PROPERTIES },
- { "waypoints_visible", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_NOT_IN_PROPERTIES },
-
- { "drawmode", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Track Drawing Mode:"), VIK_LAYER_WIDGET_RADIOGROUP, NULL },
- { "drawlines", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, N_("Draw Track Lines"), VIK_LAYER_WIDGET_CHECKBUTTON },
- { "drawpoints", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, N_("Draw Trackpoints"), VIK_LAYER_WIDGET_CHECKBUTTON },
- { "drawelevation", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, N_("Draw Elevation"), VIK_LAYER_WIDGET_CHECKBUTTON },
- { "elevation_factor", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Draw Elevation Height %:"), VIK_LAYER_WIDGET_HSCALE, params_scales + 9 },
-
- { "drawstops", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, N_("Draw Stops"), VIK_LAYER_WIDGET_CHECKBUTTON },
- { "stop_length", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Min Stop Length (seconds):"), VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 8 },
-
- { "line_thickness", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Track Thickness:"), VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 0 },
- { "bg_line_thickness", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Track BG Thickness:"), VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 6 },
- { "trackbgcolor", VIK_LAYER_PARAM_COLOR, GROUP_TRACKS, N_("Track Background Color"), VIK_LAYER_WIDGET_COLOR, 0 },
- { "speed_factor", VIK_LAYER_PARAM_DOUBLE, GROUP_TRACKS, N_("Draw by Speed Factor (%):"), VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 1 },
-
- { "drawlabels", VIK_LAYER_PARAM_BOOLEAN, GROUP_WAYPOINTS, N_("Draw Labels"), VIK_LAYER_WIDGET_CHECKBUTTON },
- { "wpcolor", VIK_LAYER_PARAM_COLOR, GROUP_WAYPOINTS, N_("Waypoint Color:"), VIK_LAYER_WIDGET_COLOR, 0 },
- { "wptextcolor", VIK_LAYER_PARAM_COLOR, GROUP_WAYPOINTS, N_("Waypoint Text:"), VIK_LAYER_WIDGET_COLOR, 0 },
- { "wpbgcolor", VIK_LAYER_PARAM_COLOR, GROUP_WAYPOINTS, N_("Background:"), VIK_LAYER_WIDGET_COLOR, 0 },
- { "wpbgand", VIK_LAYER_PARAM_BOOLEAN, GROUP_WAYPOINTS, N_("Fake BG Color Translucency:"), VIK_LAYER_WIDGET_CHECKBUTTON, 0 },
- { "wpsymbol", VIK_LAYER_PARAM_UINT, GROUP_WAYPOINTS, N_("Waypoint marker:"), VIK_LAYER_WIDGET_RADIOGROUP, NULL },
- { "wpsize", VIK_LAYER_PARAM_UINT, GROUP_WAYPOINTS, N_("Waypoint size:"), VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 7 },
- { "wpsyms", VIK_LAYER_PARAM_BOOLEAN, GROUP_WAYPOINTS, N_("Draw Waypoint Symbols:"), VIK_LAYER_WIDGET_CHECKBUTTON },
-
- { "drawimages", VIK_LAYER_PARAM_BOOLEAN, GROUP_IMAGES, N_("Draw Waypoint Images"), VIK_LAYER_WIDGET_CHECKBUTTON },
- { "image_size", VIK_LAYER_PARAM_UINT, GROUP_IMAGES, N_("Image Size (pixels):"), VIK_LAYER_WIDGET_HSCALE, params_scales + 3 },
- { "image_alpha", VIK_LAYER_PARAM_UINT, GROUP_IMAGES, N_("Image Alpha:"), VIK_LAYER_WIDGET_HSCALE, params_scales + 4 },
- { "image_cache_size", VIK_LAYER_PARAM_UINT, GROUP_IMAGES, N_("Image Memory Cache Size:"), VIK_LAYER_WIDGET_HSCALE, params_scales + 5 },
+ { "tracks_visible", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL },
+ { "waypoints_visible", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL },
+ { "routes_visible", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL },
+
+ { "drawmode", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Track Drawing Mode:"), VIK_LAYER_WIDGET_COMBOBOX, params_drawmodes, NULL, NULL },
+ { "trackcolor", VIK_LAYER_PARAM_COLOR, GROUP_TRACKS, N_("All Tracks Color:"), VIK_LAYER_WIDGET_COLOR, NULL, NULL,
+ N_("The color used when 'All Tracks Same Color' drawing mode is selected") },
+ { "drawlines", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, N_("Draw Track Lines"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL },
+ { "line_thickness", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Track Thickness:"), VIK_LAYER_WIDGET_SPINBUTTON, ¶ms_scales[0], NULL, NULL },
+ { "drawdirections", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, N_("Draw Track Direction"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL },
+ { "trkdirectionsize", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Direction Size:"), VIK_LAYER_WIDGET_SPINBUTTON, ¶ms_scales[11], NULL, NULL },
+ { "drawpoints", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, N_("Draw Trackpoints"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL },
+ { "trkpointsize", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Trackpoint Size:"), VIK_LAYER_WIDGET_SPINBUTTON, ¶ms_scales[10], NULL, NULL },
+ { "drawelevation", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, N_("Draw Elevation"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL },
+ { "elevation_factor", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Draw Elevation Height %:"), VIK_LAYER_WIDGET_HSCALE, ¶ms_scales[9], NULL, NULL },
+
+ { "drawstops", VIK_LAYER_PARAM_BOOLEAN, GROUP_TRACKS, N_("Draw Stops"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL,
+ N_("Whether to draw a marker when trackpoints are at the same position but over the minimum stop length apart in time") },
+ { "stop_length", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Min Stop Length (seconds):"), VIK_LAYER_WIDGET_SPINBUTTON, ¶ms_scales[8], NULL, NULL },
+
+ { "bg_line_thickness", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Track BG Thickness:"), VIK_LAYER_WIDGET_SPINBUTTON, ¶ms_scales[6], NULL, NULL},
+ { "trackbgcolor", VIK_LAYER_PARAM_COLOR, GROUP_TRACKS, N_("Track Background Color"), VIK_LAYER_WIDGET_COLOR, NULL, NULL, NULL },
+ { "speed_factor", VIK_LAYER_PARAM_DOUBLE, GROUP_TRACKS, N_("Draw by Speed Factor (%):"), VIK_LAYER_WIDGET_HSCALE, ¶ms_scales[1], NULL,
+ N_("The percentage factor away from the average speed determining the color used") },
+
+ { "drawlabels", VIK_LAYER_PARAM_BOOLEAN, GROUP_WAYPOINTS, N_("Draw Labels"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL },
+ { "wpfontsize", VIK_LAYER_PARAM_UINT, GROUP_WAYPOINTS, N_("Waypoint Font Size:"), VIK_LAYER_WIDGET_COMBOBOX, params_font_sizes, NULL, NULL },
+ { "wpcolor", VIK_LAYER_PARAM_COLOR, GROUP_WAYPOINTS, N_("Waypoint Color:"), VIK_LAYER_WIDGET_COLOR, NULL, NULL, NULL },
+ { "wptextcolor", VIK_LAYER_PARAM_COLOR, GROUP_WAYPOINTS, N_("Waypoint Text:"), VIK_LAYER_WIDGET_COLOR, NULL, NULL, NULL },
+ { "wpbgcolor", VIK_LAYER_PARAM_COLOR, GROUP_WAYPOINTS, N_("Background:"), VIK_LAYER_WIDGET_COLOR, NULL, NULL, NULL },
+ { "wpbgand", VIK_LAYER_PARAM_BOOLEAN, GROUP_WAYPOINTS, N_("Fake BG Color Translucency:"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL },
+ { "wpsymbol", VIK_LAYER_PARAM_UINT, GROUP_WAYPOINTS, N_("Waypoint marker:"), VIK_LAYER_WIDGET_COMBOBOX, params_wpsymbols, NULL, NULL },
+ { "wpsize", VIK_LAYER_PARAM_UINT, GROUP_WAYPOINTS, N_("Waypoint size:"), VIK_LAYER_WIDGET_SPINBUTTON, ¶ms_scales[7], NULL, NULL },
+ { "wpsyms", VIK_LAYER_PARAM_BOOLEAN, GROUP_WAYPOINTS, N_("Draw Waypoint Symbols:"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL },
+
+ { "drawimages", VIK_LAYER_PARAM_BOOLEAN, GROUP_IMAGES, N_("Draw Waypoint Images"), VIK_LAYER_WIDGET_CHECKBUTTON, NULL, NULL, NULL },
+ { "image_size", VIK_LAYER_PARAM_UINT, GROUP_IMAGES, N_("Image Size (pixels):"), VIK_LAYER_WIDGET_HSCALE, ¶ms_scales[3], NULL, NULL },
+ { "image_alpha", VIK_LAYER_PARAM_UINT, GROUP_IMAGES, N_("Image Alpha:"), VIK_LAYER_WIDGET_HSCALE, ¶ms_scales[4], NULL, NULL },
+ { "image_cache_size", VIK_LAYER_PARAM_UINT, GROUP_IMAGES, N_("Image Memory Cache Size:"), VIK_LAYER_WIDGET_HSCALE, ¶ms_scales[5], NULL, NULL },
};
-enum { PARAM_TV, PARAM_WV, PARAM_DM, PARAM_DL, PARAM_DP, PARAM_DE, PARAM_EF, PARAM_DS, PARAM_SL, PARAM_LT, PARAM_BLT, PARAM_TBGC, PARAM_TDSF, PARAM_DLA, PARAM_WPC, PARAM_WPTC, PARAM_WPBC, PARAM_WPBA, PARAM_WPSYM, PARAM_WPSIZE, PARAM_WPSYMS, PARAM_DI, PARAM_IS, PARAM_IA, PARAM_ICS, NUM_PARAMS };
+// ENUMERATION MUST BE IN THE SAME ORDER AS THE NAMED PARAMS ABOVE
+enum {
+ // Sublayer visibilities
+ PARAM_TV,
+ PARAM_WV,
+ PARAM_RV,
+ // Tracks
+ PARAM_DM,
+ PARAM_TC,
+ PARAM_DL,
+ PARAM_LT,
+ PARAM_DD,
+ PARAM_DDS,
+ PARAM_DP,
+ PARAM_DPS,
+ PARAM_DE,
+ PARAM_EF,
+ PARAM_DS,
+ PARAM_SL,
+ PARAM_BLT,
+ PARAM_TBGC,
+ PARAM_TDSF,
+ // Waypoints
+ PARAM_DLA,
+ PARAM_WPFONTSIZE,
+ PARAM_WPC,
+ PARAM_WPTC,
+ PARAM_WPBC,
+ PARAM_WPBA,
+ PARAM_WPSYM,
+ PARAM_WPSIZE,
+ PARAM_WPSYMS,
+ // WP images
+ PARAM_DI,
+ PARAM_IS,
+ PARAM_IA,
+ PARAM_ICS,
+ NUM_PARAMS
+};
/*** TO ADD A PARAM:
*** 1) Add to trw_layer_params and enumeration
/* 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_free ( VikTrwLayer *trwlayer );
static void trw_layer_draw ( VikTrwLayer *l, gpointer data );
static void trw_layer_change_coord_mode ( VikTrwLayer *vtl, VikCoordMode dest_mode );
/* End Layer Interface function definitions */
VikLayerInterface vik_trw_layer_interface = {
+ "TrackWaypoint",
N_("TrackWaypoint"),
"<control><shift>Y",
&viktrwlayer_pixbuf,
(VikLayerFuncCreate) trw_layer_create,
(VikLayerFuncRealize) trw_layer_realize,
- (VikLayerFuncPostRead) trw_layer_verify_thumbnails,
+ (VikLayerFuncPostRead) trw_layer_post_read,
(VikLayerFuncFree) trw_layer_free,
(VikLayerFuncProperties) NULL,
(VikLayerFuncSelectedViewportMenu) trw_layer_show_selected_viewport_menu,
};
-// for copy & paste
-typedef struct {
- guint len;
- guint8 data[0];
-} FlatItem;
-
GType vik_trw_layer_get_type ()
{
static GType vtl_type = 0;
else
name = NULL; // Broken :(
}
- else {
+ else if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK ) {
VikTrack *trk = g_hash_table_lookup ( vtl->tracks, sublayer);
if ( trk && trk->name )
name = trk->name;
else
name = NULL; // Broken :(
}
+ else {
+ VikTrack *trk = g_hash_table_lookup ( vtl->routes, sublayer);
+ if ( trk && trk->name )
+ name = trk->name;
+ else
+ name = NULL; // Broken :(
+ }
a_clipboard_copy( VIK_CLIPBOARD_DATA_SUBLAYER, VIK_LAYER_TRW,
subtype, len, name, data);
trw_layer_delete_item(pass_along);
}
+static void trw_layer_paste_item_cb ( gpointer pass_along[6])
+{
+ // Slightly cheating method, routing via the panels capability
+ a_clipboard_paste (VIK_LAYERS_PANEL(pass_along[1]));
+}
+
static void trw_layer_copy_item ( VikTrwLayer *vtl, gint subtype, gpointer sublayer, guint8 **item, guint *len )
{
- FlatItem *fi;
guint8 *id;
guint il;
return;
}
- if ( subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT )
- {
- vik_waypoint_marshall ( g_hash_table_lookup ( vtl->waypoints, sublayer ), &id, &il );
- // 'Simple' memory copy of byte array from the marshalling above
- *len = sizeof(FlatItem) + 1 + il; // not sure what the 1 is for yet...
- fi = g_malloc ( *len );
- fi->len = *len;
- memcpy(fi->data, id, il);
- } else {
+ GByteArray *ba = g_byte_array_new ();
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT ) {
+ vik_waypoint_marshall ( g_hash_table_lookup ( vtl->waypoints, sublayer ), &id, &il );
+ } else if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK ) {
vik_track_marshall ( g_hash_table_lookup ( vtl->tracks, sublayer ), &id, &il );
- // less magic than before...
- *len = sizeof(FlatItem) + 1 + il;
- fi = g_malloc ( *len );
- fi->len = *len;
- memcpy(fi->data, id, il);
+ } else {
+ vik_track_marshall ( g_hash_table_lookup ( vtl->routes, sublayer ), &id, &il );
}
+ g_byte_array_append ( ba, id, il );
+
g_free(id);
- *item = (guint8 *)fi;
+
+ *len = ba->len;
+ *item = ba->data;
}
static gboolean trw_layer_paste_item ( VikTrwLayer *vtl, gint subtype, guint8 *item, guint len )
{
- FlatItem *fi = (FlatItem *) item;
+ if ( !item )
+ return FALSE;
+
+ gchar *name;
- if ( subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT && fi )
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT )
{
VikWaypoint *w;
- gchar *name;
- w = vik_waypoint_unmarshall(fi->data, fi->len);
+ w = vik_waypoint_unmarshall ( item, len );
// When copying - we'll create a new name based on the original
- name = get_new_unique_sublayer_name(vtl, VIK_TRW_LAYER_SUBLAYER_WAYPOINT, w->name);
+ 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);
// Consider if redraw necessary for the new item
if ( vtl->vl.visible && vtl->waypoints_visible && w->visible )
- vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
return TRUE;
}
- if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK && fi )
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
{
VikTrack *t;
- gchar *name;
- t = vik_track_unmarshall(fi->data, fi->len);
+ t = vik_track_unmarshall ( item, len );
// When copying - we'll create a new name based on the original
- name = get_new_unique_sublayer_name(vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, t->name);
+ name = trw_layer_new_unique_sublayer_name(vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, t->name);
vik_trw_layer_add_track ( vtl, name, t );
- track_convert (name, t, &vtl->coord_mode);
+ vik_track_convert (t, vtl->coord_mode);
// Consider if redraw necessary for the new item
if ( vtl->vl.visible && vtl->tracks_visible && t->visible )
- vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
+ return TRUE;
+ }
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ {
+ VikTrack *t;
+
+ t = vik_track_unmarshall ( item, len );
+ // When copying - we'll create a new name based on the original
+ 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);
+
+ // Consider if redraw necessary for the new item
+ if ( vtl->vl.visible && vtl->routes_visible && t->visible )
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
return TRUE;
}
return FALSE;
{
case PARAM_TV: vtl->tracks_visible = data.b; break;
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;
+ 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 )
+ vtl->drawpoints_size = data.u;
+ break;
case PARAM_DE: vtl->drawelevation = data.b; break;
case PARAM_DS: vtl->drawstops = data.b; break;
case PARAM_DL: vtl->drawlines = data.b; break;
+ case PARAM_DD: vtl->drawdirections = data.b; break;
+ case PARAM_DDS:
+ if ( data.u >= MIN_ARROW_SIZE && data.u <= MAX_ARROW_SIZE )
+ vtl->drawdirections_size = data.u;
+ break;
case PARAM_SL: if ( data.u >= MIN_STOP_LENGTH && data.u <= MAX_STOP_LENGTH )
vtl->stop_length = data.u;
break;
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 );
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;
}
return TRUE;
}
{
case PARAM_TV: rv.b = vtl->tracks_visible; break;
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;
case PARAM_EF: rv.u = vtl->elevation_factor; break;
case PARAM_DS: rv.b = vtl->drawstops; break;
case PARAM_SL: rv.u = vtl->stop_length; break;
case PARAM_DL: rv.b = vtl->drawlines; break;
+ case PARAM_DD: rv.b = vtl->drawdirections; break;
+ case PARAM_DDS: rv.u = vtl->drawdirections_size; break;
case PARAM_LT: rv.u = vtl->line_thickness; break;
case PARAM_BLT: rv.u = vtl->bg_line_thickness; break;
case PARAM_DLA: rv.b = vtl->drawlabels; 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;
}
return rv;
}
static void trw_layer_marshall( VikTrwLayer *vtl, guint8 **data, gint *len )
{
guint8 *pd;
- gchar *dd;
- gsize dl;
gint pl;
- gchar *tmpname;
- FILE *f;
*data = NULL;
- if ((f = fdopen(g_file_open_tmp (NULL, &tmpname, NULL), "r+"))) {
- a_gpx_write_file(vtl, f);
- vik_layer_marshall_params(VIK_LAYER(vtl), &pd, &pl);
- fclose(f);
- f = NULL;
- g_file_get_contents(tmpname, &dd, &dl, NULL);
- *len = sizeof(pl) + pl + dl;
- *data = g_malloc(*len);
- memcpy(*data, &pl, sizeof(pl));
- memcpy(*data + sizeof(pl), pd, pl);
- memcpy(*data + sizeof(pl) + pl, dd, dl);
-
- g_free(pd);
- g_free(dd);
- g_remove(tmpname);
- g_free(tmpname);
+ // Use byte arrays to store sublayer data
+ // much like done elsewhere e.g. vik_layer_marshall_params()
+ GByteArray *ba = g_byte_array_new ( );
+
+ guint8 *sl_data;
+ guint sl_len;
+
+ guint object_length;
+ guint subtype;
+ // store:
+ // the length of the item
+ // the sublayer type of item
+ // the the actual item
+#define tlm_append(object_pointer, size, type) \
+ subtype = (type); \
+ object_length = (size); \
+ g_byte_array_append ( ba, (guint8 *)&object_length, sizeof(object_length) ); \
+ g_byte_array_append ( ba, (guint8 *)&subtype, sizeof(subtype) ); \
+ g_byte_array_append ( ba, (object_pointer), object_length );
+
+ // Layer parameters first
+ vik_layer_marshall_params(VIK_LAYER(vtl), &pd, &pl);
+ g_byte_array_append ( ba, (guint8 *)&pl, sizeof(pl) ); \
+ g_byte_array_append ( ba, pd, pl );
+ g_free ( pd );
+
+ // Now sublayer data
+ GHashTableIter iter;
+ gpointer key, value;
+
+ // Waypoints
+ g_hash_table_iter_init ( &iter, vtl->waypoints );
+ while ( g_hash_table_iter_next (&iter, &key, &value) ) {
+ vik_waypoint_marshall ( VIK_WAYPOINT(value), &sl_data, &sl_len );
+ tlm_append ( sl_data, sl_len, VIK_TRW_LAYER_SUBLAYER_WAYPOINT );
+ g_free ( sl_data );
+ }
+
+ // Tracks
+ g_hash_table_iter_init ( &iter, vtl->tracks );
+ while ( g_hash_table_iter_next (&iter, &key, &value) ) {
+ vik_track_marshall ( VIK_TRACK(value), &sl_data, &sl_len );
+ tlm_append ( sl_data, sl_len, VIK_TRW_LAYER_SUBLAYER_TRACK );
+ g_free ( sl_data );
+ }
+
+ // Routes
+ g_hash_table_iter_init ( &iter, vtl->routes );
+ while ( g_hash_table_iter_next (&iter, &key, &value) ) {
+ vik_track_marshall ( VIK_TRACK(value), &sl_data, &sl_len );
+ tlm_append ( sl_data, sl_len, VIK_TRW_LAYER_SUBLAYER_ROUTE );
+ g_free ( sl_data );
}
+
+#undef tlm_append
+
+ *data = ba->data;
+ *len = ba->len;
}
static VikTrwLayer *trw_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp )
{
- VikTrwLayer *rv = VIK_TRW_LAYER(vik_layer_create ( VIK_LAYER_TRW, vvp, NULL, FALSE ));
+ VikTrwLayer *vtl = VIK_TRW_LAYER(vik_layer_create ( VIK_LAYER_TRW, vvp, NULL, FALSE ));
gint pl;
- gchar *tmpname;
- FILE *f;
-
+ gint consumed_length;
+ // First the overall layer parameters
memcpy(&pl, data, sizeof(pl));
data += sizeof(pl);
- vik_layer_unmarshall_params ( VIK_LAYER(rv), data, pl, vvp );
+ vik_layer_unmarshall_params ( VIK_LAYER(vtl), data, pl, vvp );
data += pl;
- if (!(f = fdopen(g_file_open_tmp (NULL, &tmpname, NULL), "r+"))) {
- g_critical("couldn't open temp file");
- exit(1);
- }
- fwrite(data, len - pl - sizeof(pl), 1, f);
- rewind(f);
- a_gpx_read_file(rv, f);
- fclose(f);
- f = NULL;
- g_remove(tmpname);
- g_free(tmpname);
- return rv;
-}
+ consumed_length = pl;
+ const gint sizeof_len_and_subtype = sizeof(gint) + sizeof(gint);
-static GList * str_array_to_glist(gchar* data[])
-{
- GList *gl = NULL;
- gpointer * p;
- for (p = (gpointer)data; *p; p++)
- gl = g_list_prepend(gl, *p);
- return(g_list_reverse(gl));
+#define tlm_size (*(gint *)data)
+ // See marshalling above for order of how this is written
+#define tlm_next \
+ data += sizeof_len_and_subtype + tlm_size;
+
+ // Now the individual sublayers:
+
+ while ( *data && consumed_length < len ) {
+ // Normally four extra bytes at the end of the datastream
+ // (since it's a GByteArray and that's where it's length is stored)
+ // So only attempt read when there's an actual block of sublayer data
+ if ( consumed_length + tlm_size < len ) {
+
+ // Reuse pl to read the subtype from the data stream
+ memcpy(&pl, data+sizeof(gint), sizeof(pl));
+
+ if ( pl == VIK_TRW_LAYER_SUBLAYER_TRACK ) {
+ VikTrack *trk = vik_track_unmarshall ( data + sizeof_len_and_subtype, 0 );
+ gchar *name = g_strdup ( trk->name );
+ vik_trw_layer_add_track ( vtl, name, trk );
+ g_free ( name );
+ }
+ if ( pl == VIK_TRW_LAYER_SUBLAYER_WAYPOINT ) {
+ VikWaypoint *wp = vik_waypoint_unmarshall ( data + sizeof_len_and_subtype, 0 );
+ gchar *name = g_strdup ( wp->name );
+ vik_trw_layer_add_waypoint ( vtl, name, wp );
+ g_free ( name );
+ }
+ if ( pl == VIK_TRW_LAYER_SUBLAYER_ROUTE ) {
+ VikTrack *trk = vik_track_unmarshall ( data + sizeof_len_and_subtype, 0 );
+ gchar *name = g_strdup ( trk->name );
+ vik_trw_layer_add_route ( vtl, name, trk );
+ g_free ( name );
+ }
+ }
+ consumed_length += tlm_size + sizeof_len_and_subtype;
+ tlm_next;
+ }
+ //g_debug ("consumed_length %d vs len %d", consumed_length, len);
+
+ return vtl;
}
// Keep interesting hash function at least visible
static VikTrwLayer* trw_layer_new ( gint drawmode )
{
- if (trw_layer_params[PARAM_DM].widget_data == NULL)
- trw_layer_params[PARAM_DM].widget_data = str_array_to_glist(params_drawmodes);
- if (trw_layer_params[PARAM_WPSYM].widget_data == NULL)
- trw_layer_params[PARAM_WPSYM].widget_data = str_array_to_glist(params_wpsymbols);
-
VikTrwLayer *rv = VIK_TRW_LAYER ( g_object_new ( VIK_TRW_LAYER_TYPE, NULL ) );
- vik_layer_init ( VIK_LAYER(rv), VIK_LAYER_TRW );
+ vik_layer_set_type ( VIK_LAYER(rv), VIK_LAYER_TRW );
// It's not entirely clear the benefits of hash tables usage here - possibly the simplicity of first implementation for unique names
// Now with the name of the item stored as part of the item - these tables are effectively straightforward lists
rv->waypoints_iters = g_hash_table_new_full ( g_direct_hash, g_direct_equal, NULL, g_free );
rv->tracks = g_hash_table_new_full ( g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) vik_track_free );
rv->tracks_iters = g_hash_table_new_full ( g_direct_hash, g_direct_equal, NULL, g_free );
+ 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 );
- /* TODO: constants at top */
- rv->waypoints_visible = rv->tracks_visible = TRUE;
+ // Default values
+ rv->waypoints_visible = rv->tracks_visible = rv->routes_visible = TRUE;
rv->drawmode = drawmode;
rv->drawpoints = TRUE;
- rv->drawstops = FALSE;
- rv->drawelevation = FALSE;
+ rv->drawpoints_size = MIN_POINT_SIZE;
+ rv->drawdirections_size = 5;
rv->elevation_factor = 30;
rv->stop_length = 60;
rv->drawlines = TRUE;
- rv->wplabellayout = NULL;
- rv->wp_right_click_menu = NULL;
- rv->track_right_click_menu = NULL;
- rv->waypoint_gc = NULL;
- rv->waypoint_text_gc = NULL;
- rv->waypoint_bg_gc = NULL;
- rv->track_gc = NULL;
rv->track_draw_speed_factor = 30.0;
rv->line_thickness = 1;
- rv->bg_line_thickness = 0;
- rv->current_wp = NULL;
- rv->current_wp_id = NULL;
- rv->current_track = NULL;
- rv->current_tpl = NULL;
- rv->current_tp_track = NULL;
- rv->current_tp_id = NULL;
- rv->moving_tp = FALSE;
- rv->moving_wp = FALSE;
-
- rv->ct_sync_done = TRUE;
-
- rv->route_finder_started = FALSE;
- rv->route_finder_check_added_track = FALSE;
- rv->route_finder_current_track = NULL;
- rv->route_finder_append = FALSE;
-
- rv->waypoint_rightclick = FALSE;
- rv->last_tpl = NULL;
- rv->last_tp_track = NULL;
- rv->tpwin = NULL;
+
+ 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;
}
if ( trwlayer->waypoint_bg_gc != NULL )
g_object_unref ( G_OBJECT ( trwlayer->waypoint_bg_gc ) );
- if ( trwlayer->waypoint_font != NULL )
- gdk_font_unref ( trwlayer->waypoint_font );
-
if ( trwlayer->tpwin != NULL )
gtk_widget_destroy ( GTK_WIDGET(trwlayer->tpwin) );
g_queue_free ( trwlayer->image_cache );
}
-static void init_drawing_params ( struct DrawingParams *dp, VikViewport *vp )
+static void init_drawing_params ( struct DrawingParams *dp, VikTrwLayer *vtl, VikViewport *vp )
{
+ dp->vtl = vtl;
dp->vp = vp;
+ dp->vw = (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(dp->vtl);
dp->xmpp = vik_viewport_get_xmpp ( vp );
dp->ympp = vik_viewport_get_ympp ( vp );
dp->width = vik_viewport_get_width ( vp );
dp->height = vik_viewport_get_height ( vp );
+ dp->cc = vtl->drawdirections_size*cos(DEG2RAD(45)); // Calculate once per vtl update - even if not used
+ dp->ss = vtl->drawdirections_size*sin(DEG2RAD(45)); // Calculate once per vtl update - even if not used
+
dp->center = vik_viewport_get_center ( vp );
dp->one_zone = vik_viewport_is_one_zone ( vp ); /* false if some other projection besides UTM */
dp->lat_lon = vik_viewport_get_coord_mode ( vp ) == VIK_COORD_LATLON;
dp->cn1 = bottomright.north_south;
dp->cn2 = upperleft.north_south;
}
-
- dp->track_gc_iter = 0;
}
/*
return VIK_TRW_LAYER_TRACK_GC_BLACK;
}
-void draw_utm_skip_insignia ( VikViewport *vvp, GdkGC *gc, gint x, gint y )
+static void draw_utm_skip_insignia ( VikViewport *vvp, GdkGC *gc, gint x, gint y )
{
vik_viewport_draw_line ( vvp, gc, x+5, y, x-5, y );
vik_viewport_draw_line ( vvp, gc, x, y+5, x, y-5 );
vik_viewport_draw_line ( vvp, gc, x+5, y-5, x-5, y+5 );
}
-static void trw_layer_draw_track ( const gchar *name, VikTrack *track, struct DrawingParams *dp, gboolean drawing_white_background )
+static void trw_layer_draw_track ( const gpointer id, VikTrack *track, struct DrawingParams *dp, gboolean draw_track_outline )
{
/* TODO: this function is a mess, get rid of any redundancy */
GList *list = track->trackpoints;
gboolean drawelevation;
gdouble min_alt, max_alt, alt_diff = 0;
- const guint8 tp_size_reg = 2;
- const guint8 tp_size_cur = 4;
+ const guint8 tp_size_reg = dp->vtl->drawpoints_size;
+ const guint8 tp_size_cur = dp->vtl->drawpoints_size*2;
guint8 tp_size;
if ( dp->vtl->drawelevation )
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 && !drawing_white_background )
- trw_layer_draw_track ( name, track, dp, TRUE );
+ if ( dp->vtl->bg_line_thickness && !draw_track_outline )
+ trw_layer_draw_track ( id, track, dp, TRUE );
- if ( drawing_white_background )
+ if ( draw_track_outline )
drawpoints = drawstops = FALSE;
else {
drawpoints = dp->vtl->drawpoints;
/* if track is member of selected layer or is the current selected track
then draw in the highlight colour.
NB this supercedes the drawmode */
- if ( dp->vtl && ( ( dp->vtl == vik_window_get_selected_trw_layer ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(dp->vtl) ) ) ||
- ( dp->vtl->tracks == vik_window_get_selected_tracks ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(dp->vtl) ) ) ||
- track == vik_window_get_selected_track ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(dp->vtl) ) ) ) {
+ if ( ( dp->vtl == vik_window_get_selected_trw_layer ( dp->vw ) ) ||
+ ( !track->is_route && ( dp->vtl->tracks == vik_window_get_selected_tracks ( dp->vw ) ) ) ||
+ ( track->is_route && ( dp->vtl->routes == vik_window_get_selected_tracks ( dp->vw ) ) ) ||
+ ( track == vik_window_get_selected_track ( dp->vw ) ) ) {
main_gc = vik_viewport_get_gc_highlight (dp->vp);
drawing_highlight = TRUE;
}
- else {
- if ( dp->vtl->drawmode == DRAWMODE_ALL_BLACK )
- dp->track_gc_iter = VIK_TRW_LAYER_TRACK_GC_BLACK;
-
- main_gc = g_array_index(dp->vtl->track_gc, GdkGC *, dp->track_gc_iter);
- }
}
- else {
- if ( dp->vtl->drawmode == DRAWMODE_ALL_BLACK )
- dp->track_gc_iter = VIK_TRW_LAYER_TRACK_GC_BLACK;
-
- main_gc = g_array_index(dp->vtl->track_gc, GdkGC *, dp->track_gc_iter);
+ if ( !drawing_highlight ) {
+ // Still need to figure out the gc according to the drawing mode:
+ switch ( dp->vtl->drawmode ) {
+ case DRAWMODE_BY_TRACK:
+ if ( dp->vtl->track_1color_gc )
+ g_object_unref ( dp->vtl->track_1color_gc );
+ dp->vtl->track_1color_gc = vik_viewport_new_gc_from_color ( dp->vp, &track->color, dp->vtl->line_thickness );
+ main_gc = dp->vtl->track_1color_gc;
+ break;
+ default:
+ // 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_SINGLE);
+ break;
+ }
}
}
vik_viewport_coord_to_screen ( dp->vp, &(tp->coord), &x, &y );
- if ( (drawpoints) && dp->track_gc_iter < VIK_TRW_LAYER_TRACK_GC )
- {
+ // Draw the first point as something a bit different from the normal points
+ // ATM it's slightly bigger and a triangle
+ if ( drawpoints ) {
GdkPoint trian[3] = { { x, y-(3*tp_size) }, { x-(2*tp_size), y+(2*tp_size) }, {x+(2*tp_size), y+(2*tp_size)} };
vik_viewport_draw_polygon ( dp->vp, main_gc, TRUE, trian, 3 );
}
if ( useoldvals && x == oldx && y == oldy )
{
// Still need to process points to ensure 'stops' are drawn if required
- if ( drawstops && drawpoints && ! drawing_white_background && list->next &&
+ if ( drawstops && drawpoints && ! draw_track_outline && list->next &&
(VIK_TRACKPOINT(list->next->data)->timestamp - VIK_TRACKPOINT(list->data)->timestamp > dp->vtl->stop_length) )
vik_viewport_draw_arc ( dp->vp, g_array_index(dp->vtl->track_gc, GdkGC *, 11), TRUE, x-(3*tp_size), y-(3*tp_size), 6*tp_size, 6*tp_size, 0, 360*64 );
if ( drawpoints || dp->vtl->drawlines ) {
// setup main_gc for both point and line drawing
if ( !drawing_highlight && (dp->vtl->drawmode == DRAWMODE_BY_SPEED) ) {
- dp->track_gc_iter = track_section_colour_by_speed ( dp->vtl, tp, tp2, average_speed, low_speed, high_speed );
- main_gc = g_array_index(dp->vtl->track_gc, GdkGC *, dp->track_gc_iter);
+ main_gc = g_array_index(dp->vtl->track_gc, GdkGC *, track_section_colour_by_speed ( dp->vtl, tp, tp2, average_speed, low_speed, high_speed ) );
}
}
- if ( drawpoints && ! drawing_white_background )
+ if ( drawpoints && ! draw_track_outline )
{
if ( list->next ) {
*/
/* stops */
if ( drawstops && VIK_TRACKPOINT(list->next->data)->timestamp - VIK_TRACKPOINT(list->data)->timestamp > dp->vtl->stop_length )
- /* Stop point. Draw 6x circle. */
- vik_viewport_draw_arc ( dp->vp, g_array_index(dp->vtl->track_gc, GdkGC *, 11), TRUE, x-(3*tp_size), y-(3*tp_size), 6*tp_size, 6*tp_size, 0, 360*64 );
+ /* Stop point. Draw 6x circle. Always in redish colour */
+ vik_viewport_draw_arc ( dp->vp, g_array_index(dp->vtl->track_gc, GdkGC *, VIK_TRW_LAYER_TRACK_GC_STOP), TRUE, x-(3*tp_size), y-(3*tp_size), 6*tp_size, 6*tp_size, 0, 360*64 );
/* Regular point - draw 2x square. */
vik_viewport_draw_rectangle ( dp->vp, main_gc, TRUE, x-tp_size, y-tp_size, 2*tp_size, 2*tp_size );
if (!useoldvals)
vik_viewport_coord_to_screen ( dp->vp, &(tp2->coord), &oldx, &oldy );
- if ( drawing_white_background ) {
+ if ( draw_track_outline ) {
vik_viewport_draw_line ( dp->vp, dp->vtl->track_bg_gc, oldx, oldy, x, y);
}
else {
vik_viewport_draw_line ( dp->vp, main_gc, oldx, oldy, x, y);
+
if ( dp->vtl->drawelevation && list->next && VIK_TRACKPOINT(list->next->data)->altitude != VIK_DEFAULT_ALTITUDE ) {
GdkPoint tmp[4];
#define FIXALTITUDE(what) ((VIK_TRACKPOINT((what))->altitude-min_alt)/alt_diff*DRAW_ELEVATION_FACTOR*dp->vtl->elevation_factor/dp->xmpp)
}
}
+ if ( (!tp->newsegment) && dp->vtl->drawdirections ) {
+ // Draw an arrow at the mid point to show the direction of the track
+ // Code is a rework from vikwindow::draw_ruler()
+ gint midx = (oldx + x) / 2;
+ gint midy = (oldy + y) / 2;
+
+ gdouble len = sqrt ( ((midx-oldx) * (midx-oldx)) + ((midy-oldy) * (midy-oldy)) );
+ // Avoid divide by zero and ensure at least 1 pixel big
+ if ( len > 1 ) {
+ gdouble dx = (oldx - midx) / len;
+ gdouble dy = (oldy - midy) / len;
+ vik_viewport_draw_line ( dp->vp, main_gc, midx, midy, midx + (dx * dp->cc + dy * dp->ss), midy + (dy * dp->cc - dx * dp->ss) );
+ vik_viewport_draw_line ( dp->vp, main_gc, midx, midy, midx + (dx * dp->cc - dy * dp->ss), midy + (dy * dp->cc + dx * dp->ss) );
+ }
+ }
+
skip:
oldx = x;
oldy = y;
vik_viewport_coord_to_screen ( dp->vp, &(tp->coord), &x, &y );
if ( !drawing_highlight && (dp->vtl->drawmode == DRAWMODE_BY_SPEED) ) {
- dp->track_gc_iter = track_section_colour_by_speed ( dp->vtl, tp, tp2, average_speed, low_speed, high_speed );
- main_gc = g_array_index(dp->vtl->track_gc, GdkGC *, dp->track_gc_iter);
+ main_gc = g_array_index(dp->vtl->track_gc, GdkGC *, track_section_colour_by_speed ( dp->vtl, tp, tp2, average_speed, low_speed, high_speed ));
}
/*
*/
if ( x != oldx || y != oldy )
{
- if ( drawing_white_background )
+ if ( draw_track_outline )
vik_viewport_draw_line ( dp->vp, dp->vtl->track_bg_gc, oldx, oldy, x, y);
else
vik_viewport_draw_line ( dp->vp, main_gc, oldx, oldy, x, y);
}
}
}
- if ( dp->vtl->drawmode == DRAWMODE_BY_TRACK )
- if ( ++(dp->track_gc_iter) >= VIK_TRW_LAYER_TRACK_GC_MAX )
- dp->track_gc_iter = 0;
}
/* 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 gchar *name, VikTrack *track, struct DrawingParams *dp )
+static void trw_layer_draw_track_cb ( const gpointer id, VikTrack *track, struct DrawingParams *dp )
{
- trw_layer_draw_track ( name, track, dp, FALSE );
+ trw_layer_draw_track ( id, track, dp, FALSE );
}
static void cached_pixbuf_free ( CachedPixbuf *cp )
return strcmp ( cp->image, name );
}
-static void trw_layer_draw_waypoint ( const gchar *name, VikWaypoint *wp, struct DrawingParams *dp )
+static void trw_layer_draw_waypoint ( const gpointer id, VikWaypoint *wp, struct DrawingParams *dp )
{
if ( wp->visible )
if ( (!dp->one_zone && !dp->lat_lon) || ( ( dp->lat_lon || wp->coord.utm_zone == dp->center->utm_zone ) &&
if ( x+(w/2) > 0 && y+(h/2) > 0 && x-(w/2) < dp->width && y-(h/2) < dp->height ) /* always draw within boundaries */
{
if ( vik_viewport_get_draw_highlight ( dp->vp ) ) {
- if ( dp->vtl == vik_window_get_selected_trw_layer ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(dp->vtl) ) ||
- dp->vtl->waypoints == vik_window_get_selected_waypoints ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(dp->vtl) ) ||
- wp == vik_window_get_selected_waypoint ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(dp->vtl) ) ) {
+ if ( dp->vtl == vik_window_get_selected_trw_layer ( dp->vw ) ||
+ dp->vtl->waypoints == vik_window_get_selected_waypoints ( dp->vw ) ||
+ wp == vik_window_get_selected_waypoint ( dp->vw ) ) {
// Highlighted - so draw a little border around the chosen one
// single line seems a little weak so draw 2 of them
vik_viewport_draw_rectangle (dp->vp, vik_viewport_get_gc_highlight (dp->vp), FALSE,
/* thanks to the GPSDrive people (Fritz Ganter et al.) for hints on this part ... yah, I'm too lazy to study documentation */
gint label_x, label_y;
gint width, height;
- pango_layout_set_text ( dp->vtl->wplabellayout, wp->name, -1 );
+ // 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 ( "<span size=\"%s\">%s</span>", fsize, 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 );
+ else
+ // Fallback if parse failure
+ 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)
/* if highlight mode on, then draw background text in highlight colour */
if ( vik_viewport_get_draw_highlight ( dp->vp ) ) {
- if ( dp->vtl == vik_window_get_selected_trw_layer ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(dp->vtl) ) ||
- dp->vtl->waypoints == vik_window_get_selected_waypoints ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(dp->vtl) ) ||
- wp == vik_window_get_selected_waypoint ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(dp->vtl) ) )
+ if ( dp->vtl == vik_window_get_selected_trw_layer ( dp->vw ) ||
+ dp->vtl->waypoints == vik_window_get_selected_waypoints ( dp->vw ) ||
+ wp == vik_window_get_selected_waypoint ( dp->vw ) )
vik_viewport_draw_rectangle ( dp->vp, vik_viewport_get_gc_highlight (dp->vp), TRUE, label_x - 1, label_y-1,width+2,height+2);
else
vik_viewport_draw_rectangle ( dp->vp, dp->vtl->waypoint_bg_gc, TRUE, label_x - 1, label_y-1,width+2,height+2);
static struct DrawingParams dp;
g_assert ( l != NULL );
- init_drawing_params ( &dp, VIK_VIEWPORT(data) );
- dp.vtl = l;
+ init_drawing_params ( &dp, l, VIK_VIEWPORT(data) );
if ( l->tracks_visible )
g_hash_table_foreach ( l->tracks, (GHFunc) trw_layer_draw_track_cb, &dp );
+ if ( l->routes_visible )
+ 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_object_unref ( vtl->track_bg_gc );
vtl->track_bg_gc = NULL;
}
+ if ( vtl->track_1color_gc )
+ {
+ g_object_unref ( vtl->track_1color_gc );
+ vtl->track_1color_gc = NULL;
+ }
if ( vtl->current_track_gc )
{
g_object_unref ( vtl->current_track_gc );
vtl->current_track_gc = NULL;
}
+ if ( vtl->current_track_newpoint_gc )
+ {
+ g_object_unref ( vtl->current_track_newpoint_gc );
+ vtl->current_track_newpoint_gc = NULL;
+ }
if ( ! vtl->track_gc )
return;
g_object_unref ( vtl->track_bg_gc );
vtl->track_bg_gc = vik_viewport_new_gc ( vp, "#FFFFFF", 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
+ gint new_track_width = (vtl->line_thickness < 2) ? 2 : vtl->line_thickness;
+
if ( vtl->current_track_gc )
g_object_unref ( vtl->current_track_gc );
- vtl->current_track_gc = vik_viewport_new_gc ( vp, "#FF0000", 2 );
- gdk_gc_set_line_attributes ( vtl->current_track_gc, 2, GDK_LINE_ON_OFF_DASH, GDK_CAP_ROUND, GDK_JOIN_ROUND );
-
- vtl->track_gc = g_array_sized_new ( FALSE, FALSE, sizeof ( GdkGC * ), VIK_TRW_LAYER_TRACK_GC );
-
- gc[0] = vik_viewport_new_gc ( vp, "#2d870a", width ); /* below range */
+ vtl->current_track_gc = vik_viewport_new_gc ( vp, "#FF0000", new_track_width );
+ gdk_gc_set_line_attributes ( vtl->current_track_gc, new_track_width, GDK_LINE_ON_OFF_DASH, GDK_CAP_ROUND, GDK_JOIN_ROUND );
- gc[1] = vik_viewport_new_gc ( vp, "#0a8742", width );
- gc[2] = vik_viewport_new_gc ( vp, "#0a8783", width );
- gc[3] = vik_viewport_new_gc ( vp, "#0a4d87", width );
- gc[4] = vik_viewport_new_gc ( vp, "#05469f", width );
- gc[5] = vik_viewport_new_gc ( vp, "#1b059f", width );
- gc[6] = vik_viewport_new_gc ( vp, "#2d059f", width );
- gc[7] = vik_viewport_new_gc ( vp, "#4a059f", width );
- gc[8] = vik_viewport_new_gc ( vp, "#84059f", width );
- gc[9] = vik_viewport_new_gc ( vp, "#96059f", width );
- gc[10] = vik_viewport_new_gc ( vp, "#f22ef2", width );
+ // 'newpoint' gc is exactly the same as the current track gc
+ if ( vtl->current_track_newpoint_gc )
+ g_object_unref ( vtl->current_track_newpoint_gc );
+ vtl->current_track_newpoint_gc = vik_viewport_new_gc ( vp, "#FF0000", new_track_width );
+ gdk_gc_set_line_attributes ( vtl->current_track_newpoint_gc, new_track_width, GDK_LINE_ON_OFF_DASH, GDK_CAP_ROUND, GDK_JOIN_ROUND );
- gc[11] = vik_viewport_new_gc ( vp, "#874200", width ); /* above range */
+ vtl->track_gc = g_array_sized_new ( FALSE, FALSE, sizeof ( GdkGC * ), VIK_TRW_LAYER_TRACK_GC );
- gc[12] = vik_viewport_new_gc ( vp, "#000000", width ); /* black / no speed data */
+ gc[VIK_TRW_LAYER_TRACK_GC_STOP] = vik_viewport_new_gc ( vp, "#874200", width );
+ gc[VIK_TRW_LAYER_TRACK_GC_BLACK] = vik_viewport_new_gc ( vp, "#000000", width ); // black
gc[VIK_TRW_LAYER_TRACK_GC_SLOW] = vik_viewport_new_gc ( vp, "#E6202E", width ); // red-ish
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 );
}
return rv;
}
- PangoFontDescription *pfd;
rv->wplabellayout = gtk_widget_create_pango_layout (GTK_WIDGET(vp), NULL);
- pfd = pango_font_description_from_string (WAYPOINT_FONT);
- pango_layout_set_font_description (rv->wplabellayout, pfd);
- /* freeing PangoFontDescription, cause it has been copied by prev. call */
- pango_font_description_free (pfd);
+ pango_layout_set_font_description (rv->wplabellayout, GTK_WIDGET(vp)->style->font_desc);
+
+ gdk_color_parse ( "#000000", &(rv->track_color) ); // Black
trw_layer_new_track_gcs ( rv, vp );
rv->waypoint_bg_gc = vik_viewport_new_gc ( vp, "#8383C4", 1 );
gdk_gc_set_function ( rv->waypoint_bg_gc, GDK_AND );
- rv->waypoint_font = gdk_font_load ( "-*-helvetica-bold-r-normal-*-*-100-*-*-p-*-iso8859-1" );
-
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->coord_mode = vik_viewport_get_coord_mode ( vp );
return rv;
}
+#define SMALL_ICON_SIZE 18
+/*
+ * Can accept a null symbol, and may return null value
+ */
+static GdkPixbuf* get_wp_sym_small ( gchar *symbol )
+{
+ GdkPixbuf* wp_icon = a_get_wp_sym (symbol);
+ // ATM a_get_wp_sym returns a cached icon, with the size dependent on the preferences.
+ // So needing a small icon for the treeview may need some resizing:
+ if ( wp_icon && gdk_pixbuf_get_width ( wp_icon ) != SMALL_ICON_SIZE )
+ wp_icon = gdk_pixbuf_scale_simple ( wp_icon, SMALL_ICON_SIZE, SMALL_ICON_SIZE, GDK_INTERP_BILINEAR );
+ return wp_icon;
+}
+
static void trw_layer_realize_track ( gpointer id, VikTrack *track, gpointer pass_along[5] )
{
GtkTreeIter *new_iter = g_malloc(sizeof(GtkTreeIter));
+ GdkPixbuf *pixbuf = NULL;
+
+ if ( track->has_color ) {
+ pixbuf = gdk_pixbuf_new ( GDK_COLORSPACE_RGB, FALSE, 8, SMALL_ICON_SIZE, SMALL_ICON_SIZE );
+ // Annoyingly the GdkColor.pixel does not give the correct color when passed to gdk_pixbuf_fill (even when alloc'ed)
+ // Here is some magic found to do the conversion
+ // http://www.cs.binghamton.edu/~sgreene/cs360-2011s/topics/gtk+-2.20.1/gtk/gtkcolorbutton.c
+ guint32 pixel = ((track->color.red & 0xff00) << 16) |
+ ((track->color.green & 0xff00) << 8) |
+ (track->color.blue & 0xff00);
+
+ 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]), NULL, TRUE, TRUE );
+ 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]), NULL, TRUE, TRUE );
+ 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);
+
*new_iter = *((GtkTreeIter *) pass_along[1]);
- g_hash_table_insert ( VIK_TRW_LAYER(pass_along[2])->tracks_iters, id, new_iter );
+ if ( track->is_route )
+ g_hash_table_insert ( VIK_TRW_LAYER(pass_along[2])->routes_iters, id, new_iter );
+ else
+ g_hash_table_insert ( VIK_TRW_LAYER(pass_along[2])->tracks_iters, id, new_iter );
if ( ! track->visible )
vik_treeview_item_set_visible ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[1], FALSE );
static void trw_layer_realize_waypoint ( gpointer id, VikWaypoint *wp, gpointer pass_along[5] )
{
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]), NULL, TRUE, TRUE );
+ 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]), NULL, TRUE, TRUE );
+ 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]);
vik_treeview_item_set_visible ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[1], FALSE );
}
-
-static void trw_layer_realize ( VikTrwLayer *vtl, VikTreeview *vt, GtkTreeIter *layer_iter )
+static void trw_layer_add_sublayer_tracks ( VikTrwLayer *vtl, VikTreeview *vt, GtkTreeIter *layer_iter )
{
- GtkTreeIter iter2;
- gpointer pass_along[5] = { &(vtl->tracks_iter), &iter2, vtl, vt, GINT_TO_POINTER(VIK_TRW_LAYER_SUBLAYER_TRACK) };
-
#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
- if ( ! vtl->tracks_visible )
- vik_treeview_item_set_visible ( (VikTreeview *) vt, &(vtl->tracks_iter), FALSE );
-
- g_hash_table_foreach ( vtl->tracks, (GHFunc) trw_layer_realize_track, pass_along );
+}
+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 )
+{
+ GtkTreeIter iter2;
+ gpointer pass_along[5] = { &(vtl->tracks_iter), &iter2, vtl, vt, GINT_TO_POINTER(VIK_TRW_LAYER_SUBLAYER_TRACK) };
+
+ 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 );
+ }
+
+ if ( g_hash_table_size (vtl->routes) > 0 ) {
+
+ trw_layer_add_sublayer_routes ( vtl, vt, layer_iter );
+
+ pass_along[0] = &(vtl->routes_iter);
+ pass_along[4] = GINT_TO_POINTER(VIK_TRW_LAYER_SUBLAYER_ROUTE);
+
+ g_hash_table_foreach ( vtl->routes, (GHFunc) trw_layer_realize_track, pass_along );
- if ( ! vtl->waypoints_visible )
- vik_treeview_item_set_visible ( (VikTreeview *) vt, &(vtl->waypoints_iter), FALSE );
+ vik_treeview_item_set_visible ( (VikTreeview *) vt, &(vtl->routes_iter), vtl->routes_visible );
+ }
+
+ if ( g_hash_table_size (vtl->waypoints) > 0 ) {
+ trw_layer_add_sublayer_waypoints ( vtl, vt, layer_iter );
- pass_along[0] = &(vtl->waypoints_iter);
- pass_along[4] = GINT_TO_POINTER(VIK_TRW_LAYER_SUBLAYER_WAYPOINT);
+ pass_along[0] = &(vtl->waypoints_iter);
+ pass_along[4] = GINT_TO_POINTER(VIK_TRW_LAYER_SUBLAYER_WAYPOINT);
- g_hash_table_foreach ( vtl->waypoints, (GHFunc) trw_layer_realize_waypoint, pass_along );
+ g_hash_table_foreach ( vtl->waypoints, (GHFunc) trw_layer_realize_waypoint, pass_along );
+
+ vik_treeview_item_set_visible ( (VikTreeview *) vt, &(vtl->waypoints_iter), vtl->waypoints_visible );
+ }
}
{
case VIK_TRW_LAYER_SUBLAYER_TRACKS: return (l->tracks_visible ^= 1);
case VIK_TRW_LAYER_SUBLAYER_WAYPOINTS: return (l->waypoints_visible ^= 1);
+ case VIK_TRW_LAYER_SUBLAYER_ROUTES: return (l->routes_visible ^= 1);
case VIK_TRW_LAYER_SUBLAYER_TRACK:
{
VikTrack *t = g_hash_table_lookup ( l->tracks, sublayer );
else
return TRUE;
}
+ case VIK_TRW_LAYER_SUBLAYER_ROUTE:
+ {
+ VikTrack *t = g_hash_table_lookup ( l->routes, sublayer );
+ if (t)
+ return (t->visible ^= 1);
+ else
+ return TRUE;
+ }
}
return TRUE;
}
// Put together all the elements to form compact tooltip text
g_snprintf (tmp_buf, sizeof(tmp_buf),
- _("Tracks: %d - Waypoints: %d%s"),
- g_hash_table_size (vtl->tracks), g_hash_table_size (vtl->waypoints), tbuf2);
+ _("Tracks: %d - Waypoints: %d - Routes: %d%s"),
+ g_hash_table_size (vtl->tracks), g_hash_table_size (vtl->waypoints), g_hash_table_size (vtl->routes), tbuf2);
g_date_free (gdate_start);
g_date_free (gdate_end);
{
switch ( subtype )
{
- case VIK_TRW_LAYER_SUBLAYER_TRACKS: return NULL;
- case VIK_TRW_LAYER_SUBLAYER_WAYPOINTS: return NULL;
+ case VIK_TRW_LAYER_SUBLAYER_TRACKS:
+ {
+ // Very simple tooltip - may expand detail in the future...
+ static gchar tmp_buf[32];
+ g_snprintf (tmp_buf, sizeof(tmp_buf),
+ _("Tracks: %d"),
+ g_hash_table_size (l->tracks));
+ return tmp_buf;
+ }
+ break;
+ case VIK_TRW_LAYER_SUBLAYER_ROUTES:
+ {
+ // Very simple tooltip - may expand detail in the future...
+ static gchar tmp_buf[32];
+ g_snprintf (tmp_buf, sizeof(tmp_buf),
+ _("Routes: %d"),
+ g_hash_table_size (l->routes));
+ return tmp_buf;
+ }
+ break;
+
+ case VIK_TRW_LAYER_SUBLAYER_ROUTE:
+ // Same tooltip for a route
case VIK_TRW_LAYER_SUBLAYER_TRACK:
{
- VikTrack *tr = g_hash_table_lookup ( l->tracks, sublayer );
+ VikTrack *tr;
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
+ tr = g_hash_table_lookup ( l->tracks, sublayer );
+ else
+ tr = g_hash_table_lookup ( l->routes, sublayer );
+
if ( tr ) {
// Could be a better way of handling strings - but this works...
gchar time_buf1[20];
}
}
break;
+ case VIK_TRW_LAYER_SUBLAYER_WAYPOINTS:
+ {
+ // Very simple tooltip - may expand detail in the future...
+ static gchar tmp_buf[32];
+ g_snprintf (tmp_buf, sizeof(tmp_buf),
+ _("Waypoints: %d"),
+ g_hash_table_size (l->waypoints));
+ return tmp_buf;
+ }
+ break;
case VIK_TRW_LAYER_SUBLAYER_WAYPOINT:
{
VikWaypoint *w = g_hash_table_lookup ( l->waypoints, sublayer );
case VIK_TRW_LAYER_SUBLAYER_TRACK:
{
VikTrack *track = g_hash_table_lookup ( l->tracks, sublayer );
- vik_window_set_selected_track ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l), (gpointer)track, l, sublayer );
+ vik_window_set_selected_track ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l), (gpointer)track, l );
+ /* Mark for redraw */
+ return TRUE;
+ }
+ break;
+ case VIK_TRW_LAYER_SUBLAYER_ROUTES:
+ {
+ vik_window_set_selected_tracks ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l), l->routes, l );
+ /* Mark for redraw */
+ return TRUE;
+ }
+ break;
+ case VIK_TRW_LAYER_SUBLAYER_ROUTE:
+ {
+ VikTrack *track = g_hash_table_lookup ( l->routes, sublayer );
+ vik_window_set_selected_track ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l), (gpointer)track, l );
/* Mark for redraw */
return TRUE;
}
break;
case VIK_TRW_LAYER_SUBLAYER_WAYPOINT:
{
- VikWaypoint *wpt = g_hash_table_lookup ( l->waypoints, sublayer );
- if ( wpt ) {
- vik_window_set_selected_waypoint ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l), (gpointer)wpt, l, sublayer );
- // Show some waypoint info
- set_statusbar_msg_info_wpt ( l, wpt );
- /* Mark for redraw */
- return TRUE;
- }
+ VikWaypoint *wpt = g_hash_table_lookup ( l->waypoints, sublayer );
+ if ( wpt ) {
+ vik_window_set_selected_waypoint ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l), (gpointer)wpt, l );
+ // Show some waypoint info
+ set_statusbar_msg_info_wpt ( l, wpt );
+ /* Mark for redraw */
+ return TRUE;
+ }
}
break;
default:
return l->tracks;
}
+GHashTable *vik_trw_layer_get_routes ( VikTrwLayer *l )
+{
+ return l->routes;
+}
+
GHashTable *vik_trw_layer_get_waypoints ( VikTrwLayer *l )
{
return l->waypoints;
return g_hash_table_find ( vtl->tracks, (GHRFunc) trw_layer_track_find, (gpointer) name );
}
-static void trw_layer_find_maxmin_waypoints ( const gchar *name, const VikWaypoint *w, struct LatLon maxmin[2] )
+/*
+ * Get route by name - not guaranteed to be unique
+ * Finds the first one
+ */
+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 );
maxmin[1].lon = VIK_LATLON(&fixme)->lon;
}
-static void trw_layer_find_maxmin_tracks ( const gchar *name, GList **t, struct LatLon maxmin[2] )
+static void trw_layer_find_maxmin_tracks ( const gpointer id, const VikTrack *trk, struct LatLon maxmin[2] )
{
- GList *tr = *t;
+ GList *tr = trk->trackpoints;
static VikCoord fixme;
while ( tr )
static void trw_layer_find_maxmin (VikTrwLayer *vtl, struct LatLon maxmin[2])
{
- struct LatLon wpt_maxmin[2] = { {0.0,0.0}, {0.0,0.0} };
- struct LatLon trk_maxmin[2] = { {0.0,0.0}, {0.0,0.0} };
-
- g_hash_table_foreach ( vtl->waypoints, (GHFunc) trw_layer_find_maxmin_waypoints, wpt_maxmin );
- g_hash_table_foreach ( vtl->tracks, (GHFunc) trw_layer_find_maxmin_tracks, trk_maxmin );
- if ((wpt_maxmin[0].lat != 0.0 && wpt_maxmin[0].lat > trk_maxmin[0].lat) || trk_maxmin[0].lat == 0.0) {
- maxmin[0].lat = wpt_maxmin[0].lat;
- }
- else {
- maxmin[0].lat = trk_maxmin[0].lat;
- }
- if ((wpt_maxmin[0].lon != 0.0 && wpt_maxmin[0].lon > trk_maxmin[0].lon) || trk_maxmin[0].lon == 0.0) {
- maxmin[0].lon = wpt_maxmin[0].lon;
- }
- else {
- maxmin[0].lon = trk_maxmin[0].lon;
- }
- if ((wpt_maxmin[1].lat != 0.0 && wpt_maxmin[1].lat < trk_maxmin[1].lat) || trk_maxmin[1].lat == 0.0) {
- maxmin[1].lat = wpt_maxmin[1].lat;
- }
- else {
- maxmin[1].lat = trk_maxmin[1].lat;
- }
- if ((wpt_maxmin[1].lon != 0.0 && wpt_maxmin[1].lon < trk_maxmin[1].lon) || trk_maxmin[1].lon == 0.0) {
- maxmin[1].lon = wpt_maxmin[1].lon;
- }
- else {
- maxmin[1].lon = trk_maxmin[1].lon;
- }
+ // Continually reuse maxmin to find the latest maximum and minimum values
+ g_hash_table_foreach ( vtl->waypoints, (GHFunc) trw_layer_find_maxmin_waypoints, maxmin );
+ 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 );
}
gboolean vik_trw_layer_find_center ( VikTrwLayer *vtl, VikCoord *dest )
if ( g_file_test ( fn, G_FILE_TEST_EXISTS ) == FALSE )
{
gtk_widget_hide ( file_selector );
- failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), fn, file_type, trk );
+ failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), fn, file_type, trk, TRUE );
break;
}
else
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 );
- failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), fn, file_type, trk );
+ failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), fn, file_type, trk, TRUE );
break;
}
}
int fd;
if ((fd = g_file_open_tmp("tmp-viking.XXXXXX.gpx", &name_used, NULL)) >= 0) {
- gboolean failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), name_used, FILE_TYPE_GPX, NULL);
+ gboolean failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), name_used, FILE_TYPE_GPX, NULL, TRUE);
if (failed) {
a_dialog_error_msg (VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0]), _("Could not create temporary file for export.") );
}
gpointer layer_and_vlp[2];
layer_and_vlp[0] = pass_along[0];
layer_and_vlp[1] = pass_along[1];
- VikTrack *trk = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
+
+ 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] );
+ else
+ trk = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
if ( !trk || !trk->name )
return;
static void trw_layer_new_wikipedia_wp_viewport ( gpointer lav[2] )
{
- VikCoord one, two;
- struct LatLon one_ll, two_ll;
struct LatLon maxmin[2] = { {0.0,0.0}, {0.0,0.0} };
-
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);
- vik_viewport_screen_to_coord ( vvp, 0, 0, &one);
- vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &two);
- vik_coord_to_latlon(&one, &one_ll);
- vik_coord_to_latlon(&two, &two_ll);
- if (one_ll.lat > two_ll.lat) {
- maxmin[0].lat = one_ll.lat;
- maxmin[1].lat = two_ll.lat;
- }
- else {
- maxmin[0].lat = two_ll.lat;
- maxmin[1].lat = one_ll.lat;
- }
- if (one_ll.lon > two_ll.lon) {
- maxmin[0].lon = one_ll.lon;
- maxmin[1].lon = two_ll.lon;
- }
- else {
- maxmin[0].lon = two_ll.lon;
- maxmin[1].lon = one_ll.lon;
- }
- a_geonames_wikipedia_box((VikWindow *)(VIK_GTK_WINDOW_FROM_LAYER(vtl)), vtl, vlp, maxmin);
+
+ // 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);
+ vik_layers_panel_emit_update ( vlp );
}
static void trw_layer_new_wikipedia_wp_layer ( gpointer lav[2] )
struct LatLon maxmin[2] = { {0.0,0.0}, {0.0,0.0} };
trw_layer_find_maxmin (vtl, maxmin);
- a_geonames_wikipedia_box((VikWindow *)(VIK_GTK_WINDOW_FROM_LAYER(vtl)), vtl, vlp, maxmin);
+ a_geonames_wikipedia_box((VikWindow *)(VIK_GTK_WINDOW_FROM_LAYER(vtl)), vtl, maxmin);
+ vik_layers_panel_emit_update ( vlp );
}
#ifdef VIK_CONFIG_GEOTAG
a_acquire ( vw, vlp, vvp, &vik_datasource_gps_interface );
}
+#ifdef VIK_CONFIG_GOOGLE
/*
* Acquire into this TRW Layer from Google Directions
*/
a_acquire ( vw, vlp, vvp, &vik_datasource_google_interface );
}
+#endif
#ifdef VIK_CONFIG_OPENSTREETMAP
/*
a_acquire ( vw, vlp, vvp, &vik_datasource_osm_interface );
}
+
+/**
+ * Acquire into this TRW Layer from OSM for 'My' Traces
+ */
+static void trw_layer_acquire_osm_my_traces_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_osm_my_traces_interface );
+}
#endif
#ifdef VIK_CONFIG_GEOCACHES
}
#endif
-static void trw_layer_new_wp ( gpointer lav[2] )
+static void trw_layer_gps_upload ( gpointer lav[2] )
{
- VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
- 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 )
- vik_layers_panel_emit_update ( vlp );
+ gpointer pass_along[6];
+ pass_along[0] = lav[0];
+ pass_along[1] = lav[1];
+ pass_along[2] = NULL; // No track - operate on the layer
+ pass_along[3] = NULL;
+ pass_along[4] = NULL;
+ pass_along[5] = NULL;
+
+ trw_layer_gps_upload_any ( pass_along );
}
-static void trw_layer_auto_tracks_view ( gpointer lav[2] )
+/**
+ * If pass_along[3] is defined that this will upload just that track
+ */
+static void trw_layer_gps_upload_any ( gpointer pass_along[6] )
{
- VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
- VikLayersPanel *vlp = VIK_LAYERS_PANEL(lav[1]);
+ VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]);
+ VikLayersPanel *vlp = VIK_LAYERS_PANEL(pass_along[1]);
+
+ // May not actually get a track here as pass_along[2&3] can be null
+ VikTrack *track = NULL;
+ vik_gps_xfer_type xfer_type = TRK; // VIK_TRW_LAYER_SUBLAYER_TRACKS = 0 so hard to test different from NULL!
+ gboolean xfer_all = FALSE;
+
+ if ( pass_along[2] ) {
+ xfer_all = FALSE;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE ) {
+ track = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ xfer_type = RTE;
+ }
+ else if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_TRACK ) {
+ track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+ xfer_type = TRK;
+ }
+ else if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_WAYPOINTS ) {
+ xfer_type = WPT;
+ }
+ else if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTES ) {
+ xfer_type = RTE;
+ }
+ }
+ else if ( !pass_along[4] )
+ xfer_all = TRUE; // i.e. whole layer
+
+ if (track && !track->visible) {
+ a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vtl), _("Can not upload invisible track.") );
+ return;
+ }
+
+ GtkWidget *dialog = gtk_dialog_new_with_buttons ( _("GPS Upload"),
+ VIK_GTK_WINDOW_FROM_LAYER(pass_along[0]),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_OK,
+ GTK_RESPONSE_ACCEPT,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_REJECT,
+ NULL );
+
+ gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
+ GtkWidget *response_w = NULL;
+#if GTK_CHECK_VERSION (2, 20, 0)
+ response_w = gtk_dialog_get_widget_for_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
+#endif
+
+ if ( response_w )
+ gtk_widget_grab_focus ( response_w );
+
+ gpointer dgs = datasource_gps_setup ( dialog, xfer_type, xfer_all );
+
+ if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) != GTK_RESPONSE_ACCEPT ) {
+ datasource_gps_clean_up ( dgs );
+ gtk_widget_destroy ( dialog );
+ return;
+ }
+
+ // Get info from reused datasource dialog widgets
+ gchar* protocol = datasource_gps_get_protocol ( dgs );
+ gchar* port = datasource_gps_get_descriptor ( dgs );
+ // NB don't free the above strings as they're references to values held elsewhere
+ gboolean do_tracks = datasource_gps_get_do_tracks ( dgs );
+ gboolean do_routes = datasource_gps_get_do_routes ( dgs );
+ gboolean do_waypoints = datasource_gps_get_do_waypoints ( dgs );
+ gboolean turn_off = datasource_gps_get_off ( dgs );
+
+ gtk_widget_destroy ( dialog );
+
+ // When called from the viewport - work the corresponding layerspanel:
+ if ( !vlp ) {
+ vlp = vik_window_layers_panel ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)) );
+ }
+
+ // Apply settings to transfer to the GPS device
+ vik_gps_comm ( vtl,
+ track,
+ GPS_UP,
+ protocol,
+ port,
+ FALSE,
+ vik_layers_panel_get_viewport (vlp),
+ vlp,
+ do_tracks,
+ do_routes,
+ do_waypoints,
+ turn_off );
+}
+
+/*
+ * Acquire into this TRW Layer from any GPS Babel supported file
+ */
+static void trw_layer_acquire_file_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_file_interface );
+}
+
+static void trw_layer_new_wp ( gpointer lav[2] )
+{
+ VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+ 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 )
+ 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] )
+{
+ VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+
+ if ( ! vtl->current_track ) {
+ gchar *name = trw_layer_new_unique_sublayer_name ( vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, _("Track")) ;
+ new_track_create_common ( vtl, name );
+
+ vik_window_enable_layer_tool ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), VIK_LAYER_TRW, TOOL_CREATE_TRACK );
+ }
+}
+
+static void new_route_create_common ( VikTrwLayer *vtl, gchar *name )
+{
+ vtl->current_track = vik_track_new();
+ vtl->current_track->visible = TRUE;
+ vtl->current_track->is_route = TRUE;
+ // By default make all routes red
+ vtl->current_track->has_color = TRUE;
+ gdk_color_parse ( "red", &vtl->current_track->color );
+ vik_trw_layer_add_route ( vtl, name, vtl->current_track );
+}
+
+static void trw_layer_new_route ( gpointer lav[2] )
+{
+ VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+
+ 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 );
+ vik_window_enable_layer_tool ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), VIK_LAYER_TRW, TOOL_CREATE_ROUTE );
+ }
+}
+
+static void trw_layer_auto_routes_view ( gpointer lav[2] )
+{
+ VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+ VikLayersPanel *vlp = VIK_LAYERS_PANEL(lav[1]);
+
+ if ( g_hash_table_size (vtl->routes) > 0 ) {
+ struct LatLon maxmin[2] = { {0,0}, {0,0} };
+ g_hash_table_foreach ( vtl->routes, (GHFunc) trw_layer_find_maxmin_tracks, maxmin );
+ trw_layer_zoom_to_show_latlons ( vtl, vik_layers_panel_get_viewport (vlp), maxmin );
+ vik_layers_panel_emit_update ( vlp );
+ }
+}
+
+
+static void trw_layer_finish_track ( gpointer lav[2] )
+{
+ VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+ vtl->current_track = NULL;
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
+}
+
+static void trw_layer_auto_tracks_view ( gpointer lav[2] )
+{
+ VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+ VikLayersPanel *vlp = VIK_LAYERS_PANEL(lav[1]);
if ( g_hash_table_size (vtl->tracks) > 0 ) {
struct LatLon maxmin[2] = { {0,0}, {0,0} };
}
}
-static void trw_layer_single_waypoint_jump ( const gchar *name, const VikWaypoint *wp, gpointer vvp )
+static void trw_layer_single_waypoint_jump ( const gpointer id, const VikWaypoint *wp, gpointer vvp )
{
/* NB do not care if wp is visible or not */
vik_viewport_set_center_coord ( VIK_VIEWPORT(vvp), &(wp->coord) );
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
gtk_widget_show ( item );
+ if ( vtl->current_track ) {
+ if ( vtl->current_track->is_route )
+ item = gtk_menu_item_new_with_mnemonic ( _("_Finish Route") );
+ else
+ item = gtk_menu_item_new_with_mnemonic ( _("_Finish Track") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_finish_track), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
+
+ // Add separator
+ item = gtk_menu_item_new ();
+ gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ gtk_widget_show ( item );
+ }
+
/* Now with icons */
item = gtk_image_menu_item_new_with_mnemonic ( _("_View Layer") );
gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ZOOM_FIT, GTK_ICON_SIZE_MENU) );
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show ( item );
- item = gtk_menu_item_new_with_mnemonic ( _("View All Trac_ks") );
- g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_auto_tracks_view), pass_along );
+ GtkWidget *view_submenu = gtk_menu_new();
+ item = gtk_image_menu_item_new_with_mnemonic ( _("V_iew") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_FIND, 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), view_submenu );
- item = gtk_menu_item_new_with_mnemonic ( _("V_iew All Waypoints") );
+ item = gtk_menu_item_new_with_mnemonic ( _("View All _Tracks") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_auto_tracks_view), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (view_submenu), item);
+ gtk_widget_show ( item );
+
+ item = gtk_menu_item_new_with_mnemonic ( _("View All _Routes") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_auto_routes_view), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (view_submenu), item);
+ gtk_widget_show ( item );
+
+ item = gtk_menu_item_new_with_mnemonic ( _("View All _Waypoints") );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_auto_waypoints_view), pass_along );
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (view_submenu), item);
gtk_widget_show ( item );
item = gtk_image_menu_item_new_with_mnemonic ( _("_Goto Center of Layer") );
gtk_menu_shell_append (GTK_MENU_SHELL (export_submenu), item);
gtk_widget_show ( item );
- item = gtk_image_menu_item_new_with_mnemonic ( _("_New Waypoint...") );
+ GtkWidget *new_submenu = gtk_menu_new();
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_New") );
gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_NEW, GTK_ICON_SIZE_MENU) );
- g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_new_wp), pass_along );
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
- gtk_widget_show ( item );
-
-#ifdef VIK_CONFIG_GEONAMES
- GtkWidget *wikipedia_submenu = gtk_menu_new();
- item = gtk_image_menu_item_new_with_mnemonic ( _("_Add Wikipedia Waypoints") );
- gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ADD, 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), wikipedia_submenu);
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), new_submenu);
- item = gtk_image_menu_item_new_with_mnemonic ( _("Within _Layer Bounds") );
- gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ZOOM_FIT, GTK_ICON_SIZE_MENU) );
- g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_new_wikipedia_wp_layer), pass_along );
- gtk_menu_shell_append (GTK_MENU_SHELL (wikipedia_submenu), item);
+ item = gtk_image_menu_item_new_with_mnemonic ( _("New _Waypoint...") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_NEW, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_new_wp), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (new_submenu), item);
gtk_widget_show ( item );
- item = gtk_image_menu_item_new_with_mnemonic ( _("Within _Current View") );
- gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ZOOM_100, GTK_ICON_SIZE_MENU) );
- g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_new_wikipedia_wp_viewport), pass_along );
- gtk_menu_shell_append (GTK_MENU_SHELL (wikipedia_submenu), item);
+ item = gtk_image_menu_item_new_with_mnemonic ( _("New _Track") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_NEW, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_new_track), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (new_submenu), item);
gtk_widget_show ( item );
-#endif
+ // Make it available only when a new track *not* already in progress
+ gtk_widget_set_sensitive ( item, ! (gboolean)GPOINTER_TO_INT(vtl->current_track) );
+
+ item = gtk_image_menu_item_new_with_mnemonic ( _("New _Route") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_NEW, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_new_route), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (new_submenu), item);
+ gtk_widget_show ( item );
+ // Make it available only when a new track *not* already in progress
+ gtk_widget_set_sensitive ( item, ! (gboolean)GPOINTER_TO_INT(vtl->current_track) );
#ifdef VIK_CONFIG_GEOTAG
item = gtk_menu_item_new_with_mnemonic ( _("Geotag _Images...") );
#endif
GtkWidget *acquire_submenu = gtk_menu_new ();
- item = gtk_image_menu_item_new_with_mnemonic ( _("Ac_quire") );
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_Acquire") );
gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_GO_DOWN, GTK_ICON_SIZE_MENU) );
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show ( item );
gtk_menu_shell_append (GTK_MENU_SHELL (acquire_submenu), item);
gtk_widget_show ( item );
- item = gtk_menu_item_new_with_mnemonic ( _("From G_oogle Directions...") );
+#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 );
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...") );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_acquire_osm_cb), pass_along );
gtk_menu_shell_append (GTK_MENU_SHELL (acquire_submenu), item);
gtk_widget_show ( item );
+
+ item = gtk_menu_item_new_with_mnemonic ( _("From _My OSM Traces...") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_acquire_osm_my_traces_cb), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (acquire_submenu), item);
+ gtk_widget_show ( item );
+#endif
+
+#ifdef VIK_CONFIG_GEONAMES
+ GtkWidget *wikipedia_submenu = gtk_menu_new();
+ item = gtk_image_menu_item_new_with_mnemonic ( _("From _Wikipedia Waypoints") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU) );
+ gtk_menu_shell_append(GTK_MENU_SHELL (acquire_submenu), item);
+ gtk_widget_show(item);
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), wikipedia_submenu);
+
+ item = gtk_image_menu_item_new_with_mnemonic ( _("Within _Layer Bounds") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ZOOM_FIT, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_new_wikipedia_wp_layer), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (wikipedia_submenu), item);
+ gtk_widget_show ( item );
+
+ item = gtk_image_menu_item_new_with_mnemonic ( _("Within _Current View") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ZOOM_100, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_new_wikipedia_wp_viewport), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (wikipedia_submenu), item);
+ gtk_widget_show ( item );
#endif
#ifdef VIK_CONFIG_GEOCACHES
gtk_widget_show ( item );
#endif
+ item = gtk_menu_item_new_with_mnemonic ( _("From _File...") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_acquire_file_cb), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (acquire_submenu), item);
+ gtk_widget_show ( item );
+
+ 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) );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), upload_submenu );
+
+ item = gtk_image_menu_item_new_with_mnemonic ( _("Upload to _GPS...") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_gps_upload), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (upload_submenu), item);
+ gtk_widget_show ( item );
+
#ifdef VIK_CONFIG_OPENSTREETMAP
item = gtk_image_menu_item_new_with_mnemonic ( _("Upload to _OSM...") );
gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_GO_UP, GTK_ICON_SIZE_MENU) );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(osm_traces_upload_cb), pass_along );
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (upload_submenu), item);
gtk_widget_show ( item );
#endif
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(delete_submenu), item );
gtk_widget_show ( item );
+
+ item = gtk_image_menu_item_new_with_mnemonic ( _("Delete _All Routes") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_delete_all_routes), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(delete_submenu), item );
+ gtk_widget_show ( item );
+
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_Delete Routes From Selection...") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_INDEX, GTK_ICON_SIZE_MENU) );
+ 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(delete_submenu), item );
+ gtk_widget_show ( item );
item = gtk_image_menu_item_new_with_mnemonic ( _("Delete All _Waypoints") );
gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU) );
if ( VIK_LAYER(vtl)->realized )
{
+ // Do we need to create the sublayer:
+ if ( g_hash_table_size (vtl->waypoints) == 0 ) {
+ trw_layer_add_sublayer_waypoints ( vtl, VIK_LAYER(vtl)->vt, &(VIK_LAYER(vtl)->iter) );
+ }
+
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, NULL, TRUE, TRUE );
+ 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, NULL, TRUE, TRUE );
+ 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 );
if ( VIK_LAYER(vtl)->realized )
{
+ // Do we need to create the sublayer:
+ if ( g_hash_table_size (vtl->tracks) == 0 ) {
+ trw_layer_add_sublayer_tracks ( vtl, VIK_LAYER(vtl)->vt, &(VIK_LAYER(vtl)->iter) );
+ }
+
GtkTreeIter *iter = g_malloc(sizeof(GtkTreeIter));
// Visibility column always needed for tracks
#ifdef VIK_CONFIG_ALPHABETIZED_TRW
}
g_hash_table_insert ( vtl->tracks, GUINT_TO_POINTER(tr_uuid), t );
-
+
+ trw_layer_update_treeview ( vtl, t, GUINT_TO_POINTER(tr_uuid) );
+}
+
+// Fake Route UUIDs vi simple increasing integer
+static guint rt_uuid = 0;
+
+void vik_trw_layer_add_route ( VikTrwLayer *vtl, gchar *name, VikTrack *t )
+{
+ rt_uuid++;
+
+ vik_track_set_name (t, name);
+
+ if ( VIK_LAYER(vtl)->realized )
+ {
+ // Do we need to create the sublayer:
+ if ( g_hash_table_size (vtl->routes) == 0 ) {
+ trw_layer_add_sublayer_routes ( vtl, VIK_LAYER(vtl)->vt, &(VIK_LAYER(vtl)->iter) );
+ }
+
+ 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
+ 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
+ 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 );
+ }
+
+ g_hash_table_insert ( vtl->routes, GUINT_TO_POINTER(rt_uuid), t );
+
+ trw_layer_update_treeview ( vtl, t, GUINT_TO_POINTER(rt_uuid) );
}
/* to be called whenever a track has been deleted or may have been changed. */
{
if (vtl->current_tp_track == trk )
trw_layer_cancel_current_tp ( vtl, FALSE );
- else if (vtl->last_tp_track == trk )
- trw_layer_cancel_last_tp ( vtl );
}
-
-static gchar *get_new_unique_sublayer_name (VikTrwLayer *vtl, gint sublayer_type, const gchar *name)
+
+gchar *trw_layer_new_unique_sublayer_name (VikTrwLayer *vtl, gint sublayer_type, const gchar *name)
{
- gint i = 2;
- gchar *newname = g_strdup(name);
- while ((sublayer_type == VIK_TRW_LAYER_SUBLAYER_TRACK) ?
- (void *)vik_trw_layer_get_track(vtl, newname) : (void *)vik_trw_layer_get_waypoint(vtl, newname)) {
- gchar *new_newname = g_strdup_printf("%s#%d", name, i);
- g_free(newname);
- newname = new_newname;
- i++;
- }
+ gint i = 2;
+ gchar *newname = g_strdup(name);
+
+ gpointer id = NULL;
+ do {
+ id = NULL;
+ switch ( sublayer_type ) {
+ case VIK_TRW_LAYER_SUBLAYER_TRACK:
+ id = (gpointer) vik_trw_layer_get_track ( vtl, newname );
+ break;
+ case VIK_TRW_LAYER_SUBLAYER_WAYPOINT:
+ id = (gpointer) vik_trw_layer_get_waypoint ( vtl, newname );
+ break;
+ default:
+ id = (gpointer) vik_trw_layer_get_route ( vtl, newname );
+ break;
+ }
+ // If found a name already in use try adding 1 to it and we try again
+ if ( id ) {
+ gchar *new_newname = g_strdup_printf("%s#%d", name, i);
+ g_free(newname);
+ newname = new_newname;
+ i++;
+ }
+ } while ( id != NULL);
+
return newname;
}
} else {
// No more uniqueness of name forced when loading from a file
- vik_trw_layer_add_track ( vtl, name, tr );
+ if ( tr->is_route )
+ vik_trw_layer_add_route ( vtl, name, tr );
+ else
+ vik_trw_layer_add_track ( vtl, name, tr );
if ( vtl->route_finder_check_added_track ) {
vik_track_remove_dup_points ( tr ); /* make "double point" track work to undo */
if (type == VIK_TRW_LAYER_SUBLAYER_TRACK) {
VikTrack *trk = g_hash_table_lookup ( vtl_src->tracks, id );
- gchar *newname = get_new_unique_sublayer_name(vtl_dest, type, trk->name);
+ gchar *newname = trw_layer_new_unique_sublayer_name(vtl_dest, type, trk->name);
- VikTrack *trk2 = vik_track_copy ( trk );
+ VikTrack *trk2 = vik_track_copy ( trk, TRUE );
vik_trw_layer_add_track ( vtl_dest, newname, trk2 );
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);
+
+ VikTrack *trk2 = vik_track_copy ( trk, TRUE );
+ vik_trw_layer_add_route ( vtl_dest, newname, trk2 );
+ 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 = get_new_unique_sublayer_name(vtl_dest, type, wp->name);
+ gchar *newname = trw_layer_new_unique_sublayer_name(vtl_dest, type, wp->name);
VikWaypoint *wp2 = vik_waypoint_copy ( wp );
vik_trw_layer_add_waypoint ( vtl_dest, newname, wp2 );
if (type==VIK_TRW_LAYER_SUBLAYER_WAYPOINTS) {
g_hash_table_foreach ( vtl_src->waypoints, (GHFunc)trw_layer_enum_item, &items);
}
-
+ if (type==VIK_TRW_LAYER_SUBLAYER_ROUTES) {
+ g_hash_table_foreach ( vtl_src->routes, (GHFunc)trw_layer_enum_item, &items);
+ }
+
iter = items;
while (iter) {
if (type==VIK_TRW_LAYER_SUBLAYER_TRACKS) {
- trw_layer_move_item ( vtl_src, vtl_dest, iter->data, VIK_TRW_LAYER_SUBLAYER_TRACK);
+ trw_layer_move_item ( vtl_src, vtl_dest, iter->data, VIK_TRW_LAYER_SUBLAYER_TRACK);
+ }
+ 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);
+ trw_layer_move_item ( vtl_src, vtl_dest, iter->data, VIK_TRW_LAYER_SUBLAYER_WAYPOINT);
}
iter = iter->next;
}
vik_treeview_item_delete ( VIK_LAYER(vtl)->vt, it );
g_hash_table_remove ( vtl->tracks_iters, udata.uuid );
g_hash_table_remove ( vtl->tracks, udata.uuid );
+
+ // If last sublayer, then remove sublayer container
+ if ( g_hash_table_size (vtl->tracks) == 0 ) {
+ vik_treeview_item_delete ( VIK_LAYER(vtl)->vt, &(vtl->tracks_iter) );
+ }
+ }
+ }
+ }
+ return was_visible;
+}
+
+gboolean vik_trw_layer_delete_route ( VikTrwLayer *vtl, VikTrack *trk )
+{
+ gboolean was_visible = FALSE;
+
+ if ( trk && trk->name ) {
+
+ if ( trk == vtl->current_track ) {
+ vtl->current_track = NULL;
+ vtl->current_tp_track = NULL;
+ vtl->current_tp_id = NULL;
+ vtl->moving_tp = FALSE;
+ }
+
+ was_visible = trk->visible;
+
+ if ( trk == vtl->route_finder_current_track )
+ vtl->route_finder_current_track = NULL;
+
+ if ( trk == vtl->route_finder_added_track )
+ vtl->route_finder_added_track = NULL;
+
+ trku_udata udata;
+ udata.trk = trk;
+ udata.uuid = NULL;
+
+ // Hmmm, want key of it
+ gpointer *trkf = g_hash_table_find ( vtl->routes, (GHRFunc) trw_layer_track_find_uuid, &udata );
+
+ if ( trkf && udata.uuid ) {
+ /* could be current_tp, so we have to check */
+ trw_layer_cancel_tps_of_track ( vtl, trk );
+
+ GtkTreeIter *it = g_hash_table_lookup ( vtl->routes_iters, udata.uuid );
+
+ if ( it ) {
+ vik_treeview_item_delete ( VIK_LAYER(vtl)->vt, it );
+ g_hash_table_remove ( vtl->routes_iters, udata.uuid );
+ g_hash_table_remove ( vtl->routes, udata.uuid );
+
+ // If last sublayer, then remove sublayer container
+ if ( g_hash_table_size (vtl->routes) == 0 ) {
+ vik_treeview_item_delete ( VIK_LAYER(vtl)->vt, &(vtl->routes_iter) );
+ }
}
}
}
highest_wp_number_remove_wp(vtl, wp->name);
g_hash_table_remove ( vtl->waypoints, udata.uuid ); // last because this frees the name
+
+ // If last sublayer, then remove sublayer container
+ if ( g_hash_table_size (vtl->waypoints) == 0 ) {
+ vik_treeview_item_delete ( VIK_LAYER(vtl)->vt, &(vtl->waypoints_iter) );
+ }
}
}
/*
* Delete a track by the given name
* NOTE: ATM this will delete the first encountered Track with the specified name
- * as there be multiple track with the same name
+ * as there may be multiple tracks with the same name within the specified hash table
*/
-static gboolean trw_layer_delete_track_by_name ( VikTrwLayer *vtl, const gchar *name )
+static gboolean trw_layer_delete_track_by_name ( VikTrwLayer *vtl, const gchar *name, GHashTable *ht_tracks )
{
tpu_udata udata;
// Fake a track with the given name
udata.uuid = NULL;
// Hmmm, want key of it
- gpointer *trkf = g_hash_table_find ( vtl->tracks, (GHRFunc) trw_layer_track_find_uuid_by_name, &udata );
+ gpointer *trkf = g_hash_table_find ( ht_tracks, (GHRFunc) trw_layer_track_find_uuid_by_name, &udata );
vik_track_free (udata.trk);
- if ( trkf && udata.uuid )
- return vik_trw_layer_delete_track (vtl, g_hash_table_lookup ( vtl->tracks, udata.uuid ));
+ if ( trkf && udata.uuid ) {
+ // This could be a little better written...
+ if ( vtl->tracks == ht_tracks )
+ return vik_trw_layer_delete_track (vtl, g_hash_table_lookup ( ht_tracks, udata.uuid ));
+ if ( vtl->routes == ht_tracks )
+ return vik_trw_layer_delete_route (vtl, g_hash_table_lookup ( ht_tracks, udata.uuid ));
+ return FALSE;
+ }
else
return FALSE;
}
-static void remove_item_from_treeview(const gchar *name, GtkTreeIter *it, VikTreeview * vt)
+static void remove_item_from_treeview ( const gpointer id, GtkTreeIter *it, VikTreeview * vt )
{
vik_treeview_item_delete (vt, it );
}
+void vik_trw_layer_delete_all_routes ( VikTrwLayer *vtl )
+{
+
+ vtl->current_track = NULL;
+ vtl->route_finder_current_track = NULL;
+ vtl->route_finder_added_track = NULL;
+ if (vtl->current_tp_track)
+ trw_layer_cancel_current_tp(vtl, FALSE);
+
+ g_hash_table_foreach(vtl->routes_iters, (GHFunc) remove_item_from_treeview, VIK_LAYER(vtl)->vt);
+ g_hash_table_remove_all(vtl->routes_iters);
+ g_hash_table_remove_all(vtl->routes);
+
+ vik_treeview_item_delete ( VIK_LAYER(vtl)->vt, &(vtl->routes_iter) );
+
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
+}
+
void vik_trw_layer_delete_all_tracks ( VikTrwLayer *vtl )
{
vtl->route_finder_added_track = NULL;
if (vtl->current_tp_track)
trw_layer_cancel_current_tp(vtl, FALSE);
- if (vtl->last_tp_track)
- trw_layer_cancel_last_tp ( vtl );
g_hash_table_foreach(vtl->tracks_iters, (GHFunc) remove_item_from_treeview, VIK_LAYER(vtl)->vt);
g_hash_table_remove_all(vtl->tracks_iters);
g_hash_table_remove_all(vtl->tracks);
- vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+ vik_treeview_item_delete ( VIK_LAYER(vtl)->vt, &(vtl->tracks_iter) );
+
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
}
void vik_trw_layer_delete_all_waypoints ( VikTrwLayer *vtl )
g_hash_table_remove_all(vtl->waypoints_iters);
g_hash_table_remove_all(vtl->waypoints);
- vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+ vik_treeview_item_delete ( VIK_LAYER(vtl)->vt, &(vtl->waypoints_iter) );
+
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
}
static void trw_layer_delete_all_tracks ( gpointer lav[2] )
vik_trw_layer_delete_all_tracks (vtl);
}
+static void trw_layer_delete_all_routes ( gpointer lav[2] )
+{
+ VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+ // Get confirmation from the user
+ if ( a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
+ _("Are you sure you want to delete all routes in %s?"),
+ vik_layer_get_name ( VIK_LAYER(vtl) ) ) )
+ vik_trw_layer_delete_all_routes (vtl);
+}
+
static void trw_layer_delete_all_waypoints ( gpointer lav[2] )
{
VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
was_visible = trw_layer_delete_waypoint ( vtl, wp );
}
}
- else
+ else if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_TRACK )
{
VikTrack *trk = g_hash_table_lookup ( vtl->tracks, pass_along[3] );
if ( trk && trk->name ) {
was_visible = vik_trw_layer_delete_track ( vtl, trk );
}
}
+ else
+ {
+ VikTrack *trk = g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ if ( trk && trk->name ) {
+ if ( GPOINTER_TO_INT ( pass_along[4]) )
+ // Get confirmation from the user
+ if ( ! a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
+ _("Are you sure you want to delete the route \"%s\""),
+ trk->name ) )
+ return;
+ was_visible = vik_trw_layer_delete_route ( vtl, trk );
+ }
+ }
if ( was_visible )
- vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
}
gboolean updated = FALSE;
a_dialog_waypoint ( VIK_GTK_WINDOW_FROM_LAYER(vtl), wp->name, wp, vtl->coord_mode, FALSE, &updated );
+ if ( updated && wp->symbol && 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 )
- vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
}
}
else
{
- VikTrack *tr = g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+ VikTrack *tr;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_TRACK )
+ tr = g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+ else
+ tr = g_hash_table_lookup ( vtl->routes, pass_along[3] );
+
if ( tr && tr->name )
{
vik_trw_layer_propwin_run ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
- vtl, tr,
+ vtl,
+ tr,
pass_along[1], /* vlp */
- pass_along[5] ); /* vvp */
+ pass_along[5], /* vvp */
+ pass_along[6]); /* iter */
}
}
}
+/*
+ * Update the treeview of the track id - primarily to update the icon
+ */
+void trw_layer_update_treeview ( VikTrwLayer *vtl, VikTrack *trk, gpointer *trk_id )
+{
+ trku_udata udata;
+ udata.trk = trk;
+ udata.uuid = NULL;
+
+ gpointer *trkf = NULL;
+ if ( trk->is_route )
+ trkf = g_hash_table_find ( vtl->routes, (GHRFunc) trw_layer_track_find_uuid, &udata );
+ else
+ trkf = g_hash_table_find ( vtl->tracks, (GHRFunc) trw_layer_track_find_uuid, &udata );
+
+ if ( trkf && udata.uuid ) {
+
+ GtkTreeIter *iter = NULL;
+ if ( trk->is_route )
+ iter = g_hash_table_lookup ( vtl->routes_iters, udata.uuid );
+ else
+ iter = g_hash_table_lookup ( vtl->tracks_iters, udata.uuid );
+
+ if ( iter ) {
+ // TODO: Make this a function
+ GdkPixbuf *pixbuf = gdk_pixbuf_new ( GDK_COLORSPACE_RGB, FALSE, 8, 18, 18);
+ guint32 pixel = ((trk->color.red & 0xff00) << 16) |
+ ((trk->color.green & 0xff00) << 8) |
+ (trk->color.blue & 0xff00);
+ gdk_pixbuf_fill ( pixbuf, pixel );
+ vik_treeview_item_set_icon ( VIK_LAYER(vtl)->vt, iter, pixbuf );
+ g_object_unref (pixbuf);
+ }
+
+ }
+}
+
/*
Parameter 1 -> VikLayersPanel
Parameter 2 -> VikLayer
/* since vlp not set, vl & vvp should be valid instead! */
if ( vl && vvp ) {
vik_viewport_set_center_coord ( VIK_VIEWPORT(vvp), coord );
- vik_layer_emit_update ( VIK_LAYER(vl), FALSE );
+ vik_layer_emit_update ( VIK_LAYER(vl) );
}
}
}
static void trw_layer_goto_track_startpoint ( gpointer pass_along[6] )
{
- GList *trps = ((VikTrack *) g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] ))->trackpoints;
- if ( trps && trps->data )
- goto_coord ( pass_along[1], pass_along[0], pass_along[5], &(((VikTrackpoint *) trps->data)->coord));
+ VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+ VikTrack *track;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ track = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( track && track->trackpoints )
+ goto_coord ( pass_along[1], pass_along[0], pass_along[5], &(((VikTrackpoint *) track->trackpoints->data)->coord) );
}
static void trw_layer_goto_track_center ( gpointer pass_along[6] )
{
- /* FIXME: get this into viktrack.c, and should be ->trackpoints right? */
- GList **trps = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
- if ( trps && *trps )
+ VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+ VikTrack *track;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ track = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( track && track->trackpoints )
{
struct LatLon average, maxmin[2] = { {0,0}, {0,0} };
VikCoord coord;
- trw_layer_find_maxmin_tracks ( NULL, trps, maxmin );
+ trw_layer_find_maxmin_tracks ( NULL, track, maxmin );
average.lat = (maxmin[0].lat+maxmin[1].lat)/2;
average.lon = (maxmin[0].lon+maxmin[1].lon)/2;
- vik_coord_load_from_latlon ( &coord, VIK_TRW_LAYER(pass_along[0])->coord_mode, &average );
+ vik_coord_load_from_latlon ( &coord, vtl->coord_mode, &average );
goto_coord ( pass_along[1], pass_along[0], pass_along[5], &coord);
}
}
+static void trw_layer_convert_track_route ( gpointer pass_along[6] )
+{
+ VikTrwLayer *vtl = (VikTrwLayer *)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] );
+ else
+ trk = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( !trk )
+ return;
+
+ // Converting a track to a route can be a bit more complicated,
+ // so give a chance to change our minds:
+ if ( !trk->is_route &&
+ ( ( vik_track_get_segment_count ( trk ) > 1 ) ||
+ ( vik_track_get_average_speed ( trk ) > 0.0 ) ) ) {
+
+ if ( ! a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
+ _("Converting a track to a route removes extra track data such as segments, timestamps, etc...\nDo you want to continue?"), NULL ) )
+ return;
+}
+
+ // Copy it
+ VikTrack *trk_copy = vik_track_copy ( trk, TRUE );
+
+ // Convert
+ trk_copy->is_route = !trk_copy->is_route;
+
+ // ATM can't set name to self - so must create temporary copy
+ gchar *name = g_strdup ( trk_copy->name );
+
+ // Delete old one and then add new one
+ if ( trk->is_route ) {
+ vik_trw_layer_delete_route ( vtl, trk );
+ vik_trw_layer_add_track ( vtl, name, trk_copy );
+ }
+ else {
+ // Extra route conversion bits...
+ vik_track_merge_segments ( trk_copy );
+ vik_track_to_routepoints ( trk_copy );
+
+ vik_trw_layer_delete_track ( vtl, trk );
+ vik_trw_layer_add_route ( vtl, name, trk_copy );
+ }
+ g_free ( name );
+
+ // Update in case color of track / route changes when moving between sublayers
+ vik_layer_emit_update ( VIK_LAYER(pass_along[0]) );
+}
+
+
static void trw_layer_extend_track_end ( gpointer pass_along[6] )
{
VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]);
- VikTrack *track = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
+ VikTrack *track;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ track = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( !track )
+ return;
vtl->current_track = track;
- vik_window_enable_layer_tool ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), VIK_LAYER_TRW, TOOL_CREATE_TRACK);
+ vik_window_enable_layer_tool ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), VIK_LAYER_TRW, track->is_route ? TOOL_CREATE_ROUTE : TOOL_CREATE_TRACK);
if ( track->trackpoints )
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
*/
static void trw_layer_extend_track_end_route_finder ( gpointer pass_along[6] )
{
VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]);
- VikTrack *track = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
+ VikTrack *track = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->routes, pass_along[3] );
+ if ( !track )
+ return;
VikCoord last_coord = (((VikTrackpoint *)g_list_last(track->trackpoints)->data)->coord);
- vik_window_enable_layer_tool ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), VIK_LAYER_TRW, NUM_TOOLS );
+ vik_window_enable_layer_tool ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), VIK_LAYER_TRW, TOOL_ROUTE_FINDER );
vtl->route_finder_coord = last_coord;
vtl->route_finder_current_track = track;
vtl->route_finder_started = TRUE;
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] )
{
/* TODO: check & warn if no DEM data, or no applicable DEM data. */
/* Also warn if overwrite old elevation data */
- VikTrack *track = (VikTrack *) g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
+ VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+ VikTrack *track;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ track = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
- vik_track_apply_dem_data ( track );
+ if ( track )
+ vik_track_apply_dem_data ( track );
}
static void trw_layer_goto_track_endpoint ( gpointer pass_along[6] )
{
- GList *trps = ((VikTrack *) g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] ))->trackpoints;
+ VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+ VikTrack *track;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ track = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( !track )
+ return;
+
+ GList *trps = track->trackpoints;
if ( !trps )
return;
trps = g_list_last(trps);
static void trw_layer_goto_track_max_speed ( gpointer pass_along[6] )
{
- VikTrackpoint* vtp = vik_track_get_tp_by_max_speed ( g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] ) );
+ VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+ VikTrack *track;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ track = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( !track )
+ return;
+
+ VikTrackpoint* vtp = vik_track_get_tp_by_max_speed ( track );
if ( !vtp )
return;
goto_coord ( pass_along[1], pass_along[0], pass_along[5], &(vtp->coord));
static void trw_layer_goto_track_max_alt ( gpointer pass_along[6] )
{
- VikTrackpoint* vtp = vik_track_get_tp_by_max_alt ( g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] ) );
+ VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+ VikTrack *track;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ track = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( !track )
+ return;
+
+ VikTrackpoint* vtp = vik_track_get_tp_by_max_alt ( track );
if ( !vtp )
return;
goto_coord ( pass_along[1], pass_along[0], pass_along[5], &(vtp->coord));
static void trw_layer_goto_track_min_alt ( gpointer pass_along[6] )
{
- VikTrackpoint* vtp = vik_track_get_tp_by_min_alt ( g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] ) );
+ VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+ VikTrack *track;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ track = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( !track )
+ return;
+
+ VikTrackpoint* vtp = vik_track_get_tp_by_min_alt ( track );
if ( !vtp )
return;
goto_coord ( pass_along[1], pass_along[0], pass_along[5], &(vtp->coord));
*/
static void trw_layer_auto_track_view ( gpointer pass_along[6] )
{
- GList **trps = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
- if ( trps && *trps )
+ VikTrwLayer *vtl = (VikTrwLayer *)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] );
+ else
+ trk = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( trk && trk->trackpoints )
{
struct LatLon maxmin[2] = { {0,0}, {0,0} };
- trw_layer_find_maxmin_tracks ( NULL, trps, maxmin );
+ trw_layer_find_maxmin_tracks ( NULL, trk, maxmin );
trw_layer_zoom_to_show_latlons ( VIK_TRW_LAYER(pass_along[0]), 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]), FALSE );
+ vik_layer_emit_update ( VIK_LAYER(pass_along[0]) );
}
}
{
VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
GList *other_tracks = NULL;
- VikTrack *track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+ GHashTable *ght_tracks;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ ght_tracks = vtl->routes;
+ else
+ ght_tracks = vtl->tracks;
+
+ VikTrack *track = (VikTrack *) g_hash_table_lookup ( ght_tracks, pass_along[3] );
+
+ if ( !track )
+ return;
if ( !track->trackpoints )
return;
// i.e. either those times, or those without
udata.with_timestamps = (VIK_TRACKPOINT(track->trackpoints->data)->has_timestamp);
- g_hash_table_foreach(vtl->tracks, find_tracks_with_timestamp_type, (gpointer)&udata);
+ g_hash_table_foreach(ght_tracks, find_tracks_with_timestamp_type, (gpointer)&udata);
other_tracks = g_list_reverse(other_tracks);
if ( !other_tracks ) {
GList *other_tracks_names = NULL;
GList *iter = g_list_first ( other_tracks );
while ( iter ) {
- other_tracks_names = g_list_append ( other_tracks_names, VIK_TRACK(g_hash_table_lookup (vtl->tracks, iter->data))->name );
+ other_tracks_names = g_list_append ( other_tracks_names, VIK_TRACK(g_hash_table_lookup (ght_tracks, iter->data))->name );
iter = g_list_next ( iter );
}
- other_tracks_names = g_list_sort_with_data (other_tracks_names, sort_alphabetically, NULL);
+ other_tracks_names = g_list_sort_with_data (other_tracks_names, sort_alphabetically, NULL);
+
+ GList *merge_list = a_dialog_select_from_list(VIK_GTK_WINDOW_FROM_LAYER(vtl),
+ other_tracks_names,
+ TRUE,
+ _("Merge with..."),
+ track->is_route ? _("Select route to merge with") : _("Select track to merge with"));
+ g_list_free(other_tracks);
+ g_list_free(other_tracks_names);
+
+ if (merge_list)
+ {
+ GList *l;
+ for (l = merge_list; l != NULL; l = g_list_next(l)) {
+ VikTrack *merge_track;
+ if ( track->is_route )
+ merge_track = vik_trw_layer_get_route ( vtl, l->data );
+ else
+ 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;
+ if ( track->is_route )
+ vik_trw_layer_delete_route (vtl, merge_track);
+ else
+ vik_trw_layer_delete_track (vtl, merge_track);
+ 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) );
+ }
+}
+
+// c.f. trw_layer_sorted_track_id_by_name_list
+// but don't add the specified track to the list (normally current track)
+static void trw_layer_sorted_track_id_by_name_list_exclude_self (const gpointer id, const VikTrack *trk, gpointer udata)
+{
+ twt_udata *user_data = udata;
+
+ // Skip self
+ if (trk->trackpoints == user_data->exclude) {
+ return;
+ }
+
+ // Sort named list alphabetically
+ *(user_data->result) = g_list_insert_sorted_with_data (*(user_data->result), trk->name, sort_alphabetically, NULL);
+}
+
+/**
+ * Join - this allows combining 'tracks' and 'track routes'
+ * i.e. doesn't care about whether tracks have consistent timestamps
+ * ATM can only append one track at a time to the currently selected track
+ */
+static void trw_layer_append_track ( gpointer pass_along[6] )
+{
+
+ VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+ VikTrack *trk;
+ GHashTable *ght_tracks;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ ght_tracks = vtl->routes;
+ else
+ ght_tracks = vtl->tracks;
+
+ trk = (VikTrack *) g_hash_table_lookup ( ght_tracks, pass_along[3] );
+
+ if ( !trk )
+ return;
+
+ GList *other_tracks_names = NULL;
+
+ // Sort alphabetically for user presentation
+ // Convert into list of names for usage with dialog function
+ // TODO: Need to consider how to work best when we can have multiple tracks the same name...
+ twt_udata udata;
+ udata.result = &other_tracks_names;
+ udata.exclude = trk->trackpoints;
+
+ g_hash_table_foreach(ght_tracks, (GHFunc) trw_layer_sorted_track_id_by_name_list_exclude_self, (gpointer)&udata);
+
+ // Note the limit to selecting one track only
+ // this is to control the ordering of appending tracks, i.e. the selected track always goes after the current track
+ // (otherwise with multiple select the ordering would not be controllable by the user - automatically being alphabetically)
+ GList *append_list = a_dialog_select_from_list(VIK_GTK_WINDOW_FROM_LAYER(vtl),
+ other_tracks_names,
+ FALSE,
+ trk->is_route ? _("Append Route"): _("Append Track"),
+ trk->is_route ? _("Select the route to append after the current route") :
+ _("Select the track to append after the current track") );
+
+ g_list_free(other_tracks_names);
+
+ // It's a list, but shouldn't contain more than one other track!
+ if ( append_list ) {
+ GList *l;
+ for (l = append_list; l != NULL; l = g_list_next(l)) {
+ // TODO: at present this uses the first track found by name,
+ // which with potential multiple same named tracks may not be the one selected...
+ VikTrack *append_track;
+ if ( trk->is_route )
+ append_track = vik_trw_layer_get_route ( vtl, l->data );
+ else
+ 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;
+ if ( trk->is_route )
+ vik_trw_layer_delete_route (vtl, append_track);
+ else
+ vik_trw_layer_delete_track (vtl, append_track);
+ }
+ }
+ 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) );
+ }
+}
+
+/**
+ * Very similar to trw_layer_append_track for joining
+ * but this allows selection from the 'other' list
+ * If a track is selected, then is shows routes and joins the selected one
+ * If a route is selected, then is shows tracks and joins the selected one
+ */
+static void trw_layer_append_other ( gpointer pass_along[6] )
+{
+
+ VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+ VikTrack *trk;
+ GHashTable *ght_mykind, *ght_others;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE ) {
+ ght_mykind = vtl->routes;
+ ght_others = vtl->tracks;
+ }
+ else {
+ ght_mykind = vtl->tracks;
+ ght_others = vtl->routes;
+ }
+
+ trk = (VikTrack *) g_hash_table_lookup ( ght_mykind, pass_along[3] );
+
+ if ( !trk )
+ return;
+
+ GList *other_tracks_names = NULL;
+
+ // Sort alphabetically for user presentation
+ // Convert into list of names for usage with dialog function
+ // TODO: Need to consider how to work best when we can have multiple tracks the same name...
+ twt_udata udata;
+ udata.result = &other_tracks_names;
+ udata.exclude = trk->trackpoints;
+
+ g_hash_table_foreach(ght_others, (GHFunc) trw_layer_sorted_track_id_by_name_list_exclude_self, (gpointer)&udata);
+
+ // Note the limit to selecting one track only
+ // this is to control the ordering of appending tracks, i.e. the selected track always goes after the current track
+ // (otherwise with multiple select the ordering would not be controllable by the user - automatically being alphabetically)
+ GList *append_list = a_dialog_select_from_list(VIK_GTK_WINDOW_FROM_LAYER(vtl),
+ other_tracks_names,
+ FALSE,
+ trk->is_route ? _("Append Track"): _("Append Route"),
+ trk->is_route ? _("Select the track to append after the current route") :
+ _("Select the route to append after the current track") );
- GList *merge_list = a_dialog_select_from_list(VIK_GTK_WINDOW_FROM_LAYER(vtl),
- other_tracks_names, TRUE,
- _("Merge with..."), _("Select track to merge with"));
- g_list_free(other_tracks);
g_list_free(other_tracks_names);
- if (merge_list)
- {
+ // It's a list, but shouldn't contain more than one other track!
+ if ( append_list ) {
GList *l;
- for (l = merge_list; l != NULL; l = g_list_next(l)) {
- VikTrack *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_trw_layer_delete_track (vtl, merge_track);
- track->trackpoints = g_list_sort(track->trackpoints, trackpoint_compare);
+ for (l = append_list; l != NULL; l = g_list_next(l)) {
+ // TODO: at present this uses the first track found by name,
+ // which with potential multiple same named tracks may not be the one selected...
+
+ // Get FROM THE OTHER TYPE list
+ VikTrack *append_track;
+ if ( trk->is_route )
+ append_track = vik_trw_layer_get_track ( vtl, l->data );
+ else
+ append_track = vik_trw_layer_get_route ( vtl, l->data );
+
+ if ( append_track ) {
+
+ if ( !append_track->is_route &&
+ ( ( vik_track_get_segment_count ( append_track ) > 1 ) ||
+ ( vik_track_get_average_speed ( append_track ) > 0.0 ) ) ) {
+
+ if ( a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
+ _("Converting a track to a route removes extra track data such as segments, timestamps, etc...\nDo you want to continue?"), NULL ) ) {
+ vik_track_merge_segments ( append_track );
+ vik_track_to_routepoints ( append_track );
+ }
+ else {
+ break;
+ }
+ }
+
+ trk->trackpoints = g_list_concat(trk->trackpoints, append_track->trackpoints);
+ append_track->trackpoints = NULL;
+
+ // Delete copied which is FROM THE OTHER TYPE list
+ if ( trk->is_route )
+ vik_trw_layer_delete_track (vtl, append_track);
+ else
+ vik_trw_layer_delete_route (vtl, append_track);
}
}
- /* TODO: free data before free merge_list */
- for (l = merge_list; l != NULL; l = g_list_next(l))
+ for (l = append_list; l != NULL; l = g_list_next(l))
g_free(l->data);
- g_list_free(merge_list);
- vik_layer_emit_update( VIK_LAYER(vtl), FALSE );
+ g_list_free(append_list);
+ vik_layer_emit_update( VIK_LAYER(vtl) );
}
}
+/* merge by segments */
+static void trw_layer_merge_by_segment ( gpointer pass_along[6] )
+{
+ VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+ VikTrack *trk = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+ guint segments = vik_track_merge_segments ( trk );
+ // NB currently no need to redraw as segments not actually shown on the display
+ // However inform the user of what happened:
+ gchar str[64];
+ const gchar *tmp_str = ngettext("%d segment merged", "%d segments merged", segments);
+ g_snprintf(str, 64, tmp_str, segments);
+ a_dialog_info_msg (VIK_GTK_WINDOW_FROM_LAYER(vtl), str );
+}
+
/* merge by time routine */
static void trw_layer_merge_by_timestamp ( gpointer pass_along[6] )
{
}
g_list_free(nearby_tracks);
- vik_layer_emit_update( VIK_LAYER(vtl), FALSE );
+ vik_layer_emit_update( VIK_LAYER(vtl) );
}
/**
- * Split a track at the currently selected trackpoint,
- * asking the user for the new name
+ * Split a track at the currently selected trackpoint
*/
-static void trw_layer_split_at_selected_trackpoint ( VikTrwLayer *vtl )
+static void trw_layer_split_at_selected_trackpoint ( VikTrwLayer *vtl, gint subtype )
{
if ( !vtl->current_tpl )
return;
if ( vtl->current_tpl->next && vtl->current_tpl->prev ) {
- gchar *name = get_new_unique_sublayer_name(vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, vtl->current_tp_track->name);
- if ( ( name = a_dialog_new_track ( VIK_GTK_WINDOW_FROM_LAYER(vtl), vtl->tracks, name ) ) )
- {
- VikTrack *tr = vik_track_new ();
+ gchar *name = trw_layer_new_unique_sublayer_name(vtl, subtype, vtl->current_tp_track->name);
+ if ( name ) {
+ VikTrack *tr = vik_track_copy ( vtl->current_tp_track, FALSE );
GList *newglist = g_list_alloc ();
newglist->prev = NULL;
newglist->next = vtl->current_tpl->next;
vtl->current_tpl = newglist; /* change tp to first of new track. */
vtl->current_tp_track = tr;
- tr->visible = TRUE;
-
- vik_trw_layer_add_track ( vtl, name, tr );
+ if ( tr->is_route )
+ vik_trw_layer_add_route ( vtl, name, tr );
+ else
+ vik_trw_layer_add_track ( vtl, name, tr );
trku_udata udata;
udata.trk = tr;
udata.uuid = NULL;
// Also need id of newly created track
- gpointer *trkf = g_hash_table_find ( vtl->tracks, (GHRFunc) trw_layer_track_find_uuid, &udata );
+ gpointer *trkf;
+ if ( tr->is_route )
+ trkf = g_hash_table_find ( vtl->routes, (GHRFunc) trw_layer_track_find_uuid, &udata );
+ else
+ trkf = g_hash_table_find ( vtl->tracks, (GHRFunc) trw_layer_track_find_uuid, &udata );
+
if ( trkf && udata.uuid )
vtl->current_tp_id = udata.uuid;
else
vtl->current_tp_id = NULL;
- vik_layer_emit_update(VIK_LAYER(vtl), FALSE);
+ vik_layer_emit_update(VIK_LAYER(vtl));
}
}
}
/* split by time routine */
static void trw_layer_split_by_timestamp ( gpointer pass_along[6] )
{
- VikTrack *track = (VikTrack *) g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
+ VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+ VikTrack *track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
GList *trps = track->trackpoints;
GList *iter;
GList *newlists = NULL;
GList *newtps = NULL;
- guint i;
static guint thr = 1;
time_t ts, prev_ts;
/* put lists of trackpoints into tracks */
iter = newlists;
- i = 1;
// Only bother updating if the split results in new tracks
if (g_list_length (newlists) > 1) {
while (iter) {
gchar *new_tr_name;
VikTrack *tr;
- tr = vik_track_new();
- tr->visible = track->visible;
+ tr = vik_track_copy ( track, FALSE );
tr->trackpoints = (GList *)(iter->data);
- new_tr_name = g_strdup_printf ("%s #%d", track->name, i++);
- vik_trw_layer_add_track(VIK_TRW_LAYER(pass_along[0]), new_tr_name, tr);
+ 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_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);*/
iter = g_list_next(iter);
}
// Remove original track and then update the display
- vik_trw_layer_delete_track (VIK_TRW_LAYER(pass_along[0]), track);
- vik_layer_emit_update(VIK_LAYER(pass_along[0]), FALSE);
+ vik_trw_layer_delete_track (vtl, track);
+ vik_layer_emit_update(VIK_LAYER(pass_along[0]));
}
g_list_free(newlists);
}
static void trw_layer_split_by_n_points ( gpointer pass_along[6] )
{
VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
- VikTrack *track = (VikTrack *)g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+ VikTrack *track;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ track = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( !track )
+ return;
// Check valid track
GList *trps = track->trackpoints;
/* put lists of trackpoints into tracks */
iter = newlists;
- guint i = 1;
// Only bother updating if the split results in new tracks
if (g_list_length (newlists) > 1) {
while (iter) {
gchar *new_tr_name;
VikTrack *tr;
- tr = vik_track_new();
- tr->visible = track->visible;
+ tr = vik_track_copy ( track, FALSE );
tr->trackpoints = (GList *)(iter->data);
- new_tr_name = g_strdup_printf ("%s #%d", track->name, i++);
- vik_trw_layer_add_track(VIK_TRW_LAYER(pass_along[0]), new_tr_name, tr);
-
+ if ( track->is_route ) {
+ new_tr_name = trw_layer_new_unique_sublayer_name ( vtl, VIK_TRW_LAYER_SUBLAYER_ROUTE, track->name);
+ vik_trw_layer_add_route(vtl, new_tr_name, tr);
+ }
+ else {
+ 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);
+ }
iter = g_list_next(iter);
}
// Remove original track and then update the display
- vik_trw_layer_delete_track (VIK_TRW_LAYER(pass_along[0]), track);
- vik_layer_emit_update(VIK_LAYER(pass_along[0]), FALSE);
+ if ( track->is_route )
+ vik_trw_layer_delete_route (vtl, track);
+ else
+ vik_trw_layer_delete_track (vtl, track);
+ vik_layer_emit_update(VIK_LAYER(pass_along[0]));
}
g_list_free(newlists);
}
static void trw_layer_split_at_trackpoint ( gpointer pass_along[6] )
{
VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
- trw_layer_split_at_selected_trackpoint ( vtl );
+ gint subtype = GPOINTER_TO_INT (pass_along[2]);
+ trw_layer_split_at_selected_trackpoint ( vtl, subtype );
+}
+
+/**
+ * Split a track by its segments
+ * Routes do not have segments so don't call this for routes
+ */
+static void trw_layer_split_segments ( gpointer pass_along[6] )
+{
+ VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+ VikTrack *trk = g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( !trk )
+ return;
+
+ guint ntracks;
+
+ VikTrack **tracks = vik_track_split_into_segments (trk, &ntracks);
+ gchar *new_tr_name;
+ guint i;
+ for ( i = 0; i < ntracks; i++ ) {
+ 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] );
+ }
+ }
+ if ( tracks ) {
+ g_free ( tracks );
+ // Remove original track
+ vik_trw_layer_delete_track ( vtl, trk );
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
+ }
+ else {
+ a_dialog_error_msg (VIK_GTK_WINDOW_FROM_LAYER(vtl), _("Can not split track as it has no segments"));
+ }
}
/* end of split/merge routines */
+/**
+ * Delete adjacent track points at the same position
+ * AKA Delete Dulplicates on the Properties Window
+ */
+static void trw_layer_delete_points_same_position ( gpointer pass_along[6] )
+{
+ VikTrwLayer *vtl = (VikTrwLayer *)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] );
+ else
+ trk = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( !trk )
+ return;
+
+ gulong removed = vik_track_remove_dup_points ( trk );
+
+ // Track has been updated so update tps:
+ trw_layer_cancel_tps_of_track ( vtl, trk );
+
+ // Inform user how much was deleted as it's not obvious from the normal view
+ gchar str[64];
+ const gchar *tmp_str = ngettext("Deleted %ld point", "Deleted %ld points", removed);
+ g_snprintf(str, 64, tmp_str, removed);
+ a_dialog_info_msg (VIK_GTK_WINDOW_FROM_LAYER(vtl), str);
+
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
+}
+
+/**
+ * Delete adjacent track points with the same timestamp
+ * Normally new tracks that are 'routes' won't have any timestamps so should be OK to clean up the track
+ */
+static void trw_layer_delete_points_same_time ( gpointer pass_along[6] )
+{
+ VikTrwLayer *vtl = (VikTrwLayer *)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] );
+ else
+ trk = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( !trk )
+ return;
+
+ gulong removed = vik_track_remove_same_time_points ( trk );
+
+ // Track has been updated so update tps:
+ trw_layer_cancel_tps_of_track ( vtl, trk );
+
+ // Inform user how much was deleted as it's not obvious from the normal view
+ gchar str[64];
+ const gchar *tmp_str = ngettext("Deleted %ld point", "Deleted %ld points", removed);
+ g_snprintf(str, 64, tmp_str, removed);
+ a_dialog_info_msg (VIK_GTK_WINDOW_FROM_LAYER(vtl), str);
+
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
+}
+
/**
* Reverse a track
*/
static void trw_layer_reverse ( gpointer pass_along[6] )
{
VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
- VikTrack *track = (VikTrack *)g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+ VikTrack *track;
+ if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ track = (VikTrack *) g_hash_table_lookup ( vtl->routes, pass_along[3] );
+ else
+ track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+ if ( ! track )
+ return;
// Check valid track
GList *trps = track->trackpoints;
vik_track_reverse ( track );
- vik_layer_emit_update ( VIK_LAYER(pass_along[0]), FALSE );
+ vik_layer_emit_update ( VIK_LAYER(pass_along[0]) );
}
/**
}
/**
- * Find out if any tracks have the same name in this layer
+ * Find out if any tracks have the same name in this hash table
*/
-static gboolean trw_layer_has_same_track_names ( VikTrwLayer *vtl )
+static gboolean trw_layer_has_same_track_names ( GHashTable *ht_tracks )
{
// Sort items by name, then compare if any next to each other are the same
GList *track_names = NULL;
- g_hash_table_foreach ( vtl->tracks, (GHFunc) trw_layer_sorted_track_id_by_name_list, &track_names );
+ g_hash_table_foreach ( ht_tracks, (GHFunc) trw_layer_sorted_track_id_by_name_list, &track_names );
// No tracks
if ( ! track_names )
}
/**
- * Force unqiue track names for this layer
+ * Force unqiue track names for the track table specified
* Note the panel is a required parameter to enable the update of the names displayed
+ * Specify if on tracks or else on routes
*/
-static void vik_trw_layer_uniquify_tracks ( VikTrwLayer *vtl, VikLayersPanel *vlp )
+static void vik_trw_layer_uniquify_tracks ( VikTrwLayer *vtl, VikLayersPanel *vlp, GHashTable *track_table, gboolean ontrack )
{
// . Search list for an instance of repeated name
// . get track of this name
udata.has_same_track_name = FALSE;
udata.same_track_name = NULL;
- g_hash_table_foreach ( vtl->tracks, (GHFunc) trw_layer_sorted_track_id_by_name_list, &track_names );
+ g_hash_table_foreach ( track_table, (GHFunc) trw_layer_sorted_track_id_by_name_list, &track_names );
// No tracks
if ( ! track_names )
while ( udata.has_same_track_name ) {
// Find a track with the same name
- VikTrack *trk = vik_trw_layer_get_track ( vtl, (gpointer) udata.same_track_name );
+ VikTrack *trk;
+ if ( ontrack )
+ trk = vik_trw_layer_get_track ( vtl, (gpointer) udata.same_track_name );
+ else
+ trk = vik_trw_layer_get_route ( vtl, (gpointer) udata.same_track_name );
if ( ! trk ) {
// Broken :(
}
// Rename it
- gchar *newname = get_new_unique_sublayer_name ( vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, udata.same_track_name );
+ gchar *newname = trw_layer_new_unique_sublayer_name ( vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, udata.same_track_name );
vik_track_set_name ( trk, newname );
trku_udata udataU;
udataU.uuid = NULL;
// Need want key of it for treeview update
- gpointer *trkf = g_hash_table_find ( vtl->tracks, (GHRFunc) trw_layer_track_find_uuid, &udataU );
+ gpointer *trkf = g_hash_table_find ( track_table, (GHRFunc) trw_layer_track_find_uuid, &udataU );
if ( trkf && udataU.uuid ) {
- GtkTreeIter *it = g_hash_table_lookup ( vtl->tracks_iters, udataU.uuid );
+ GtkTreeIter *it;
+ if ( ontrack )
+ it = g_hash_table_lookup ( vtl->tracks_iters, udataU.uuid );
+ else
+ it = g_hash_table_lookup ( vtl->routes_iters, udataU.uuid );
if ( it ) {
vik_treeview_item_set_name ( VIK_LAYER(vtl)->vt, it, newname );
// Start trying to find same names again...
track_names = NULL;
- g_hash_table_foreach ( vtl->tracks, (GHFunc) trw_layer_sorted_track_id_by_name_list, &track_names );
+ g_hash_table_foreach ( track_table, (GHFunc) trw_layer_sorted_track_id_by_name_list, &track_names );
udata.has_same_track_name = FALSE;
GList *dummy_list2 = g_list_sort_with_data ( track_names, check_tracks_for_same_name, &udata );
GList *all = NULL;
// Ensure list of track names offered is unique
- if ( trw_layer_has_same_track_names ( vtl ) ) {
+ if ( trw_layer_has_same_track_names ( vtl->tracks ) ) {
if ( a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
_("Multiple entries with the same name exist. This method only works with unique names. Force unique names now?"), NULL ) ) {
- vik_trw_layer_uniquify_tracks ( vtl, VIK_LAYERS_PANEL(lav[1]) );
+ vik_trw_layer_uniquify_tracks ( vtl, VIK_LAYERS_PANEL(lav[1]), vtl->tracks, TRUE );
}
else
return;
GList *l;
for (l = delete_list; l != NULL; l = g_list_next(l)) {
// This deletes first trk it finds of that name (but uniqueness is enforced above)
- trw_layer_delete_track_by_name (vtl, l->data);
+ trw_layer_delete_track_by_name (vtl, l->data, vtl->tracks);
+ }
+ g_list_free(delete_list);
+ vik_layer_emit_update( VIK_LAYER(vtl) );
+ }
+}
+
+/**
+ *
+ */
+static void trw_layer_delete_routes_from_selection ( gpointer lav[2] )
+{
+ VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+ GList *all = NULL;
+
+ // Ensure list of track names offered is unique
+ if ( trw_layer_has_same_track_names ( vtl->routes ) ) {
+ if ( a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
+ _("Multiple entries with the same name exist. This method only works with unique names. Force unique names now?"), NULL ) ) {
+ vik_trw_layer_uniquify_tracks ( vtl, VIK_LAYERS_PANEL(lav[1]), vtl->routes, FALSE );
+ }
+ else
+ return;
+ }
+
+ // Sort list alphabetically for better presentation
+ g_hash_table_foreach(vtl->routes, (GHFunc) trw_layer_sorted_track_id_by_name_list, &all);
+
+ if ( ! all ) {
+ a_dialog_error_msg (VIK_GTK_WINDOW_FROM_LAYER(vtl), _("No routes found"));
+ return;
+ }
+
+ // Get list of items to delete from the user
+ GList *delete_list = a_dialog_select_from_list ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
+ all,
+ TRUE,
+ _("Delete Selection"),
+ _("Select routes to delete") );
+ g_list_free(all);
+
+ // Delete requested routes
+ // since specificly requested, IMHO no need for extra confirmation
+ if ( delete_list ) {
+ GList *l;
+ for (l = delete_list; l != NULL; l = g_list_next(l)) {
+ // This deletes first route it finds of that name (but uniqueness is enforced above)
+ trw_layer_delete_track_by_name (vtl, l->data, vtl->routes);
}
g_list_free(delete_list);
- vik_layer_emit_update( VIK_LAYER(vtl), FALSE );
+ vik_layer_emit_update( VIK_LAYER(vtl) );
}
}
}
// Rename it
- gchar *newname = get_new_unique_sublayer_name ( vtl, VIK_TRW_LAYER_SUBLAYER_WAYPOINT, udata.same_waypoint_name );
+ 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;
trw_layer_delete_waypoint_by_name (vtl, l->data);
}
g_list_free(delete_list);
- vik_layer_emit_update( VIK_LAYER(vtl), FALSE );
+ vik_layer_emit_update( VIK_LAYER(vtl) );
}
}
static void trw_layer_waypoint_gc_webpage ( gpointer pass_along[6] )
{
- gchar *webpage = g_strdup_printf("http://www.geocaching.com/seek/cache_details.aspx?wp=%s", (gchar *) pass_along[3] );
+ VikWaypoint *wp = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->waypoints, pass_along[3] );
+ if ( !wp )
+ return;
+ gchar *webpage = g_strdup_printf("http://www.geocaching.com/seek/cache_details.aspx?wp=%s", wp->name );
open_url(VIK_GTK_WINDOW_FROM_LAYER(VIK_LAYER(pass_along[0])), webpage);
g_free ( webpage );
}
+static void trw_layer_waypoint_webpage ( gpointer pass_along[6] )
+{
+ VikWaypoint *wp = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->waypoints, pass_along[3] );
+ if ( !wp )
+ return;
+ if ( !strncmp(wp->comment, "http", 4) ) {
+ open_url(VIK_GTK_WINDOW_FROM_LAYER(VIK_LAYER(pass_along[0])), wp->comment);
+ } else if ( !strncmp(wp->description, "http", 4) ) {
+ open_url(VIK_GTK_WINDOW_FROM_LAYER(VIK_LAYER(pass_along[0])), wp->description);
+ }
+}
+
static const gchar* trw_layer_sublayer_rename_request ( VikTrwLayer *l, const gchar *newname, gpointer vlp, gint subtype, gpointer sublayer, GtkTreeIter *iter )
{
if ( subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT )
if ( wpf ) {
// An existing waypoint has been found with the requested name
if ( ! a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(l),
- _("A waypoint with the name \"%s\" already exists. Really create one with the same name?"),
+ _("A waypoint with the name \"%s\" already exists. Really rename to the same name?"),
newname ) )
return NULL;
}
if ( trkf ) {
// An existing track has been found with the requested name
if ( ! a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(l),
- _("A track with the name \"%s\" already exists. Really create one with the same name?"),
+ _("A track with the name \"%s\" already exists. Really rename to the same name?"),
+ newname ) )
+ return NULL;
+ }
+ // Update track name and refresh GUI parts
+ vik_track_set_name (trk, newname);
+
+ // Update any subwindows that could be displaying this track which has changed name
+ // Only one Track Edit Window
+ if ( l->current_tp_track == trk && l->tpwin ) {
+ vik_trw_layer_tpwin_set_track_name ( l->tpwin, newname );
+ }
+ // 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_layers_panel_emit_update ( VIK_LAYERS_PANEL(vlp) );
+
+ return newname;
+ }
+
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_ROUTE )
+ {
+ VikTrack *trk = g_hash_table_lookup ( l->routes, sublayer );
+
+ // No actual change to the name supplied
+ if (strcmp(newname, trk->name) == 0)
+ return NULL;
+
+ VikTrack *trkf = vik_trw_layer_get_route ( l, (gpointer) newname );
+
+ if ( trkf ) {
+ // An existing track has been found with the requested name
+ if ( ! a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(l),
+ _("A route with the name \"%s\" already exists. Really rename to the same name?"),
newname ) )
return NULL;
}
a_acquire_set_filter_track ( trk );
}
+#ifdef VIK_CONFIG_GOOGLE
static gboolean is_valid_google_route ( VikTrwLayer *vtl, const gpointer track_id )
{
- VikTrack *tr = g_hash_table_lookup ( vtl->tracks, track_id );
+ VikTrack *tr = g_hash_table_lookup ( vtl->routes, track_id );
return ( tr && tr->comment && strlen(tr->comment) > 7 && !strncmp(tr->comment, "from:", 5) );
}
-static void trw_layer_track_google_route_webpage ( gpointer pass_along[6] )
+static void trw_layer_google_route_webpage ( gpointer pass_along[6] )
{
- VikTrack *tr = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
+ VikTrack *tr = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->routes, pass_along[3] );
if ( tr ) {
gchar *escaped = uri_escape ( tr->comment );
gchar *webpage = g_strdup_printf("http://maps.google.com/maps?f=q&hl=en&q=%s", escaped );
g_free ( webpage );
}
}
+#endif
/* vlp can be NULL if necessary - i.e. right-click from a tool */
/* viewpoint is now available instead */
pass_along[6] = iter;
pass_along[7] = NULL; // For misc purposes - maybe track or waypoint
- if ( subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT || subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT || subtype == VIK_TRW_LAYER_SUBLAYER_TRACK || subtype == VIK_TRW_LAYER_SUBLAYER_ROUTE )
{
rv = TRUE;
gtk_widget_show ( item );
if (subtype == VIK_TRW_LAYER_SUBLAYER_TRACK) {
- VikTrwLayer *vtl = l;
- VikTrack *tr = g_hash_table_lookup ( vtl->tracks, sublayer );
+ VikTrack *tr = g_hash_table_lookup ( l->tracks, sublayer );
+ if (tr && tr->property_dialog)
+ gtk_widget_set_sensitive(GTK_WIDGET(item), FALSE );
+ }
+ if (subtype == VIK_TRW_LAYER_SUBLAYER_ROUTE) {
+ VikTrack *tr = g_hash_table_lookup ( l->routes, sublayer );
if (tr && tr->property_dialog)
gtk_widget_set_sensitive(GTK_WIDGET(item), FALSE );
}
#endif
}
+ if ( wp )
+ {
+ if ( ( wp->comment && !strncmp(wp->comment, "http", 4) ) ||
+ ( wp->description && !strncmp(wp->description, "http", 4) )) {
+ item = gtk_image_menu_item_new_with_mnemonic ( _("Visit _Webpage") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_NETWORK, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_waypoint_webpage), 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 ) {
+ item = gtk_image_menu_item_new_from_stock ( GTK_STOCK_PASTE, NULL );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_paste_item_cb), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ gtk_widget_show ( item );
+ // TODO: only enable if suitable item is in clipboard - want to determine *which* sublayer type
+ if ( a_clipboard_type ( ) == VIK_CLIPBOARD_DATA_SUBLAYER )
+ gtk_widget_set_sensitive ( item, TRUE );
+ else
+ gtk_widget_set_sensitive ( item, FALSE );
+
+ // Add separator
+ item = gtk_menu_item_new ();
+ gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ gtk_widget_show ( item );
+ }
+
if ( vlp && (subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINTS || subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT) )
{
rv = TRUE;
{
rv = TRUE;
+ if ( l->current_track && !l->current_track->is_route ) {
+ item = gtk_menu_item_new_with_mnemonic ( _("_Finish Track") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_finish_track), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
+ // Add separator
+ item = gtk_menu_item_new ();
+ gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ gtk_widget_show ( item );
+ }
+
item = gtk_image_menu_item_new_with_mnemonic ( _("_View All Tracks") );
gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ZOOM_FIT, GTK_ICON_SIZE_MENU) );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_auto_tracks_view), pass_along );
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show ( item );
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_New Track") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_NEW, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_new_track), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
+ // Make it available only when a new track *not* already in progress
+ gtk_widget_set_sensitive ( item, ! (gboolean)GPOINTER_TO_INT(l->current_track) );
+
item = gtk_image_menu_item_new_with_mnemonic ( _("Delete _All Tracks") );
gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU) );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_delete_all_tracks), pass_along );
gtk_widget_show ( item );
}
- if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_ROUTES )
+ {
+ rv = TRUE;
+
+ if ( l->current_track && l->current_track->is_route ) {
+ item = gtk_menu_item_new_with_mnemonic ( _("_Finish Route") );
+ // Reuse finish track method
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_finish_track), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
+ // Add separator
+ item = gtk_menu_item_new ();
+ gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ gtk_widget_show ( item );
+ }
+
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_View All Routes") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ZOOM_FIT, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_auto_routes_view), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
+
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_New Route") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_NEW, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_new_route), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
+ // Make it available only when a new track *not* already in progress
+ gtk_widget_set_sensitive ( item, ! (gboolean)GPOINTER_TO_INT(l->current_track) );
+
+ item = gtk_image_menu_item_new_with_mnemonic ( _("Delete _All Routes") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_delete_all_routes), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ gtk_widget_show ( item );
+
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_Delete Routes From Selection...") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_INDEX, GTK_ICON_SIZE_MENU) );
+ 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 *upload_submenu = gtk_menu_new ();
+
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK || subtype == VIK_TRW_LAYER_SUBLAYER_ROUTE )
{
- GtkWidget *goto_submenu;
item = gtk_menu_item_new ();
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
gtk_widget_show ( item );
+ if ( l->current_track && subtype == VIK_TRW_LAYER_SUBLAYER_TRACK && !l->current_track->is_route )
+ item = gtk_menu_item_new_with_mnemonic ( _("_Finish Track") );
+ if ( l->current_track && subtype == VIK_TRW_LAYER_SUBLAYER_ROUTE && l->current_track->is_route )
+ item = gtk_menu_item_new_with_mnemonic ( _("_Finish Route") );
+ if ( l->current_track ) {
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_finish_track), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
+
+ // Add separator
+ item = gtk_menu_item_new ();
+ gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ gtk_widget_show ( item );
+ }
+
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_View Track") );
+ else
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_View Route") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ZOOM_FIT, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_auto_track_view), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ gtk_widget_show ( item );
+
+ GtkWidget *goto_submenu;
goto_submenu = gtk_menu_new ();
item = gtk_image_menu_item_new_with_mnemonic ( _("_Goto") );
gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_MENU) );
gtk_menu_shell_append ( GTK_MENU_SHELL(goto_submenu), item );
gtk_widget_show ( item );
- item = gtk_image_menu_item_new_with_mnemonic ( _("_Maximum Speed") );
- gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_MEDIA_FORWARD, GTK_ICON_SIZE_MENU) );
- g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_goto_track_max_speed), pass_along );
- gtk_menu_shell_append ( GTK_MENU_SHELL(goto_submenu), item );
+ // Routes don't have speeds
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK ) {
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_Maximum Speed") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_MEDIA_FORWARD, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_goto_track_max_speed), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(goto_submenu), item );
+ gtk_widget_show ( item );
+ }
+
+ GtkWidget *combine_submenu;
+ combine_submenu = gtk_menu_new ();
+ item = gtk_image_menu_item_new_with_mnemonic ( _("Co_mbine") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_CONNECT, 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), combine_submenu );
- item = gtk_image_menu_item_new_with_mnemonic ( _("_View Track") );
- gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ZOOM_FIT, GTK_ICON_SIZE_MENU) );
- g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_auto_track_view), pass_along );
- gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ // Routes don't have times or segments...
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK ) {
+ item = gtk_menu_item_new_with_mnemonic ( _("_Merge By Time...") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_merge_by_timestamp), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(combine_submenu), item );
+ gtk_widget_show ( item );
+
+ item = gtk_menu_item_new_with_mnemonic ( _("Merge _Segments") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_merge_by_segment), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(combine_submenu), item );
+ gtk_widget_show ( item );
+ }
+
+ item = gtk_menu_item_new_with_mnemonic ( _("Merge _With Other Tracks...") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_merge_with_other), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(combine_submenu), item );
gtk_widget_show ( item );
- item = gtk_menu_item_new_with_mnemonic ( _("_Merge By Time...") );
- g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_merge_by_timestamp), pass_along );
- gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
+ item = gtk_menu_item_new_with_mnemonic ( _("_Append Track...") );
+ else
+ item = gtk_menu_item_new_with_mnemonic ( _("_Append Route...") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_append_track), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(combine_submenu), item );
gtk_widget_show ( item );
- item = gtk_menu_item_new_with_mnemonic ( _("Merge _With Other Tracks...") );
- g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_merge_with_other), pass_along );
- gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
+ item = gtk_menu_item_new_with_mnemonic ( _("Append _Route...") );
+ else
+ item = gtk_menu_item_new_with_mnemonic ( _("Append _Track...") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_append_other), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(combine_submenu), item );
gtk_widget_show ( item );
GtkWidget *split_submenu;
gtk_widget_show ( item );
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), split_submenu );
- item = gtk_menu_item_new_with_mnemonic ( _("_Split By Time...") );
- g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_split_by_timestamp), pass_along );
- gtk_menu_shell_append ( GTK_MENU_SHELL(split_submenu), item );
- gtk_widget_show ( item );
+ // Routes don't have times or segments...
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK ) {
+ item = gtk_menu_item_new_with_mnemonic ( _("_Split By Time...") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_split_by_timestamp), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(split_submenu), item );
+ gtk_widget_show ( item );
+
+ // ATM always enable this entry - don't want to have to analyse the track before displaying the menu - to keep the menu speedy
+ item = gtk_menu_item_new_with_mnemonic ( _("Split Se_gments") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_split_segments), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(split_submenu), item );
+ gtk_widget_show ( item );
+ }
item = gtk_menu_item_new_with_mnemonic ( _("Split By _Number of Points...") );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_split_by_n_points), pass_along );
// Make it available only when a trackpoint is selected.
gtk_widget_set_sensitive ( item, (gboolean)GPOINTER_TO_INT(l->current_tpl) );
- item = gtk_image_menu_item_new_with_mnemonic ( _("_Reverse Track") );
+ GtkWidget *delete_submenu;
+ delete_submenu = gtk_menu_new ();
+ item = gtk_image_menu_item_new_with_mnemonic ( _("Delete Poi_nts") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_DELETE, 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), delete_submenu );
+
+ item = gtk_menu_item_new_with_mnemonic ( _("Delete Points With The Same _Position") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_delete_points_same_position), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(delete_submenu), item );
+ gtk_widget_show ( item );
+
+ item = gtk_menu_item_new_with_mnemonic ( _("Delete Points With The Same _Time") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_delete_points_same_time), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(delete_submenu), item );
+ gtk_widget_show ( item );
+
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_Reverse Track") );
+ else
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_Reverse Route") );
gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_GO_BACK, GTK_ICON_SIZE_MENU) );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_reverse), pass_along );
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
/* ATM This function is only available via the layers panel, due to the method in finding out the maps in use */
if ( vlp ) {
- item = gtk_image_menu_item_new_with_mnemonic ( _("Down_load Maps Along Track...") );
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
+ 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
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_menu_shell_append ( GTK_MENU_SHELL(menu), item );
gtk_widget_show ( item );
- item = gtk_image_menu_item_new_with_mnemonic ( _("Export Trac_k as GPX...") );
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_Export Track as GPX...") );
+ else
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_Export Route as GPX...") );
gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_HARDDISK, GTK_ICON_SIZE_MENU) );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_export_gpx_track), pass_along );
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
gtk_widget_show ( item );
- item = gtk_image_menu_item_new_with_mnemonic ( _("E_xtend Track End") );
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
+ item = gtk_image_menu_item_new_with_mnemonic ( _("E_xtend Track End") );
+ else
+ item = gtk_image_menu_item_new_with_mnemonic ( _("E_xtend Route End") );
gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU) );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_extend_track_end), pass_along );
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
gtk_widget_show ( item );
- item = gtk_image_menu_item_new_with_mnemonic ( _("Extend _Using Route Finder") );
- gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock ("Route Finder", GTK_ICON_SIZE_MENU) ); // Own icon - see stock_icons in vikwindow.c
- g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_extend_track_end_route_finder), pass_along );
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
+ item = gtk_image_menu_item_new_with_mnemonic ( _("C_onvert to a Route") );
+ else
+ item = gtk_image_menu_item_new_with_mnemonic ( _("C_onvert to a Track") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_CONVERT, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_convert_track_route), pass_along );
+ 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
+ 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 ) {
+ 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) );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), upload_submenu );
+
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_Upload to GPS...") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_gps_upload_any), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(upload_submenu), item );
+ gtk_widget_show ( item );
+ }
+ }
+
+#ifdef VIK_CONFIG_GOOGLE
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_ROUTE && is_valid_google_route ( l, sublayer ) )
+ {
+ item = gtk_image_menu_item_new_with_mnemonic ( _("_View Google Directions") );
+ gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_NETWORK, GTK_ICON_SIZE_MENU) );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_google_route_webpage), pass_along );
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
gtk_widget_show ( item );
+ }
+#endif
+ // Some things aren't usable with routes
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK ) {
#ifdef VIK_CONFIG_OPENSTREETMAP
item = gtk_image_menu_item_new_with_mnemonic ( _("Upload to _OSM...") );
// Convert internal pointer into actual track for usage outside this file
pass_along[7] = g_hash_table_lookup ( l->tracks, sublayer);
- g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(osm_traces_upload_track_cb), pass_along );
gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_GO_UP, GTK_ICON_SIZE_MENU) );
- gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(osm_traces_upload_track_cb), pass_along );
+ gtk_menu_shell_append ( GTK_MENU_SHELL(upload_submenu), item );
gtk_widget_show ( item );
#endif
- if ( is_valid_google_route ( l, sublayer ) )
- {
- item = gtk_image_menu_item_new_with_mnemonic ( _("_View Google Directions") );
- gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_NETWORK, GTK_ICON_SIZE_MENU) );
- g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_track_google_route_webpage), pass_along );
- gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
- gtk_widget_show ( item );
- }
-
item = gtk_image_menu_item_new_with_mnemonic ( _("Use with _Filter") );
gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_INDEX, GTK_ICON_SIZE_MENU) );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_track_use_with_filter), pass_along );
/* ATM This function is only available via the layers panel, due to needing a vlp */
if ( vlp ) {
item = a_acquire_track_menu ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(l)), vlp,
- vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vlp)),
- g_hash_table_lookup ( l->tracks, (gchar *) sublayer ) );
+ vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vlp)),
+ g_hash_table_lookup ( l->tracks, (gchar *) sublayer ) );
if ( item ) {
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
- gtk_widget_show ( item );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
}
}
#ifdef VIK_CONFIG_GEOTAG
- item = gtk_menu_item_new_with_mnemonic ( _("Geotag _Images...") );
- g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_geotagging_track), pass_along );
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
- gtk_widget_show ( item );
+ item = gtk_menu_item_new_with_mnemonic ( _("Geotag _Images...") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_geotagging_track), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
#endif
+ }
+ if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK || subtype == VIK_TRW_LAYER_SUBLAYER_ROUTE ) {
// Only show on viewport popmenu when a trackpoint is selected
if ( ! vlp && l->current_tpl ) {
// Add separator
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
gtk_widget_show ( item );
}
-
}
return rv;
/* DOP / sat values remain at defaults as not they do not seem applicable to a dreamt up point */
/* Insert new point into the trackpoints list after the current TP */
- VikTrack *tr = g_hash_table_lookup ( vtl->tracks, vtl->current_tp_id );
- gint index = g_list_index ( tr->trackpoints, tp_current );
+ VikTrack *trk = g_hash_table_lookup ( vtl->tracks, vtl->current_tp_id );
+ if ( !trk )
+ // Otherwise try routes
+ trk = g_hash_table_lookup ( vtl->routes, vtl->current_tp_id );
+ if ( !trk )
+ return;
+
+ gint index = g_list_index ( trk->trackpoints, tp_current );
if ( index > -1 ) {
- tr->trackpoints = g_list_insert (tr->trackpoints, tp_new, index+1 );
+ trk->trackpoints = g_list_insert ( trk->trackpoints, tp_new, index+1 );
}
}
}
-/* to be called when last_tpl no longer exists. */
-static void trw_layer_cancel_last_tp ( VikTrwLayer *vtl )
-{
- if ( vtl->tpwin ) /* can't join with a non-existant TP. */
- vik_trw_layer_tpwin_disable_join ( vtl->tpwin );
- vtl->last_tpl = NULL;
- vtl->last_tp_track = NULL;
-}
-
static void trw_layer_cancel_current_tp ( VikTrwLayer *vtl, gboolean destroy )
{
if ( vtl->tpwin )
vtl->current_tpl = NULL;
vtl->current_tp_track = NULL;
vtl->current_tp_id = NULL;
- vik_layer_emit_update(VIK_LAYER(vtl), FALSE);
+ vik_layer_emit_update(VIK_LAYER(vtl));
}
}
if ( response == VIK_TRW_LAYER_TPWIN_SPLIT && vtl->current_tpl->next && vtl->current_tpl->prev )
{
- trw_layer_split_at_selected_trackpoint ( vtl );
+ trw_layer_split_at_selected_trackpoint ( vtl, vtl->current_tp_track->is_route ? VIK_TRW_LAYER_SUBLAYER_ROUTE : VIK_TRW_LAYER_SUBLAYER_TRACK );
vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track->name );
}
else if ( response == VIK_TRW_LAYER_TPWIN_DELETE )
{
VikTrack *tr = g_hash_table_lookup ( vtl->tracks, vtl->current_tp_id );
+ if ( tr == NULL )
+ tr = g_hash_table_lookup ( vtl->routes, vtl->current_tp_id );
if ( tr == NULL )
return;
GList *new_tpl;
- /* can't join with a non-existent trackpoint */
- vtl->last_tpl = NULL;
- vtl->last_tp_track = NULL;
+ // Find available adjacent trackpoint
if ( (new_tpl = vtl->current_tpl->next) || (new_tpl = vtl->current_tpl->prev) )
{
if ( VIK_TRACKPOINT(vtl->current_tpl->data)->newsegment && vtl->current_tpl->next )
VIK_TRACKPOINT(vtl->current_tpl->next->data)->newsegment = TRUE; /* don't concat segments on del */
- tr->trackpoints = g_list_remove_link ( tr->trackpoints, vtl->current_tpl ); /* this nulls current_tpl->prev and next */
+ // Delete current trackpoint
+ vik_trackpoint_free ( vtl->current_tpl->data );
+ tr->trackpoints = g_list_delete_link ( tr->trackpoints, vtl->current_tpl );
+
+ // Set to current to the available adjacent trackpoint
+ vtl->current_tpl = new_tpl;
- /* at this point the old trackpoint exists, but the list links are correct (new), so it is safe to do this. */
+ // Reset dialog with the available adjacent trackpoint
if ( vtl->current_tp_track )
vik_trw_layer_tpwin_set_tp ( vtl->tpwin, new_tpl, vtl->current_tp_track->name );
- trw_layer_cancel_last_tp ( vtl );
-
- g_free ( vtl->current_tpl->data ); /* TODO: vik_trackpoint_free() */
- g_list_free_1 ( vtl->current_tpl );
- vtl->current_tpl = new_tpl;
- vik_layer_emit_update(VIK_LAYER(vtl), FALSE);
+ vik_layer_emit_update(VIK_LAYER(vtl));
}
else
{
- tr->trackpoints = g_list_remove_link ( tr->trackpoints, vtl->current_tpl );
- g_free ( vtl->current_tpl->data ); /* TODO longone: vik_trackpoint_new() and vik_trackpoint_free() */
- g_list_free_1 ( vtl->current_tpl );
+ // Delete current trackpoint
+ vik_trackpoint_free ( vtl->current_tpl->data );
+ tr->trackpoints = g_list_delete_link ( tr->trackpoints, vtl->current_tpl );
trw_layer_cancel_current_tp ( vtl, FALSE );
}
}
else if ( response == VIK_TRW_LAYER_TPWIN_FORWARD && vtl->current_tpl->next )
{
- vtl->last_tpl = vtl->current_tpl;
if ( vtl->current_tp_track )
vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl = vtl->current_tpl->next, vtl->current_tp_track->name );
- vik_layer_emit_update(VIK_LAYER(vtl), FALSE); /* TODO longone: either move or only update if tp is inside drawing window */
+ vik_layer_emit_update(VIK_LAYER(vtl)); /* TODO longone: either move or only update if tp is inside drawing window */
}
else if ( response == VIK_TRW_LAYER_TPWIN_BACK && vtl->current_tpl->prev )
{
- vtl->last_tpl = vtl->current_tpl;
if ( vtl->current_tp_track )
vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl = vtl->current_tpl->prev, vtl->current_tp_track->name );
- vik_layer_emit_update(VIK_LAYER(vtl), FALSE);
- }
- else if ( response == VIK_TRW_LAYER_TPWIN_JOIN )
- {
- // Check tracks exist and are different before joining
- if ( ! vtl->last_tp_track || ! vtl->current_tp_track || vtl->last_tp_track == vtl->current_tp_track )
- return;
-
- VikTrack *tr1 = vtl->last_tp_track;
- VikTrack *tr2 = vtl->current_tp_track;
-
- VikTrack *tr_first = tr1, *tr_last = tr2;
-
- if ( (!vtl->last_tpl->next) && (!vtl->current_tpl->next) ) /* both endpoints */
- vik_track_reverse ( tr2 ); /* reverse the second, that way second track clicked will be later. */
- else if ( (!vtl->last_tpl->prev) && (!vtl->current_tpl->prev) )
- vik_track_reverse ( tr1 );
- else if ( (!vtl->last_tpl->prev) && (!vtl->current_tpl->next) ) /* clicked startpoint, then endpoint -- concat end to start */
- {
- tr_first = tr2;
- tr_last = tr1;
- }
- /* default -- clicked endpoint then startpoint -- connect endpoint to startpoint */
-
- if ( tr_last->trackpoints ) /* deleting this part here joins them into 1 segmented track. useful but there's no place in the UI for this feature. segments should be deprecated anyway. */
- VIK_TRACKPOINT(tr_last->trackpoints->data)->newsegment = FALSE;
- tr1->trackpoints = g_list_concat ( tr_first->trackpoints, tr_last->trackpoints );
- tr2->trackpoints = NULL;
-
- vtl->current_tp_track = vtl->last_tp_track; /* current_tp stays the same (believe it or not!) */
- vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track->name );
-
- /* if we did this before, trw_layer_delete_track would have canceled the current tp because
- * it was the current track. canceling the current tp would have set vtl->current_tpl to NULL */
- vik_trw_layer_delete_track ( vtl, vtl->current_tp_track );
-
- trw_layer_cancel_last_tp ( vtl ); /* same TP, can't join. */
- vik_layer_emit_update(VIK_LAYER(vtl), FALSE);
+ vik_layer_emit_update(VIK_LAYER(vtl));
}
else if ( response == VIK_TRW_LAYER_TPWIN_INSERT && vtl->current_tpl->next )
{
trw_layer_insert_tp_after_current_tp ( vtl );
- vik_layer_emit_update(VIK_LAYER(vtl), FALSE);
+ vik_layer_emit_update(VIK_LAYER(vtl));
}
else if ( response == VIK_TRW_LAYER_TPWIN_DATA_CHANGED )
- vik_layer_emit_update(VIK_LAYER(vtl), FALSE);
+ vik_layer_emit_update(VIK_LAYER(vtl));
}
static void trw_layer_tpwin_init ( VikTrwLayer *vtl )
}
}
+// ATM: Leave this as 'Track' only.
+// Not overly bothered about having a snap to route trackpoint capability
static VikTrackpoint *closest_tp_in_five_pixel_interval ( VikTrwLayer *vtl, VikViewport *vvp, gint x, gint y )
{
TPSearchParams params;
if ( vtl->tpwin )
if ( vtl->current_tp_track )
vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track->name );
-
- // Don't really know what this is for but seems like it might be handy...
- /* can't join with itself! */
- trw_layer_cancel_last_tp ( vtl );
}
}
vtl->current_wp_id = NULL;
trw_layer_cancel_current_tp ( vtl, FALSE );
- vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
return TRUE;
}
return FALSE;
if (!vtl || vtl->vl.type != VIK_LAYER_TRW)
return FALSE;
- if ( !vtl->tracks_visible && !vtl->waypoints_visible )
+ if ( !vtl->tracks_visible && !vtl->waypoints_visible && !vtl->routes_visible )
return FALSE;
// Go for waypoints first as these often will be near a track, but it's likely the wp is wanted rather then the track
vtl->current_wp = wp_params.closest_wp;
vtl->current_wp_id = wp_params.closest_wp_id;
- vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
return TRUE;
}
}
- if (vtl->tracks_visible) {
- TPSearchParams tp_params;
- tp_params.vvp = vvp;
- tp_params.x = event->x;
- tp_params.y = event->y;
- tp_params.closest_track_id = NULL;
- tp_params.closest_tp = NULL;
+ // Used for both track and route lists
+ TPSearchParams tp_params;
+ tp_params.vvp = vvp;
+ tp_params.x = event->x;
+ tp_params.y = event->y;
+ tp_params.closest_track_id = NULL;
+ tp_params.closest_tp = NULL;
+ if (vtl->tracks_visible) {
g_hash_table_foreach ( vtl->tracks, (GHFunc) track_search_closest_tp, &tp_params);
if ( tp_params.closest_tp ) {
if ( vtl->tpwin )
vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track->name );
- vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
+ return TRUE;
+ }
+ }
+
+ // Try again for routes
+ if (vtl->routes_visible) {
+ g_hash_table_foreach ( vtl->routes, (GHFunc) track_search_closest_tp, &tp_params);
+
+ if ( tp_params.closest_tp ) {
+
+ // Always select + highlight the track
+ vik_treeview_select_iter ( VIK_LAYER(vtl)->vt, g_hash_table_lookup ( vtl->routes_iters, tp_params.closest_track_id ), TRUE );
+
+ tet->is_waypoint = FALSE;
+
+ // Select the Trackpoint
+ // Can move it immediately when control held or it's the previously selected tp
+ if ( event->state & GDK_CONTROL_MASK ||
+ vtl->current_tpl == tp_params.closest_tpl ) {
+ // Put into 'move buffer'
+ // NB vvp & vw already set in tet
+ tet->vtl = (gpointer)vtl;
+ marker_begin_move (tet, event->x, event->y);
+ }
+
+ vtl->current_tpl = tp_params.closest_tpl;
+ vtl->current_tp_id = tp_params.closest_track_id;
+ vtl->current_tp_track = g_hash_table_lookup ( vtl->routes, tp_params.closest_track_id );
+
+ set_statusbar_msg_info_trkpt ( vtl, tp_params.closest_tp );
+
+ if ( vtl->tpwin )
+ vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track->name );
+
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
return TRUE;
}
}
if (!vtl || vtl->vl.type != VIK_LAYER_TRW)
return FALSE;
- if ( !vtl->tracks_visible && !vtl->waypoints_visible )
+ if ( !vtl->tracks_visible && !vtl->waypoints_visible && !vtl->routes_visible )
return FALSE;
/* Post menu for the currently selected item */
VikTrack *track = (VikTrack*)vik_window_get_selected_track ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(vtl) );
if ( track && track->visible ) {
- if ( vik_window_get_selected_name ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(vtl) ) ) {
+ if ( track->name ) {
if ( vtl->track_right_click_menu )
- gtk_object_sink ( GTK_OBJECT(vtl->track_right_click_menu) );
+ gtk_object_sink ( GTK_OBJECT(vtl->track_right_click_menu) );
vtl->track_right_click_menu = GTK_MENU ( gtk_menu_new () );
- trw_layer_sublayer_add_menu_items ( vtl,
- vtl->track_right_click_menu,
- NULL,
- VIK_TRW_LAYER_SUBLAYER_TRACK,
- vik_window_get_selected_name ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(vtl) ),
- g_hash_table_lookup ( vtl->tracks_iters, vik_window_get_selected_name ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(vtl) ) ),
- vvp);
+ trku_udata udataU;
+ udataU.trk = track;
+ udataU.uuid = NULL;
+
+ gpointer *trkf;
+ if ( track->is_route )
+ trkf = g_hash_table_find ( vtl->routes, (GHRFunc) trw_layer_track_find_uuid, &udataU );
+ else
+ trkf = g_hash_table_find ( vtl->tracks, (GHRFunc) trw_layer_track_find_uuid, &udataU );
+
+ if ( trkf && udataU.uuid ) {
+
+ GtkTreeIter *iter;
+ if ( track->is_route )
+ iter = g_hash_table_lookup ( vtl->routes_iters, udataU.uuid );
+ else
+ iter = g_hash_table_lookup ( vtl->tracks_iters, udataU.uuid );
+
+ trw_layer_sublayer_add_menu_items ( vtl,
+ vtl->track_right_click_menu,
+ NULL,
+ track->is_route ? VIK_TRW_LAYER_SUBLAYER_ROUTE : VIK_TRW_LAYER_SUBLAYER_TRACK,
+ udataU.uuid,
+ iter,
+ vvp );
+ }
gtk_menu_popup ( vtl->track_right_click_menu, NULL, NULL, NULL, NULL, event->button, gtk_get_current_event_time() );
/* See if a waypoint is selected */
VikWaypoint *waypoint = (VikWaypoint*)vik_window_get_selected_waypoint ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(vtl) );
if ( waypoint && waypoint->visible ) {
- if ( vik_window_get_selected_name ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(vtl) ) ) {
+ if ( waypoint->name ) {
if ( vtl->wp_right_click_menu )
- gtk_object_sink ( GTK_OBJECT(vtl->wp_right_click_menu) );
+ gtk_object_sink ( GTK_OBJECT(vtl->wp_right_click_menu) );
vtl->wp_right_click_menu = GTK_MENU ( gtk_menu_new () );
- trw_layer_sublayer_add_menu_items ( vtl,
- vtl->wp_right_click_menu,
- NULL,
- VIK_TRW_LAYER_SUBLAYER_WAYPOINT,
- vik_window_get_selected_name ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(vtl) ),
- g_hash_table_lookup ( vtl->waypoints_iters, vik_window_get_selected_name ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(vtl) ) ),
- vvp);
+
+ wpu_udata udata;
+ udata.wp = waypoint;
+ udata.uuid = NULL;
+
+ gpointer *wpf = g_hash_table_find ( vtl->waypoints, (GHRFunc) trw_layer_waypoint_find_uuid, (gpointer) &udata );
+
+ if ( wpf && udata.uuid ) {
+ GtkTreeIter *iter = g_hash_table_lookup ( vtl->waypoints_iters, udata.uuid );
+
+ trw_layer_sublayer_add_menu_items ( vtl,
+ vtl->wp_right_click_menu,
+ NULL,
+ VIK_TRW_LAYER_SUBLAYER_WAYPOINT,
+ udata.uuid,
+ iter,
+ vvp );
+ }
gtk_menu_popup ( vtl->wp_right_click_menu, NULL, NULL, NULL, NULL, event->button, gtk_get_current_event_time() );
return TRUE;
g_hash_table_foreach ( vtl->waypoints, (GHFunc) waypoint_search_closest_tp, ¶ms);
if ( vtl->current_wp == params.closest_wp && vtl->current_wp != NULL )
{
- /* how do we get here? I'm putting in the abort until we can figure it out. -alex */
+ // how do we get here?
marker_begin_move(t, event->x, event->y);
g_critical("shouldn't be here");
- exit(1);
+ return FALSE;
}
else if ( params.closest_wp )
{
vtl->current_wp_id = params.closest_wp_id;
/* could make it so don't update if old WP is off screen and new is null but oh well */
- vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
return TRUE;
}
vtl->current_wp = NULL;
vtl->current_wp_id = NULL;
vtl->waypoint_rightclick = FALSE;
- vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
return FALSE;
}
marker_end_move ( t );
vtl->current_wp->coord = new_coord;
- vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
return TRUE;
}
/* PUT IN RIGHT PLACE!!! */
return FALSE;
}
-/**** Begin track ***/
-static gpointer tool_begin_track_create ( VikWindow *vw, VikViewport *vvp)
-{
- return vvp;
-}
-
-static gboolean tool_begin_track_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp )
-{
- vtl->current_track = NULL;
- return tool_new_track_click ( vtl, event, vvp );
-}
-
/*** New track ****/
static gpointer tool_new_track_create ( VikWindow *vw, VikViewport *vvp)
typedef struct {
VikTrwLayer *vtl;
- VikViewport *vvp;
- gint x1,y1,x2,y2,x3,y3;
- const gchar* str;
-} new_track_move_passalong_t;
-
-/* sync and undraw, but only when we have time */
-static gboolean ct_sync ( gpointer passalong )
-{
- new_track_move_passalong_t *p = (new_track_move_passalong_t *) passalong;
+ GdkDrawable *drawable;
+ GdkGC *gc;
+ GdkPixmap *pixmap;
+} draw_sync_t;
- vik_viewport_sync ( p->vvp );
- gdk_gc_set_function ( p->vtl->current_track_gc, GDK_INVERT );
- vik_viewport_draw_line ( p->vvp, p->vtl->current_track_gc, p->x1, p->y1, p->x2, p->y2 );
- vik_viewport_draw_string (p->vvp, gdk_font_from_description (pango_font_description_from_string ("Sans 8")), p->vtl->current_track_gc, p->x3, p->y3, p->str);
- gdk_gc_set_function ( p->vtl->current_track_gc, GDK_COPY );
-
- g_free ( (gpointer) p->str ) ;
- p->vtl->ct_sync_done = TRUE;
- g_free ( p );
+/*
+ * Draw specified pixmap
+ */
+static gboolean draw_sync ( gpointer data )
+{
+ draw_sync_t *ds = (draw_sync_t*) data;
+ // Sometimes don't want to draw
+ // normally because another update has taken precedent such as panning the display
+ // which means this pixmap is no longer valid
+ if ( ds->vtl->draw_sync_do ) {
+ gdk_threads_enter();
+ gdk_draw_drawable (ds->drawable,
+ ds->gc,
+ ds->pixmap,
+ 0, 0, 0, 0, -1, -1);
+ ds->vtl->draw_sync_done = TRUE;
+ gdk_threads_leave();
+ }
return FALSE;
}
-static const gchar* distance_string (gdouble distance)
+static gchar* distance_string (gdouble distance)
{
gchar str[128];
/*
* Actually set the message in statusbar
*/
-static void statusbar_write (const gchar *distance_string, gdouble elev_gain, gdouble elev_loss, VikTrwLayer *vtl )
+static void statusbar_write (gdouble distance, gdouble elev_gain, gdouble elev_loss, gdouble last_step, gdouble angle, VikTrwLayer *vtl )
{
// Only show elevation data when track has some elevation properties
gchar str_gain_loss[64];
str_gain_loss[0] = '\0';
+ gchar str_last_step[64];
+ str_last_step[0] = '\0';
+ gchar *str_total = distance_string (distance);
if ( (elev_gain > 0.1) || (elev_loss > 0.1) ) {
if ( a_vik_get_units_height () == VIK_UNITS_HEIGHT_METRES )
else
g_sprintf(str_gain_loss, _(" - Gain %dft:Loss %dft"), (int)VIK_METERS_TO_FEET(elev_gain), (int)VIK_METERS_TO_FEET(elev_loss));
}
+
+ if ( last_step > 0 ) {
+ gchar *tmp = distance_string (last_step);
+ g_sprintf(str_last_step, _(" - Bearing %3.1f° - Step %s"), RAD2DEG(angle), tmp);
+ g_free ( tmp );
+ }
+
+ VikWindow *vw = VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl));
// Write with full gain/loss information
- gchar *msg = g_strdup_printf ( "%s%s", distance_string, str_gain_loss);
- vik_statusbar_set_message ( vik_window_get_statusbar (VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl))), VIK_STATUSBAR_INFO, msg );
+ gchar *msg = g_strdup_printf ( "Total %s%s%s", str_total, str_last_step, str_gain_loss);
+ vik_statusbar_set_message ( vik_window_get_statusbar (vw), VIK_STATUSBAR_INFO, msg );
g_free ( msg );
+ g_free ( str_total );
}
/*
/* Find out actual distance of current track */
gdouble distance = vik_track_get_length (vtl->current_track);
- const gchar *str = distance_string (distance);
-
- statusbar_write (str, elev_gain, elev_loss, vtl);
- g_free ((gpointer)str);
+ statusbar_write (distance, elev_gain, elev_loss, 0, 0, vtl);
}
static VikLayerToolFuncStatus tool_new_track_move ( VikTrwLayer *vtl, GdkEventMotion *event, VikViewport *vvp )
{
/* if we haven't sync'ed yet, we don't have time to do more. */
- if ( vtl->ct_sync_done && vtl->current_track && vtl->current_track->trackpoints ) {
- GList *iter = vtl->current_track->trackpoints;
- new_track_move_passalong_t *passalong;
+ if ( vtl->draw_sync_done && vtl->current_track && vtl->current_track->trackpoints ) {
+ GList *iter = g_list_last ( vtl->current_track->trackpoints );
+ VikTrackpoint *last_tpt = VIK_TRACKPOINT(iter->data);
+
+ static GdkPixmap *pixmap = NULL;
+ int w1, h1, w2, h2;
+ // Need to check in case window has been resized
+ w1 = vik_viewport_get_width(vvp);
+ h1 = vik_viewport_get_height(vvp);
+ if (!pixmap) {
+ pixmap = gdk_pixmap_new ( GTK_WIDGET(vvp)->window, w1, h1, -1 );
+ }
+ gdk_drawable_get_size (pixmap, &w2, &h2);
+ if (w1 != w2 || h1 != h2) {
+ g_object_unref ( G_OBJECT ( pixmap ) );
+ pixmap = gdk_pixmap_new ( GTK_WIDGET(vvp)->window, w1, h1, -1 );
+ }
+
+ // Reset to background
+ gdk_draw_drawable (pixmap,
+ vtl->current_track_newpoint_gc,
+ vik_viewport_get_pixmap(vvp),
+ 0, 0, 0, 0, -1, -1);
+
+ draw_sync_t *passalong;
gint x1, y1;
- while ( iter->next )
- iter = iter->next;
- gdk_gc_set_function ( vtl->current_track_gc, GDK_INVERT );
- vik_viewport_coord_to_screen ( vvp, &(VIK_TRACKPOINT(iter->data)->coord), &x1, &y1 );
- vik_viewport_draw_line ( vvp, vtl->current_track_gc, x1, y1, event->x, event->y );
+ vik_viewport_coord_to_screen ( vvp, &(last_tpt->coord), &x1, &y1 );
+
+ // FOR SCREEN OVERLAYS WE MUST DRAW INTO THIS PIXMAP (when using the reset method)
+ // otherwise using vik_viewport_draw_* functions puts the data into the base pixmap,
+ // thus when we come to reset to the background it would include what we have already drawn!!
+ gdk_draw_line ( pixmap,
+ vtl->current_track_newpoint_gc,
+ x1, y1, event->x, event->y );
+ // Using this reset method is more reliable than trying to undraw previous efforts via the GDK_INVERT method
/* Find out actual distance of current track */
gdouble distance = vik_track_get_length (vtl->current_track);
struct LatLon ll;
vik_viewport_screen_to_coord ( vvp, (gint) event->x, (gint) event->y, &coord );
vik_coord_to_latlon ( &coord, &ll );
- distance = distance + vik_coord_diff( &coord, &(VIK_TRACKPOINT(iter->data)->coord));
+ gdouble last_step = vik_coord_diff( &coord, &(last_tpt->coord));
+ distance = distance + last_step;
// Get elevation data
gdouble elev_gain, elev_loss;
gdouble elev_new;
elev_new = (gdouble) a_dems_get_elev_by_coord ( &coord, VIK_DEM_INTERPOL_BEST );
if ( elev_new != VIK_DEM_INVALID_ELEVATION ) {
- if ( VIK_TRACKPOINT(iter->data)->altitude != VIK_DEFAULT_ALTITUDE ) {
+ if ( last_tpt->altitude != VIK_DEFAULT_ALTITUDE ) {
// Adjust elevation of last track point
- if ( elev_new > VIK_TRACKPOINT(iter->data)->altitude )
+ if ( elev_new > last_tpt->altitude )
// Going up
- elev_gain += elev_new - VIK_TRACKPOINT(iter->data)->altitude;
+ elev_gain += elev_new - last_tpt->altitude;
else
// Going down
- elev_loss += VIK_TRACKPOINT(iter->data)->altitude - elev_new;
+ elev_loss += last_tpt->altitude - elev_new;
}
}
-
- const gchar *str = distance_string (distance);
+
+ 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);
+
+ pango_layout_set_text (pl, str, -1);
+ gint wd, hd;
+ pango_layout_get_pixel_size ( pl, &wd, &hd );
+
gint xd,yd;
- /* offset from cursor a bit */
+ // offset from cursor a bit depending on font size
xd = event->x + 10;
- yd = event->y - 10;
- /* note attempted setting text using pango layouts - but the 'undraw' technique didn't work */
- vik_viewport_draw_string (vvp, gdk_font_from_description (pango_font_description_from_string ("Sans 8")), vtl->current_track_gc, xd, yd, str);
+ yd = event->y - hd;
+
+ // Create a background block to make the text easier to read over the background map
+ GdkGC *background_block_gc = vik_viewport_new_gc ( vvp, "#cccccc", 1);
+ gdk_draw_rectangle (pixmap, background_block_gc, TRUE, xd-2, yd-2, wd+4, hd+2);
+ gdk_draw_layout (pixmap, vtl->current_track_newpoint_gc, xd, yd, pl);
- gdk_gc_set_function ( vtl->current_track_gc, GDK_COPY );
+ g_object_unref ( G_OBJECT ( pl ) );
+ g_object_unref ( G_OBJECT ( background_block_gc ) );
- passalong = g_new(new_track_move_passalong_t,1); /* freed by sync */
+ passalong = g_new(draw_sync_t,1); // freed by draw_sync()
passalong->vtl = vtl;
- passalong->vvp = vvp;
- passalong->x1 = x1;
- passalong->y1 = y1;
- passalong->x2 = event->x;
- passalong->y2 = event->y;
- passalong->x3 = xd;
- passalong->y3 = yd;
- passalong->str = str;
+ passalong->pixmap = pixmap;
+ passalong->drawable = GTK_WIDGET(vvp)->window;
+ passalong->gc = vtl->current_track_newpoint_gc;
+
+ gdouble angle;
+ gdouble baseangle;
+ vik_viewport_compute_bearing ( vvp, x1, y1, event->x, event->y, &angle, &baseangle );
// Update statusbar with full gain/loss information
- statusbar_write (str, elev_gain, elev_loss, vtl);
+ statusbar_write (distance, elev_gain, elev_loss, last_step, angle, vtl);
+
+ g_free (str);
- /* this will sync and undraw when we have time to */
- g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, ct_sync, passalong, NULL);
- vtl->ct_sync_done = FALSE;
+ // draw pixmap when we have time to
+ g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, draw_sync, passalong, NULL);
+ vtl->draw_sync_done = FALSE;
return VIK_LAYER_TOOL_ACK_GRAB_FOCUS;
}
return VIK_LAYER_TOOL_ACK;
{
if ( vtl->current_track && event->keyval == GDK_Escape ) {
vtl->current_track = NULL;
- vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
return TRUE;
} else if ( vtl->current_track && event->keyval == GDK_BackSpace ) {
/* undo */
g_free ( last->data );
vtl->current_track->trackpoints = g_list_remove_link ( vtl->current_track->trackpoints, last );
}
-
+
update_statusbar ( vtl );
- vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
return TRUE;
}
return FALSE;
}
-static gboolean tool_new_track_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp )
+/*
+ * Common function to handle trackpoint button requests on either a route or a track
+ * . enables adding a point via normal click
+ * . enables removal of last point via right click
+ * . finishing of the track or route via double clicking
+ */
+static gboolean tool_new_track_or_route_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp )
{
VikTrackpoint *tp;
if (!vtl || vtl->vl.type != VIK_LAYER_TRW)
return FALSE;
- if ( event->button == 3 && vtl->current_track )
+ if ( event->button == 2 ) {
+ // As the display is panning, the new track pixmap is now invalid so don't draw it
+ // otherwise this drawing done results in flickering back to an old image
+ vtl->draw_sync_do = FALSE;
+ return FALSE;
+ }
+
+ if ( event->button == 3 )
{
+ if ( !vtl->current_track )
+ return FALSE;
/* undo */
if ( vtl->current_track->trackpoints )
{
}
update_statusbar ( vtl );
- vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
return TRUE;
}
/* undo last, then end */
vtl->current_track = NULL;
}
- vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
return TRUE;
}
- if ( ! vtl->current_track )
- {
- gchar *name = get_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 ) ) )
- {
- vtl->current_track = vik_track_new();
- vtl->current_track->visible = TRUE;
- vik_trw_layer_add_track ( vtl, name, vtl->current_track );
-
- /* incase it was created by begin track */
- vik_window_enable_layer_tool ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), VIK_LAYER_TRW, TOOL_CREATE_TRACK );
- }
- else
- return TRUE;
- }
tp = vik_trackpoint_new();
vik_viewport_screen_to_coord ( vvp, event->x, event->y, &(tp->coord) );
tp->newsegment = FALSE;
tp->has_timestamp = FALSE;
tp->timestamp = 0;
- vtl->current_track->trackpoints = g_list_append ( vtl->current_track->trackpoints, tp );
- /* Auto attempt to get elevation from DEM data (if it's available) */
- vik_track_apply_dem_data_last_trackpoint ( vtl->current_track );
+
+ if ( vtl->current_track ) {
+ vtl->current_track->trackpoints = g_list_append ( vtl->current_track->trackpoints, tp );
+ /* Auto attempt to get elevation from DEM data (if it's available) */
+ vik_track_apply_dem_data_last_trackpoint ( vtl->current_track );
+ }
vtl->ct_x1 = vtl->ct_x2;
vtl->ct_y1 = vtl->ct_y2;
vtl->ct_x2 = event->x;
vtl->ct_y2 = event->y;
- vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
return TRUE;
}
+static gboolean tool_new_track_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp )
+{
+ // ----------------------------------------------------- if current is a route - switch to new track
+ 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_TRACK, _("Track"));
+ if ( ( name = a_dialog_new_track ( VIK_GTK_WINDOW_FROM_LAYER(vtl), vtl->tracks, name, FALSE ) ) )
+ {
+ new_track_create_common ( vtl, name );
+ }
+ else
+ return TRUE;
+ }
+ return tool_new_track_or_route_click ( vtl, event, vvp );
+}
+
+static void tool_new_track_release ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp )
+{
+ if ( event->button == 2 ) {
+ // Pan moving ended - enable potential point drawing again
+ vtl->draw_sync_do = TRUE;
+ vtl->draw_sync_done = TRUE;
+ }
+}
+
+/*** New route ****/
+
+static gpointer tool_new_route_create ( VikWindow *vw, VikViewport *vvp)
+{
+ return vvp;
+}
+
+static gboolean tool_new_route_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp )
+{
+ // -------------------------- if current is a track - switch to new route
+ 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 ) ) )
+ new_route_create_common ( vtl, name );
+ else
+ return TRUE;
+ }
+ return tool_new_track_or_route_click ( vtl, event, vvp );
+}
+
/*** New waypoint ****/
static gpointer tool_new_waypoint_create ( VikWindow *vw, VikViewport *vvp)
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)
- vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
return TRUE;
}
if (!vtl || vtl->vl.type != VIK_LAYER_TRW)
return FALSE;
- if ( !vtl->vl.visible || !vtl->tracks_visible )
+ if ( !vtl->vl.visible || !vtl->tracks_visible || !vtl->routes_visible )
return FALSE;
if ( vtl->current_tpl )
return TRUE;
}
- vtl->last_tpl = vtl->current_tpl;
- vtl->last_tp_track = vtl->current_tp_track;
}
- g_hash_table_foreach ( vtl->tracks, (GHFunc) track_search_closest_tp, ¶ms);
+ if ( vtl->tracks_visible )
+ g_hash_table_foreach ( vtl->tracks, (GHFunc) track_search_closest_tp, ¶ms);
if ( params.closest_tp )
{
vtl->current_tp_track = g_hash_table_lookup ( vtl->tracks, params.closest_track_id );
trw_layer_tpwin_init ( vtl );
set_statusbar_msg_info_trkpt ( vtl, params.closest_tp );
- vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
+ return TRUE;
+ }
+
+ if ( vtl->routes_visible )
+ g_hash_table_foreach ( vtl->routes, (GHFunc) track_search_closest_tp, ¶ms);
+
+ if ( params.closest_tp )
+ {
+ vik_treeview_select_iter ( VIK_LAYER(vtl)->vt, g_hash_table_lookup ( vtl->routes_iters, params.closest_track_id ), TRUE );
+ vtl->current_tpl = params.closest_tpl;
+ vtl->current_tp_id = params.closest_track_id;
+ vtl->current_tp_track = g_hash_table_lookup ( vtl->routes, params.closest_track_id );
+ trw_layer_tpwin_init ( vtl );
+ set_statusbar_msg_info_trkpt ( vtl, params.closest_tp );
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
return TRUE;
}
/* diff dist is diff from orig */
if ( vtl->tpwin )
vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track->name );
- /* can't join with itself! */
- trw_layer_cancel_last_tp ( vtl );
- vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
return TRUE;
}
return FALSE;
}
+#ifdef VIK_CONFIG_GOOGLE
/*** Route Finder ***/
static gpointer tool_route_finder_create ( VikWindow *vw, VikViewport *vvp)
{
if ( new_end ) {
vtl->route_finder_coord = *new_end;
g_free ( new_end );
- vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
/* remove last ' to:...' */
if ( vtl->route_finder_current_track->comment ) {
gchar *last_to = strrchr ( vtl->route_finder_current_track->comment, 't' );
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));
- a_babel_convert_from_url ( vtl, url, "kml", NULL, NULL );
+ // 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 );
/* see if anything was done -- a track was added or appended to */
vtl->route_finder_check_added_track = FALSE;
vtl->route_finder_append = FALSE;
- vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+ vik_layer_emit_update ( VIK_LAYER(vtl) );
} else {
vtl->route_finder_started = TRUE;
vtl->route_finder_coord = tmp;
}
return TRUE;
}
+#endif
/*** Show picture ****/
}
/* Params are: vvp, event, last match found or NULL */
-static void tool_show_picture_wp ( char *name, VikWaypoint *wp, gpointer params[3] )
+static void tool_show_picture_wp ( const gpointer id, VikWaypoint *wp, gpointer params[3] )
{
if ( wp->image && wp->visible )
{
***************************************************************************/
-
-
-
-static void image_wp_make_list ( char *name, VikWaypoint *wp, GSList **pics )
+static void image_wp_make_list ( const gpointer id, VikWaypoint *wp, GSList **pics )
{
if ( wp->image && ( ! a_thumbnails_exists ( wp->image ) ) )
*pics = g_slist_append ( *pics, (gpointer) g_strdup ( wp->image ) );
// Redraw to show the thumbnails as they are now created
if ( IS_VIK_LAYER(tctd->vtl) )
- vik_layer_emit_update ( VIK_LAYER(tctd->vtl), TRUE ); // Yes update from background thread
+ vik_layer_emit_update ( VIK_LAYER(tctd->vtl) ); // NB update from background thread
return 0;
}
}
}
+static const gchar* my_track_colors ( gint ii )
+{
+ static const gchar* colors[VIK_TRW_LAYER_TRACK_GCS] = {
+ "#2d870a",
+ "#135D34",
+ "#0a8783",
+ "#0e4d87",
+ "#05469f",
+ "#695CBB",
+ "#2d059f",
+ "#4a059f",
+ "#5A171A",
+ "#96059f"
+ };
+ // Fast and reliable way of returning a colour
+ return colors[(ii % VIK_TRW_LAYER_TRACK_GCS)];
+}
+
+static void trw_layer_track_alloc_colors ( VikTrwLayer *vtl )
+{
+ GHashTableIter iter;
+ gpointer key, value;
+
+ gint ii = 0;
+ // Tracks
+ g_hash_table_iter_init ( &iter, vtl->tracks );
+
+ while ( g_hash_table_iter_next (&iter, &key, &value) ) {
+
+ // Tracks get a random spread of colours if not already assigned
+ if ( ! VIK_TRACK(value)->has_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;
+ }
+
+ trw_layer_update_treeview ( vtl, VIK_TRACK(value), key );
+
+ ii++;
+ if (ii > VIK_TRW_LAYER_TRACK_GCS)
+ ii = 0;
+ }
+
+ // Routes
+ ii = 0;
+ g_hash_table_iter_init ( &iter, vtl->routes );
+
+ while ( g_hash_table_iter_next (&iter, &key, &value) ) {
+
+ // Routes get an intermix of reds
+ if ( ! VIK_TRACK(value)->has_color ) {
+ if ( ii )
+ gdk_color_parse ( "#FF0000" , &(VIK_TRACK(value)->color) ); // Red
+ else
+ gdk_color_parse ( "#B40916" , &(VIK_TRACK(value)->color) ); // Dark Red
+ VIK_TRACK(value)->has_color = TRUE;
+ }
+
+ trw_layer_update_treeview ( vtl, VIK_TRACK(value), key );
+
+ ii = !ii;
+ }
+}
+
+static void trw_layer_post_read ( VikTrwLayer *vtl, GtkWidget *vp )
+{
+ trw_layer_verify_thumbnails ( vtl, vp );
+ trw_layer_track_alloc_colors ( vtl );
+}
+
VikCoordMode vik_trw_layer_get_coord_mode ( VikTrwLayer *vtl )
{
return vtl->coord_mode;
gboolean vik_trw_layer_uniquify ( VikTrwLayer *vtl, VikLayersPanel *vlp )
{
if ( vtl && vlp ) {
- vik_trw_layer_uniquify_tracks ( vtl, vlp );
+ vik_trw_layer_uniquify_tracks ( vtl, vlp, vtl->tracks, TRUE );
+ vik_trw_layer_uniquify_tracks ( vtl, vlp, vtl->routes, FALSE );
vik_trw_layer_uniquify_waypoints ( vtl, vlp );
return TRUE;
}
vik_coord_convert ( &(wp->coord), *dest_mode );
}
-static void track_convert ( const gchar *name, VikTrack *tr, VikCoordMode *dest_mode )
+static void track_convert ( const gpointer id, VikTrack *tr, VikCoordMode *dest_mode )
{
vik_track_convert ( tr, *dest_mode );
}
vtl->coord_mode = dest_mode;
g_hash_table_foreach ( vtl->waypoints, (GHFunc) waypoint_convert, &dest_mode );
g_hash_table_foreach ( vtl->tracks, (GHFunc) track_convert, &dest_mode );
+ g_hash_table_foreach ( vtl->routes, (GHFunc) track_convert, &dest_mode );
}
}
}
for (rect_iter = rects_to_download; rect_iter; rect_iter = rect_iter->next) {
- maps_layer_download_section_without_redraw(vml, vvp, &(((Rect *)(rect_iter->data))->tl), &(((Rect *)(rect_iter->data))->br), zoom_level);
+ maps_layer_download_section (vml, vvp, &(((Rect *)(rect_iter->data))->tl), &(((Rect *)(rect_iter->data))->br), zoom_level);
}
if (fillins) {
VikTrwLayer *vtl = pass_along[0];
VikLayersPanel *vlp = pass_along[1];
- VikTrack *tr = (VikTrack *) g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
+ 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] );
+ else
+ trk = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+ if ( !trk )
+ return;
+
VikViewport *vvp = vik_window_viewport((VikWindow *)(VIK_GTK_WINDOW_FROM_LAYER(vtl)));
GList *vmls = vik_layers_panel_get_all_layers_of_type(vlp, VIK_LAYER_MAPS, TRUE); // Includes hidden map layer types
if (!a_dialog_map_n_zoom(VIK_GTK_WINDOW_FROM_LAYER(vtl), map_names, default_map, zoomlist, default_zoom, &selected_map, &selected_zoom))
goto done;
- vik_track_download_map(tr, map_layers[selected_map], vvp, zoom_vals[selected_zoom]);
+ vik_track_download_map(trk, map_layers[selected_map], vvp, zoom_vals[selected_zoom]);
done:
for (i = 0; i < num_maps; i++)