Contents of /trunk/src/goto.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 233 - (show annotations)
Wed Dec 9 19:45:36 2009 UTC (14 years, 4 months ago) by harbaum
File MIME type: text/plain
File size: 20167 byte(s)
File selection fremantleized
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 static float rad2deg(float rad) {
42 return fmodf(360.0 + (180.0/M_PI) * rad, 360.0);
43 }
44
45 static void compass_draw(GtkWidget *widget, cache_context_t *context) {
46 float f;
47 int i;
48
49 gint width = widget->allocation.width;
50 gint height = widget->allocation.height;
51 gint diameter = (height < width)?height:width;
52
53 gint xcenter = width/2;
54 gint ycenter = height/2;
55 gint radius = diameter/2;
56
57 /* erase background */
58 gdk_draw_rectangle(context->gotoc.compass_pixmap,
59 widget->style->bg_gc[GTK_STATE_NORMAL], TRUE,
60 0, 0, width, height);
61
62 /* use white rosetta background unless the real background */
63 /* is very bright. Use bright grey then */
64
65 if(widget->style->bg[GTK_STATE_NORMAL].red +
66 widget->style->bg[GTK_STATE_NORMAL].green +
67 widget->style->bg[GTK_STATE_NORMAL].blue < 3*60000) {
68 /* background is very bright, use white */
69 gdk_draw_arc(context->gotoc.compass_pixmap, widget->style->white_gc, TRUE,
70 (width-diameter)/2, (height-diameter)/2, diameter, diameter,
71 0, 360*64);
72 } else {
73 GdkGC *lgrey_gc = gdk_gc_new(context->gotoc.compass_pixmap);
74 gdk_gc_copy(lgrey_gc, widget->style->black_gc);
75 GdkColor lgrey_color;
76 gdk_color_parse("#DDDDDD", &lgrey_color);
77 gdk_gc_set_rgb_fg_color(lgrey_gc, &lgrey_color);
78
79 gdk_draw_arc(context->gotoc.compass_pixmap, lgrey_gc, TRUE,
80 (width-diameter)/2, (height-diameter)/2, diameter, diameter,
81 0, 360*64);
82 }
83
84 /* draw the locked/unlocked icon */
85 gdk_draw_pixbuf(context->gotoc.compass_pixmap,
86 widget->style->fg_gc[GTK_STATE_NORMAL],
87 icon_get(ICON_MISC, context->appdata->compass_locked?0:1),
88 0, 0, (width-diameter)/2 + diameter/32,
89 (height+diameter)/2 - 16 - diameter/32 , 16, 16,
90 GDK_RGB_DITHER_NONE,0,0);
91
92 /* don't update heading if the compass is locked */
93 if(!context->appdata->compass_locked) {
94 int i, valid = 0, cnt=0;
95 double x_sum = 0.0, y_sum = 0.0;
96
97 /* shift heading buffer up one entry and add new value at entry 0 */
98 for(i=MAX_AVERAGE-1;i>0;i--)
99 context->gotoc.head_avg[i] = context->gotoc.head_avg[i-1];
100 context->gotoc.head_avg[0] = gps_get_heading(context->appdata)*M_PI/180.0;
101
102 // printf("Damping = %d\n", context->appdata->compass_damping);
103 // printf("add heading %f\n", rad2deg(context->gotoc.head_avg[0]));
104
105 /* determine number of valid entries */
106 for(i=0;i<MAX_AVERAGE && valid<context->appdata->compass_damping;i++)
107 if(!isnan(context->gotoc.head_avg[i]))
108 valid++;
109
110 /* map back to angle if at least one value has been added */
111 if(valid) {
112 /* map all valid antries onto a circle */
113 for(i=0;i<MAX_AVERAGE && cnt<context->appdata->compass_damping;i++) {
114 if(!isnan(context->gotoc.head_avg[i])) {
115 float weight = 1.0 - ((float)(cnt++)/(float)valid);
116 printf("weight = %f * %f\n",
117 weight, rad2deg(context->gotoc.head_avg[i]));
118 x_sum += weight * sin(context->gotoc.head_avg[i]);
119 y_sum += weight * cos(context->gotoc.head_avg[i]);
120 }
121 }
122
123 printf("%d valid heading entries\n", valid);
124 context->gotoc.heading = atan2(x_sum, y_sum);
125 printf("averaged heading: %f\n",
126 rad2deg(context->gotoc.heading));
127 } else {
128 // printf("no valid heading, keeping old value heading\n");
129 }
130 }
131
132 if(!isnan(context->gotoc.heading)) {
133
134 for(i=0,f=0;f<2*M_PI-M_PI/8;f+=M_PI/4,i++) {
135 float ang = f - context->gotoc.heading;
136
137 if(!(i&1)) {
138 /* draw diamonds */
139 GdkPoint diamond[4];
140
141 #define OUT (1.0-LETTER_SPACE)
142
143 diamond[0].x = xcenter + radius * OUT * sin(ang);
144 diamond[0].y = ycenter + radius * OUT * -cos(ang);
145
146 diamond[1].x = xcenter + radius * (OUT-DIAMOND_HEIGHT/2) *
147 sin(ang+DIAMOND_WIDTH);
148 diamond[1].y = ycenter + radius * (OUT-DIAMOND_HEIGHT/2)*
149 -cos(ang+DIAMOND_WIDTH);
150
151 diamond[2].x = xcenter + radius * (OUT-DIAMOND_HEIGHT) * sin(ang);
152 diamond[2].y = ycenter + radius * (OUT-DIAMOND_HEIGHT) * -cos(ang);
153
154 diamond[3].x = xcenter + radius * (OUT-DIAMOND_HEIGHT/2) *
155 sin(ang-DIAMOND_WIDTH);
156 diamond[3].y = ycenter + radius * (OUT-DIAMOND_HEIGHT/2) *
157 -cos(ang-DIAMOND_WIDTH);
158
159 gdk_draw_polygon(context->gotoc.compass_pixmap,
160 widget->style->black_gc, TRUE,
161 diamond, sizeof(diamond)/sizeof(GdkPoint));
162
163 const char *str[] = { "N", "E", "S", "W" };
164 PangoLayout *layout = gtk_widget_create_pango_layout(widget, _(str[i/2]));
165 int tw, th;
166 pango_layout_get_pixel_size(layout, &tw, &th);
167
168 gdk_draw_layout(context->gotoc.compass_pixmap, widget->style->black_gc,
169 xcenter + radius * (1.0-LETTER_SPACE/2)*sin(ang) - tw/2,
170 ycenter + radius * (1.0-LETTER_SPACE/2)*-cos(ang) - th/2,
171 layout);
172
173 g_object_unref(layout);
174 } else
175 gdk_draw_line(context->gotoc.compass_pixmap, widget->style->black_gc,
176 xcenter + radius * 0.9 * sin(ang),
177 ycenter + radius * 0.9 * -cos(ang),
178 xcenter + radius * 1.0 * sin(ang),
179 ycenter + radius * 1.0 * -cos(ang));
180 }
181
182 /* draw arrow */
183
184 /* setup required colors */
185 GdkGC *arrow_gc = gdk_gc_new(context->gotoc.compass_pixmap);
186 gdk_gc_copy(arrow_gc, widget->style->black_gc);
187 GdkColor arrow_color;
188 gdk_color_parse("#800000", &arrow_color);
189 gdk_gc_set_rgb_fg_color(arrow_gc, &arrow_color);
190
191 GdkPoint arrow[4];
192
193 pos_t *pos = gps_get_pos(context->appdata);
194 if(pos && !isnan(pos->lat) && !isnan(pos->lon)) {
195 context->appdata->gps = *pos; /* save position */
196
197 float arot =
198 gpx_pos_get_bearing(*pos, context->gotoc.pos) *
199 M_PI/180 - context->gotoc.heading;
200
201 arrow[0].x = xcenter + radius * ARROW_LENGTH * sin(arot);
202 arrow[0].y = ycenter + radius * ARROW_LENGTH * -cos(arot);
203
204 arrow[1].x = xcenter + radius * -ARROW_LENGTH * sin(arot+ARROW_WIDTH);
205 arrow[1].y = ycenter + radius * -ARROW_LENGTH * -cos(arot+ARROW_WIDTH);
206
207 arrow[2].x = xcenter + radius * -0.5 * ARROW_LENGTH * sin(arot);
208 arrow[2].y = ycenter + radius * -0.5 * ARROW_LENGTH * -cos(arot);
209
210 arrow[3].x = xcenter + radius * -ARROW_LENGTH * sin(arot-ARROW_WIDTH);
211 arrow[3].y = ycenter + radius * -ARROW_LENGTH * -cos(arot-ARROW_WIDTH);
212
213 gdk_draw_polygon(context->gotoc.compass_pixmap, arrow_gc, TRUE,
214 arrow, sizeof(arrow)/sizeof(GdkPoint));
215 } else {
216 PangoLayout *layout;
217
218 if(context->appdata->use_gps)
219 layout = gtk_widget_create_pango_layout(widget, _("No fix"));
220 else
221 layout = gtk_widget_create_pango_layout(widget, _("GPS disabled"));
222
223 int tw, th;
224 pango_layout_get_pixel_size(layout, &tw, &th);
225
226 gdk_draw_layout(context->gotoc.compass_pixmap, widget->style->black_gc,
227 xcenter - tw/2, ycenter - th/2, layout);
228
229 g_object_unref(layout);
230 }
231 }
232 }
233
234 /* Create a new backing pixmap of the appropriate size */
235 static gint compass_configure_event(GtkWidget *widget,
236 GdkEventConfigure *event, gpointer data) {
237 cache_context_t *context = (cache_context_t*)data;
238
239 if(context->gotoc.compass_pixmap)
240 gdk_pixmap_unref(context->gotoc.compass_pixmap);
241
242 context->gotoc.compass_pixmap = gdk_pixmap_new(widget->window,
243 widget->allocation.width,
244 widget->allocation.height,
245 -1);
246 compass_draw(widget, context);
247 // goto_update(context);
248
249 return TRUE;
250 }
251
252 /* Redraw the screen from the backing pixmap */
253 static gint compass_expose_event(GtkWidget *widget, GdkEventExpose *event,
254 gpointer data) {
255 cache_context_t *context = (cache_context_t*)data;
256
257 gdk_draw_pixmap(widget->window,
258 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
259 context->gotoc.compass_pixmap,
260 event->area.x, event->area.y,
261 event->area.x, event->area.y,
262 event->area.width, event->area.height);
263
264 return FALSE;
265 }
266
267 static void sat_draw(GtkWidget *widget, cache_context_t *context) {
268 gint width = widget->allocation.width;
269 gint height = widget->allocation.height;
270
271 /* erase background */
272 gdk_draw_rectangle(context->gotoc.sat_pixmap,
273 widget->style->bg_gc[GTK_STATE_NORMAL], TRUE,
274 0, 0, width, height);
275
276 gps_sat_t *sat = gps_get_sats(context->appdata);
277 if(sat && sat->num) {
278 /* setup required colors */
279 GdkGC *used_gc = gdk_gc_new(context->gotoc.sat_pixmap);
280 gdk_gc_copy(used_gc, widget->style->black_gc);
281 GdkColor used_color;
282 gdk_color_parse("#008000", &used_color); // green
283 gdk_gc_set_rgb_fg_color(used_gc, &used_color);
284
285 #define SAT_SPACING 3
286 int i, x;
287 int swid = (width-SAT_SPACING*(sat->num-1))/sat->num;
288
289 /* as of xgps, a ss of 40 and more is "plenty" */
290 int max_ss = 40;
291 for(i=0;i<sat->num;i++)
292 if(sat->ss[i] > max_ss) sat->ss[i] = max_ss;
293
294 if(swid > 40) {
295 swid = 40;
296 x = (width-sat->num*swid)/2;
297 } else
298 x = 0;
299
300 for(i=0;i<sat->num;i++) {
301 char str[32];
302 #ifdef USE_MAEMO
303 snprintf(str, sizeof(str), "<span size=\"small\">%d</span>", sat->PRN[i]);
304 PangoLayout *layout = gtk_widget_create_pango_layout(widget, NULL);
305 pango_layout_set_markup(layout, str, strlen(str));
306 #else
307 snprintf(str, sizeof(str), "%d", sat->PRN[i]);
308 PangoLayout *layout = gtk_widget_create_pango_layout(widget, str);
309 #endif
310
311 int tw, th;
312 pango_layout_get_pixel_size(layout, &tw, &th);
313 gdk_draw_layout(context->gotoc.sat_pixmap,
314 widget->style->text_gc[GTK_STATE_NORMAL],
315 x + swid/2 - tw/2, height - th, layout);
316
317 g_object_unref(layout);
318
319 int h = (height-th) * sat->ss[i] / max_ss;
320
321 gdk_draw_rectangle(context->gotoc.sat_pixmap,
322 sat->used[i]?used_gc:widget->style->fg_gc[GTK_STATE_NORMAL],
323 TRUE, x, height-h-th, swid, h);
324
325 x += SAT_SPACING+swid;
326 }
327
328 /* free sat infos */
329 free(sat->PRN);
330 free(sat->ss);
331 free(sat->used);
332 } else {
333 PangoLayout *layout =
334 gtk_widget_create_pango_layout(widget, _("No SAT info"));
335 int tw, th;
336 pango_layout_get_pixel_size(layout, &tw, &th);
337 gdk_draw_layout(context->gotoc.sat_pixmap,
338 widget->style->text_gc[GTK_STATE_NORMAL],
339 (width - tw)/2, (height - th)/2, layout);
340
341 g_object_unref(layout);
342 }
343
344 /* free the sat structure */
345 if(sat)
346 free(sat);
347 }
348
349 /* Create a new backing pixmap of the appropriate size */
350 static gint sat_configure_event(GtkWidget *widget, GdkEventConfigure *event,
351 gpointer data) {
352 cache_context_t *context = (cache_context_t*)data;
353
354 if(context->gotoc.sat_pixmap)
355 gdk_pixmap_unref(context->gotoc.sat_pixmap);
356
357 context->gotoc.sat_pixmap = gdk_pixmap_new(widget->window,
358 widget->allocation.width,
359 widget->allocation.height,
360 -1);
361 sat_draw(widget, context);
362
363 return TRUE;
364 }
365
366 /* Redraw the screen from the backing pixmap */
367 static gint sat_expose_event(GtkWidget *widget, GdkEventExpose *event,
368 gpointer data) {
369 cache_context_t *context = (cache_context_t*)data;
370
371 gdk_draw_pixmap(widget->window,
372 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
373 context->gotoc.sat_pixmap,
374 event->area.x, event->area.y,
375 event->area.x, event->area.y,
376 event->area.width, event->area.height);
377
378 return FALSE;
379 }
380
381 gint goto_destroy_event(GtkWidget *widget, gpointer data ) {
382 cache_context_t *context = (cache_context_t*)data;
383
384 printf("destroying goto view\n");
385
386 /* stop timer */
387 if(context->gotoc.handler_id)
388 gtk_timeout_remove(context->gotoc.handler_id);
389
390 return FALSE;
391 }
392
393 static gboolean goto_update(gpointer data) {
394 cache_context_t *context = (cache_context_t*)data;
395
396 if(context->gotoc.sat_pixmap) {
397 static int sub = 0;
398
399 if(!sub) {
400 /* draw sat view */
401 sat_draw(context->gotoc.sat_area, context);
402 gtk_widget_queue_draw_area(context->gotoc.sat_area, 0,0,
403 context->gotoc.sat_area->allocation.width,
404 context->gotoc.sat_area->allocation.height);
405 }
406
407 if(sub++ == 5) sub = 0;
408 }
409
410 if(context->gotoc.compass_pixmap) {
411 /* draw compass */
412 compass_draw(context->gotoc.compass_area, context);
413 gtk_widget_queue_draw_area(context->gotoc.compass_area, 0,0,
414 context->gotoc.compass_area->allocation.width,
415 context->gotoc.compass_area->allocation.height);
416 }
417
418 pos_t *pos = gps_get_pos(context->appdata);
419 if(pos && !isnan(pos->lat) && !isnan(pos->lon) &&
420 !isnan(context->gotoc.pos.lat) && !isnan(context->gotoc.pos.lon)) {
421 char str[16];
422 gpx_pos_get_distance_str(str, sizeof(str),
423 *pos, context->gotoc.pos,
424 context->appdata->imperial);
425 gtk_label_set_text(GTK_LABEL(context->gotoc.distance_label), str);
426
427 snprintf(str, sizeof(str), _("%.1f°"),
428 gpx_pos_get_bearing(*pos, context->gotoc.pos));
429 gtk_label_set_text(GTK_LABEL(context->gotoc.bearing_label), str);
430 } else {
431 gtk_label_set_text(GTK_LABEL(context->gotoc.distance_label), "-----");
432 gtk_label_set_text(GTK_LABEL(context->gotoc.bearing_label), "-----");
433 }
434
435 float eph = gps_get_eph(context->appdata);
436 if(isnan(eph))
437 gtk_label_set_text(GTK_LABEL(context->gotoc.eph_label), "-----");
438 else {
439 char str[16];
440 /* distance needs to be given in km */
441 if(context->appdata->imperial)
442 eph /= (6371.0/3959.0); // km to miles
443
444 distance_str(str, sizeof(str), eph/1000.0, context->appdata->imperial);
445 gtk_label_set_text(GTK_LABEL(context->gotoc.eph_label), str);
446 }
447
448 return TRUE; // fire again
449 }
450
451 static gboolean compass_clicked_event(GtkWidget *widget, GdkEventButton *event,
452 gpointer user_data) {
453 cache_context_t *context = (cache_context_t*)user_data;
454
455 context->appdata->compass_locked = !context->appdata->compass_locked;
456
457 printf("compass is now %slocked\n",
458 context->appdata->compass_locked?"":"un");
459
460 if(context->gotoc.compass_pixmap) {
461 /* draw compass */
462 compass_draw(context->gotoc.compass_area, context);
463 gtk_widget_queue_draw_area(context->gotoc.compass_area, 0,0,
464 context->gotoc.compass_area->allocation.width,
465 context->gotoc.compass_area->allocation.height);
466 }
467 return FALSE;
468 }
469
470 static void pos_modified(GtkWidget *widget, gpointer data ) {
471 cache_context_t *context = (cache_context_t*)data;
472
473 /* extract position from entries */
474 context->gotoc.pos.lat = lat_entry_get(context->gotoc.lat_entry);
475 context->gotoc.pos.lon = lon_entry_get(context->gotoc.lon_entry);
476
477 goto_update(context);
478 }
479
480 GtkWidget *goto_cache(cache_context_t *context) {
481 int i;
482
483 /* clear list used for averaging */
484 for(i=0;i<MAX_AVERAGE;i++)
485 context->gotoc.head_avg[i] = NAN;
486
487 context->gotoc.pos = gpx_cache_pos(context->cache);
488
489 GtkWidget *hbox = gtk_hbox_new(FALSE, 32);
490
491 context->gotoc.compass_area = gtk_drawing_area_new();
492 gtk_drawing_area_size(GTK_DRAWING_AREA(context->gotoc.compass_area),
493 COMPASS_SIZE, COMPASS_SIZE);
494
495 gtk_signal_connect(GTK_OBJECT(context->gotoc.compass_area), "expose_event",
496 (GtkSignalFunc)compass_expose_event, context);
497 gtk_signal_connect(GTK_OBJECT(context->gotoc.compass_area),"configure_event",
498 (GtkSignalFunc)compass_configure_event, context);
499 gtk_signal_connect(GTK_OBJECT(context->gotoc.compass_area),
500 "button_press_event",
501 (GtkSignalFunc)compass_clicked_event, context);
502
503 gtk_widget_set_events(context->gotoc.compass_area, GDK_EXPOSURE_MASK);
504 gtk_widget_add_events(context->gotoc.compass_area, GDK_BUTTON_PRESS_MASK);
505 gtk_box_pack_start_defaults(GTK_BOX(hbox), context->gotoc.compass_area);
506
507 GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
508 GtkWidget *table = gtk_table_new(5, 3, FALSE);
509
510 /* ---------- destination coordinates ------- */
511
512 /* SIZE_SMALL doesn't work here as setting the label returns to normal */
513 gtk_table_attach_defaults(GTK_TABLE(table), left_label_new(_("Latitude:")), 0,1,0,1);
514 context->gotoc.lat_entry = lat_entry_new(context->gotoc.pos.lat);
515 gtk_table_attach_defaults(GTK_TABLE(table), context->gotoc.lat_entry, 1,2,0,1);
516 gtk_table_attach_defaults(GTK_TABLE(table), left_label_new(_("Longitude:")), 0,1,1,2);
517 context->gotoc.lon_entry = lon_entry_new(context->gotoc.pos.lon);
518 gtk_table_attach_defaults(GTK_TABLE(table), context->gotoc.lon_entry, 1,2,1,2);
519
520 g_signal_connect(G_OBJECT(context->gotoc.lat_entry), "changed",
521 G_CALLBACK(pos_modified), context);
522 g_signal_connect(G_OBJECT(context->gotoc.lon_entry), "changed",
523 G_CALLBACK(pos_modified), context);
524
525 gtk_table_attach_defaults(GTK_TABLE(table), preset_coordinate_picker(context->appdata,
526 context->gotoc.lat_entry, context->gotoc.lon_entry), 2,3,0,1);
527
528 gtk_table_attach_defaults(GTK_TABLE(table), goto_coordinate(context->appdata,
529 context->gotoc.lat_entry, context->gotoc.lon_entry), 2,3,1,2);
530
531 gtk_table_set_row_spacing(GTK_TABLE(table), 1, 16);
532 gtk_table_set_col_spacing(GTK_TABLE(table), 0, 16);
533
534 /* -------------- distance label ------------------------- */
535 gtk_table_attach_defaults(GTK_TABLE(table), left_label_new(_("Distance:")), 0,1,2,3);
536 gtk_table_attach_defaults(GTK_TABLE(table),
537 (context->gotoc.distance_label = gtk_label_new("-----")), 1,2,2,3);
538
539 /* -------------- bearing label ------------------------- */
540 gtk_table_attach_defaults(GTK_TABLE(table), left_label_new(_("Bearing:")), 0,1,3,4);
541 gtk_table_attach_defaults(GTK_TABLE(table),
542 (context->gotoc.bearing_label = gtk_label_new("-----")), 1,2,3,4);
543
544 /* -------------- error label ------------------------- */
545 gtk_table_attach_defaults(GTK_TABLE(table), left_label_new(_("Est. error:")), 0,1,4,5);
546 gtk_table_attach_defaults(GTK_TABLE(table),
547 (context->gotoc.eph_label = gtk_label_new("-----")), 1,2,4,5);
548
549 gtk_table_set_row_spacing(GTK_TABLE(table), 4, 16);
550
551 /* -------------- sat view box ------------------------- */
552 GtkWidget *ihbox = gtk_hbox_new(FALSE,0);
553
554 context->gotoc.sat_area = gtk_drawing_area_new();
555 gtk_drawing_area_size(GTK_DRAWING_AREA(context->gotoc.sat_area),
556 SAT_WIDTH, SAT_HEIGHT);
557
558 gtk_signal_connect(GTK_OBJECT(context->gotoc.sat_area), "expose_event",
559 (GtkSignalFunc)sat_expose_event, context);
560 gtk_signal_connect(GTK_OBJECT(context->gotoc.sat_area),"configure_event",
561 (GtkSignalFunc)sat_configure_event, context);
562
563 gtk_widget_set_events(context->gotoc.sat_area, GDK_EXPOSURE_MASK);
564
565 gtk_box_pack_start(GTK_BOX(ihbox), context->gotoc.sat_area, 1,0,0);
566
567 gtk_table_attach_defaults(GTK_TABLE(table), ihbox, 0,3,5,6);
568
569 /* ------------------------------------------------------- */
570
571 gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, FALSE, 0);
572 gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
573
574 context->gotoc.handler_id =
575 gtk_timeout_add(UPDATE_MS, goto_update, context);
576
577 return hbox;
578 }
579
580 void goto_coordinate_update(cache_context_t *context) {
581 static pos_t pos = { 0.0, 0.0 };
582
583 if(!context->notes.modified)
584 return;
585
586 pos_t npos = notes_get_pos(context);
587 if(pos_differ(&npos, &pos)) {
588 pos = npos;
589
590 lat_entry_set(context->gotoc.lat_entry, npos.lat);
591 lon_entry_set(context->gotoc.lon_entry, npos.lon);
592 }
593 }