+// 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, tool_ed_t* tet )
+{
+ if ( event->button != 1 )
+ return FALSE;
+
+ if (!vtl || vtl->vl.type != VIK_LAYER_TRW)
+ return FALSE;
+
+ 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
+
+ if (vtl->waypoints_visible) {
+ WPSearchParams wp_params;
+ wp_params.vvp = vvp;
+ wp_params.x = event->x;
+ wp_params.y = event->y;
+ wp_params.closest_wp_name = NULL;
+ wp_params.closest_wp = NULL;
+
+ 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;
+ }
+ }
+
+ 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_name = NULL;
+ tp_params.closest_tp = NULL;
+
+ 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;
+}
+