Contents of /trunk/src/goto.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 212 - (hide annotations)
Wed Nov 25 13:52:17 2009 UTC (14 years, 5 months ago) by harbaum
File MIME type: text/plain
File size: 25316 byte(s)
Coordinate popup
1 harbaum 1 /*
2     * Copyright (C) 2008 Till Harbaum <till@harbaum.org>.
3     *
4     * This file is part of GPXView.
5     *
6     * GPXView 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 3 of the License, or
9     * (at your option) any later version.
10     *
11     * GPXView 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 GPXView. If not, see <http://www.gnu.org/licenses/>.
18     */
19    
20     #include <stdio.h>
21     #include <string.h>
22     #include <math.h>
23    
24     #include "gpxview.h"
25    
26     #ifdef USE_MAEMO
27     #include "dbus.h"
28     #endif
29    
30     #define COMPASS_SIZE 230
31     #define LETTER_SPACE 0.2
32     #define DIAMOND_WIDTH 0.05
33     #define DIAMOND_HEIGHT 0.2
34     #define ARROW_WIDTH 0.3
35     #define ARROW_LENGTH 0.7
36     #define UPDATE_MS 1000 /* gps updates are sent once a second */
37    
38     #define SAT_WIDTH 330
39     #define SAT_HEIGHT 60
40    
41     /* http://www.gtk.org/tutorial1.2/gtk_tut-30.html */
42     /* http://developer.gimp.org/api/2.0/gdk/gdk-Drawing-Primitives.html */
43    
44    
45     static float rad2deg(float rad) {
46     return fmodf(360.0 + (180.0/M_PI) * rad, 360.0);
47     }
48    
49     static void compass_draw(GtkWidget *widget, cache_context_t *context) {
50     float f;
51     int i;
52    
53     gint width = widget->allocation.width;
54     gint height = widget->allocation.height;
55     gint diameter = (height < width)?height:width;
56    
57     gint xcenter = width/2;
58     gint ycenter = height/2;
59     gint radius = diameter/2;
60    
61     /* erase background */
62     gdk_draw_rectangle(context->gotoc.compass_pixmap,
63     widget->style->bg_gc[GTK_STATE_NORMAL], TRUE,
64     0, 0, width, height);
65    
66     /* use white rosetta background unless the real background */
67     /* is very bright. Use bright grey then */
68    
69     if(widget->style->bg[GTK_STATE_NORMAL].red +
70     widget->style->bg[GTK_STATE_NORMAL].green +
71     widget->style->bg[GTK_STATE_NORMAL].blue < 3*60000) {
72     /* background is very bright, use white */
73     gdk_draw_arc(context->gotoc.compass_pixmap, widget->style->white_gc, TRUE,
74     (width-diameter)/2, (height-diameter)/2, diameter, diameter,
75     0, 360*64);
76     } else {
77     GdkGC *lgrey_gc = gdk_gc_new(context->gotoc.compass_pixmap);
78     gdk_gc_copy(lgrey_gc, widget->style->black_gc);
79     GdkColor lgrey_color;
80     gdk_color_parse("#DDDDDD", &lgrey_color);
81     gdk_gc_set_rgb_fg_color(lgrey_gc, &lgrey_color);
82    
83     gdk_draw_arc(context->gotoc.compass_pixmap, lgrey_gc, TRUE,
84     (width-diameter)/2, (height-diameter)/2, diameter, diameter,
85     0, 360*64);
86     }
87    
88     /* draw the locked/unlocked icon */
89     gdk_draw_pixbuf(context->gotoc.compass_pixmap,
90     widget->style->fg_gc[GTK_STATE_NORMAL],
91 harbaum 189 icon_get(ICON_MISC, context->appdata->compass_locked?1:2),
92 harbaum 1 0, 0, (width-diameter)/2 + diameter/32,
93     (height+diameter)/2 - 16 - diameter/32 , 16, 16,
94     GDK_RGB_DITHER_NONE,0,0);
95    
96     /* don't update heading if the compass is locked */
97     if(!context->appdata->compass_locked) {
98     int i, valid = 0, cnt=0;
99     double x_sum = 0.0, y_sum = 0.0;
100    
101     /* shift heading buffer up one entry and add new value at entry 0 */
102     for(i=MAX_AVERAGE-1;i>0;i--)
103     context->gotoc.head_avg[i] = context->gotoc.head_avg[i-1];
104     context->gotoc.head_avg[0] = gps_get_heading(context->appdata)*M_PI/180.0;
105    
106     // printf("Damping = %d\n", context->appdata->compass_damping);
107     // printf("add heading %f\n", rad2deg(context->gotoc.head_avg[0]));
108    
109     /* determine number of valid entries */
110     for(i=0;i<MAX_AVERAGE && valid<context->appdata->compass_damping;i++)
111     if(!isnan(context->gotoc.head_avg[i]))
112     valid++;
113    
114     /* map back to angle if at least one value has been added */
115     if(valid) {
116     /* map all valid antries onto a circle */
117     for(i=0;i<MAX_AVERAGE && cnt<context->appdata->compass_damping;i++) {
118     if(!isnan(context->gotoc.head_avg[i])) {
119     float weight = 1.0 - ((float)(cnt++)/(float)valid);
120     printf("weight = %f * %f\n",
121     weight, rad2deg(context->gotoc.head_avg[i]));
122     x_sum += weight * sin(context->gotoc.head_avg[i]);
123     y_sum += weight * cos(context->gotoc.head_avg[i]);
124     }
125     }
126    
127     printf("%d valid heading entries\n", valid);
128     context->gotoc.heading = atan2(x_sum, y_sum);
129     printf("averaged heading: %f\n",
130     rad2deg(context->gotoc.heading));
131     } else {
132     // printf("no valid heading, keeping old value heading\n");
133     }
134     }
135    
136     if(!isnan(context->gotoc.heading)) {
137    
138     for(i=0,f=0;f<2*M_PI-M_PI/8;f+=M_PI/4,i++) {
139     float ang = f - context->gotoc.heading;
140    
141     if(!(i&1)) {
142     /* draw diamonds */
143     GdkPoint diamond[4];
144    
145     #define OUT (1.0-LETTER_SPACE)
146    
147     diamond[0].x = xcenter + radius * OUT * sin(ang);
148     diamond[0].y = ycenter + radius * OUT * -cos(ang);
149    
150     diamond[1].x = xcenter + radius * (OUT-DIAMOND_HEIGHT/2) *
151     sin(ang+DIAMOND_WIDTH);
152     diamond[1].y = ycenter + radius * (OUT-DIAMOND_HEIGHT/2)*
153     -cos(ang+DIAMOND_WIDTH);
154    
155     diamond[2].x = xcenter + radius * (OUT-DIAMOND_HEIGHT) * sin(ang);
156     diamond[2].y = ycenter + radius * (OUT-DIAMOND_HEIGHT) * -cos(ang);
157    
158     diamond[3].x = xcenter + radius * (OUT-DIAMOND_HEIGHT/2) *
159     sin(ang-DIAMOND_WIDTH);
160     diamond[3].y = ycenter + radius * (OUT-DIAMOND_HEIGHT/2) *
161     -cos(ang-DIAMOND_WIDTH);
162    
163     gdk_draw_polygon(context->gotoc.compass_pixmap,
164     widget->style->black_gc, TRUE,
165     diamond, sizeof(diamond)/sizeof(GdkPoint));
166    
167     const char *str[] = { "N", "E", "S", "W" };
168     PangoLayout *layout = gtk_widget_create_pango_layout(widget, _(str[i/2]));
169     int tw, th;
170     pango_layout_get_pixel_size(layout, &tw, &th);
171    
172     gdk_draw_layout(context->gotoc.compass_pixmap, widget->style->black_gc,
173     xcenter + radius * (1.0-LETTER_SPACE/2)*sin(ang) - tw/2,
174     ycenter + radius * (1.0-LETTER_SPACE/2)*-cos(ang) - th/2,
175     layout);
176    
177     g_object_unref(layout);
178     } else
179     gdk_draw_line(context->gotoc.compass_pixmap, widget->style->black_gc,
180     xcenter + radius * 0.9 * sin(ang),
181     ycenter + radius * 0.9 * -cos(ang),
182     xcenter + radius * 1.0 * sin(ang),
183     ycenter + radius * 1.0 * -cos(ang));
184     }
185    
186     /* draw arrow */
187    
188     /* setup required colors */
189     GdkGC *arrow_gc = gdk_gc_new(context->gotoc.compass_pixmap);
190     gdk_gc_copy(arrow_gc, widget->style->black_gc);
191     GdkColor arrow_color;
192     gdk_color_parse("#800000", &arrow_color);
193     gdk_gc_set_rgb_fg_color(arrow_gc, &arrow_color);
194    
195     GdkPoint arrow[4];
196    
197     pos_t *pos = gps_get_pos(context->appdata);
198 harbaum 47 if(pos && !isnan(pos->lat) && !isnan(pos->lon)) {
199 harbaum 1 context->appdata->gps = *pos; /* save position */
200    
201     float arot =
202     gpx_pos_get_bearing(*pos, context->gotoc.pos) *
203     M_PI/180 - context->gotoc.heading;
204    
205     arrow[0].x = xcenter + radius * ARROW_LENGTH * sin(arot);
206     arrow[0].y = ycenter + radius * ARROW_LENGTH * -cos(arot);
207    
208     arrow[1].x = xcenter + radius * -ARROW_LENGTH * sin(arot+ARROW_WIDTH);
209     arrow[1].y = ycenter + radius * -ARROW_LENGTH * -cos(arot+ARROW_WIDTH);
210    
211     arrow[2].x = xcenter + radius * -0.5 * ARROW_LENGTH * sin(arot);
212     arrow[2].y = ycenter + radius * -0.5 * ARROW_LENGTH * -cos(arot);
213    
214     arrow[3].x = xcenter + radius * -ARROW_LENGTH * sin(arot-ARROW_WIDTH);
215     arrow[3].y = ycenter + radius * -ARROW_LENGTH * -cos(arot-ARROW_WIDTH);
216    
217     gdk_draw_polygon(context->gotoc.compass_pixmap, arrow_gc, TRUE,
218     arrow, sizeof(arrow)/sizeof(GdkPoint));
219     } else {
220     PangoLayout *layout;
221    
222     if(context->appdata->use_gps)
223     layout = gtk_widget_create_pango_layout(widget, _("No fix"));
224     else
225     layout = gtk_widget_create_pango_layout(widget, _("GPS disabled"));
226    
227     int tw, th;
228     pango_layout_get_pixel_size(layout, &tw, &th);
229    
230     gdk_draw_layout(context->gotoc.compass_pixmap, widget->style->black_gc,
231     xcenter - tw/2, ycenter - th/2, layout);
232    
233     g_object_unref(layout);
234     }
235     }
236     }
237    
238     /* Create a new backing pixmap of the appropriate size */
239     static gint compass_configure_event(GtkWidget *widget,
240     GdkEventConfigure *event, gpointer data) {
241     cache_context_t *context = (cache_context_t*)data;
242    
243     if(context->gotoc.compass_pixmap)
244     gdk_pixmap_unref(context->gotoc.compass_pixmap);
245    
246     context->gotoc.compass_pixmap = gdk_pixmap_new(widget->window,
247     widget->allocation.width,
248     widget->allocation.height,
249     -1);
250     compass_draw(widget, context);
251     // goto_update(context);
252    
253     return TRUE;
254     }
255    
256     /* Redraw the screen from the backing pixmap */
257     static gint compass_expose_event(GtkWidget *widget, GdkEventExpose *event,
258     gpointer data) {
259     cache_context_t *context = (cache_context_t*)data;
260    
261     gdk_draw_pixmap(widget->window,
262     widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
263     context->gotoc.compass_pixmap,
264     event->area.x, event->area.y,
265     event->area.x, event->area.y,
266     event->area.width, event->area.height);
267    
268     return FALSE;
269     }
270    
271     static void sat_draw(GtkWidget *widget, cache_context_t *context) {
272     gint width = widget->allocation.width;
273     gint height = widget->allocation.height;
274    
275     /* erase background */
276     gdk_draw_rectangle(context->gotoc.sat_pixmap,
277     widget->style->bg_gc[GTK_STATE_NORMAL], TRUE,
278     0, 0, width, height);
279    
280     gps_sat_t *sat = gps_get_sats(context->appdata);
281     if(sat && sat->num) {
282     /* setup required colors */
283     GdkGC *used_gc = gdk_gc_new(context->gotoc.sat_pixmap);
284     gdk_gc_copy(used_gc, widget->style->black_gc);
285     GdkColor used_color;
286     gdk_color_parse("#008000", &used_color); // green
287     gdk_gc_set_rgb_fg_color(used_gc, &used_color);
288    
289     #define SAT_SPACING 3
290     int i, x;
291     int swid = (width-SAT_SPACING*(sat->num-1))/sat->num;
292    
293     /* as of xgps, a ss of 40 and more is "plenty" */
294     int max_ss = 40;
295     for(i=0;i<sat->num;i++)
296     if(sat->ss[i] > max_ss) sat->ss[i] = max_ss;
297    
298     if(swid > 40) {
299     swid = 40;
300     x = (width-sat->num*swid)/2;
301     } else
302     x = 0;
303    
304     for(i=0;i<sat->num;i++) {
305     char str[32];
306     #ifdef USE_MAEMO
307     snprintf(str, sizeof(str), "<span size=\"small\">%d</span>", sat->PRN[i]);
308     PangoLayout *layout = gtk_widget_create_pango_layout(widget, NULL);
309     pango_layout_set_markup(layout, str, strlen(str));
310     #else
311     snprintf(str, sizeof(str), "%d", sat->PRN[i]);
312     PangoLayout *layout = gtk_widget_create_pango_layout(widget, str);
313     #endif
314    
315     int tw, th;
316     pango_layout_get_pixel_size(layout, &tw, &th);
317 harbaum 47 gdk_draw_layout(context->gotoc.sat_pixmap,
318     widget->style->text_gc[GTK_STATE_NORMAL],
319 harbaum 1 x + swid/2 - tw/2, height - th, layout);
320    
321     g_object_unref(layout);
322    
323     int h = (height-th) * sat->ss[i] / max_ss;
324    
325     gdk_draw_rectangle(context->gotoc.sat_pixmap,
326 harbaum 47 sat->used[i]?used_gc:widget->style->fg_gc[GTK_STATE_NORMAL],
327     TRUE, x, height-h-th, swid, h);
328 harbaum 1
329     x += SAT_SPACING+swid;
330     }
331    
332     /* free sat infos */
333     free(sat->PRN);
334     free(sat->ss);
335     free(sat->used);
336     } else {
337 harbaum 47 PangoLayout *layout =
338     gtk_widget_create_pango_layout(widget, _("No SAT info"));
339 harbaum 1 int tw, th;
340     pango_layout_get_pixel_size(layout, &tw, &th);
341 harbaum 47 gdk_draw_layout(context->gotoc.sat_pixmap,
342     widget->style->text_gc[GTK_STATE_NORMAL],
343 harbaum 1 (width - tw)/2, (height - th)/2, layout);
344    
345     g_object_unref(layout);
346     }
347    
348     /* free the sat structure */
349     if(sat)
350     free(sat);
351     }
352    
353     /* Create a new backing pixmap of the appropriate size */
354     static gint sat_configure_event(GtkWidget *widget, GdkEventConfigure *event,
355     gpointer data) {
356     cache_context_t *context = (cache_context_t*)data;
357    
358     if(context->gotoc.sat_pixmap)
359     gdk_pixmap_unref(context->gotoc.sat_pixmap);
360    
361     context->gotoc.sat_pixmap = gdk_pixmap_new(widget->window,
362     widget->allocation.width,
363     widget->allocation.height,
364     -1);
365     sat_draw(widget, context);
366    
367     return TRUE;
368     }
369    
370     /* Redraw the screen from the backing pixmap */
371     static gint sat_expose_event(GtkWidget *widget, GdkEventExpose *event,
372     gpointer data) {
373     cache_context_t *context = (cache_context_t*)data;
374    
375     gdk_draw_pixmap(widget->window,
376     widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
377     context->gotoc.sat_pixmap,
378     event->area.x, event->area.y,
379     event->area.x, event->area.y,
380     event->area.width, event->area.height);
381    
382     return FALSE;
383     }
384    
385     gint goto_destroy_event(GtkWidget *widget, gpointer data ) {
386     cache_context_t *context = (cache_context_t*)data;
387    
388     printf("destroying goto view\n");
389    
390     /* stop timer */
391     if(context->gotoc.handler_id)
392     gtk_timeout_remove(context->gotoc.handler_id);
393    
394     return FALSE;
395     }
396    
397     static gboolean goto_update(gpointer data) {
398     cache_context_t *context = (cache_context_t*)data;
399    
400     if(context->gotoc.sat_pixmap) {
401     static int sub = 0;
402    
403     if(!sub) {
404     /* draw sat view */
405     sat_draw(context->gotoc.sat_area, context);
406     gtk_widget_queue_draw_area(context->gotoc.sat_area, 0,0,
407     context->gotoc.sat_area->allocation.width,
408     context->gotoc.sat_area->allocation.height);
409     }
410    
411     if(sub++ == 5) sub = 0;
412     }
413    
414     if(context->gotoc.compass_pixmap) {
415     /* draw compass */
416     compass_draw(context->gotoc.compass_area, context);
417     gtk_widget_queue_draw_area(context->gotoc.compass_area, 0,0,
418     context->gotoc.compass_area->allocation.width,
419     context->gotoc.compass_area->allocation.height);
420     }
421    
422     pos_t *pos = gps_get_pos(context->appdata);
423 harbaum 47 if(pos && !isnan(pos->lat) && !isnan(pos->lon) &&
424     !isnan(context->gotoc.pos.lat) && !isnan(context->gotoc.pos.lon)) {
425 harbaum 1 char str[16];
426     gpx_pos_get_distance_str(str, sizeof(str),
427     *pos, context->gotoc.pos,
428     context->appdata->imperial);
429     gtk_label_set_text(GTK_LABEL(context->gotoc.distance_label), str);
430    
431     snprintf(str, sizeof(str), _("%.1f°"),
432     gpx_pos_get_bearing(*pos, context->gotoc.pos));
433     gtk_label_set_text(GTK_LABEL(context->gotoc.bearing_label), str);
434     } else {
435     gtk_label_set_text(GTK_LABEL(context->gotoc.distance_label), "-----");
436     gtk_label_set_text(GTK_LABEL(context->gotoc.bearing_label), "-----");
437     }
438    
439 harbaum 53 float eph = gps_get_eph(context->appdata);
440     if(isnan(eph))
441     gtk_label_set_text(GTK_LABEL(context->gotoc.eph_label), "-----");
442 harbaum 1 else {
443     char str[16];
444 harbaum 53 /* distance needs to be given in km */
445     if(context->appdata->imperial)
446     eph /= (6371.0/3959.0); // km to miles
447    
448     distance_str(str, sizeof(str), eph/1000.0, context->appdata->imperial);
449     gtk_label_set_text(GTK_LABEL(context->gotoc.eph_label), str);
450 harbaum 1 }
451    
452     return TRUE; // fire again
453     }
454    
455     static gint waypoint_changed_event(GtkWidget *widget, gpointer data ) {
456     cache_context_t *context = (cache_context_t*)data;
457     int wpt_idx = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
458    
459     /* get position of selected waypoint */
460     if(wpt_idx == 0)
461     context->gotoc.pos = context->appdata->geomath;
462     else if(wpt_idx == 1)
463     // context->gotoc.pos = gpx_cache_pos(context->cache);
464     context->gotoc.pos = notes_get_pos(context);
465     else {
466     wpt_t *wpt = context->cache->wpt;
467     while(wpt_idx > 2) {
468     g_assert(wpt != NULL);
469     wpt = wpt->next;
470     wpt_idx--;
471     }
472     context->gotoc.pos = wpt->pos;
473     }
474    
475     char str[32];
476     pos_lat_str(str, sizeof(str), context->gotoc.pos.lat);
477     gtk_label_set_text(GTK_LABEL(context->gotoc.lat_lbl), str);
478     pos_lon_str(str, sizeof(str), context->gotoc.pos.lon);
479     gtk_label_set_text(GTK_LABEL(context->gotoc.lon_lbl), str);
480    
481     goto_update(context);
482    
483     return FALSE;
484     }
485    
486     static void manual_pos_update(cache_context_t *context) {
487     context->gotoc.pos.lat = context->appdata->manual_goto.lat;
488     context->gotoc.pos.lon = context->appdata->manual_goto.lon;
489    
490     char str[32];
491     pos_lat_str(str, sizeof(str), context->gotoc.pos.lat);
492     gtk_label_set_text(GTK_LABEL(context->gotoc.lat_lbl), str);
493     pos_lon_str(str, sizeof(str), context->gotoc.pos.lon);
494     gtk_label_set_text(GTK_LABEL(context->gotoc.lon_lbl), str);
495    
496     goto_update(context);
497     }
498    
499     static void on_posedit_clicked(GtkWidget *button, gpointer data) {
500     cache_context_t *context = (cache_context_t*)data;
501    
502     GtkWidget *dialog = gtk_dialog_new_with_buttons(_("Edit Position"),
503     GTK_WINDOW(context->appdata->window), GTK_DIALOG_MODAL,
504     GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
505     GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL);
506    
507     GtkWidget *lat, *lon, *label;
508     GtkWidget *table = gtk_table_new(2, 2, FALSE);
509    
510     gtk_table_attach_defaults(GTK_TABLE(table),
511     label = gtk_label_new(_("Latitude:")), 0, 1, 0, 1);
512     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
513     gtk_table_attach_defaults(GTK_TABLE(table),
514     lat = lat_entry_new(context->appdata->manual_goto.lat),
515     1, 2, 0, 1);
516    
517     gtk_table_attach_defaults(GTK_TABLE(table),
518     label = gtk_label_new(_("Longitude:")), 0, 1, 1, 2);
519     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
520     gtk_table_attach_defaults(GTK_TABLE(table),
521     lon = lon_entry_new(context->appdata->manual_goto.lon),
522     1, 2, 1, 2);
523    
524     gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox), table);
525    
526     gtk_widget_show_all(dialog);
527    
528     if(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) {
529     if(isnan(lat_get(lat)) || isnan(lon_get(lon)))
530     errorf(_("Ignoring invalid position"));
531     else {
532     context->appdata->manual_goto.lat = lat_get(lat);
533     context->appdata->manual_goto.lon = lon_get(lon);
534    
535     manual_pos_update(context);
536     }
537     }
538     gtk_widget_destroy(dialog);
539     }
540    
541     static gint radio_changed_event(GtkWidget *widget, gpointer data ) {
542     cache_context_t *context = (cache_context_t*)data;
543    
544     if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
545     manual_pos_update(context);
546     gtk_widget_set_sensitive(context->gotoc.edit_but, TRUE);
547     } else {
548     waypoint_changed_event(context->gotoc.cbox, data);
549     gtk_widget_set_sensitive(context->gotoc.edit_but, FALSE);
550     }
551    
552     return FALSE;
553     }
554    
555 harbaum 122 #ifdef ENABLE_MAEMO_MAPPER
556 harbaum 1 static void on_mm_button_clicked(GtkButton *button, gpointer data) {
557     cache_context_t *context = (cache_context_t*)data;
558    
559     dbus_mm_set_position(context->appdata, &context->gotoc.pos);
560     }
561     #endif
562    
563     static gboolean compass_clicked_event(GtkWidget *widget, GdkEventButton *event,
564     gpointer user_data) {
565     cache_context_t *context = (cache_context_t*)user_data;
566    
567     context->appdata->compass_locked = !context->appdata->compass_locked;
568    
569     printf("compass is now %slocked\n",
570     context->appdata->compass_locked?"":"un");
571    
572     if(context->gotoc.compass_pixmap) {
573     /* draw compass */
574     compass_draw(context->gotoc.compass_area, context);
575     gtk_widget_queue_draw_area(context->gotoc.compass_area, 0,0,
576     context->gotoc.compass_area->allocation.width,
577     context->gotoc.compass_area->allocation.height);
578     }
579     return FALSE;
580     }
581    
582     GtkWidget *goto_cache(cache_context_t *context) {
583     int i;
584    
585     /* clear list used for averaging */
586     for(i=0;i<MAX_AVERAGE;i++)
587     context->gotoc.head_avg[i] = NAN;
588    
589     context->gotoc.pos = gpx_cache_pos(context->cache);
590    
591     GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
592    
593     context->gotoc.compass_area = gtk_drawing_area_new();
594     gtk_drawing_area_size(GTK_DRAWING_AREA(context->gotoc.compass_area),
595     COMPASS_SIZE, COMPASS_SIZE);
596    
597     gtk_signal_connect(GTK_OBJECT(context->gotoc.compass_area), "expose_event",
598     (GtkSignalFunc)compass_expose_event, context);
599     gtk_signal_connect(GTK_OBJECT(context->gotoc.compass_area),"configure_event",
600     (GtkSignalFunc)compass_configure_event, context);
601     gtk_signal_connect(GTK_OBJECT(context->gotoc.compass_area),
602     "button_press_event",
603     (GtkSignalFunc)compass_clicked_event, context);
604    
605     gtk_widget_set_events(context->gotoc.compass_area, GDK_EXPOSURE_MASK);
606     gtk_widget_add_events(context->gotoc.compass_area, GDK_BUTTON_PRESS_MASK);
607     gtk_box_pack_start_defaults(GTK_BOX(hbox), context->gotoc.compass_area);
608    
609     GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
610     GtkWidget *table = gtk_table_new(8, 2, FALSE);
611    
612     /* ---------- combo box containing waypoint names ------- */
613     GtkWidget *radio = gtk_radio_button_new_with_label(NULL, _("Waypoint:"));
614     gtk_table_attach_defaults(GTK_TABLE(table), radio, 0,1,0,1);
615    
616     context->gotoc.cbox = gtk_combo_box_new_text();
617     gtk_combo_box_append_text(GTK_COMBO_BOX(context->gotoc.cbox), _("Geomath"));
618     gtk_combo_box_append_text(GTK_COMBO_BOX(context->gotoc.cbox),
619     context->cache->id);
620    
621     wpt_t *wpt = context->cache->wpt;
622     while(wpt) {
623     gtk_combo_box_append_text(GTK_COMBO_BOX(context->gotoc.cbox), wpt->id);
624     wpt = wpt->next;
625     }
626     gtk_combo_box_set_active(GTK_COMBO_BOX(context->gotoc.cbox), 1);
627     gtk_signal_connect(GTK_OBJECT(context->gotoc.cbox), "changed",
628     (GtkSignalFunc)waypoint_changed_event, context);
629     gtk_table_attach_defaults(GTK_TABLE(table), context->gotoc.cbox, 1,2,0,1);
630    
631     /* -------------- manual entry field ------------------------- */
632     gtk_table_attach_defaults(GTK_TABLE(table),
633     gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radio),
634     _("Manual:")), 0,1,1,2);
635     gtk_signal_connect(GTK_OBJECT(radio), "clicked",
636     (GtkSignalFunc)radio_changed_event, context);
637    
638 harbaum 7 context->gotoc.edit_but = gtk_button_new_with_label(_("Edit"));
639 harbaum 1 gtk_table_attach_defaults(GTK_TABLE(table), context->gotoc.edit_but, 1,2,1,2);
640     gtk_signal_connect(GTK_OBJECT(context->gotoc.edit_but), "clicked",
641     (GtkSignalFunc)on_posedit_clicked, context);
642     gtk_widget_set_sensitive(context->gotoc.edit_but, FALSE);
643    
644     #if 0
645 harbaum 212 context->gotoc.man_lat = entry_new();
646 harbaum 1 gtk_table_attach_defaults(GTK_TABLE(table), context->gotoc.man_lat, 1,2,1,2);
647     pos_lat_str(str, sizeof(str), context->appdata->manual_goto.lat);
648     gtk_entry_set_text(GTK_ENTRY(context->gotoc.man_lat), str);
649     textbox_disable(context->gotoc.man_lat);
650 harbaum 212 context->gotoc.man_lon = entry_new();
651 harbaum 1 gtk_table_attach_defaults(GTK_TABLE(table), context->gotoc.man_lon, 1,2,2,3);
652     pos_lon_str(str, sizeof(str), context->appdata->manual_goto.lon);
653     gtk_entry_set_text(GTK_ENTRY(context->gotoc.man_lon), str);
654     textbox_disable(context->gotoc.man_lon);
655    
656     gtk_signal_connect(GTK_OBJECT(context->gotoc.man_lat), "changed",
657     (GtkSignalFunc)entry_changed_event, context);
658     gtk_signal_connect(GTK_OBJECT(context->gotoc.man_lon), "changed",
659     (GtkSignalFunc)entry_changed_event, context);
660     #endif
661    
662     gtk_table_set_row_spacing(GTK_TABLE(table), 2, 16);
663    
664     /* -------------- waypoint coordinates ------------------------- */
665     /* SIZE_SMALL doesn't work here as setting the label returns to normal */
666     context->gotoc.lat_lbl = pos_lat(context->gotoc.pos.lat, SIZE_NORMAL,
667     STRIKETHROUGH_NONE);
668     gtk_table_attach_defaults(GTK_TABLE(table), context->gotoc.lat_lbl,0,1,3,4);
669     context->gotoc.lon_lbl = pos_lon(context->gotoc.pos.lon, SIZE_NORMAL,
670     STRIKETHROUGH_NONE);
671     gtk_table_attach_defaults(GTK_TABLE(table), context->gotoc.lon_lbl,1,2,3,4);
672    
673     /* -------------- distance label ------------------------- */
674     gtk_table_attach_defaults(GTK_TABLE(table),
675     gtk_label_new(_("Distance:")), 0,1,4,5);
676     gtk_table_attach_defaults(GTK_TABLE(table),
677     (context->gotoc.distance_label = gtk_label_new("-----")), 1,2,4,5);
678    
679     /* -------------- bearing label ------------------------- */
680     gtk_table_attach_defaults(GTK_TABLE(table),
681     gtk_label_new(_("Bearing:")), 0,1,5,6);
682     gtk_table_attach_defaults(GTK_TABLE(table),
683     (context->gotoc.bearing_label = gtk_label_new("-----")), 1,2,5,6);
684    
685     /* -------------- error label ------------------------- */
686     gtk_table_attach_defaults(GTK_TABLE(table),
687     gtk_label_new(_("Est. error:")), 0,1,6,7);
688     gtk_table_attach_defaults(GTK_TABLE(table),
689 harbaum 53 (context->gotoc.eph_label = gtk_label_new("-----")), 1,2,6,7);
690 harbaum 1
691     gtk_table_set_row_spacing(GTK_TABLE(table), 6, 16);
692    
693     /* -------------- sat view box ------------------------- */
694     GtkWidget *ihbox = gtk_hbox_new(FALSE,0);
695    
696     context->gotoc.sat_area = gtk_drawing_area_new();
697     gtk_drawing_area_size(GTK_DRAWING_AREA(context->gotoc.sat_area),
698     SAT_WIDTH, SAT_HEIGHT);
699    
700     gtk_signal_connect(GTK_OBJECT(context->gotoc.sat_area), "expose_event",
701     (GtkSignalFunc)sat_expose_event, context);
702     gtk_signal_connect(GTK_OBJECT(context->gotoc.sat_area),"configure_event",
703     (GtkSignalFunc)sat_configure_event, context);
704    
705     gtk_widget_set_events(context->gotoc.sat_area, GDK_EXPOSURE_MASK);
706    
707     gtk_box_pack_start(GTK_BOX(ihbox), context->gotoc.sat_area, 1,0,0);
708    
709 harbaum 122 #ifdef ENABLE_MAEMO_MAPPER
710 harbaum 1 GtkWidget *mm_button = gtk_button_new();
711     gtk_button_set_image(GTK_BUTTON(mm_button), icon_get_widget(ICON_MISC, 0));
712     gtk_signal_connect(GTK_OBJECT(mm_button), "clicked",
713     (GtkSignalFunc)on_mm_button_clicked, context);
714     gtk_box_pack_start(GTK_BOX(ihbox), mm_button, 1,0,0);
715     #endif
716     gtk_table_attach_defaults(GTK_TABLE(table), ihbox, 0,2,7,8);
717    
718     /* ------------------------------------------------------- */
719    
720     gtk_box_pack_start(GTK_BOX(vbox), table, 1,0,0);
721     gtk_box_pack_start(GTK_BOX(hbox), vbox, 1,0,0);
722    
723     context->gotoc.handler_id = gtk_timeout_add(UPDATE_MS,
724     goto_update, context);
725    
726     return hbox;
727     }
728    
729     void goto_coordinate_update(cache_context_t *context) {
730     if(!context->notes.modified)
731     return;
732    
733     waypoint_changed_event(context->gotoc.cbox, context);
734     }