]> git.street.me.uk Git - andy/viking.git/blobdiff - src/viktrwlayer.c
Minimum GTK+2.14 required for the build.
[andy/viking.git] / src / viktrwlayer.c
index 5917d84c280581c83a22d039b9058fbdca00571f..cbc3351a1fb8845eecade535cff15c3c05c81780 100644 (file)
@@ -1892,7 +1892,7 @@ static VikTrwLayer* trw_layer_create ( VikViewport *vp )
   VikTrwLayer *rv = trw_layer_new1 ( vp );
   vik_layer_rename ( VIK_LAYER(rv), vik_trw_layer_interface.name );
 
-  if ( vp == NULL || GTK_WIDGET(vp)->window == NULL ) {
+  if ( vp == NULL || gtk_widget_get_window(GTK_WIDGET(vp)) == NULL ) {
     /* early exit, as the rest is GUI related */
     return rv;
   }
@@ -2719,7 +2719,9 @@ static void trw_layer_export ( gpointer layer_and_vlp[2], const gchar *title, co
     if ( g_file_test ( fn, G_FILE_TEST_EXISTS ) == FALSE )
     {
       gtk_widget_hide ( file_selector );
+      vik_window_set_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0])) );
       failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), fn, file_type, trk, TRUE );
+      vik_window_clear_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0])) );
       break;
     }
     else
@@ -2727,7 +2729,9 @@ static void trw_layer_export ( gpointer layer_and_vlp[2], const gchar *title, co
       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 );
+        vik_window_set_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0])) );
        failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), fn, file_type, trk, TRUE );
+        vik_window_clear_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0])) );
         break;
       }
     }
@@ -2781,7 +2785,9 @@ static void trw_layer_export_external_gpx ( gpointer layer_and_vlp[2], const gch
   int fd;
 
   if ((fd = g_file_open_tmp("tmp-viking.XXXXXX.gpx", &name_used, NULL)) >= 0) {
+    vik_window_set_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0])) );
     gboolean failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), name_used, FILE_TYPE_GPX, NULL, TRUE);
+    vik_window_clear_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0])) );
     if (failed) {
       a_dialog_error_msg (VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0]), _("Could not create temporary file for export.") );
     }
@@ -2871,8 +2877,8 @@ static void trw_layer_goto_wp ( gpointer layer_and_vlp[2] )
   label = gtk_label_new(_("Waypoint Name:"));
   entry = gtk_entry_new();
 
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dia)->vbox), label, FALSE, FALSE, 0);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dia)->vbox), entry, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dia))), label, FALSE, FALSE, 0);
+  gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dia))), entry, FALSE, FALSE, 0);
   gtk_widget_show_all ( label );
   gtk_widget_show_all ( entry );
 
