]> git.street.me.uk Git - andy/viking.git/blob - src/viktrwlayer_tpwin.c
[DOC] Add documentation on new public routing function
[andy/viking.git] / src / viktrwlayer_tpwin.c
1 /*
2  * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
3  *
4  * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <gtk/gtk.h>
27 #include <glib/gi18n.h>
28 #include <time.h>
29
30 #include "coords.h"
31 #include "vikcoord.h"
32 #include "viktrack.h"
33 #include "viktrwlayer_tpwin.h"
34 #include "vikwaypoint.h"
35 #include "dialog.h"
36 #include "globals.h"
37
38 struct _VikTrwLayerTpwin {
39   GtkDialog parent;
40   GtkSpinButton *lat, *lon, *alt;
41   GtkLabel *track_name, *ts, *localtime, *diff_dist, *diff_time, *diff_speed, *hdop, *vdop, *pdop, *sat;
42   // Previously these buttons were in a glist, however I think the ordering behaviour is implicit
43   //  thus control manually to ensure operating on the correct button
44   GtkWidget *button_close;
45   GtkWidget *button_delete;
46   GtkWidget *button_insert;
47   GtkWidget *button_split;
48   GtkWidget *button_back;
49   GtkWidget *button_forward;
50   VikTrackpoint *cur_tp;
51   gboolean sync_to_tp_block;
52 };
53
54 GType vik_trw_layer_tpwin_get_type (void)
55 {
56   static GType tpwin_type = 0;
57
58   if (!tpwin_type)
59   {
60     static const GTypeInfo tpwin_info = 
61     {
62       sizeof (VikTrwLayerTpwinClass),
63       NULL, /* base_init */
64       NULL, /* base_finalize */
65       NULL, /* class init */
66       NULL, /* class_finalize */
67       NULL, /* class_data */
68       sizeof (VikTrwLayerTpwin),
69       0,
70       NULL /* instance init */
71     };
72     tpwin_type = g_type_register_static ( GTK_TYPE_DIALOG, "VikTrwLayerTpwin", &tpwin_info, 0 );
73   }
74
75   return tpwin_type;
76 }
77
78 static void tpwin_sync_ll_to_tp ( VikTrwLayerTpwin *tpwin )
79 {
80   if ( tpwin->cur_tp && (!tpwin->sync_to_tp_block) )
81   {
82     struct LatLon ll;
83     VikCoord coord;
84     ll.lat = gtk_spin_button_get_value ( tpwin->lat );
85     ll.lon = gtk_spin_button_get_value ( tpwin->lon );
86     vik_coord_load_from_latlon ( &coord, tpwin->cur_tp->coord.mode, &ll );
87
88     /* don't redraw unless we really have to */
89     if ( vik_coord_diff(&(tpwin->cur_tp->coord), &coord) > 0.05 ) /* may not be exact due to rounding */
90     {
91       tpwin->cur_tp->coord = coord;
92       gtk_dialog_response ( GTK_DIALOG(tpwin), VIK_TRW_LAYER_TPWIN_DATA_CHANGED );
93     }
94   }
95 }
96
97 static void tpwin_sync_alt_to_tp ( VikTrwLayerTpwin *tpwin )
98 {
99   if ( tpwin->cur_tp && (!tpwin->sync_to_tp_block) ) {
100     // Always store internally in metres
101     vik_units_height_t height_units = a_vik_get_units_height ();
102     switch (height_units) {
103     case VIK_UNITS_HEIGHT_METRES:
104       tpwin->cur_tp->altitude = gtk_spin_button_get_value ( tpwin->alt );
105       break;
106     case VIK_UNITS_HEIGHT_FEET:
107       tpwin->cur_tp->altitude = VIK_FEET_TO_METERS(gtk_spin_button_get_value ( tpwin->alt ));
108       break;
109     default:
110       tpwin->cur_tp->altitude = gtk_spin_button_get_value ( tpwin->alt );
111       g_critical("Houston, we've had a problem. height=%d", height_units);
112     }
113   }
114 }
115
116 VikTrwLayerTpwin *vik_trw_layer_tpwin_new ( GtkWindow *parent )
117 {
118   static gchar *left_label_texts[] = { N_("<b>Part of Track:</b>"),
119                                        N_("<b>Latitude:</b>"),
120                                        N_("<b>Longitude:</b>"),
121                                        N_("<b>Altitude:</b>"),
122                                        N_("<b>Timestamp:</b>"),
123                                        N_("<b>Time:</b>") };
124   static gchar *right_label_texts[] = { N_("<b>Distance Difference:</b>"),
125                                         N_("<b>Time Difference:</b>"),
126                                         N_("<b>\"Speed\" Between:</b>"),
127                                         N_("<b>VDOP:</b>"),
128                                         N_("<b>HDOP:</b>"),
129                                         N_("<b>PDOP:</b>"),
130                                         N_("<b>SAT/FIX:</b>")
131                                         };
132
133   VikTrwLayerTpwin *tpwin = VIK_TRW_LAYER_TPWIN ( g_object_new ( VIK_TRW_LAYER_TPWIN_TYPE, NULL ) );
134   GtkWidget *main_hbox, *left_vbox, *right_vbox;
135   GtkWidget *diff_left_vbox, *diff_right_vbox;
136   
137
138   gtk_window_set_transient_for ( GTK_WINDOW(tpwin), parent );
139   gtk_window_set_title ( GTK_WINDOW(tpwin), _("Trackpoint") );
140
141   tpwin->button_close = gtk_dialog_add_button ( GTK_DIALOG(tpwin), GTK_STOCK_CLOSE, VIK_TRW_LAYER_TPWIN_CLOSE);
142   tpwin->button_insert = gtk_dialog_add_button ( GTK_DIALOG(tpwin), _("_Insert After"), VIK_TRW_LAYER_TPWIN_INSERT);
143   tpwin->button_delete = gtk_dialog_add_button ( GTK_DIALOG(tpwin), GTK_STOCK_DELETE, VIK_TRW_LAYER_TPWIN_DELETE);
144   tpwin->button_split = gtk_dialog_add_button ( GTK_DIALOG(tpwin), _("Split Here"), VIK_TRW_LAYER_TPWIN_SPLIT);
145   tpwin->button_back = gtk_dialog_add_button ( GTK_DIALOG(tpwin), GTK_STOCK_GO_BACK, VIK_TRW_LAYER_TPWIN_BACK);
146   tpwin->button_forward = gtk_dialog_add_button ( GTK_DIALOG(tpwin), GTK_STOCK_GO_FORWARD, VIK_TRW_LAYER_TPWIN_FORWARD);
147
148   /*
149   gtk_dialog_add_buttons ( GTK_DIALOG(tpwin),
150       GTK_STOCK_CLOSE, VIK_TRW_LAYER_TPWIN_CLOSE,
151       _("_Insert After"), VIK_TRW_LAYER_TPWIN_INSERT,
152       GTK_STOCK_DELETE, VIK_TRW_LAYER_TPWIN_DELETE,
153       _("Split Here"), VIK_TRW_LAYER_TPWIN_SPLIT,
154       GTK_STOCK_GO_BACK, VIK_TRW_LAYER_TPWIN_BACK,
155       GTK_STOCK_GO_FORWARD, VIK_TRW_LAYER_TPWIN_FORWARD,
156       NULL );
157   tpwin->buttons = gtk_container_get_children(GTK_CONTAINER(GTK_DIALOG(tpwin)->action_area));
158   */
159
160   /* main track info */
161   left_vbox = a_dialog_create_label_vbox ( left_label_texts, sizeof(left_label_texts) / sizeof(left_label_texts[0]) );
162
163   tpwin->track_name = GTK_LABEL(gtk_label_new(NULL));
164   tpwin->ts = GTK_LABEL(gtk_label_new(NULL));
165   tpwin->localtime = GTK_LABEL(gtk_label_new(NULL));
166
167   tpwin->lat = GTK_SPIN_BUTTON(gtk_spin_button_new( GTK_ADJUSTMENT(gtk_adjustment_new (
168                                  0, -90, 90, 0.00005, 0.01, 0 )), 0.00005, 6));
169   tpwin->lon = GTK_SPIN_BUTTON(gtk_spin_button_new( GTK_ADJUSTMENT(gtk_adjustment_new (
170                                  0, -180, 180, 0.00005, 0.01, 0 )), 0.00005, 6));
171
172   g_signal_connect_swapped ( G_OBJECT(tpwin->lat), "value-changed", G_CALLBACK(tpwin_sync_ll_to_tp), tpwin );
173   g_signal_connect_swapped ( G_OBJECT(tpwin->lon), "value-changed", G_CALLBACK(tpwin_sync_ll_to_tp), tpwin );
174
175   tpwin->alt = GTK_SPIN_BUTTON(gtk_spin_button_new( GTK_ADJUSTMENT(gtk_adjustment_new (
176                                  0, -1000, 25000, 10, 100, 0 )), 10, 2));
177
178   g_signal_connect_swapped ( G_OBJECT(tpwin->alt), "value-changed", G_CALLBACK(tpwin_sync_alt_to_tp), tpwin );
179
180   right_vbox = gtk_vbox_new ( FALSE, 3 );
181   gtk_box_pack_start ( GTK_BOX(right_vbox), GTK_WIDGET(tpwin->track_name), FALSE, FALSE, 5 );
182   gtk_box_pack_start ( GTK_BOX(right_vbox), GTK_WIDGET(tpwin->lat), FALSE, FALSE, 5 );
183   gtk_box_pack_start ( GTK_BOX(right_vbox), GTK_WIDGET(tpwin->lon), FALSE, FALSE, 5 );
184   gtk_box_pack_start ( GTK_BOX(right_vbox), GTK_WIDGET(tpwin->alt), FALSE, FALSE, 5 );
185   gtk_box_pack_start ( GTK_BOX(right_vbox), GTK_WIDGET(tpwin->ts), FALSE, FALSE, 5 );
186   gtk_box_pack_start ( GTK_BOX(right_vbox), GTK_WIDGET(tpwin->localtime), FALSE, FALSE, 5 );
187
188   /* diff info */
189   diff_left_vbox = a_dialog_create_label_vbox ( right_label_texts, sizeof(right_label_texts) / sizeof(right_label_texts[0]) );
190
191   tpwin->diff_dist = GTK_LABEL(gtk_label_new(NULL));
192   tpwin->diff_time = GTK_LABEL(gtk_label_new(NULL));
193   tpwin->diff_speed = GTK_LABEL(gtk_label_new(NULL));
194
195   tpwin->vdop = GTK_LABEL(gtk_label_new(NULL));
196   tpwin->hdop = GTK_LABEL(gtk_label_new(NULL));
197   tpwin->pdop = GTK_LABEL(gtk_label_new(NULL));
198   tpwin->sat = GTK_LABEL(gtk_label_new(NULL));
199
200   diff_right_vbox = gtk_vbox_new ( FALSE, 3 );
201   gtk_box_pack_start ( GTK_BOX(diff_right_vbox), GTK_WIDGET(tpwin->diff_dist), FALSE, FALSE, 5 );
202   gtk_box_pack_start ( GTK_BOX(diff_right_vbox), GTK_WIDGET(tpwin->diff_time), FALSE, FALSE, 5 );
203   gtk_box_pack_start ( GTK_BOX(diff_right_vbox), GTK_WIDGET(tpwin->diff_speed), FALSE, FALSE, 5 );
204
205   gtk_box_pack_start ( GTK_BOX(diff_right_vbox), GTK_WIDGET(tpwin->vdop), FALSE, FALSE, 5 );
206   gtk_box_pack_start ( GTK_BOX(diff_right_vbox), GTK_WIDGET(tpwin->hdop), FALSE, FALSE, 5 );
207   gtk_box_pack_start ( GTK_BOX(diff_right_vbox), GTK_WIDGET(tpwin->pdop), FALSE, FALSE, 5 );
208   gtk_box_pack_start ( GTK_BOX(diff_right_vbox), GTK_WIDGET(tpwin->sat), FALSE, FALSE, 5 );
209
210   main_hbox = gtk_hbox_new( FALSE, 0 );
211   gtk_box_pack_start ( GTK_BOX(main_hbox), left_vbox, TRUE, TRUE, 0 );
212   gtk_box_pack_start ( GTK_BOX(main_hbox), right_vbox, TRUE, TRUE, 0 );
213   gtk_box_pack_start ( GTK_BOX(main_hbox), diff_left_vbox, TRUE, TRUE, 0 );
214   gtk_box_pack_start ( GTK_BOX(main_hbox), diff_right_vbox, TRUE, TRUE, 0 );
215
216   gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(tpwin))), main_hbox, FALSE, FALSE, 0 );
217
218   tpwin->cur_tp = NULL;
219
220   return tpwin;
221 }
222
223 void vik_trw_layer_tpwin_set_empty ( VikTrwLayerTpwin *tpwin )
224 {
225   gtk_label_set_text ( tpwin->track_name, NULL );
226   gtk_label_set_text ( tpwin->ts, NULL );
227   gtk_label_set_text ( tpwin->localtime, NULL );
228
229   gtk_widget_set_sensitive ( GTK_WIDGET(tpwin->lat), FALSE );
230   gtk_widget_set_sensitive ( GTK_WIDGET(tpwin->lon), FALSE );
231   gtk_widget_set_sensitive ( GTK_WIDGET(tpwin->alt), FALSE );
232
233   // Only keep close button enabled
234   gtk_widget_set_sensitive ( tpwin->button_insert, FALSE );
235   gtk_widget_set_sensitive ( tpwin->button_split, FALSE );
236   gtk_widget_set_sensitive ( tpwin->button_delete, FALSE );
237   gtk_widget_set_sensitive ( tpwin->button_back, FALSE );
238   gtk_widget_set_sensitive ( tpwin->button_forward, FALSE );
239
240   gtk_label_set_text ( tpwin->diff_dist, NULL );
241   gtk_label_set_text ( tpwin->diff_time, NULL );
242   gtk_label_set_text ( tpwin->diff_speed, NULL );
243   gtk_label_set_text ( tpwin->vdop, NULL );
244   gtk_label_set_text ( tpwin->hdop, NULL );
245   gtk_label_set_text ( tpwin->pdop, NULL );
246   gtk_label_set_text ( tpwin->sat, NULL );
247 }
248
249 void vik_trw_layer_tpwin_set_tp ( VikTrwLayerTpwin *tpwin, GList *tpl, gchar *track_name )
250 {
251   static char tmp_str[64];
252   static struct LatLon ll;
253   VikTrackpoint *tp = VIK_TRACKPOINT(tpl->data);
254
255   /* Only can insert if not at the end (otherwise use extend track) */
256   gtk_widget_set_sensitive ( tpwin->button_insert, (gboolean) GPOINTER_TO_INT (tpl->next) );
257   gtk_widget_set_sensitive ( tpwin->button_delete, TRUE );
258
259   /* We can only split up a track if it's not an endpoint. Makes sense to me. */
260   gtk_widget_set_sensitive ( tpwin->button_split, tpl->next && tpl->prev );
261
262   gtk_widget_set_sensitive ( tpwin->button_forward, (gboolean) GPOINTER_TO_INT (tpl->next) );
263   gtk_widget_set_sensitive ( tpwin->button_back, (gboolean) GPOINTER_TO_INT (tpl->prev) );
264
265   gtk_widget_set_sensitive ( GTK_WIDGET(tpwin->lat), TRUE );
266   gtk_widget_set_sensitive ( GTK_WIDGET(tpwin->lon), TRUE );
267   gtk_widget_set_sensitive ( GTK_WIDGET(tpwin->alt), TRUE );
268
269   gtk_label_set_text ( tpwin->track_name, track_name );
270
271   tpwin->sync_to_tp_block = TRUE; /* don't update while setting data. */
272
273   vik_coord_to_latlon ( &(tp->coord), &ll );
274   gtk_spin_button_set_value ( tpwin->lat, ll.lat );
275   gtk_spin_button_set_value ( tpwin->lon, ll.lon );
276   vik_units_height_t height_units = a_vik_get_units_height ();
277   switch (height_units) {
278   case VIK_UNITS_HEIGHT_METRES:
279     gtk_spin_button_set_value ( tpwin->alt, tp->altitude );
280     break;
281   case VIK_UNITS_HEIGHT_FEET:
282     gtk_spin_button_set_value ( tpwin->alt, VIK_METERS_TO_FEET(tp->altitude) );
283     break;
284   default:
285     gtk_spin_button_set_value ( tpwin->alt, tp->altitude );
286     g_critical("Houston, we've had a problem. height=%d", height_units);
287   }
288
289
290   tpwin->sync_to_tp_block = FALSE; /* don't update whlie setting data. */
291
292
293   if ( tp->has_timestamp )
294   {
295     g_snprintf ( tmp_str, sizeof(tmp_str), "%ld", tp->timestamp );
296     gtk_label_set_text ( tpwin->ts, tmp_str );
297     strftime ( tmp_str, sizeof(tmp_str), "%c", localtime(&(tp->timestamp)) );
298     gtk_label_set_text ( tpwin->localtime, tmp_str );
299   }
300   else
301   {
302     gtk_label_set_text (tpwin->ts, NULL );
303     gtk_label_set_text (tpwin->localtime, NULL );
304   }
305
306   vik_units_distance_t dist_units = a_vik_get_units_distance ();
307   if ( tpwin->cur_tp )
308   {
309     switch (dist_units) {
310     case VIK_UNITS_DISTANCE_KILOMETRES:
311       g_snprintf ( tmp_str, sizeof(tmp_str), "%.2f m", vik_coord_diff(&(tp->coord), &(tpwin->cur_tp->coord)));
312       break;
313     case VIK_UNITS_DISTANCE_MILES:
314       g_snprintf ( tmp_str, sizeof(tmp_str), "%.2f yards", vik_coord_diff(&(tp->coord), &(tpwin->cur_tp->coord))*1.0936133);
315       break;
316     default:
317       g_critical("Houston, we've had a problem. distance=%d", dist_units);
318     }
319
320     gtk_label_set_text ( tpwin->diff_dist, tmp_str );
321     if ( tp->has_timestamp && tpwin->cur_tp->has_timestamp )
322     {
323       g_snprintf ( tmp_str, sizeof(tmp_str), "%ld s", tp->timestamp - tpwin->cur_tp->timestamp);
324       gtk_label_set_text ( tpwin->diff_time, tmp_str );
325       if ( tp->timestamp == tpwin->cur_tp->timestamp )
326         gtk_label_set_text ( tpwin->diff_speed, "--" );
327       else
328       {
329         vik_units_speed_t speed_units = a_vik_get_units_speed ();
330         switch (speed_units) {
331         case VIK_UNITS_SPEED_KILOMETRES_PER_HOUR:
332           g_snprintf ( tmp_str, sizeof(tmp_str), "%.2f km/h", VIK_MPS_TO_KPH(vik_coord_diff(&(tp->coord), &(tpwin->cur_tp->coord)) / (ABS(tp->timestamp - tpwin->cur_tp->timestamp))) );
333           break;
334         case VIK_UNITS_SPEED_MILES_PER_HOUR:
335           g_snprintf ( tmp_str, sizeof(tmp_str), "%.2f mph", VIK_MPS_TO_MPH(vik_coord_diff(&(tp->coord), &(tpwin->cur_tp->coord)) / (ABS(tp->timestamp - tpwin->cur_tp->timestamp))) );
336           break;
337         case VIK_UNITS_SPEED_METRES_PER_SECOND:
338           g_snprintf ( tmp_str, sizeof(tmp_str), "%.2f m/s", vik_coord_diff(&(tp->coord), &(tpwin->cur_tp->coord)) / ABS(tp->timestamp - tpwin->cur_tp->timestamp) );
339           break;
340         case VIK_UNITS_SPEED_KNOTS:
341           g_snprintf ( tmp_str, sizeof(tmp_str), "%.2f knots", VIK_MPS_TO_KNOTS(vik_coord_diff(&(tp->coord), &(tpwin->cur_tp->coord)) / (ABS(tp->timestamp - tpwin->cur_tp->timestamp))) );
342           break;
343         default:
344           g_snprintf ( tmp_str, sizeof(tmp_str), "--" );
345           g_critical("Houston, we've had a problem. speed=%d", speed_units);
346         }
347         gtk_label_set_text ( tpwin->diff_speed, tmp_str );
348       }
349     }
350     else
351     {
352       gtk_label_set_text ( tpwin->diff_time, NULL );
353       gtk_label_set_text ( tpwin->diff_speed, NULL );
354     }
355   }
356
357   switch (dist_units) {
358   case VIK_UNITS_DISTANCE_KILOMETRES:
359     g_snprintf ( tmp_str, sizeof(tmp_str), "%.5f m", tp->hdop );
360     gtk_label_set_text ( tpwin->hdop, tmp_str );
361     g_snprintf ( tmp_str, sizeof(tmp_str), "%.5f m", tp->pdop );
362     gtk_label_set_text ( tpwin->pdop, tmp_str );
363     break;
364   case VIK_UNITS_DISTANCE_MILES:
365     g_snprintf ( tmp_str, sizeof(tmp_str), "%.5f yards", tp->hdop*1.0936133 );
366     gtk_label_set_text ( tpwin->hdop, tmp_str );
367     g_snprintf ( tmp_str, sizeof(tmp_str), "%.5f yards", tp->pdop*1.0936133 );
368     gtk_label_set_text ( tpwin->pdop, tmp_str );
369     break;
370   default:
371     g_critical("Houston, we've had a problem. distance=%d", dist_units);
372   }
373
374   switch (height_units) {
375   case VIK_UNITS_HEIGHT_METRES:
376     g_snprintf ( tmp_str, sizeof(tmp_str), "%.5f m", tp->vdop );
377     break;
378   case VIK_UNITS_HEIGHT_FEET:
379     g_snprintf ( tmp_str, sizeof(tmp_str), "%.5f feet", VIK_METERS_TO_FEET(tp->vdop) );
380     break;
381   default:
382     g_snprintf ( tmp_str, sizeof(tmp_str), "--" );
383     g_critical("Houston, we've had a problem. height=%d", height_units);
384   }
385   gtk_label_set_text ( tpwin->vdop, tmp_str );
386
387   g_snprintf ( tmp_str, sizeof(tmp_str), "%d / %d", tp->nsats, tp->fix_mode );
388   gtk_label_set_text ( tpwin->sat, tmp_str );
389
390   tpwin->cur_tp = tp;
391 }
392
393 void vik_trw_layer_tpwin_set_track_name ( VikTrwLayerTpwin *tpwin, const gchar *track_name )
394 {
395   gtk_label_set_text ( tpwin->track_name, track_name );
396 }