X-Git-Url: https://git.street.me.uk/andy/viking.git/blobdiff_plain/77ad64fa07e804ab2a78f50104109335abe73f71..539ba03824a31edbe738121113793cb69b611f34:/src/viktrwlayer.c?ds=sidebyside diff --git a/src/viktrwlayer.c b/src/viktrwlayer.c index 2da2491a..9bafdaca 100644 --- a/src/viktrwlayer.c +++ b/src/viktrwlayer.c @@ -239,7 +239,10 @@ 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_split_by_timestamp ( gpointer pass_along[6] ); static void trw_layer_split_by_n_points ( gpointer pass_along[6] ); -static void trw_layer_download_map_along_track_cb (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_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, const gchar* trackname, guint file_type ); @@ -274,7 +277,10 @@ static gboolean trw_layer_paste_item ( VikTrwLayer *vtl, gint subtype, guint8 *i static void trw_layer_free_copied_item ( gint subtype, gpointer item ); static void trw_layer_drag_drop_request ( VikTrwLayer *vtl_src, VikTrwLayer *vtl_dest, GtkTreeIter *src_item_iter, GtkTreePath *dest_path ); -static gboolean trw_layer_select_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ); +static gboolean trw_layer_select_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp, tool_ed_t *t ); +static gboolean trw_layer_select_move ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp, tool_ed_t *t ); +static gboolean trw_layer_select_release ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp, tool_ed_t *t ); +static gboolean trw_layer_show_selected_viewport_menu ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ); static void trw_layer_insert_tp_after_current_tp ( VikTrwLayer *vtl ); static void trw_layer_cancel_last_tp ( VikTrwLayer *vtl ); @@ -472,6 +478,9 @@ VikLayerInterface vik_trw_layer_interface = { (VikLayerFuncDragDropRequest) trw_layer_drag_drop_request, (VikLayerFuncSelectClick) trw_layer_select_click, + (VikLayerFuncSelectMove) trw_layer_select_move, + (VikLayerFuncSelectRelease) trw_layer_select_release, + (VikLayerFuncSelectedViewportMenu) trw_layer_show_selected_viewport_menu, }; /* for copy & paste (I think?) */ @@ -1789,6 +1798,11 @@ static const gchar* trw_layer_sublayer_tooltip ( VikTrwLayer *l, gint subtype, g */ gboolean vik_trw_layer_selected ( VikTrwLayer *l, gint subtype, gpointer sublayer, gint type, gpointer vlp ) { + // Reset + l->current_wp = NULL; + l->current_wp_name = NULL; + trw_layer_cancel_current_tp ( l, FALSE ); + switch ( type ) { case VIK_TREEVIEW_TYPE_LAYER: @@ -1805,28 +1819,28 @@ gboolean vik_trw_layer_selected ( VikTrwLayer *l, gint subtype, gpointer sublaye { case VIK_TRW_LAYER_SUBLAYER_TRACKS: { - vik_window_set_selected_tracks ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l), l->tracks ); + vik_window_set_selected_tracks ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l), l->tracks, l ); /* Mark for redraw */ return TRUE; } break; case VIK_TRW_LAYER_SUBLAYER_TRACK: { - vik_window_set_selected_track ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l), g_hash_table_lookup ( l->tracks, sublayer ) ); + vik_window_set_selected_track ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l), g_hash_table_lookup ( l->tracks, sublayer ), l, sublayer ); /* Mark for redraw */ return TRUE; } break; case VIK_TRW_LAYER_SUBLAYER_WAYPOINTS: { - vik_window_set_selected_waypoints ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l), l->waypoints ); + vik_window_set_selected_waypoints ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l), l->waypoints, l ); /* Mark for redraw */ return TRUE; } break; case VIK_TRW_LAYER_SUBLAYER_WAYPOINT: { - vik_window_set_selected_waypoint ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l), g_hash_table_lookup ( l->waypoints, sublayer ) ); + vik_window_set_selected_waypoint ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l), g_hash_table_lookup ( l->waypoints, sublayer ), l, sublayer ); /* Mark for redraw */ return TRUE; } @@ -2071,6 +2085,18 @@ static void trw_layer_export_gpx ( gpointer layer_and_vlp[2] ) trw_layer_export ( layer_and_vlp, _("Export Layer"), vik_layer_get_name(VIK_LAYER(layer_and_vlp[0])), NULL, FILE_TYPE_GPX ); } +static void trw_layer_export_kml ( gpointer layer_and_vlp[2] ) +{ + /* Auto append '.kml' to the name (providing it's not already there) for the default filename */ + gchar *auto_save_name = g_strdup ( vik_layer_get_name(VIK_LAYER(layer_and_vlp[0])) ); + if ( ! check_file_ext ( auto_save_name, ".kml" ) ) + auto_save_name = g_strconcat ( auto_save_name, ".kml", NULL ); + + trw_layer_export ( layer_and_vlp, _("Export Layer"), auto_save_name, NULL, FILE_TYPE_KML ); + + g_free ( auto_save_name ); +} + static void trw_layer_export_gpx_track ( gpointer pass_along[6] ) { gpointer layer_and_vlp[2]; @@ -2283,7 +2309,7 @@ void vik_trw_layer_add_menu_items ( VikTrwLayer *vtl, GtkMenu *menu, gpointer vl gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show ( item ); - item = gtk_menu_item_new_with_mnemonic ( _("Goto _Waypoint") ); + item = gtk_menu_item_new_with_mnemonic ( _("Goto _Waypoint...") ); g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_goto_wp), pass_along ); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show ( item ); @@ -2294,22 +2320,27 @@ void vik_trw_layer_add_menu_items ( VikTrwLayer *vtl, GtkMenu *menu, gpointer vl gtk_widget_show ( item ); gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), export_submenu ); - item = gtk_menu_item_new_with_mnemonic ( _("Export as GPS_Point") ); + item = gtk_menu_item_new_with_mnemonic ( _("Export as GPS_Point...") ); g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_export_gpspoint), pass_along ); gtk_menu_shell_append (GTK_MENU_SHELL (export_submenu), item); gtk_widget_show ( item ); - item = gtk_menu_item_new_with_mnemonic ( _("Export as GPS_Mapper") ); + item = gtk_menu_item_new_with_mnemonic ( _("Export as GPS_Mapper...") ); g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_export_gpsmapper), pass_along ); gtk_menu_shell_append (GTK_MENU_SHELL (export_submenu), item); gtk_widget_show ( item ); - item = gtk_menu_item_new_with_mnemonic ( _("Export as _GPX") ); + item = gtk_menu_item_new_with_mnemonic ( _("Export as _GPX...") ); g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_export_gpx), pass_along ); gtk_menu_shell_append (GTK_MENU_SHELL (export_submenu), item); gtk_widget_show ( item ); - item = gtk_menu_item_new_with_mnemonic ( _("_New Waypoint") ); + item = gtk_menu_item_new_with_mnemonic ( _("Export as _KML...") ); + g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_export_kml), pass_along ); + gtk_menu_shell_append (GTK_MENU_SHELL (export_submenu), item); + gtk_widget_show ( item ); + + item = gtk_menu_item_new_with_mnemonic ( _("_New Waypoint...") ); 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 ); @@ -2333,7 +2364,7 @@ void vik_trw_layer_add_menu_items ( VikTrwLayer *vtl, GtkMenu *menu, gpointer vl #endif #ifdef VIK_CONFIG_OPENSTREETMAP - item = gtk_menu_item_new_with_mnemonic ( _("Upload to _OSM") ); + item = gtk_menu_item_new_with_mnemonic ( _("Upload to _OSM...") ); 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_widget_show ( item ); @@ -2785,6 +2816,12 @@ static void trw_layer_auto_track_view ( gpointer pass_along[5] ) } } +static void trw_layer_edit_trackpoint ( gpointer pass_along[6] ) +{ + VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]); + trw_layer_tpwin_init ( vtl ); +} + /************************************* * merge/split by time routines *************************************/ @@ -3090,7 +3127,7 @@ static void trw_layer_split_by_timestamp ( gpointer pass_along[6] ) } if (ts - prev_ts > thr*60) { /* flush accumulated trackpoints into new list */ - newlists = g_list_prepend(newlists, g_list_reverse(newtps)); + newlists = g_list_append(newlists, g_list_reverse(newtps)); newtps = NULL; } @@ -3100,30 +3137,33 @@ static void trw_layer_split_by_timestamp ( gpointer pass_along[6] ) iter = g_list_next(iter); } if (newtps) { - newlists = g_list_prepend(newlists, g_list_reverse(newtps)); + newlists = g_list_append(newlists, g_list_reverse(newtps)); } /* put lists of trackpoints into tracks */ iter = newlists; i = 1; - while (iter) { - gchar *new_tr_name; - VikTrack *tr; + // 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->trackpoints = (GList *)(iter->data); + tr = vik_track_new(); + tr->visible = track->visible; + tr->trackpoints = (GList *)(iter->data); - new_tr_name = g_strdup_printf("%s #%d", (gchar *) pass_along[3], i++); - vik_trw_layer_add_track(VIK_TRW_LAYER(pass_along[0]), new_tr_name, tr); - /* g_print("adding track %s, times %d - %d\n", new_tr_name, VIK_TRACKPOINT(tr->trackpoints->data)->timestamp, + new_tr_name = g_strdup_printf("%s #%d", (gchar *) pass_along[3], i++); + vik_trw_layer_add_track(VIK_TRW_LAYER(pass_along[0]), 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); + iter = g_list_next(iter); + } + vik_trw_layer_delete_track(VIK_TRW_LAYER(pass_along[0]), (gchar *)pass_along[3]); + vik_layer_emit_update(VIK_LAYER(pass_along[0])); } g_list_free(newlists); - vik_trw_layer_delete_track(VIK_TRW_LAYER(pass_along[0]), (gchar *)pass_along[3]); - vik_layer_emit_update(VIK_LAYER(pass_along[0])); } /** @@ -3418,6 +3458,7 @@ gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu, item = gtk_menu_item_new (); gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); gtk_widget_show ( item ); + separator_created = TRUE; } item = gtk_menu_item_new_with_mnemonic ( _("_Visit Geocache Webpage") ); @@ -3426,18 +3467,51 @@ gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu, gtk_widget_show ( item ); } + VikWaypoint *wp = g_hash_table_lookup ( VIK_TRW_LAYER(l)->waypoints, sublayer ); + + if ( wp && wp->image ) + { + if ( !separator_created ) { + item = gtk_menu_item_new (); + gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); + gtk_widget_show ( item ); + separator_created = TRUE; + } + + // Set up image paramater + pass_along[5] = wp->image; + + item = gtk_menu_item_new_with_mnemonic ( _("_Show Picture...") ); + g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_show_picture), pass_along ); + gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); + gtk_widget_show ( item ); + } + } } if ( vlp && (subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINTS || subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT) ) { rv = TRUE; - item = gtk_menu_item_new_with_mnemonic ( _("_New Waypoint") ); + item = gtk_menu_item_new_with_mnemonic ( _("_New Waypoint...") ); 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 ); } + if ( subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINTS ) + { + 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_widget_show ( item ); + + item = gtk_menu_item_new_with_mnemonic ( _("Goto _Waypoint...") ); + g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_goto_wp), pass_along ); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + gtk_widget_show ( item ); + } + if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK ) { GtkWidget *goto_submenu; @@ -3486,7 +3560,7 @@ gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu, gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); gtk_widget_show ( item ); - item = gtk_menu_item_new_with_mnemonic ( _("_Merge By Time") ); + 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 ); gtk_widget_show ( item ); @@ -3496,12 +3570,12 @@ gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu, gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); gtk_widget_show ( item ); - item = gtk_menu_item_new_with_mnemonic ( _("_Split By Time") ); + 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(menu), item ); gtk_widget_show ( item ); - item = gtk_menu_item_new_with_mnemonic ( _("Split By _Number of Points") ); + 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 ); gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); gtk_widget_show ( item ); @@ -3519,7 +3593,7 @@ gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu, gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); gtk_widget_show ( item ); - item = gtk_menu_item_new_with_mnemonic ( _("Export Trac_k as GPX") ); + item = gtk_menu_item_new_with_mnemonic ( _("Export Trac_k as GPX...") ); 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 ); @@ -3535,7 +3609,7 @@ gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu, gtk_widget_show ( item ); #ifdef VIK_CONFIG_OPENSTREETMAP - item = gtk_menu_item_new_with_mnemonic ( _("Upload to _OSM") ); + item = gtk_menu_item_new_with_mnemonic ( _("Upload to _OSM...") ); g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(osm_traces_upload_track_cb), pass_along ); gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); gtk_widget_show ( item ); @@ -3564,6 +3638,21 @@ gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu, gtk_widget_show ( item ); } } + + // Only show on viewport popmenu when a trackpoint is selected + if ( ! vlp && l->current_tpl ) { + // 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 ( _("_Edit Trackpoint") ); + gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_PROPERTIES, GTK_ICON_SIZE_MENU) ); + g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_edit_trackpoint), pass_along ); + gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item ); + gtk_widget_show ( item ); + } + } return rv; @@ -3820,16 +3909,30 @@ static void waypoint_search_closest_tp ( gchar *name, VikWaypoint *wp, WPSearchP return; vik_viewport_coord_to_screen ( params->vvp, &(wp->coord), &x, &y ); - - if ( abs (x - params->x) <= WAYPOINT_SIZE_APPROX && abs (y - params->y) <= WAYPOINT_SIZE_APPROX && - ((!params->closest_wp) || /* was the old waypoint we already found closer than this one? */ - abs(x - params->x)+abs(y - params->y) < abs(x - params->closest_x)+abs(y - params->closest_y))) - { - params->closest_wp_name = name; - params->closest_wp = wp; - params->closest_x = x; - params->closest_y = y; + + // If waypoint has an image then use the image size to select + if ( wp->image ) { + gint slackx, slacky; + slackx = wp->image_width / 2; + slacky = wp->image_height / 2; + + if ( x <= params->x + slackx && x >= params->x - slackx + && y <= params->y + slacky && y >= params->y - slacky ) { + params->closest_wp_name = name; + params->closest_wp = wp; + params->closest_x = x; + params->closest_y = y; + } } + else if ( abs (x - params->x) <= WAYPOINT_SIZE_APPROX && abs (y - params->y) <= WAYPOINT_SIZE_APPROX && + ((!params->closest_wp) || /* was the old waypoint we already found closer than this one? */ + abs(x - params->x)+abs(y - params->y) < abs(x - params->closest_x)+abs(y - params->closest_y))) + { + params->closest_wp_name = name; + params->closest_wp = wp; + params->closest_x = x; + params->closest_y = y; + } } static void track_search_closest_tp ( gchar *name, VikTrack *t, TPSearchParams *params ) @@ -3885,12 +3988,106 @@ static VikWaypoint *closest_wp_in_five_pixel_interval ( VikTrwLayer *vtl, VikVie return params.closest_wp; } +// Some forward declarations +static void marker_begin_move ( tool_ed_t *t, gint x, gint y ); +static void marker_moveto ( tool_ed_t *t, gint x, gint y ); +static void marker_end_move ( tool_ed_t *t ); +// + +static gboolean trw_layer_select_move ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp, tool_ed_t* t ) +{ + if ( t->holding ) { + VikCoord new_coord; + vik_viewport_screen_to_coord ( vvp, event->x, event->y, &new_coord ); + + // Here always allow snapping back to the original location + // this is useful when one decides not to move the thing afterall + // If one wants to move the item only a little bit then don't hold down the 'snap' key! + + // snap to TP + if ( event->state & GDK_CONTROL_MASK ) + { + VikTrackpoint *tp = closest_tp_in_five_pixel_interval ( vtl, vvp, event->x, event->y ); + if ( tp ) + new_coord = tp->coord; + } + + // snap to WP + if ( event->state & GDK_SHIFT_MASK ) + { + VikWaypoint *wp = closest_wp_in_five_pixel_interval ( vtl, vvp, event->x, event->y ); + if ( wp ) + new_coord = wp->coord; + } + + gint x, y; + vik_viewport_coord_to_screen ( vvp, &new_coord, &x, &y ); + + marker_moveto ( t, x, y ); + + return TRUE; + } + return FALSE; +} + +static gboolean trw_layer_select_release ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp, tool_ed_t* t ) +{ + if ( t->holding && event->button == 1 ) + { + VikCoord new_coord; + vik_viewport_screen_to_coord ( vvp, event->x, event->y, &new_coord ); + + // snap to TP + if ( event->state & GDK_CONTROL_MASK ) + { + VikTrackpoint *tp = closest_tp_in_five_pixel_interval ( vtl, vvp, event->x, event->y ); + if ( tp ) + new_coord = tp->coord; + } + + // snap to WP + if ( event->state & GDK_SHIFT_MASK ) + { + VikWaypoint *wp = closest_wp_in_five_pixel_interval ( vtl, vvp, event->x, event->y ); + if ( wp ) + new_coord = wp->coord; + } + + marker_end_move ( t ); + + // Determine if working on a waypoint or a trackpoint + if ( t->is_waypoint ) + vtl->current_wp->coord = new_coord; + else { + if ( vtl->current_tpl ) { + VIK_TRACKPOINT(vtl->current_tpl->data)->coord = new_coord; + + if ( vtl->tpwin ) + 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 ); + } + } + + // Reset + vtl->current_wp = NULL; + vtl->current_wp_name = NULL; + trw_layer_cancel_current_tp ( vtl, FALSE ); + + vik_layer_emit_update ( VIK_LAYER(vtl) ); + return TRUE; + } + return FALSE; +} + /* Returns true if a waypoint or track is found near the requested event position for this particular layer The item found is automatically selected This is a tool like feature but routed via the layer interface, since it's instigated by a 'global' layer tool in vikwindow.c */ -static gboolean trw_layer_select_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ) +static gboolean trw_layer_select_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp, tool_ed_t* tet ) { if ( event->button != 1 ) return FALSE; @@ -3901,7 +4098,7 @@ static gboolean trw_layer_select_click ( VikTrwLayer *vtl, GdkEventButton *event if ( !vtl->tracks_visible && !vtl->waypoints_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 */ + // Go for waypoints first as these often will be near a track, but it's likely the wp is wanted rather then the track if (vtl->waypoints_visible) { WPSearchParams wp_params; @@ -3914,8 +4111,27 @@ static gboolean trw_layer_select_click ( VikTrwLayer *vtl, GdkEventButton *event g_hash_table_foreach ( vtl->waypoints, (GHFunc) waypoint_search_closest_tp, &wp_params); if ( wp_params.closest_wp ) { + + // Select vik_treeview_select_iter ( VIK_LAYER(vtl)->vt, g_hash_table_lookup ( vtl->waypoints_iters, wp_params.closest_wp_name ), TRUE ); + + // Too easy to move it so must be holding shift to start immediately moving it + // or otherwise be previously selected + if ( event->state & GDK_SHIFT_MASK || + vtl->current_wp == wp_params.closest_wp ) { + // Put into 'move buffer' + // NB vvp & vw already set in tet + tet->vtl = (gpointer)vtl; + tet->is_waypoint = TRUE; + + marker_begin_move (tet, event->x, event->y); + } + + vtl->current_wp = wp_params.closest_wp; + vtl->current_wp_name = wp_params.closest_wp_name; + vik_layer_emit_update ( VIK_LAYER(vtl) ); + return TRUE; } } @@ -3931,13 +4147,101 @@ static gboolean trw_layer_select_click ( VikTrwLayer *vtl, GdkEventButton *event g_hash_table_foreach ( vtl->tracks, (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->tracks_iters, tp_params.closest_track_name ), 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_track_name = tp_params.closest_track_name; + + 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; } } /* these aren't the droids you're looking for */ + vtl->current_wp = NULL; + vtl->current_wp_name = NULL; + trw_layer_cancel_current_tp ( vtl, FALSE ); + + return FALSE; +} + +static gboolean trw_layer_show_selected_viewport_menu ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ) +{ + if ( event->button != 3 ) + return FALSE; + + if (!vtl || vtl->vl.type != VIK_LAYER_TRW) + return FALSE; + + if ( !vtl->tracks_visible && !vtl->waypoints_visible ) + return FALSE; + + /* Post menu for the currently selected item */ + + /* See if a track is selected */ + 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 ( 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 () ); + + vik_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); + + gtk_menu_popup ( vtl->track_right_click_menu, NULL, NULL, NULL, NULL, event->button, gtk_get_current_event_time() ); + + return TRUE; + } + } + + /* 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 ( 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 () ); + vik_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); + gtk_menu_popup ( vtl->wp_right_click_menu, NULL, NULL, NULL, NULL, event->button, gtk_get_current_event_time() ); + + return TRUE; + } + } + return FALSE; } @@ -3954,13 +4258,6 @@ static gboolean tool_sync(gpointer data) return FALSE; } -typedef struct { - VikViewport *vvp; - gboolean holding; - GdkGC *gc; - int oldx, oldy; -} tool_ed_t; - static void marker_begin_move ( tool_ed_t *t, gint x, gint y ) { t->holding = TRUE; @@ -4603,6 +4900,25 @@ static void tool_show_picture_wp ( char *name, VikWaypoint *wp, gpointer params[ } } +static void trw_layer_show_picture ( gpointer pass_along[6] ) +{ + /* thanks to the Gaim people for showing me ShellExecute and g_spawn_command_line_async */ +#ifdef WINDOWS + ShellExecute(NULL, NULL, (char *) pass_along[2], NULL, ".\\", 0); +#else /* WINDOWS */ + GError *err = NULL; + gchar *quoted_file = g_shell_quote ( (gchar *) pass_along[5] ); + gchar *cmd = g_strdup_printf ( "eog %s", quoted_file ); + g_free ( quoted_file ); + if ( ! g_spawn_command_line_async ( cmd, &err ) ) + { + a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER( pass_along[0]), _("Could not launch eog to open file.") ); + g_error_free ( err ); + } + g_free ( cmd ); +#endif /* WINDOWS */ +} + static gboolean tool_show_picture_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ) { gpointer params[3] = { vvp, event, NULL }; @@ -4611,21 +4927,10 @@ static gboolean tool_show_picture_click ( VikTrwLayer *vtl, GdkEventButton *even g_hash_table_foreach ( vtl->waypoints, (GHFunc) tool_show_picture_wp, params ); if ( params[2] ) { - /* thanks to the Gaim people for showing me ShellExecute and g_spawn_command_line_async */ -#ifdef WINDOWS - ShellExecute(NULL, NULL, (char *) params[2], NULL, ".\\", 0); -#else /* WINDOWS */ - GError *err = NULL; - gchar *quoted_file = g_shell_quote ( (gchar *) params[2] ); - gchar *cmd = g_strdup_printf ( "eog %s", quoted_file ); - g_free ( quoted_file ); - if ( ! g_spawn_command_line_async ( cmd, &err ) ) - { - a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vtl), _("Could not launch eog to open file.") ); - g_error_free ( err ); - } - g_free ( cmd ); -#endif /* WINDOWS */ + static gpointer pass_along[6]; + pass_along[0] = vtl; + pass_along[5] = params[2]; + trw_layer_show_picture ( pass_along ); return TRUE; /* found a match */ } else @@ -4923,7 +5228,7 @@ static void trw_layer_download_map_along_track_cb ( gpointer pass_along[6] ) VikTrack *tr = (VikTrack *) g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] ); 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); + GList *vmls = vik_layers_panel_get_all_layers_of_type(vlp, VIK_LAYER_MAPS, TRUE); // Includes hidden map layer types int num_maps = g_list_length(vmls); if (!num_maps) {