From be5554c5e2370fe2f507dcde6dd76b6f4482ae9f Mon Sep 17 00:00:00 2001 From: Rob Norris Date: Tue, 5 Nov 2013 00:33:06 +0000 Subject: [PATCH] Enable a history of requested positions. Positions are stored on specific Go To requests (such entered position coordinates or to waypoint/track positions). Currently panning and zooming do not modify the requested position. Moving backwards and forwards through the list is supported sort of like a web browsers history of pages. As the positions are not specifically named (just raw coordinates), nothing advanced like showing the list of positions or jumping over multiple positions is offered. Finer details such as the maximum size of the history list are controlled by Viking's internal preferences. --- help/C/viking.xml | 11 ++ src/file.c | 2 +- src/menu.xml.h | 4 + src/vikgeoreflayer.c | 2 +- src/vikgoto.c | 2 +- src/vikgpslayer.c | 2 +- src/viktrwlayer.c | 12 +- src/viktrwlayer_propwin.c | 4 +- src/viktrwlayer_waypointlist.c | 2 +- src/vikviewport.c | 217 ++++++++++++++++++++++++++++++++- src/vikviewport.h | 11 +- src/vikwindow.c | 63 +++++++++- 12 files changed, 305 insertions(+), 27 deletions(-) diff --git a/help/C/viking.xml b/help/C/viking.xml index be4b5542..b6d9e804 100644 --- a/help/C/viking.xml +++ b/help/C/viking.xml @@ -2989,6 +2989,17 @@ Accept: */* trkpt_selected_statusbar_format=KEATDN This string is in the Message Format Code + + viewport_history_size=20 + + + viewport_history_diff_dist=500 + In metres. + + Go Back or Go Forward requests over this range from the last history location will move back to that position. + If within this range it will skip over this location and move on to the next saved history location. + +
diff --git a/src/file.c b/src/file.c index 09870af6..ae22df2c 100644 --- a/src/file.c +++ b/src/file.c @@ -546,7 +546,7 @@ name=this } if ( ll.lat != 0.0 || ll.lon != 0.0 ) - vik_viewport_set_center_latlon ( VIK_VIEWPORT(vp), &ll ); + vik_viewport_set_center_latlon ( VIK_VIEWPORT(vp), &ll, TRUE ); if ( ( ! VIK_LAYER(top)->visible ) && VIK_LAYER(top)->realized ) vik_treeview_item_set_visible ( VIK_LAYER(top)->vt, &(VIK_LAYER(top)->iter), FALSE ); diff --git a/src/menu.xml.h b/src/menu.xml.h index ea048916..50160f1f 100644 --- a/src/menu.xml.h +++ b/src/menu.xml.h @@ -69,6 +69,8 @@ static const char *menu_xml = " " " " " " + " " + " " " " " " " " @@ -134,6 +136,8 @@ static const char *menu_xml = " " " " " " + " " + " " " " " " " " diff --git a/src/vikgeoreflayer.c b/src/vikgeoreflayer.c index fc975c37..cffd692e 100644 --- a/src/vikgeoreflayer.c +++ b/src/vikgeoreflayer.c @@ -644,7 +644,7 @@ static void georef_layer_goto_center ( gpointer vgl_vlp[2] ) utm.northing = vgl->corner.northing - (vgl->height * vgl->mpp_northing / 2); vik_coord_load_from_utm ( &coord, vik_viewport_get_coord_mode ( vp ), &utm ); - vik_viewport_set_center_coord ( vp, &coord ); + vik_viewport_set_center_coord ( vp, &coord, TRUE ); vik_layers_panel_emit_update ( VIK_LAYERS_PANEL(vgl_vlp[1]) ); } diff --git a/src/vikgoto.c b/src/vikgoto.c index 7293162d..4e742abb 100644 --- a/src/vikgoto.c +++ b/src/vikgoto.c @@ -250,7 +250,7 @@ void a_vik_goto(VikWindow *vw, VikViewport *vvp) if (last_successful_goto_str) g_free(last_successful_goto_str); last_successful_goto_str = g_strdup(last_goto_str); - vik_viewport_set_center_coord(vvp, &new_center); + vik_viewport_set_center_coord(vvp, &new_center, TRUE); more = FALSE; } else if (!prompt_try_again(vw)) diff --git a/src/vikgpslayer.c b/src/vikgpslayer.c index 53de676e..77d1878d 100644 --- a/src/vikgpslayer.c +++ b/src/vikgpslayer.c @@ -1629,7 +1629,7 @@ static void gpsd_raw_hook(VglGpsd *vgpsd, gchar *data) if ((vgl->vehicle_position == VEHICLE_POSITION_CENTERED) || (vgl->realtime_jump_to_start && vgl->first_realtime_trackpoint)) { - vik_viewport_set_center_coord(vvp, &vehicle_coord); + vik_viewport_set_center_coord(vvp, &vehicle_coord, FALSE); update_all = TRUE; } else if (vgl->vehicle_position == VEHICLE_POSITION_ON_SCREEN) { diff --git a/src/viktrwlayer.c b/src/viktrwlayer.c index 0d467fe1..8176c78f 100644 --- a/src/viktrwlayer.c +++ b/src/viktrwlayer.c @@ -884,7 +884,7 @@ gboolean vik_trw_layer_find_date ( VikTrwLayer *vtl, const gchar *date_str, VikC vik_treeview_select_iter ( VIK_LAYER(vtl)->vt, g_hash_table_lookup (vtl->tracks_iters, df.trk_id), TRUE ); } else if ( df.wpt ) { - vik_viewport_set_center_coord ( vvp, &(df.wpt->coord) ); + vik_viewport_set_center_coord ( vvp, &(df.wpt->coord), TRUE ); vik_treeview_select_iter ( VIK_LAYER(vtl)->vt, g_hash_table_lookup (vtl->waypoints_iters, df.wpt_id), TRUE ); } vik_layer_emit_update ( VIK_LAYER(vtl) ); @@ -3235,7 +3235,7 @@ void trw_layer_zoom_to_show_latlons ( VikTrwLayer *vtl, VikViewport *vvp, struct struct LatLon average = { (maxmin[0].lat+maxmin[1].lat)/2, (maxmin[0].lon+maxmin[1].lon)/2 }; VikCoord coord; vik_coord_load_from_latlon ( &coord, vtl->coord_mode, &average ); - vik_viewport_set_center_coord ( vvp, &coord ); + vik_viewport_set_center_coord ( vvp, &coord, TRUE ); /* Convert into definite 'smallest' and 'largest' positions */ struct LatLon minmin; @@ -3420,7 +3420,7 @@ static void trw_layer_goto_wp ( menu_array_layer values ) a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vtl), _("Waypoint not found in this layer.") ); else { - vik_viewport_set_center_coord ( vik_layers_panel_get_viewport(vlp), &(wp->coord) ); + vik_viewport_set_center_coord ( vik_layers_panel_get_viewport(vlp), &(wp->coord), TRUE ); vik_layers_panel_emit_update ( vlp ); // Find and select on the side panel @@ -3858,7 +3858,7 @@ static void trw_layer_auto_tracks_view ( menu_array_layer values ) 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) ); + vik_viewport_set_center_coord ( VIK_VIEWPORT(vvp), &(wp->coord), TRUE ); } static void trw_layer_auto_waypoints_view ( menu_array_layer values ) @@ -5050,13 +5050,13 @@ void trw_layer_update_treeview ( VikTrwLayer *vtl, VikTrack *trk ) static void goto_coord ( gpointer *vlp, gpointer vl, gpointer vvp, const VikCoord *coord ) { if ( vlp ) { - vik_viewport_set_center_coord ( vik_layers_panel_get_viewport (VIK_LAYERS_PANEL(vlp)), coord ); + vik_viewport_set_center_coord ( vik_layers_panel_get_viewport (VIK_LAYERS_PANEL(vlp)), coord, TRUE ); vik_layers_panel_emit_update ( VIK_LAYERS_PANEL(vlp) ); } else { /* since vlp not set, vl & vvp should be valid instead! */ if ( vl && vvp ) { - vik_viewport_set_center_coord ( VIK_VIEWPORT(vvp), coord ); + vik_viewport_set_center_coord ( VIK_VIEWPORT(vvp), coord, TRUE ); vik_layer_emit_update ( VIK_LAYER(vl) ); } } diff --git a/src/viktrwlayer_propwin.c b/src/viktrwlayer_propwin.c index dccaf7be..1b8248b7 100644 --- a/src/viktrwlayer_propwin.c +++ b/src/viktrwlayer_propwin.c @@ -305,13 +305,13 @@ static VikTrackpoint *set_center_at_graph_position(gdouble event_x, if ( trackpoint ) { VikCoord coord = trackpoint->coord; if ( vlp ) { - vik_viewport_set_center_coord ( vik_layers_panel_get_viewport(vlp), &coord ); + vik_viewport_set_center_coord ( vik_layers_panel_get_viewport(vlp), &coord, TRUE ); vik_layers_panel_emit_update ( vlp ); } else { /* since vlp not set, vvp should be valid instead! */ if ( vvp ) - vik_viewport_set_center_coord ( vvp, &coord ); + vik_viewport_set_center_coord ( vvp, &coord, TRUE ); vik_layer_emit_update ( VIK_LAYER(vtl) ); } } diff --git a/src/viktrwlayer_waypointlist.c b/src/viktrwlayer_waypointlist.c index d99e0088..ce09ef6b 100644 --- a/src/viktrwlayer_waypointlist.c +++ b/src/viktrwlayer_waypointlist.c @@ -191,7 +191,7 @@ static void trw_layer_waypoint_view ( menu_array_values values ) VikWaypoint *wpt = VIK_WAYPOINT(values[MA_WPT]); VikViewport *vvp = VIK_VIEWPORT(values[MA_VVP]); - vik_viewport_set_center_coord ( vvp, &(wpt->coord) ); + vik_viewport_set_center_coord ( vvp, &(wpt->coord), TRUE ); trw_layer_waypoint_select (values); diff --git a/src/vikviewport.c b/src/vikviewport.c index f7c98ffa..ad0a4d49 100644 --- a/src/vikviewport.c +++ b/src/vikviewport.c @@ -2,6 +2,7 @@ * viking -- GPS Data and Topo Analyzer, Explorer, and Manager * * Copyright (C) 2003-2007, Evan Battaglia + * Copyright (C) 2013, Rob Norris * * Lat/Lon plotting functions calcxy* are from GPSDrive * GPSDrive Copyright (C) 2001-2004 Fritz Ganter @@ -57,6 +58,8 @@ static gint PAD = 10; static void viewport_finalize ( GObject *gob ); static void viewport_utm_zone_check ( VikViewport *vvp ); +static void update_centers ( VikViewport *vvp ); +static void free_centers ( VikViewport *vvp, guint start ); static gboolean calcxy(double *x, double *y, double lg, double lt, double zero_long, double zero_lat, double pixelfact_x, double pixelfact_y, gint mapSizeX2, gint mapSizeY2 ); static gboolean calcxy_rev(double *lg, double *lt, gint x, gint y, double zero_long, double zero_lat, double pixelfact_x, double pixelfact_y, gint mapSizeX2, gint mapSizeY2 ); @@ -67,7 +70,6 @@ static void viewport_init_ra(); static GObjectClass *parent_class; - struct _VikViewport { GtkDrawingArea drawing_area; GdkPixmap *scr_buffer; @@ -77,6 +79,10 @@ struct _VikViewport { VikCoordMode coord_mode; gdouble xmpp, ympp; gdouble xmfactor, ymfactor; + GList *centers; // The history of requested positions + guint centers_index; // current position within the history list + guint centers_max; // configurable maximum size of the history list + guint centers_radius; // Metres GdkPixbuf *alpha_pixbuf; guint8 alpha_pixbuf_width; @@ -127,6 +133,12 @@ viewport_utm_zone_width ( VikViewport *vvp ) return 0.0; } +enum { + VW_UPDATED_CENTER_SIGNAL = 0, + VW_LAST_SIGNAL, +}; +static guint viewport_signals[VW_LAST_SIGNAL] = { 0 }; + G_DEFINE_TYPE (VikViewport, vik_viewport, GTK_TYPE_DRAWING_AREA) static void @@ -140,6 +152,10 @@ vik_viewport_class_init ( VikViewportClass *klass ) object_class->finalize = viewport_finalize; parent_class = g_type_class_peek_parent (klass); + + viewport_signals[VW_UPDATED_CENTER_SIGNAL] = g_signal_new ( "updated_center", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (VikViewportClass, updated_center), NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } VikViewport *vik_viewport_new () @@ -152,6 +168,8 @@ VikViewport *vik_viewport_new () #define VIK_SETTINGS_VIEW_LAST_LONGITUDE "viewport_last_longitude" #define VIK_SETTINGS_VIEW_LAST_ZOOM_X "viewport_last_zoom_xpp" #define VIK_SETTINGS_VIEW_LAST_ZOOM_Y "viewport_last_zoom_ypp" +#define VIK_SETTINGS_VIEW_HISTORY_SIZE "viewport_history_size" +#define VIK_SETTINGS_VIEW_HISTORY_DIFF_DIST "viewport_history_diff_dist" static void vik_viewport_init ( VikViewport *vvp ) @@ -199,6 +217,15 @@ vik_viewport_init ( VikViewport *vvp ) vvp->scale_bg_gc = NULL; vvp->copyrights = NULL; + vvp->centers = NULL; + vvp->centers_index = 0; + vvp->centers_max = 20; + gint tmp = vvp->centers_max; + if ( a_settings_get_integer ( VIK_SETTINGS_VIEW_HISTORY_SIZE, &tmp ) ) + vvp->centers_max = tmp; + vvp->centers_radius = 500; + if ( a_settings_get_integer ( VIK_SETTINGS_VIEW_HISTORY_DIFF_DIST, &tmp ) ) + vvp->centers_radius = tmp; vvp->draw_scale = TRUE; vvp->draw_centermark = TRUE; @@ -208,6 +235,9 @@ vik_viewport_init ( VikViewport *vvp ) vvp->snapshot_buffer = NULL; vvp->half_drawn = FALSE; + // Initiate center history + update_centers ( vvp ); + g_signal_connect (G_OBJECT(vvp), "configure_event", G_CALLBACK(vik_viewport_configure), NULL); #if GTK_CHECK_VERSION (2,18,0) @@ -393,6 +423,9 @@ static void viewport_finalize ( GObject *gob ) a_settings_set_double ( VIK_SETTINGS_VIEW_LAST_ZOOM_Y, vvp->ympp ); } + if ( vvp->centers ) + free_centers ( vvp, 0 ); + if ( vvp->scr_buffer ) g_object_unref ( G_OBJECT ( vvp->scr_buffer ) ); @@ -815,23 +848,197 @@ static void viewport_utm_zone_check ( VikViewport *vvp ) } } -void vik_viewport_set_center_latlon ( VikViewport *vvp, const struct LatLon *ll ) +/** + * Free an individual center position in the history list + */ +static void free_center ( VikViewport *vvp, guint index ) +{ + VikCoord *coord = g_list_nth_data ( vvp->centers, index ); + if ( coord ) + g_free ( coord ); + GList *gl = g_list_nth ( vvp->centers, index ); + if ( gl ) + vvp->centers = g_list_delete_link ( vvp->centers, gl ); +} + +/** + * Free a set of center positions in the history list, + * from the indicated start index to the end of the list + */ +static void free_centers ( VikViewport *vvp, guint start ) +{ + // Have to work backward since we delete items referenced by the '_nth()' values, + // otherwise if processed forward - removing the lower nth index entries would change the subsequent indexing + for ( guint i = g_list_length(vvp->centers)-1; i > start; i-- ) + free_center ( vvp, i ); +} + +/** + * Store the current center position into the history list + * and emit a signal to notify clients the list has been updated + */ +static void update_centers ( VikViewport *vvp ) +{ + VikCoord *new_center = g_malloc(sizeof (VikCoord)); + *new_center = vvp->center; + + if ( vvp->centers_index ) { + + if ( vvp->centers_index == vvp->centers_max-1 ) { + // List is full, so drop the oldest value to make room for the new one + free_center ( vvp, 0 ); + vvp->centers_index--; + } + else { + // Reset the now unused section of the list + // Free from the index to the end + free_centers ( vvp, vvp->centers_index+1 ); + } + + } + + // Store new position + // NB ATM this can be the same location as the last one in the list + vvp->centers = g_list_append ( vvp->centers, new_center ); + + // Reset to the end (NB should be same as centers_index++) + vvp->centers_index = g_list_length ( vvp->centers ) - 1; + + // Inform interested subscribers that this change has occurred + g_signal_emit ( G_OBJECT(vvp), viewport_signals[VW_UPDATED_CENTER_SIGNAL], 0 ); +} + +/** + * vik_viewport_go_back: + * + * Move back in the position history + * + * Returns: %TRUE one success + */ +gboolean vik_viewport_go_back ( VikViewport *vvp ) +{ + // see if the current position is different from the last saved center position within a certain radius + VikCoord *center = g_list_nth_data ( vvp->centers, vvp->centers_index ); + if ( center ) { + // Consider an exclusion size (should it zoom level dependent, rather than a fixed value?) + // When still near to the last saved position we'll jump over it to the one before + if ( vik_coord_diff ( center, &vvp->center ) > vvp->centers_radius ) { + + if ( vvp->centers_index == g_list_length(vvp->centers)-1 ) { + // Only when we haven't already moved back in the list + // Remember where this request came from + // (alternatively we could insert in the list on every back attempt) + update_centers ( vvp ); + } + + } + // 'Go back' if possible + // NB if we inserted a position above, then this will then move to the last saved position + // otherwise this will skip to the previous saved position, as it's probably somewhere else. + if ( vvp->centers_index > 0 ) + vvp->centers_index--; + } + else { + return FALSE; + } + + VikCoord *new_center = g_list_nth_data ( vvp->centers, vvp->centers_index ); + if ( new_center ) { + vik_viewport_set_center_coord ( vvp, new_center, FALSE ); + return TRUE; + } + return FALSE; +} + +/** + * vik_viewport_go_forward: + * + * Move forward in the position history + * + * Returns: %TRUE one success + */ +gboolean vik_viewport_go_forward ( VikViewport *vvp ) +{ + if ( vvp->centers_index == vvp->centers_max-1 ) + return FALSE; + + vvp->centers_index++; + VikCoord *new_center = g_list_nth_data ( vvp->centers, vvp->centers_index ); + if ( new_center ) { + vik_viewport_set_center_coord ( vvp, new_center, FALSE ); + return TRUE; + } + else + // Set to end of list + vvp->centers_index = g_list_length(vvp->centers) - 1; + + return FALSE; +} + +/** + * vik_viewport_back_available: + * + * Returns: %TRUE when a previous position in the history is available + */ +gboolean vik_viewport_back_available ( const VikViewport *vvp ) +{ + return ( vvp->centers_index > 0 ); +} + +/** + * vik_viewport_forward_available: + * + * Returns: %TRUE when a next position in the history is available + */ +gboolean vik_viewport_forward_available ( const VikViewport *vvp ) +{ + return ( vvp->centers_index < g_list_length(vvp->centers)-1 ); +} + +/** + * vik_viewport_set_center_latlon: + * @vvp: The viewport to reposition. + * @ll: The new center position in Lat/Lon format + * @save_position: Whether this new position should be saved into the history of positions + * Normally only specific user requests should be saved (i.e. to not include Pan and Zoom repositions) + */ +void vik_viewport_set_center_latlon ( VikViewport *vvp, const struct LatLon *ll, gboolean save_position ) { vik_coord_load_from_latlon ( &(vvp->center), vvp->coord_mode, ll ); + if ( save_position ) + update_centers ( vvp ); if ( vvp->coord_mode == VIK_COORD_UTM ) viewport_utm_zone_check ( vvp ); } -void vik_viewport_set_center_utm ( VikViewport *vvp, const struct UTM *utm ) +/** + * vik_viewport_set_center_utm: + * @vvp: The viewport to reposition. + * @utm: The new center position in UTM format + * @save_position: Whether this new position should be saved into the history of positions + * Normally only specific user requests should be saved (i.e. to not include Pan and Zoom repositions) + */ +void vik_viewport_set_center_utm ( VikViewport *vvp, const struct UTM *utm, gboolean save_position ) { vik_coord_load_from_utm ( &(vvp->center), vvp->coord_mode, utm ); + if ( save_position ) + update_centers ( vvp ); if ( vvp->coord_mode == VIK_COORD_UTM ) viewport_utm_zone_check ( vvp ); } -void vik_viewport_set_center_coord ( VikViewport *vvp, const VikCoord *coord ) +/** + * vik_viewport_set_center_coord: + * @vvp: The viewport to reposition. + * @coord: The new center position in a VikCoord type + * @save_position: Whether this new position should be saved into the history of positions + * Normally only specific user requests should be saved (i.e. to not include Pan and Zoom repositions) + */ +void vik_viewport_set_center_coord ( VikViewport *vvp, const VikCoord *coord, gboolean save_position ) { vvp->center = *coord; + if ( save_position ) + update_centers ( vvp ); if ( vvp->coord_mode == VIK_COORD_UTM ) viewport_utm_zone_check ( vvp ); } @@ -894,7 +1101,7 @@ void vik_viewport_set_center_screen ( VikViewport *vvp, int x, int y ) } else { VikCoord tmp; vik_viewport_screen_to_coord ( vvp, x, y, &tmp ); - vik_viewport_set_center_coord ( vvp, &tmp ); + vik_viewport_set_center_coord ( vvp, &tmp, FALSE ); } } diff --git a/src/vikviewport.h b/src/vikviewport.h index 27f291da..14136453 100644 --- a/src/vikviewport.h +++ b/src/vikviewport.h @@ -54,6 +54,7 @@ typedef struct _VikViewportClass VikViewportClass; struct _VikViewportClass { GtkDrawingAreaClass drawing_area_class; + void (*updated_center) (VikViewport *vw); }; GType vik_viewport_get_type (); @@ -82,16 +83,20 @@ void vik_viewport_zoom_out ( VikViewport *vvp ); /* viewport position */ const VikCoord *vik_viewport_get_center ( VikViewport *vvp ); -void vik_viewport_set_center_coord ( VikViewport *vvp, const VikCoord *coord ); +void vik_viewport_set_center_coord ( VikViewport *vvp, const VikCoord *coord, gboolean save_position ); void vik_viewport_set_center_screen ( VikViewport *vvp, int x, int y ); void vik_viewport_center_for_zonen ( VikViewport *vvp, struct UTM *center, int zone); gchar vik_viewport_leftmost_zone ( VikViewport *vvp ); gchar vik_viewport_rightmost_zone ( VikViewport *vvp ); -void vik_viewport_set_center_utm ( VikViewport *vvp, const struct UTM *utm ); -void vik_viewport_set_center_latlon ( VikViewport *vvp, const struct LatLon *ll ); +void vik_viewport_set_center_utm ( VikViewport *vvp, const struct UTM *utm, gboolean save_position ); +void vik_viewport_set_center_latlon ( VikViewport *vvp, const struct LatLon *ll, gboolean save_position ); void vik_viewport_corners_for_zonen ( VikViewport *vvp, int zone, VikCoord *ul, VikCoord *br ); void vik_viewport_get_min_max_lat_lon ( VikViewport *vp, gdouble *min_lat, gdouble *max_lat, gdouble *min_lon, gdouble *max_lon ); +gboolean vik_viewport_go_back ( VikViewport *vvp ); +gboolean vik_viewport_go_forward ( VikViewport *vvp ); +gboolean vik_viewport_back_available ( const VikViewport *vvp ); +gboolean vik_viewport_forward_available ( const VikViewport *vvp ); /* drawmode management */ typedef enum { diff --git a/src/vikwindow.c b/src/vikwindow.c index 1e3fb9bc..dd6c046a 100644 --- a/src/vikwindow.c +++ b/src/vikwindow.c @@ -95,6 +95,7 @@ static gboolean delete_event( VikWindow *vw ); static gboolean key_press_event( VikWindow *vw, GdkEventKey *event, gpointer data ); +static void center_changed_cb ( VikWindow *vw ); static void window_configure_event ( VikWindow *vw ); static void draw_sync ( VikWindow *vw ); static void draw_redraw ( VikWindow *vw ); @@ -404,7 +405,7 @@ static int determine_location_thread ( VikWindow *vw, gpointer threaddata ) } vik_viewport_set_zoom ( vw->viking_vvp, zoom ); - vik_viewport_set_center_latlon ( vw->viking_vvp, &ll ); + vik_viewport_set_center_latlon ( vw->viking_vvp, &ll, FALSE ); gchar *message = g_strdup_printf ( _("Location found: %s"), name ); vik_window_statusbar_update ( vw, message, VIK_STATUSBAR_INFO ); @@ -754,6 +755,9 @@ static void vik_window_init ( VikWindow *vw ) g_signal_connect (G_OBJECT (vw), "delete_event", G_CALLBACK (delete_event), NULL); + // Own signals + g_signal_connect_swapped (G_OBJECT(vw->viking_vvp), "updated_center", G_CALLBACK(center_changed_cb), vw); + // Signals from GTK g_signal_connect_swapped (G_OBJECT(vw->viking_vvp), "expose_event", G_CALLBACK(draw_sync), vw); g_signal_connect_swapped (G_OBJECT(vw->viking_vvp), "configure_event", G_CALLBACK(window_configure_event), vw); gtk_widget_add_events ( GTK_WIDGET(vw->viking_vvp), GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK ); @@ -768,6 +772,9 @@ static void vik_window_init ( VikWindow *vw ) // Allow key presses to be processed anywhere g_signal_connect_swapped (G_OBJECT (vw), "key_press_event", G_CALLBACK (key_press_event), vw); + // Set initial button sensitivity + center_changed_cb ( vw ); + hpaned = gtk_hpaned_new (); gtk_paned_pack1 ( GTK_PANED(hpaned), GTK_WIDGET (vw->viking_vlp), FALSE, FALSE ); gtk_paned_pack2 ( GTK_PANED(hpaned), GTK_WIDGET (vw->viking_vvp), TRUE, TRUE ); @@ -1790,7 +1797,7 @@ static VikLayerToolFuncStatus zoomtool_release (VikLayer *vl, GdkEventButton *ev VikCoord new_center; vik_coord_load_from_latlon ( &new_center, vik_viewport_get_coord_mode ( zts->vw->viking_vvp ), &average ); - vik_viewport_set_center_coord ( zts->vw->viking_vvp, &new_center ); + vik_viewport_set_center_coord ( zts->vw->viking_vvp, &new_center, FALSE ); /* Convert into definite 'smallest' and 'largest' positions */ struct LatLon minmin; @@ -2100,10 +2107,52 @@ static void draw_goto_cb ( GtkAction *a, VikWindow *vw ) return; } - vik_viewport_set_center_coord ( vw->viking_vvp, &new_center ); + vik_viewport_set_center_coord ( vw->viking_vvp, &new_center, TRUE ); draw_update ( vw ); } +/** + * center_changed_cb: + */ +static void center_changed_cb ( VikWindow *vw ) +{ +// ATM Keep back always available, so when we pan - we can jump to the last requested position +/* + GtkAction* action_back = gtk_action_group_get_action ( vw->action_group, "GoBack" ); + if ( action_back ) { + gtk_action_set_sensitive ( action_back, vik_viewport_back_available(vw->viking_vvp) ); + } +*/ + GtkAction* action_forward = gtk_action_group_get_action ( vw->action_group, "GoForward" ); + if ( action_forward ) { + gtk_action_set_sensitive ( action_forward, vik_viewport_forward_available(vw->viking_vvp) ); + } +} + +/** + * draw_goto_back_and_forth: + */ +static void draw_goto_back_and_forth ( GtkAction *a, VikWindow *vw ) +{ + gboolean changed = FALSE; + if (!strcmp(gtk_action_get_name(a), "GoBack")) { + changed = vik_viewport_go_back ( vw->viking_vvp ); + } + else if (!strcmp(gtk_action_get_name(a), "GoForward")) { + changed = vik_viewport_go_forward ( vw->viking_vvp ); + } + else { + return; + } + + // Recheck buttons sensitivities, as the center changed signal is not sent on back/forward changes + // (otherwise we would get stuck in an infinite loop!) + center_changed_cb ( vw ); + + if ( changed ) + draw_update ( vw ); +} + /** * Refresh maps displayed */ @@ -3061,7 +3110,7 @@ static void goto_default_location( GtkAction *a, VikWindow *vw) struct LatLon ll; ll.lat = a_vik_get_default_lat(); ll.lon = a_vik_get_default_long(); - vik_viewport_set_center_latlon(vw->viking_vvp, &ll); + vik_viewport_set_center_latlon(vw->viking_vvp, &ll, TRUE); vik_layers_panel_emit_update(vw->viking_vlp); } @@ -3319,7 +3368,7 @@ static void save_image_dir ( VikWindow *vw, const gchar *fn, guint w, guint h, g utm.northing -= ((gdouble)y - (((gdouble)tiles_h)+1)/2) * (h*zoom); /* move to correct place. */ - vik_viewport_set_center_utm ( vw->viking_vvp, &utm ); + vik_viewport_set_center_utm ( vw->viking_vvp, &utm, FALSE ); draw_redraw ( vw ); @@ -3336,7 +3385,7 @@ static void save_image_dir ( VikWindow *vw, const gchar *fn, guint w, guint h, g } } - vik_viewport_set_center_utm ( vw->viking_vvp, &utm_orig ); + vik_viewport_set_center_utm ( vw->viking_vvp, &utm_orig, FALSE ); vik_viewport_set_xmpp ( vw->viking_vvp, old_xmpp ); vik_viewport_set_ympp ( vw->viking_vvp, old_ympp ); vik_viewport_configure ( vw->viking_vvp ); @@ -3788,6 +3837,8 @@ static GtkActionEntry entries[] = { { "Exit", GTK_STOCK_QUIT, N_("E_xit"), "W", N_("Exit the program"), (GCallback)window_close }, { "SaveExit", GTK_STOCK_QUIT, N_("Save and Exit"), NULL, N_("Save and Exit the program"), (GCallback)save_file_and_exit }, + { "GoBack", GTK_STOCK_GO_BACK, N_("Go to the Pre_vious Location"), NULL, N_("Go to the previous location"), (GCallback)draw_goto_back_and_forth }, + { "GoForward", GTK_STOCK_GO_FORWARD, N_("Go to the _Next Location"), NULL, N_("Go to the next location"), (GCallback)draw_goto_back_and_forth }, { "GotoDefaultLocation", GTK_STOCK_HOME, N_("Go to the _Default Location"), NULL, N_("Go to the default location"), (GCallback)goto_default_location }, { "GotoSearch", GTK_STOCK_JUMP_TO, N_("Go to _Location..."), NULL, N_("Go to address/place using text search"), (GCallback)goto_address }, { "GotoLL", GTK_STOCK_JUMP_TO, N_("_Go to Lat/Lon..."), NULL, N_("Go to arbitrary lat/lon coordinate"), (GCallback)draw_goto_cb }, -- 2.39.5