@@ -2926,7 +2932,7 @@ gboolean vik_trw_layer_new_waypoint ( VikTrwLayer *vtl, GtkWindow *w, const VikC
   if ( elev != VIK_DEM_INVALID_ELEVATION )
     wp->altitude = (gdouble)elev;
 
-  returned_name = a_dialog_waypoint ( w, default_name, wp, vtl->coord_mode, TRUE, &updated );
+  returned_name = a_dialog_waypoint ( w, default_name, vtl, wp, vtl->coord_mode, TRUE, &updated );
 
   if ( returned_name )
   {
@@ -3844,10 +3850,16 @@ static void trw_layer_enum_item ( gpointer id, GList **tr, GList **l )
  */
 static void trw_layer_move_item ( VikTrwLayer *vtl_src, VikTrwLayer *vtl_dest, gpointer id, gint type )
 {
+  gboolean rename = ( vtl_src != vtl_dest );
+
   if (type == VIK_TRW_LAYER_SUBLAYER_TRACK) {
     VikTrack *trk = g_hash_table_lookup ( vtl_src->tracks, id );
 
-    gchar *newname = trw_layer_new_unique_sublayer_name(vtl_dest, type, trk->name);
+    gchar *newname;
+    if ( rename )
+      newname = trw_layer_new_unique_sublayer_name ( vtl_dest, type, trk->name );
+    else
+      newname = g_strdup ( trk->name );
 
     VikTrack *trk2 = vik_track_copy ( trk, TRUE );
     vik_trw_layer_add_track ( vtl_dest, newname, trk2 );
@@ -3857,7 +3869,11 @@ static void trw_layer_move_item ( VikTrwLayer *vtl_src, VikTrwLayer *vtl_dest, g
   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);
+    gchar *newname;
+    if ( rename )
+      newname = trw_layer_new_unique_sublayer_name ( vtl_dest, type, trk->name );
+    else
+      newname = g_strdup ( trk->name );
 
     VikTrack *trk2 = vik_track_copy ( trk, TRUE );
     vik_trw_layer_add_route ( vtl_dest, newname, trk2 );
@@ -3867,14 +3883,21 @@ static void trw_layer_move_item ( VikTrwLayer *vtl_src, VikTrwLayer *vtl_dest, g
   if (type == VIK_TRW_LAYER_SUBLAYER_WAYPOINT) {
     VikWaypoint *wp = g_hash_table_lookup ( vtl_src->waypoints, id );
 
-    gchar *newname = trw_layer_new_unique_sublayer_name(vtl_dest, type, wp->name);
+    gchar *newname;
+    if ( rename )
+      newname = trw_layer_new_unique_sublayer_name ( vtl_dest, type, wp->name );
+    else
+      newname = g_strdup ( wp->name );
 
     VikWaypoint *wp2 = vik_waypoint_copy ( wp );
     vik_trw_layer_add_waypoint ( vtl_dest, newname, wp2 );
     trw_layer_delete_waypoint ( vtl_src, wp );
 
-    trw_layer_calculate_bounds_waypoints ( vtl_dest );
-    trw_layer_calculate_bounds_waypoints ( vtl_src );
+    // If no change - don't need to recalculate bounds
+    if ( !rename ) {
+      trw_layer_calculate_bounds_waypoints ( vtl_dest );
+      trw_layer_calculate_bounds_waypoints ( vtl_src );
+    }
   }
 }
 
@@ -4303,7 +4326,7 @@ static void trw_layer_properties_item ( gpointer pass_along[7] )
     if ( wp && wp->name )
     {
       gboolean updated = FALSE;
-      a_dialog_waypoint ( VIK_GTK_WINDOW_FROM_LAYER(vtl), wp->name, wp, vtl->coord_mode, FALSE, &updated );
+      a_dialog_waypoint ( VIK_GTK_WINDOW_FROM_LAYER(vtl), wp->name, vtl, wp, vtl->coord_mode, FALSE, &updated );
 
       if ( updated && pass_along[6] )
         vik_treeview_item_set_icon ( VIK_LAYER(vtl)->vt, pass_along[6], get_wp_sym_small (wp->symbol) );
@@ -6876,6 +6899,95 @@ static void trw_layer_tpwin_response ( VikTrwLayer *vtl, gint response )
     vik_layer_emit_update(VIK_LAYER(vtl));
 }
 
+/**
+ * trw_layer_dialog_shift:
+ * @vertical: The reposition strategy. If Vertical moves dialog vertically, otherwise moves it horizontally
+ *
+ * Try to reposition a dialog if it's over the specified coord
+ *  so to not obscure the item of interest
+ */
+void trw_layer_dialog_shift ( VikTrwLayer *vtl, GtkWindow *dialog, VikCoord *coord, gboolean vertical )
+{
+  GtkWindow *parent = VIK_GTK_WINDOW_FROM_LAYER(vtl); //i.e. the main window
+
+  // get parent window position & size
+  gint win_pos_x, win_pos_y;
+  gtk_window_get_position ( parent, &win_pos_x, &win_pos_y );
+
+  gint win_size_x, win_size_y;
+  gtk_window_get_size ( parent, &win_size_x, &win_size_y );
+
+  // get own dialog size
+  gint dia_size_x, dia_size_y;
+  gtk_window_get_size ( dialog, &dia_size_x, &dia_size_y );
+
+  // get own dialog position
+  gint dia_pos_x, dia_pos_y;
+  gtk_window_get_position ( dialog, &dia_pos_x, &dia_pos_y );
+
+  // Dialog not 'realized'/positioned - so can't really do any repositioning logic
+  if ( dia_pos_x > 2 && dia_pos_y > 2 ) {
+
+    VikViewport *vvp = vik_window_viewport ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)) );
+
+    gint vp_xx, vp_yy; // In viewport pixels
+    vik_viewport_coord_to_screen ( vvp, coord, &vp_xx, &vp_yy );
+
+    // Work out the 'bounding box' in pixel terms of the dialog and only move it when over the position
+
+    gint dest_x = 0;
+    gint dest_y = 0;
+    if ( gtk_widget_translate_coordinates ( GTK_WIDGET(vvp), GTK_WIDGET(parent), 0, 0, &dest_x, &dest_y ) ) {
+
+      // Transform Viewport pixels into absolute pixels
+      gint tmp_xx = vp_xx + dest_x + win_pos_x - 10;
+      gint tmp_yy = vp_yy + dest_y + win_pos_y - 10;
+
+      // Is dialog over the point (to within an  ^^ edge value)
+      if ( (tmp_xx > dia_pos_x) && (tmp_xx < (dia_pos_x + dia_size_x)) &&
+           (tmp_yy > dia_pos_y) && (tmp_yy < (dia_pos_y + dia_size_y)) ) {
+
+        if ( vertical ) {
+         // Shift up<->down
+          gint hh = vik_viewport_get_height ( vvp );
+
+          // Consider the difference in viewport to the full window
+          gint offset_y = dest_y;
+          // Add difference between dialog and window sizes
+          offset_y += win_pos_y + (hh/2 - dia_size_y)/2;
+
+          if ( vp_yy > hh/2 ) {
+            // Point in bottom half, move window to top half
+            gtk_window_move ( dialog, dia_pos_x, offset_y );
+          }
+          else {
+            // Point in top half, move dialog down
+            gtk_window_move ( dialog, dia_pos_x, hh/2 + offset_y );
+          }
+       }
+       else {
+         // Shift left<->right
+          gint ww = vik_viewport_get_width ( vvp );
+
+          // Consider the difference in viewport to the full window
+          gint offset_x = dest_x;
+          // Add difference between dialog and window sizes
+          offset_x += win_pos_x + (ww/2 - dia_size_x)/2;
+
+          if ( vp_xx > ww/2 ) {
+            // Point on right, move window to left
+            gtk_window_move ( dialog, offset_x, dia_pos_y );
+          }
+          else {
+            // Point on left, move right
+            gtk_window_move ( dialog, ww/2 + offset_x, dia_pos_y );
+          }
+       }
+      }
+    }
+  }
+}
+
 static void trw_layer_tpwin_init ( VikTrwLayer *vtl )
 {
   if ( ! vtl->tpwin )
@@ -6884,8 +6996,18 @@ static void trw_layer_tpwin_init ( VikTrwLayer *vtl )
     g_signal_connect_swapped ( GTK_DIALOG(vtl->tpwin), "response", G_CALLBACK(trw_layer_tpwin_response), vtl );
     /* connect signals -- DELETE SIGNAL VERY IMPORTANT TO SET TO NULL */
     g_signal_connect_swapped ( vtl->tpwin, "delete-event", G_CALLBACK(trw_layer_cancel_current_tp), vtl );
+
     gtk_widget_show_all ( GTK_WIDGET(vtl->tpwin) );
+
+    if ( vtl->current_tpl ) {
+      // get tp pixel position
+      VikTrackpoint *tp = VIK_TRACKPOINT(vtl->current_tpl->data);
+
+      // Shift up<->down to try not to obscure the trackpoint.
+      trw_layer_dialog_shift ( vtl, GTK_WINDOW(vtl->tpwin), &(tp->coord), TRUE );
+    }
   }
+
   if ( vtl->current_tpl )
     if ( vtl->current_tp_track )
       vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track->name );
