From ee43b10160d46972f287500755ca49dab8fd4e9c Mon Sep 17 00:00:00 2001 From: Matthew Hague Date: Tue, 4 Feb 2014 23:44:09 +0000 Subject: [PATCH] Improve the Route Finder Tool Changed route finder User Interface workings, it is now similar to the new route tool such that it shows the 'as the crow flys' direct line route, but on creation of each new trackpoint the route from the last trackpoint is calculated using online services. The user can switch between adding points with the new route tool or with the route finder tool, removed a lot of the vtk->route_finder fields and merged them with the new route fields instead, added code to ensure that double trackpoints get added at the joins between planned route segments. Changed so that enforcing duplicates in viktrwlayer.c appending a track duplicates the end of the old track not the start of the new Changed a bit of logic in route finder click to deal with a current empty route not created by the route finder Like the current Create Track and Route tools, the Route Finder handles clicks when in pan mode and avoids extra dispay sync refreshing to avoid display flicker. Update the UI during routing to show a busy cursor and info about the requests being made are shown in the statusbar (particularly in case the online requests are slow). New icons haven been produced for route finder. Signed-off-by: Rob Norris --- src/icons/cursor_route_finder.png | Bin 973 -> 1042 bytes src/icons/route_finder_18.png | Bin 494 -> 565 bytes src/viktrwlayer.c | 200 +++++++++++++++++++----------- 3 files changed, 128 insertions(+), 72 deletions(-) diff --git a/src/icons/cursor_route_finder.png b/src/icons/cursor_route_finder.png index a808be29cefdba3de28d00d37e90c4e1ffaa2e48..4b19f13697f4d51a7f510b84d30deb25dea0bb57 100644 GIT binary patch delta 809 zcmV+^1J?Y_2a*VoBo78+OGiWi{{a60|De66laW9k9o_*E4h=M~p=n0|0072mR9JLF zZ*6U5Zgc<3HfBm-Gu-#HJq?4RMu>;*fpnlTsHzQ54eYG=qbK`2Bu@!606*7oX2ZHk(}l z9+|PpWKxbqkbk|;)7dWogra_u$)pSq57%r)wzjrRi2-)j*4FID@YWujNF>BCjDNbs zMkUhYl1PtBBsMCEL_+E+P&HtY&CSi{)6>%g0s(;Q_E=5RP!xq5ul61H_&9k1*Xx^g z1-Y{Gz&e&{fLUPGw*C-}MwywJp{uJ4;G#WP*LCYUK7Zl)E2ESfG-bD&{l8Gue*j>$ zYW)?6j*N`VR@QfHdu|iJ&<(5T;^HCzkFTEWJ#ZZBh{xl(v9U3(z4*!JsdfNdE?1fE z&8?c9hob(YJ%&fHJzduk5p+$*FpRPqm0vCJ-U>Yb?zSUwqkVz#@o}Y508g=41fcl4 zfMK**8-GhnOOC+m<1q6Y1<0E-pp{gsbAWI-3_x331?uIPLwfu0HUfaAX%zs?8bXi9 zbFk3lMwvLDFUPO1HyJ=xEdaOM&HVg)&G=9#N4C*a z&AK)Wqo(if?lx}-%^PJNdI9KvvJJqu@PIWFhvhX5z$~U~IzJYChZb)tfU2qhba!_H n@N0SWSb0rRU}a^cp--|u){#QxVhXaE00000NkvXXu0mjfJobSU delta 766 zcmV;_0Q`JXGN1qe010qNS#tmY z3ljhU3ljkVnw%H_000McNliru+6o8&86J^(G28$E0K#-dSad^gZEa<4bdheme@0ps z3jhEDe@R3^R9M5!md{HYK@`V7YwRI}K)|~o6+$JT$6^Uyh2H%i+Fp9GNK^zX@z9G1 z?LXixCrk01Q^Z3Mz1R)3JxH$>YMQ#)otf9eW|wTT27jz>A3S!KdEc4Oy!U2U_z&$_ znu|-%U#13ddU~2FggB0qDug(Wf0HUi2#^*;1RxEFA%Mq*hy{2|h-(2J3c`v37%8xA zo4L8UIPJq_V1IvK`fkahlht^+jf6u`mNAt zG(<$C{JAYksT+Hv(U8F&7;LPsz{mOd`8U1qSAAm{AXBYYyIN}ij5dh)j2jyp*VcJ+ za}yCE(B0MYA~G%_`Fg!Be8b63~0|Uf%X)|53TUVyS%)NxQI|F6i`Yf z0}wW$rQ-W36uuATw#tuhn##6#QzLjb{IT4{c)mqsq0 wD1hgA08C6w0PuTfAmPTk#4@nEyL%_?KM1poj507*qoM6N<$f(gG~`2YX_ diff --git a/src/icons/route_finder_18.png b/src/icons/route_finder_18.png index 291447935c48d4cd325a813da08e2d6ee2972e3e..15def871ca1ee86850f7d269fd7f02cedac9d3b3 100644 GIT binary patch delta 513 zcmV+c0{;E(1GNN@Bo78+OGiWi{{a60|De66laW9kf8GHR4J{IF!Gk5x|3gKjHwEc6 z-U0>n&{Ho#O+ssSemoD`9e0wn7JM+f^WMz&v+uoOHUOf2zpuE4-8tFu{4Y0O6UXr~ zpd(<#e_Bf%$Nwgsz{|&<0Z0zEu+{>s0FwxawAKVc!2NdDh0re=WPkZnq2EbN=4ukthDJyi2`azXAO8 zO4F%wnE*7KO#sT}3;5dy9;kRoQQ;WTsdhaol}dAh*)nt8JV+@A3d4|At2NWotjr`y zvi*mLJ}6C7M1=FnImQ?^_P;TBa*IZz0YIfv@o?kum|U0JQZXZ=veJywtiL)&L=X{1 zXQPofM1*R!>Xo+SHCt)cUJTGmyScS?;TR5w^Ucl!$GhtQtUVt9@U^+&dbY?e1?3{6 z4d0*Lz7nz!q*V4hs?}-${Mz5X*0soWUPirMkN>eh;_0Q`JXGN1qe010qNS#tmY z3ljhU3ljkVnw%H_000McNliru+6o8&5*l^mEDitw0d7e|K~y-)rIbrb13?gmznBq> zArQzB6a;ZK2haoPVcbMQ5(x}J7j7g+@dA2+Sq23423eSgnt$o)E*CmY8fSvhf_^~P z|M6G9DnOK`so{?i$MLqRN(AgU=ZNEYV@R5&06V}u0wNKiQmJr!HxCjY&UV*=L&n;w diff --git a/src/viktrwlayer.c b/src/viktrwlayer.c index 6af595ef..84d963a1 100644 --- a/src/viktrwlayer.c +++ b/src/viktrwlayer.c @@ -202,10 +202,8 @@ struct _VikTrwLayer { /* route finder tool */ gboolean route_finder_started; - VikCoord route_finder_coord; gboolean route_finder_check_added_track; VikTrack *route_finder_added_track; - VikTrack *route_finder_current_track; gboolean route_finder_append; gboolean drawlabels; @@ -390,8 +388,9 @@ static void tool_new_track_release ( VikTrwLayer *vtl, GdkEventButton *event, Vi static gboolean tool_new_track_key_press ( VikTrwLayer *vtl, GdkEventKey *event, VikViewport *vvp ); static gpointer tool_new_waypoint_create ( VikWindow *vw, VikViewport *vvp); static gboolean tool_new_waypoint_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ); -static gpointer tool_route_finder_create ( VikWindow *vw, VikViewport *vvp); -static gboolean tool_route_finder_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ); +static gpointer tool_extended_route_finder_create ( VikWindow *vw, VikViewport *vvp); +static gboolean tool_extended_route_finder_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ); +static gboolean tool_extended_route_finder_key_press ( VikTrwLayer *vtl, GdkEventKey *event, VikViewport *vvp ); static void cached_pixbuf_free ( CachedPixbuf *cp ); static gint cached_pixbuf_cmp ( CachedPixbuf *cp, const gchar *name ); @@ -438,6 +437,15 @@ static VikToolInterface trw_layer_tools[] = { TRUE, // Still need to handle clicks when in PAN mode to disable the potential trackpoint drawing GDK_CURSOR_IS_PIXMAP, &cursor_new_route_pixbuf, NULL }, + { { "ExtendedRouteFinder", "vik-icon-Route Finder", N_("Route _Finder"), "F", N_("Route Finder"), 0 }, + (VikToolConstructorFunc) tool_extended_route_finder_create, NULL, NULL, NULL, + (VikToolMouseFunc) tool_extended_route_finder_click, + (VikToolMouseMoveFunc) tool_new_track_move, // -\# + (VikToolMouseFunc) tool_new_track_release, // -> Reuse these track methods on a route + (VikToolKeyFunc) tool_extended_route_finder_key_press, + TRUE, // Still need to handle clicks when in PAN mode to disable the potential trackpoint drawing + GDK_CURSOR_IS_PIXMAP, &cursor_route_finder_pixbuf, NULL }, + { { "EditWaypoint", "vik-icon-Edit Waypoint", N_("_Edit Waypoint"), "E", N_("Edit Waypoint"), 0 }, (VikToolConstructorFunc) tool_edit_waypoint_create, (VikToolDestructorFunc) tool_edit_waypoint_destroy, @@ -464,21 +472,16 @@ static VikToolInterface trw_layer_tools[] = { FALSE, GDK_CURSOR_IS_PIXMAP, &cursor_showpic_pixbuf, NULL }, - { { "RouteFinder", "vik-icon-Route Finder", N_("Route _Finder"), "F", N_("Route Finder"), 0 }, - (VikToolConstructorFunc) tool_route_finder_create, NULL, NULL, NULL, - (VikToolMouseFunc) tool_route_finder_click, NULL, NULL, (VikToolKeyFunc) NULL, - FALSE, - GDK_CURSOR_IS_PIXMAP, &cursor_route_finder_pixbuf, NULL }, }; enum { TOOL_CREATE_WAYPOINT=0, TOOL_CREATE_TRACK, TOOL_CREATE_ROUTE, + TOOL_ROUTE_FINDER, TOOL_EDIT_WAYPOINT, TOOL_EDIT_TRACKPOINT, TOOL_SHOW_PICTURE, - TOOL_ROUTE_FINDER, NUM_TOOLS }; @@ -3880,6 +3883,7 @@ static void trw_layer_finish_track ( menu_array_layer values ) { VikTrwLayer *vtl = VIK_TRW_LAYER(values[MA_VTL]); vtl->current_track = NULL; + vtl->route_finder_started = FALSE; vik_layer_emit_update ( VIK_LAYER(vtl) ); } @@ -4434,9 +4438,19 @@ void vik_trw_layer_filein_add_waypoint ( VikTrwLayer *vtl, gchar *name, VikWaypo void vik_trw_layer_filein_add_track ( VikTrwLayer *vtl, gchar *name, VikTrack *tr ) { - if ( vtl->route_finder_append && vtl->route_finder_current_track ) { + if ( vtl->route_finder_append && vtl->current_track ) { vik_track_remove_dup_points ( tr ); /* make "double point" track work to undo */ - vik_track_steal_and_append_trackpoints ( vtl->route_finder_current_track, tr ); + + // enforce end of current track equal to start of tr + VikTrackpoint *cur_end = vik_track_get_tp_last ( vtl->current_track ); + VikTrackpoint *new_start = vik_track_get_tp_first ( tr ); + if ( ! vik_coord_equals ( &cur_end->coord, &new_start->coord ) ) { + vik_track_add_trackpoint ( vtl->current_track, + vik_trackpoint_copy ( cur_end ), + FALSE ); + } + + vik_track_steal_and_append_trackpoints ( vtl->current_track, tr ); vik_track_free ( tr ); vtl->route_finder_append = FALSE; /* this means we have added it */ } else { @@ -4577,13 +4591,11 @@ gboolean vik_trw_layer_delete_track ( VikTrwLayer *vtl, VikTrack *trk ) vtl->current_tp_track = NULL; vtl->current_tp_id = NULL; vtl->moving_tp = FALSE; + vtl->route_finder_started = 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; @@ -4632,9 +4644,6 @@ gboolean vik_trw_layer_delete_route ( VikTrwLayer *vtl, VikTrack *trk ) 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; @@ -4805,7 +4814,6 @@ 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); @@ -4823,7 +4831,6 @@ void vik_trw_layer_delete_all_tracks ( 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); @@ -5229,15 +5236,13 @@ static void trw_layer_extend_track_end_route_finder ( menu_array_sublayer values VikTrack *track = g_hash_table_lookup ( vtl->routes, values[MA_SUBLAYER_ID] ); if ( !track ) return; - if ( !track->trackpoints ) - return; vik_window_enable_layer_tool ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), VIK_LAYER_TRW, TOOL_ROUTE_FINDER ); - vtl->route_finder_coord = vik_track_get_tp_last(track)->coord; - vtl->route_finder_current_track = track; + vtl->current_track = track; vtl->route_finder_started = TRUE; - goto_coord ( values[MA_VLP], vtl, values[MA_VVP], &vtl->route_finder_coord ); + if ( track->trackpoints ) + goto_coord ( values[MA_VLP], vtl, values[MA_VVP], &vik_track_get_tp_last(track)->coord ); } /** @@ -9661,6 +9666,9 @@ static gboolean tool_new_track_or_route_click ( VikTrwLayer *vtl, GdkEventButton static gboolean tool_new_track_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ) { + // if we were running the route finder, cancel it + vtl->route_finder_started = FALSE; + // ----------------------------------------------------- if current is a route - switch to new track if ( event->button == 1 && ( ! vtl->current_track || (vtl->current_track && vtl->current_track->is_route ) )) { @@ -9694,8 +9702,12 @@ static gpointer tool_new_route_create ( VikWindow *vw, VikViewport *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 ) ) ) + // if we were running the route finder, cancel it + vtl->route_finder_started = FALSE; + + // -------------------------- 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), name, TRUE ) ) ) { @@ -9898,77 +9910,121 @@ static gboolean tool_edit_trackpoint_release ( VikTrwLayer *vtl, GdkEventButton } -/*** Route Finder ***/ -static gpointer tool_route_finder_create ( VikWindow *vw, VikViewport *vvp) +/*** Extended Route Finder ***/ + +static gpointer tool_extended_route_finder_create ( VikWindow *vw, VikViewport *vvp) { return vvp; } -static gboolean tool_route_finder_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ) +static void tool_extended_route_finder_undo ( VikTrwLayer *vtl ) +{ + VikCoord *new_end; + new_end = vik_track_cut_back_to_double_point ( vtl->current_track ); + if ( new_end ) { + g_free ( new_end ); + vik_layer_emit_update ( VIK_LAYER(vtl) ); + + /* remove last ' to:...' */ + if ( vtl->current_track->comment ) { + gchar *last_to = strrchr ( vtl->current_track->comment, 't' ); + if ( last_to && (last_to - vtl->current_track->comment > 1) ) { + gchar *new_comment = g_strndup ( vtl->current_track->comment, + last_to - vtl->current_track->comment - 1); + vik_track_set_comment_no_copy ( vtl->current_track, new_comment ); + } + } + } +} + + +static gboolean tool_extended_route_finder_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ) { VikCoord tmp; if ( !vtl ) return FALSE; vik_viewport_screen_to_coord ( vvp, event->x, event->y, &tmp ); - if ( event->button == 3 && vtl->route_finder_current_track ) { - VikCoord *new_end; - new_end = vik_track_cut_back_to_double_point ( vtl->route_finder_current_track ); - if ( new_end ) { - vtl->route_finder_coord = *new_end; - g_free ( new_end ); - 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' ); - if ( last_to && (last_to - vtl->route_finder_current_track->comment > 1) ) { - gchar *new_comment = g_strndup ( vtl->route_finder_current_track->comment, - last_to - vtl->route_finder_current_track->comment - 1); - vik_track_set_comment_no_copy ( vtl->route_finder_current_track, new_comment ); - } - } - } + if ( event->button == 3 && vtl->current_track ) { + tool_extended_route_finder_undo ( vtl ); + } + else if ( event->button == 2 ) { + vtl->draw_sync_do = FALSE; + return FALSE; } - else if ( vtl->route_finder_started || (event->state & GDK_CONTROL_MASK && vtl->route_finder_current_track) ) { + // if we started the track but via undo deleted all the track points, begin again + else if ( vtl->current_track && vtl->current_track->is_route && ! vik_track_get_tp_first ( vtl->current_track ) ) { + return tool_new_track_or_route_click ( vtl, event, vvp ); + } + else if ( ( vtl->current_track && vtl->current_track->is_route ) || + ( event->state & GDK_CONTROL_MASK && vtl->current_track ) ) { struct LatLon start, end; - vik_coord_to_latlon ( &(vtl->route_finder_coord), &start ); + VikTrackpoint *tp_start = vik_track_get_tp_last ( vtl->current_track ); + vik_coord_to_latlon ( &(tp_start->coord), &start ); vik_coord_to_latlon ( &(tmp), &end ); - vtl->route_finder_coord = tmp; /* for continuations */ - /* these are checked when adding a track from a file (vik_trw_layer_filein_add_track) */ - if ( event->state & GDK_CONTROL_MASK && vtl->route_finder_current_track ) { - vtl->route_finder_append = TRUE; // merge tracks. keep started true. - } else { - vtl->route_finder_check_added_track = TRUE; - vtl->route_finder_started = FALSE; + vtl->route_finder_started = TRUE; + vtl->route_finder_append = TRUE; // merge tracks. keep started true. + + // update UI to let user know what's going on + VikStatusbar *sb = vik_window_get_statusbar (VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl))); + VikRoutingEngine *engine = vik_routing_default_engine ( ); + if ( ! engine ) { + vik_statusbar_set_message ( sb, VIK_STATUSBAR_INFO, "Cannot plan route without a default routing engine." ); + return TRUE; } + gchar *msg = g_strdup_printf ( _("Querying %s for route between (%.3f, %.3f) and (%.3f, %.3f)."), + vik_routing_engine_get_label ( engine ), + start.lat, start.lon, end.lat, end.lon ); + vik_statusbar_set_message ( sb, VIK_STATUSBAR_INFO, msg ); + g_free ( msg ); + vik_window_set_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)) ); - vik_routing_default_find ( vtl, start, end); - /* see if anything was done -- a track was added or appended to */ - if ( vtl->route_finder_check_added_track && vtl->route_finder_added_track ) { - vik_track_set_comment_no_copy ( vtl->route_finder_added_track, g_strdup_printf("from: %f,%f to: %f,%f", start.lat, start.lon, end.lat, end.lon ) ); - } else if ( vtl->route_finder_append == FALSE && vtl->route_finder_current_track ) { - /* route_finder_append was originally TRUE but set to FALSE by filein_add_track */ - gchar *new_comment = g_strdup_printf("%s to: %f,%f", vtl->route_finder_current_track->comment, end.lat, end.lon ); - vik_track_set_comment_no_copy ( vtl->route_finder_current_track, new_comment ); - } + /* Give GTK a change to display the new status bar before querying the web */ + while ( gtk_events_pending ( ) ) + gtk_main_iteration ( ); - if ( vtl->route_finder_added_track ) - vik_track_calculate_bounds ( vtl->route_finder_added_track ); + gboolean find_status = vik_routing_default_find ( vtl, start, end ); - vtl->route_finder_added_track = NULL; - vtl->route_finder_check_added_track = FALSE; - vtl->route_finder_append = FALSE; + /* Update UI to say we're done */ + vik_window_clear_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)) ); + msg = ( find_status ) ? g_strdup_printf ( _("%s returned route between (%.3f, %.3f) and (%.3f, %.3f)."), + vik_routing_engine_get_label ( engine ), + start.lat, start.lon, end.lat, end.lon ) + : g_strdup_printf ( _("Error getting route from %s."), + vik_routing_engine_get_label ( engine ) ); + vik_statusbar_set_message ( sb, VIK_STATUSBAR_INFO, msg ); + g_free ( msg ); vik_layer_emit_update ( VIK_LAYER(vtl) ); } else { + vtl->current_track = NULL; + + // create a new route where we will add the planned route to + gboolean ret = tool_new_route_click( vtl, event, vvp ); + vtl->route_finder_started = TRUE; - vtl->route_finder_coord = tmp; - vtl->route_finder_current_track = NULL; + + return ret; } return TRUE; } +static gboolean tool_extended_route_finder_key_press ( VikTrwLayer *vtl, GdkEventKey *event, VikViewport *vvp ) +{ + if ( vtl->current_track && event->keyval == GDK_Escape ) { + vtl->route_finder_started = FALSE; + vtl->current_track = NULL; + vik_layer_emit_update ( VIK_LAYER(vtl) ); + return TRUE; + } else if ( vtl->current_track && event->keyval == GDK_BackSpace ) { + tool_extended_route_finder_undo ( vtl ); + } + return FALSE; +} + + + /*** Show picture ****/ static gpointer tool_show_picture_create ( VikWindow *vw, VikViewport *vvp) -- 2.39.5