@@ -6901,6 +7023,7 @@ static void trw_layer_tpwin_init ( VikTrwLayer *vtl )
 typedef struct {
   gint x, y;
   gint closest_x, closest_y;
+  gboolean draw_images;
   gpointer *closest_wp_id;
   VikWaypoint *closest_wp;
   VikViewport *vvp;
@@ -6925,7 +7048,7 @@ static void waypoint_search_closest_tp ( gpointer id, VikWaypoint *wp, WPSearchP
   vik_viewport_coord_to_screen ( params->vvp, &(wp->coord), &x, &y );
 
   // If waypoint has an image then use the image size to select
-  if ( wp->image ) {
+  if ( params->draw_images && wp->image ) {
     gint slackx, slacky;
     slackx = wp->image_width / 2;
     slacky = wp->image_height / 2;
@@ -7002,6 +7125,7 @@ static VikWaypoint *closest_wp_in_five_pixel_interval ( VikTrwLayer *vtl, VikVie
   params.x = x;
   params.y = y;
   params.vvp = vvp;
+  params.draw_images = vtl->drawimages;
   params.closest_wp = NULL;
   params.closest_wp_id = NULL;
   g_hash_table_foreach ( vtl->waypoints, (GHFunc) waypoint_search_closest_tp, &params);
@@ -7131,6 +7255,7 @@ static gboolean trw_layer_select_click ( VikTrwLayer *vtl, GdkEventButton *event
     wp_params.vvp = vvp;
     wp_params.x = event->x;
     wp_params.y = event->y;
+    wp_params.draw_images = vtl->drawimages;
     wp_params.closest_wp_id = NULL;
     wp_params.closest_wp = NULL;
 
@@ -7436,6 +7561,7 @@ static gboolean tool_edit_waypoint_click ( VikTrwLayer *vtl, GdkEventButton *eve
   params.vvp = vvp;
   params.x = event->x;
   params.y = event->y;
+  params.draw_images = vtl->drawimages;
   params.closest_wp_id = NULL;
   /* TODO: should get track listitem so we can break it up, make a new track, mess it up, all that. */
   params.closest_wp = NULL;
@@ -7690,12 +7816,12 @@ static VikLayerToolFuncStatus tool_new_track_move ( VikTrwLayer *vtl, GdkEventMo
     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 );
+      pixmap = gdk_pixmap_new ( gtk_widget_get_window(GTK_WIDGET(vvp)), 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 );
+      pixmap = gdk_pixmap_new ( gtk_widget_get_window(GTK_WIDGET(vvp)), w1, h1, -1 );
     }
 
     // Reset to background
@@ -7772,7 +7898,7 @@ static VikLayerToolFuncStatus tool_new_track_move ( VikTrwLayer *vtl, GdkEventMo
     passalong = g_new(draw_sync_t,1); // freed by draw_sync()
     passalong->vtl = vtl;
     passalong->pixmap = pixmap;
-    passalong->drawable = GTK_WIDGET(vvp)->window;
+    passalong->drawable = gtk_widget_get_window(GTK_WIDGET(vvp));
     passalong->gc = vtl->current_track_newpoint_gc;
 
     gdouble angle;