2 * Copyright (C) 2006, 2007 John Costigan.
4 * POI and GPS-Info code originally written by Cezary Jackiewicz.
6 * Default map data provided by http://www.openstreetmap.org/
8 * This file is part of Maemo Mapper.
10 * Maemo Mapper is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
15 * Maemo Mapper is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with Maemo Mapper. If not, see <http://www.gnu.org/licenses/>.
34 #include "aprs_decode.h"
38 # include <hildon/hildon-help.h>
39 # include <hildon/hildon-note.h>
40 # include <hildon/hildon-file-chooser-dialog.h>
41 # include <hildon/hildon-banner.h>
42 # include <hildon/hildon-sound.h>
44 # include <osso-helplib.h>
45 # include <hildon-widgets/hildon-note.h>
46 # include <hildon-widgets/hildon-file-chooser-dialog.h>
47 # include <hildon-widgets/hildon-banner.h>
48 # include <hildon-widgets/hildon-system-sound.h>
57 #include "gdk-pixbuf-rotate.h"
65 #define VELVEC_SIZE_FACTOR (4)
67 static GtkWidget *_sat_details_panel = NULL;
68 static GtkWidget *_sdi_lat = NULL;
69 static GtkWidget *_sdi_lon = NULL;
70 static GtkWidget *_sdi_spd = NULL;
71 static GtkWidget *_sdi_alt = NULL;
72 static GtkWidget *_sdi_hea = NULL;
73 static GtkWidget *_sdi_tim = NULL;
74 static GtkWidget *_sdi_vie = NULL;
75 static GtkWidget *_sdi_use = NULL;
76 static GtkWidget *_sdi_fix = NULL;
77 static GtkWidget *_sdi_fqu = NULL;
78 static GtkWidget *_sdi_msp = NULL;
79 static gint _redraw_count = 0;
81 static gint _mark_bufx1 = -1;
82 static gint _mark_bufx2 = -1;
83 static gint _mark_bufy1 = -1;
84 static gint _mark_bufy2 = -1;
85 static gint _mark_minx = -1;
86 static gint _mark_miny = -1;
87 static gint _mark_width = -1;
88 static gint _mark_height = -1;
89 static GdkRectangle _scale_rect = { 0, 0, 0, 0};
90 static GdkRectangle _zoom_rect = { 0, 0, 0, 0};
91 static gint _dl_errors = 0;
93 static volatile gint _pending_replaces = 0;
96 GdkRectangle _comprose_rect = { 0, 0, 0, 0};
97 PangoLayout *_scale_layout = NULL;
98 PangoLayout *_zoom_layout = NULL;
99 PangoLayout *_comprose_layout = NULL;
100 GdkGC *_speed_limit_gc1 = NULL;
101 GdkGC *_speed_limit_gc2 = NULL;
102 PangoLayout *_speed_limit_layout = NULL;
103 PangoLayout *_sat_panel_layout = NULL;
104 PangoLayout *_heading_panel_layout = NULL;
105 PangoFontDescription *_heading_panel_fontdesc = NULL;
106 GdkGC *_sat_info_gc1 = NULL;
107 GdkGC *_sat_info_gc2 = NULL;
108 PangoLayout *_sat_info_layout = NULL;
109 PangoLayout *_sat_details_layout = NULL;
110 PangoLayout *_sat_details_expose_layout = NULL;
113 PangoLayout *_aprs_label_layout = NULL;
114 #endif // INCLUDE_APRS
116 #define SCALE_WIDTH (100)
121 printf("%s()\n", __PRETTY_FUNCTION__);
125 hildon_play_system_sound(
126 "/usr/share/sounds/ui-information_note.wav");
128 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
133 //// START OF APRS CODE
134 gint add_aprs_label(gchar *label, gint label_len, gint x, gint y)
138 pango_layout_set_text(_aprs_label_layout, label, label_len);
140 pango_layout_get_pixel_size(_aprs_label_layout, &width, &height);
142 /* Draw the layout itself. */
143 gdk_draw_layout( _map_pixmap,
144 _gc[COLORABLE_APRS_STATION],
146 y - (gint)((gfloat)height/2.0f),
152 gboolean extract_aprs_symbol(const gchar symbol, const char primary, GdkPixbuf **pixbuf,
157 // GdkPixbuf *pixbuf = NULL;
158 GError *error = NULL;
162 const gint startSymbol = ' ';
163 const gint symbols_per_column = 16;
164 const gint symbols_per_row = 6;
165 /*const gint*/ *symbol_size = 96/symbols_per_row;
167 gint symbol_number = (gint)symbol - startSymbol;
169 if(symbol_number<0 || symbol_number > symbols_per_row * symbols_per_column) symbol_number = 0;
171 if(primary == '/') snprintf(filename, sizeof(filename), "/usr/share/icons/hicolor/scalable/hildon/allicons.png");
172 else snprintf(filename, sizeof(filename), "/usr/share/icons/hicolor/scalable/hildon/allicon2.png");
174 *symbol_column = (gint)(symbol_number/symbols_per_column);
175 *symbol_row = symbol_number - ((*symbol_column)*symbols_per_column);
178 *pixbuf = gdk_pixbuf_new_from_file(filename, &error);
186 if( (*symbol_size)*(*symbol_column) < 0 || (*symbol_size)*(*symbol_row) < 0 )
194 gboolean draw_aprs_symbol(const gchar symbol, const gchar primary, const gint poix, const gint poiy, gint* imageSize)
196 GdkPixbuf *pixbuf = NULL;
198 gint symbol_column = 0;
200 gint symbol_size = 0;
202 if(!extract_aprs_symbol(symbol, primary, &pixbuf,
209 /* We found an icon to draw. */
214 symbol_size*symbol_column, symbol_size*symbol_row,
215 poix - symbol_size / 2,
216 poiy - symbol_size / 2,
217 symbol_size, symbol_size,
218 GDK_RGB_DITHER_NONE, 0, 0);
219 g_object_unref(pixbuf);
221 *imageSize = symbol_size;
228 void plot_aprs_station(AprsDataRow *p_station, gboolean single )
230 if(_poi_zoom <= _zoom) return ;
238 // TODO - if this station has been ploted before, then redraw the map at that position
240 if(p_station->newest_trackpoint != NULL)
242 AprsTrackRow *pPreviousPoint = p_station->newest_trackpoint;
244 lat1 = convert_lat_l2d(pPreviousPoint->trail_lat_pos);
245 lon1 = convert_lon_l2d(pPreviousPoint->trail_long_pos);
247 latlon2unit(lat1, lon1, unitx, unity);
248 unit2buf(unitx, unity, poix, poiy);
249 fprintf(stderr, "Removing old pos.\n");
256 if(poix+100 > _view_width_pixels) poix = _view_width_pixels;
257 if(poiy+50 > _view_height_pixels) poiy = _view_height_pixels;
261 _map_widget->style->fg_gc[GTK_STATE_ACTIVE],
266 GDK_RGB_DITHER_NONE, 0, 0);
268 // TODO - this will only redraw the background, not any POI´s or other items
271 lat1 = convert_lat_l2d(p_station->coord_lat);
272 lon1 = convert_lon_l2d(p_station->coord_lon);
274 latlon2unit(lat1, lon1, unitx, unity);
275 unit2buf(unitx, unity, poix, poiy);
277 // Ignore this station if it's position is not on the screen
278 if(poix < 0 || poix > _view_width_pixels
279 || poiy < 0 || poiy > _view_height_pixels)
282 gchar label[MAX_CALLSIGN+1];
283 snprintf(label, sizeof(label), "%s", p_station->call_sign);
285 if(!draw_aprs_symbol(p_station->aprs_symbol.aprs_symbol, p_station->aprs_symbol.aprs_type, poix, poiy, &image_size))
287 /* No icon for POI or for category or default POI icon file.
288 Draw default purple square. */
289 gdk_draw_rectangle(_map_pixmap, _gc[COLORABLE_APRS_STATION], TRUE,
290 poix - (gint)(1.5f * _draw_width),
291 poiy - (gint)(1.5f * _draw_width),
295 image_size = 3 * _draw_width;
298 gint label_width = 0;
300 gint _aprs_label_zoom = _poi_zoom - 1;
302 if(_aprs_label_zoom > _zoom)
304 label_width = add_aprs_label(label, strlen(label), poix + image_size, poiy);
309 gint offset = (gint)((gfloat)image_size/2.0f);
311 gtk_widget_queue_draw_area(
315 (2*image_size) + label_width,
322 #endif // INCLUDE_APRS
324 //// END OF APRS CODE
332 static gint x = 0, y = 0, width = 0, height = 0;
333 printf("%s()\n", __PRETTY_FUNCTION__);
335 cur_speed = _gps.speed * UNITS_CONVERT[_units];
337 if(cur_speed > _speed_limit)
339 gc = _speed_limit_gc1;
342 _speed_excess = TRUE;
343 g_timeout_add_full(G_PRIORITY_HIGH_IDLE,
344 5000, (GSourceFunc)speed_excess, NULL, NULL);
349 gc = _speed_limit_gc2;
350 _speed_excess = FALSE;
353 /* remove previous number */
354 if (width != 0 && height != 0) {
355 gtk_widget_queue_draw_area (_map_widget,
360 gdk_window_process_all_updates();
363 buffer = g_strdup_printf("%0.0f", cur_speed);
364 pango_layout_set_text(_speed_limit_layout, buffer, -1);
367 pango_layout_get_pixel_size(_speed_limit_layout, &width, &height);
369 switch (_speed_location)
371 case SPEED_LOCATION_TOP_RIGHT:
372 x = _map_widget->allocation.width - 10 - width;
375 case SPEED_LOCATION_BOTTOM_RIGHT:
376 x = _map_widget->allocation.width - 10 - width;
377 y = _map_widget->allocation.height - 10 - height;
379 case SPEED_LOCATION_BOTTOM_LEFT:
381 y = _map_widget->allocation.height - 10 - height;
389 gdk_draw_layout(_map_widget->window,
392 _speed_limit_layout);
395 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
399 gps_display_details(void)
401 gchar *buffer, litbuf[LL_FMT_LEN], buffer2[LL_FMT_LEN];
402 printf("%s()\n", __PRETTY_FUNCTION__);
407 gtk_label_set_label(GTK_LABEL(_sdi_lat), " --- ");
408 gtk_label_set_label(GTK_LABEL(_sdi_lon), " --- ");
409 gtk_label_set_label(GTK_LABEL(_sdi_spd), " --- ");
410 gtk_label_set_label(GTK_LABEL(_sdi_alt), " --- ");
411 gtk_label_set_label(GTK_LABEL(_sdi_hea), " --- ");
412 gtk_label_set_label(GTK_LABEL(_sdi_tim), " --:--:-- ");
416 gfloat speed = _gps.speed * UNITS_CONVERT[_units];
418 format_lat_lon(_gps.lat, _gps.lon, litbuf, buffer2);
421 //lat_format(_gps.lat, litbuf);
422 gtk_label_set_label(GTK_LABEL(_sdi_lat), litbuf);
425 //lon_format(_gps.lon, litbuf);
426 //gtk_label_set_label(GTK_LABEL(_sdi_lon), litbuf);
427 if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use)
428 gtk_label_set_label(GTK_LABEL(_sdi_lon), buffer2);
434 buffer = g_strdup_printf("%.1f mph", speed);
437 buffer = g_strdup_printf("%.1f kn", speed);
440 buffer = g_strdup_printf("%.1f km/h", speed);
443 gtk_label_set_label(GTK_LABEL(_sdi_spd), buffer);
451 buffer = g_strdup_printf("%d ft",
452 (gint)(_pos.altitude * 3.2808399f));
455 buffer = g_strdup_printf("%d m", _pos.altitude);
458 gtk_label_set_label(GTK_LABEL(_sdi_alt), buffer);
462 buffer = g_strdup_printf("%0.0f°", _gps.heading);
463 gtk_label_set_label(GTK_LABEL(_sdi_hea), buffer);
467 strftime(litbuf, 15, "%X", localtime(&_pos.time));
468 gtk_label_set_label(GTK_LABEL(_sdi_tim), litbuf);
472 buffer = g_strdup_printf("%d", _gps.satinview);
473 gtk_label_set_label(GTK_LABEL(_sdi_vie), buffer);
477 buffer = g_strdup_printf("%d", _gps.satinuse);
478 gtk_label_set_label(GTK_LABEL(_sdi_use), buffer);
485 case 3: buffer = g_strdup_printf("%dD fix", _gps.fix); break;
486 default: buffer = g_strdup_printf("nofix"); break;
488 gtk_label_set_label(GTK_LABEL(_sdi_fix), buffer);
492 buffer = g_strdup("none");
495 switch (_gps.fixquality)
497 case 1 : buffer = g_strdup_printf(_("SPS")); break;
498 case 2 : buffer = g_strdup_printf(_("DGPS")); break;
499 case 3 : buffer = g_strdup_printf(_("PPS")); break;
500 case 4 : buffer = g_strdup_printf(_("Real Time Kinematic")); break;
501 case 5 : buffer = g_strdup_printf(_("Float RTK")); break;
502 case 6 : buffer = g_strdup_printf(_("Estimated")); break;
503 case 7 : buffer = g_strdup_printf(_("Manual")); break;
504 case 8 : buffer = g_strdup_printf(_("Simulation")); break;
505 default : buffer = g_strdup_printf(_("none")); break;
508 gtk_label_set_label(GTK_LABEL(_sdi_fqu), buffer);
513 gfloat maxspeed = _gps.maxspeed * UNITS_CONVERT[_units];
519 buffer = g_strdup_printf("%.1f mph", maxspeed);
522 buffer = g_strdup_printf("%.1f kn", maxspeed);
525 buffer = g_strdup_printf("%.1f km/h", maxspeed);
528 gtk_label_set_label(GTK_LABEL(_sdi_msp), buffer);
532 /* refresh sat panel */
533 gtk_widget_queue_draw_area(GTK_WIDGET(_sat_details_panel),
535 _sat_details_panel->allocation.width,
536 _sat_details_panel->allocation.height);
538 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
543 gps_display_data(void)
545 gchar *buffer, litbuf[LL_FMT_LEN], buffer2[LL_FMT_LEN];
546 printf("%s()\n", __PRETTY_FUNCTION__);
551 gtk_label_set_label(GTK_LABEL(_text_lat), " --- ");
552 gtk_label_set_label(GTK_LABEL(_text_lon), " --- ");
553 gtk_label_set_label(GTK_LABEL(_text_speed), " --- ");
554 gtk_label_set_label(GTK_LABEL(_text_alt), " --- ");
555 gtk_label_set_label(GTK_LABEL(_text_time), " --:--:-- ");
559 gfloat speed = _gps.speed * UNITS_CONVERT[_units];
561 format_lat_lon(_gps.lat, _gps.lon, litbuf, buffer2);
564 //lat_format(_gps.lat, litbuf);
565 gtk_label_set_label(GTK_LABEL(_text_lat), litbuf);
568 //lon_format(_gps.lon, litbuf);
569 if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use)
570 gtk_label_set_label(GTK_LABEL(_text_lon), buffer2);
576 buffer = g_strdup_printf("Spd: %.1f mph", speed);
579 buffer = g_strdup_printf("Spd: %.1f kn", speed);
582 buffer = g_strdup_printf("Spd: %.1f km/h", speed);
585 gtk_label_set_label(GTK_LABEL(_text_speed), buffer);
593 buffer = g_strdup_printf("Alt: %d ft",
594 (gint)(_pos.altitude * 3.2808399f));
597 buffer = g_strdup_printf("Alt: %d m", _pos.altitude);
599 gtk_label_set_label(GTK_LABEL(_text_alt), buffer);
603 strftime(litbuf, 15, "%X", localtime(&_pos.time));
604 gtk_label_set_label(GTK_LABEL(_text_time), litbuf);
607 /* refresh sat panel */
608 gtk_widget_queue_draw_area(GTK_WIDGET(_sat_panel),
610 _sat_panel->allocation.width,
611 _sat_panel->allocation.height);
613 /* refresh heading panel*/
614 gtk_widget_queue_draw_area(GTK_WIDGET(_heading_panel),
616 _heading_panel->allocation.width,
617 _heading_panel->allocation.height);
619 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
626 printf("%s()\n", __PRETTY_FUNCTION__);
636 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
642 printf("%s()\n", __PRETTY_FUNCTION__);
644 if(_gps_info && _enable_gps)
645 gtk_widget_show_all(GTK_WIDGET(_gps_widget));
649 gtk_widget_hide(GTK_WIDGET(_gps_widget));
652 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
656 draw_sat_info(GtkWidget *widget, gint x0, gint y0,
657 gint width, gint height, gboolean showsnr)
660 gint step, i, j, snr_height, bymargin, xoffset, yoffset;
663 printf("%s()\n", __PRETTY_FUNCTION__);
667 /* Bootom margin - 12% */
668 bymargin = height * 0.88f;
671 gdk_draw_line(widget->window,
672 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
673 xoffset + 5, yoffset + bymargin,
674 xoffset + width - 10 - 2, yoffset + bymargin);
675 gdk_draw_line(widget->window,
676 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
677 xoffset + 5, yoffset + bymargin - 1,
678 xoffset + width - 10 - 2, yoffset + bymargin - 1);
680 if(_gps.satinview > 0 )
682 /* Left margin - 5pix, Right margin - 5pix */
683 step = (width - 10) / _gps.satinview;
685 for(i = 0; i < _gps.satinview; i++)
687 /* Sat used or not */
689 for(j = 0; j < _gps.satinuse ; j++)
691 if(_gps.satforfix[j] == _gps_sat[i].prn)
699 snr_height = _gps_sat[i].snr * height * 0.78f / 100;
700 y = height * 0.1f + (height * 0.78f - snr_height);
702 /* draw sat rectangle... */
703 gdk_draw_rectangle(widget->window,
711 if(showsnr && _gps_sat[i].snr > 0)
714 tmp = g_strdup_printf("%02d", _gps_sat[i].snr);
715 pango_layout_set_text(_sat_info_layout, tmp, 2);
716 pango_layout_get_pixel_size(_sat_info_layout, &x1, &y1);
717 gdk_draw_layout(widget->window,
718 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
719 xoffset + x + ((step - 2) - x1)/2,
725 /* ...and sat number */
726 tmp = g_strdup_printf("%02d", _gps_sat[i].prn);
727 pango_layout_set_text(_sat_info_layout, tmp, 2);
728 pango_layout_get_pixel_size(_sat_info_layout, &x1, &y1);
729 gdk_draw_layout(widget->window,
730 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
731 xoffset + x + ((step - 2) - x1)/2 ,
732 yoffset + bymargin + 1,
738 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
743 draw_sat_details(GtkWidget *widget, gint x0, gint y0,
744 gint width, gint height)
746 gint i, j, x, y, size, halfsize, xoffset, yoffset;
750 GdkGC *gc1, *gc2, *gc3, *gc;
751 gchar *buffer = NULL;
752 printf("%s()\n", __PRETTY_FUNCTION__);
754 size = MIN(width, height);
758 xoffset = x0 + (width - height - 10) / 2;
764 yoffset = y0 + (height - width - 10) / 2;
768 gdk_draw_arc(widget->window,
769 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
771 xoffset + 2, yoffset + 2, size - 4, size - 4,
775 gdk_draw_arc(widget->window,
776 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
778 xoffset + size/6, yoffset + size/6,
783 gdk_draw_arc(widget->window,
784 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
786 xoffset + size/6*2, yoffset + size/6*2,
790 gint line[12] = {0,30,60,90,120,150,180,210,240,270,300,330};
792 for(i = 0; i < 6; i++)
795 tmp = deg2rad(line[i]);
796 gdk_draw_line(widget->window,
797 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
798 xoffset + halfsize + (halfsize -2) * sinf(tmp),
799 yoffset + halfsize - (halfsize -2) * cosf(tmp),
800 xoffset + halfsize - (halfsize -2) * sinf(tmp),
801 yoffset + halfsize + (halfsize -2) * cosf(tmp));
804 for(i = 0; i < 12; i++)
806 tmp = deg2rad(line[i]);
809 buffer = g_strdup_printf("N");
811 buffer = g_strdup_printf("%d°", line[i]);
812 pango_layout_set_text(_sat_details_layout, buffer, -1);
813 pango_layout_get_pixel_size(_sat_details_layout, &x, &y);
814 gdk_draw_layout(widget->window,
815 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
816 (xoffset + halfsize + (halfsize - size/12) * sinf(tmp)) - x/2,
817 (yoffset + halfsize - (halfsize - size/12) * cosf(tmp)) - y/2,
818 _sat_details_layout);
824 buffer = g_strdup_printf("30°");
825 pango_layout_set_text(_sat_details_layout, buffer, -1);
826 pango_layout_get_pixel_size(_sat_details_layout, &x, &y);
827 gdk_draw_layout(widget->window,
828 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
829 (xoffset + halfsize + size/6*2 * sinf(tmp)) - x/2,
830 (yoffset + halfsize - size/6*2 * cosf(tmp)) - y/2,
831 _sat_details_layout);
836 buffer = g_strdup_printf("60°");
837 pango_layout_set_text(_sat_details_layout, buffer, -1);
838 pango_layout_get_pixel_size(_sat_details_layout, &x, &y);
839 gdk_draw_layout(widget->window,
840 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
841 (xoffset + halfsize + size/6 * sinf(tmp)) - x/2,
842 (yoffset + halfsize - size/6 * cosf(tmp)) - y/2,
843 _sat_details_layout);
849 gc1 = gdk_gc_new (widget->window);
850 gdk_gc_set_rgb_fg_color (gc1, &color);
855 gc2 = gdk_gc_new (widget->window);
856 gdk_gc_set_rgb_fg_color (gc2, &color);
859 color.green = 0xffff;
861 gc3 = gdk_gc_new (widget->window);
862 gdk_gc_set_rgb_fg_color (gc3, &color);
864 for(i = 0; i < _gps.satinview; i++)
866 /* Sat used or not */
868 for(j = 0; j < _gps.satinuse ; j++)
870 if(_gps.satforfix[j] == _gps_sat[i].prn)
877 tmp = deg2rad(_gps_sat[i].azimuth);
878 x = xoffset + halfsize
879 + (90 - _gps_sat[i].elevation)*halfsize/90 * sinf(tmp);
880 y = yoffset + halfsize
881 - (90 - _gps_sat[i].elevation)*halfsize/90 * cosf(tmp);
883 gdk_draw_arc (widget->window,
885 x - 10, y - 10, 20, 20,
888 buffer = g_strdup_printf("%02d", _gps_sat[i].prn);
889 pango_layout_set_text(_sat_details_layout, buffer, -1);
890 pango_layout_get_pixel_size(_sat_details_layout, &x1, &y1);
891 gdk_draw_layout(widget->window,
895 _sat_details_layout);
898 g_object_unref (gc1);
899 g_object_unref (gc2);
900 g_object_unref (gc3);
902 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
908 sat_details_panel_expose(GtkWidget *widget, GdkEventExpose *event)
910 gint width, height, x, y;
911 gchar *buffer = NULL;
912 printf("%s()\n", __PRETTY_FUNCTION__);
914 width = widget->allocation.width;
915 height = widget->allocation.height * 0.9;
917 draw_sat_info(widget, 0, 0, width/2, height, TRUE);
918 draw_sat_details(widget, width/2, 0, width/2, height);
920 buffer = g_strdup_printf(
922 _("Satellites in view"), _gps.satinview,
923 _("in use"), _gps.satinuse);
924 pango_layout_set_text(_sat_details_expose_layout, buffer, -1);
925 pango_layout_get_pixel_size(_sat_details_expose_layout, &x, &y);
926 gdk_draw_layout(widget->window,
927 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
930 _sat_details_expose_layout);
933 buffer = g_strdup_printf("HDOP: %.01f", _gps.hdop);
934 pango_layout_set_text(_sat_details_expose_layout, buffer, -1);
935 pango_layout_get_pixel_size(_sat_details_expose_layout, &x, &y);
936 gdk_draw_layout(widget->window,
937 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
940 _sat_details_expose_layout);
942 buffer = g_strdup_printf("PDOP: %.01f", _gps.pdop);
943 pango_layout_set_text(_sat_details_expose_layout, buffer, -1);
944 pango_layout_get_pixel_size(_sat_details_expose_layout, &x, &y);
945 gdk_draw_layout(widget->window,
946 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
948 (height/6) - y/2 + 20,
949 _sat_details_expose_layout);
951 buffer = g_strdup_printf("VDOP: %.01f", _gps.vdop);
952 pango_layout_set_text(_sat_details_expose_layout, buffer, -1);
953 pango_layout_get_pixel_size(_sat_details_expose_layout, &x, &y);
954 gdk_draw_layout(widget->window,
955 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
957 (height/6) - y/2 + 40,
958 _sat_details_expose_layout);
961 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
968 static GtkWidget *dialog = NULL;
969 static GtkWidget *table = NULL;
970 static GtkWidget *label = NULL;
971 static GtkWidget *notebook = NULL;
972 printf("%s()\n", __PRETTY_FUNCTION__);
976 dialog = gtk_dialog_new_with_buttons(_("GPS Details"),
977 GTK_WINDOW(_window), GTK_DIALOG_MODAL,
978 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
981 gtk_window_set_default_size(GTK_WINDOW(dialog), 600, 300);
983 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
984 notebook = gtk_notebook_new(), TRUE, TRUE, 0);
987 gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
988 table = gtk_table_new(4, 6, FALSE),
989 label = gtk_label_new(_("GPS Information")));
991 _sat_details_panel = gtk_drawing_area_new ();
992 gtk_widget_set_size_request (_sat_details_panel, 300, 300);
993 /* sat details info */
994 gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
996 label = gtk_label_new(_("Satellites details")));
997 g_signal_connect (G_OBJECT (_sat_details_panel), "expose_event",
998 G_CALLBACK (sat_details_panel_expose), NULL);
1000 gtk_table_attach(GTK_TABLE(table),
1001 label = gtk_label_new(_("Latitude")),
1002 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, 0, 20, 4);
1003 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1004 gtk_table_attach(GTK_TABLE(table),
1005 _sdi_lat = gtk_label_new(" --- "),
1006 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
1007 gtk_misc_set_alignment(GTK_MISC(_sdi_lat), 0.f, 0.5f);
1009 gtk_table_attach(GTK_TABLE(table),
1010 label = gtk_label_new(_("Longitude")),
1011 0, 1, 1, 2, GTK_EXPAND | GTK_FILL, 0, 20, 4);
1012 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1013 gtk_table_attach(GTK_TABLE(table),
1014 _sdi_lon = gtk_label_new(" --- "),
1015 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
1016 gtk_misc_set_alignment(GTK_MISC(_sdi_lon), 0.f, 0.5f);
1018 gtk_table_attach(GTK_TABLE(table),
1019 label = gtk_label_new(_("Speed")),
1020 0, 1, 2, 3, GTK_EXPAND | GTK_FILL, 0, 20, 4);
1021 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1022 gtk_table_attach(GTK_TABLE(table),
1023 _sdi_spd = gtk_label_new(" --- "),
1024 1, 2, 2, 3, GTK_EXPAND | GTK_FILL, 0, 2, 4);
1025 gtk_misc_set_alignment(GTK_MISC(_sdi_spd), 0.f, 0.5f);
1027 gtk_table_attach(GTK_TABLE(table),
1028 label = gtk_label_new(_("Altitude")),
1029 0, 1, 3, 4, GTK_EXPAND | GTK_FILL, 0, 20, 4);
1030 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1031 gtk_table_attach(GTK_TABLE(table),
1032 _sdi_alt = gtk_label_new(" --- "),
1033 1, 2, 3, 4, GTK_EXPAND | GTK_FILL, 0, 2, 4);
1034 gtk_misc_set_alignment(GTK_MISC(_sdi_alt), 0.f, 0.5f);
1036 gtk_table_attach(GTK_TABLE(table),
1037 label = gtk_label_new(_("Heading")),
1038 0, 1, 4, 5, GTK_EXPAND | GTK_FILL, 0, 20, 4);
1039 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1040 gtk_table_attach(GTK_TABLE(table),
1041 _sdi_hea = gtk_label_new(" --- "),
1042 1, 2, 4, 5, GTK_EXPAND | GTK_FILL, 0, 2, 4);
1043 gtk_misc_set_alignment(GTK_MISC(_sdi_hea), 0.f, 0.5f);
1045 gtk_table_attach(GTK_TABLE(table),
1046 label = gtk_label_new(_("Local time")),
1047 0, 1, 5, 6, GTK_EXPAND | GTK_FILL, 0, 20, 4);
1048 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1049 gtk_table_attach(GTK_TABLE(table),
1050 _sdi_tim = gtk_label_new(" --:--:-- "),
1051 1, 2, 5, 6, GTK_EXPAND | GTK_FILL, 0, 2, 4);
1052 gtk_misc_set_alignment(GTK_MISC(_sdi_tim), 0.f, 0.5f);
1054 gtk_table_attach(GTK_TABLE(table),
1055 label = gtk_label_new(_("Sat in view")),
1056 2, 3, 0, 1, GTK_EXPAND | GTK_FILL, 0, 20, 4);
1057 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1058 gtk_table_attach(GTK_TABLE(table),
1059 _sdi_vie = gtk_label_new("0"),
1060 3, 4, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
1061 gtk_misc_set_alignment(GTK_MISC(_sdi_vie), 0.f, 0.5f);
1063 gtk_table_attach(GTK_TABLE(table),
1064 label = gtk_label_new(_("Sat in use")),
1065 2, 3, 1, 2, GTK_EXPAND | GTK_FILL, 0, 20, 4);
1066 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1067 gtk_table_attach(GTK_TABLE(table),
1068 _sdi_use = gtk_label_new("0"),
1069 3, 4, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
1070 gtk_misc_set_alignment(GTK_MISC(_sdi_use), 0.f, 0.5f);
1072 gtk_table_attach(GTK_TABLE(table),
1073 label = gtk_label_new(_("Fix")),
1074 2, 3, 2, 3, GTK_EXPAND | GTK_FILL, 0, 20, 4);
1075 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1076 gtk_table_attach(GTK_TABLE(table),
1077 _sdi_fix = gtk_label_new(_("nofix")),
1078 3, 4, 2, 3, GTK_EXPAND | GTK_FILL, 0, 2, 4);
1079 gtk_misc_set_alignment(GTK_MISC(_sdi_fix), 0.f, 0.5f);
1081 gtk_table_attach(GTK_TABLE(table),
1082 label = gtk_label_new(_("Fix Quality")),
1083 2, 3, 3, 4, GTK_EXPAND | GTK_FILL, 0, 20, 4);
1084 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1085 gtk_table_attach(GTK_TABLE(table),
1086 _sdi_fqu = gtk_label_new(_("none")),
1087 3, 4, 3, 4, GTK_EXPAND | GTK_FILL, 0, 2, 4);
1088 gtk_misc_set_alignment(GTK_MISC(_sdi_fqu), 0.f, 0.5f);
1090 gtk_table_attach(GTK_TABLE(table),
1091 label = gtk_label_new(_("Max speed")),
1092 2, 3, 5, 6, GTK_EXPAND | GTK_FILL, 0, 20, 4);
1093 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1094 gtk_table_attach(GTK_TABLE(table),
1095 _sdi_msp = gtk_label_new(" --- "),
1096 3, 4, 5, 6, GTK_EXPAND | GTK_FILL, 0, 2, 4);
1097 gtk_misc_set_alignment(GTK_MISC(_sdi_msp), 0.f, 0.5f);
1100 gtk_widget_show_all(dialog);
1101 _satdetails_on = TRUE;
1102 gps_display_details();
1103 while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
1105 _satdetails_on = FALSE;
1108 gtk_widget_hide(dialog);
1110 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
1115 * Render a single track line to _map_pixmap. If either point on the line
1116 * is a break (defined as unity == 0), a circle is drawn at the other point.
1117 * IT IS AN ERROR FOR BOTH POINTS TO INDICATE A BREAK.
1120 map_render_segment(GdkGC *gc_norm, GdkGC *gc_alt,
1121 gint unitx1, gint unity1, gint unitx2, gint unity2)
1123 /* vprintf("%s(%d, %d, %d, %d)\n", __PRETTY_FUNCTION__,
1124 unitx1, unity1, unitx2, unity2); */
1129 unit2buf(unitx2, unity2, x2, y2);
1130 if(((unsigned)(x2+_draw_width) <= _view_width_pixels+2*_draw_width)
1131 &&((unsigned)(y2+_draw_width) <= _view_height_pixels+2*_draw_width))
1133 gdk_draw_arc(_map_pixmap, gc_alt,
1134 FALSE, /* FALSE: not filled. */
1139 0, /* start at 0 degrees. */
1146 unit2buf(unitx1, unity1, x1, y1);
1147 if(((unsigned)(x1+_draw_width) <= _view_width_pixels+2*_draw_width)
1148 &&((unsigned)(y1+_draw_width) <= _view_height_pixels+2*_draw_width))
1150 gdk_draw_arc(_map_pixmap, gc_alt,
1151 FALSE, /* FALSE: not filled. */
1156 0, /* start at 0 degrees. */
1162 gint x1, y1, x2, y2;
1163 unit2buf(unitx1, unity1, x1, y1);
1164 unit2buf(unitx2, unity2, x2, y2);
1165 /* Make sure this line could possibly be visible. */
1166 if(!((x1 > _view_width_pixels && x2 > _view_width_pixels)
1167 || (x1 < 0 && x2 < 0)
1168 || (y1 > _view_height_pixels && y2 > _view_height_pixels)
1169 || (y1 < 0 && y2 < 0)))
1170 gdk_draw_line(_map_pixmap, gc_norm, x1, y1, x2, y2);
1173 /* vprintf("%s(): return\n", __PRETTY_FUNCTION__); */
1177 * Render all track data onto the _map_pixmap. Note that this does not
1178 * clear the pixmap of previous track data (use map_force_redraw() for
1179 * that), and also note that this method does not queue any redraws, so it
1180 * is up to the caller to decide which part of the track really needs to be
1184 map_render_path(Path *path, GdkGC **gc)
1188 printf("%s()\n", __PRETTY_FUNCTION__);
1190 /* gc is a pointer to the first GC to use (for plain points). (gc + 1)
1191 * is a pointer to the GC to use for waypoints, and (gc + 2) is a pointer
1192 * to the GC to use for breaks. */
1194 /* else there is a route to draw. */
1195 for(curr = path->head, wcurr = path->whead; curr++ != path->tail; )
1197 /* Draw the line from (curr - 1) to (curr). */
1198 map_render_segment(gc[0], gc[2],
1199 curr[-1].unitx, curr[-1].unity, curr->unitx, curr->unity);
1201 /* Now, check if curr is a waypoint. */
1202 if(wcurr <= path->wtail && wcurr->point == curr)
1205 unit2buf(wcurr->point->unitx, wcurr->point->unity, x1, y1);
1206 gdk_draw_arc(_map_pixmap,
1208 FALSE, /* FALSE: not filled. */
1213 0, /* start at 0 degrees. */
1219 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
1225 printf("%s()\n", __PRETTY_FUNCTION__);
1227 if((_show_paths & ROUTES_MASK) && _route.head != _route.tail)
1230 map_render_path(&_route, _gc + COLORABLE_ROUTE);
1232 next_way = path_get_next_way();
1234 /* Now, draw the next waypoint on top of all other waypoints. */
1238 unit2buf(next_way->point->unitx, next_way->point->unity, x1, y1);
1239 /* Draw the next waypoint as a break. */
1240 gdk_draw_arc(_map_pixmap,
1241 _gc[COLORABLE_ROUTE_BREAK],
1242 FALSE, /* FALSE: not filled. */
1247 0, /* start at 0 degrees. */
1251 if(_show_paths & TRACKS_MASK)
1252 map_render_path(&_track, _gc + COLORABLE_TRACK);
1254 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
1258 * Update all GdkGC objects to reflect the current _draw_width.
1260 #define UPDATE_GC(gc) \
1261 gdk_gc_set_line_attributes(gc, \
1262 _draw_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
1267 printf("%s()\n", __PRETTY_FUNCTION__);
1269 for(i = 0; i < COLORABLE_ENUM_COUNT; i++)
1271 gdk_color_alloc(gtk_widget_get_colormap(_map_widget), &_color[i]);
1273 g_object_unref(_gc[i]);
1274 _gc[i] = gdk_gc_new(_map_pixmap);
1275 gdk_gc_set_foreground(_gc[i], &_color[i]);
1276 gdk_gc_set_line_attributes(_gc[i],
1277 _draw_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
1280 /* Update the _map_widget's gc's. */
1281 gdk_gc_set_line_attributes(
1282 _map_widget->style->fg_gc[GTK_STATE_ACTIVE],
1283 2, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
1284 gdk_gc_set_line_attributes(
1285 _map_widget->style->bg_gc[GTK_STATE_ACTIVE],
1286 2, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
1288 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
1292 * Call gtk_window_present() on Maemo Mapper. This also checks the
1293 * configuration and brings up the Settings dialog if the GPS Receiver is
1294 * not set up, the first time it is called.
1299 static gint been_here = 0;
1300 static gint done_here = 0;
1301 printf("%s()\n", __PRETTY_FUNCTION__);
1305 /* Set connection state first, to avoid going into this if twice. */
1310 gtk_window_present(GTK_WINDOW(_window));
1312 confirm = hildon_note_new_confirmation(GTK_WINDOW(_window),
1313 _("It looks like this is your first time running"
1314 " Maemo Mapper. Press OK to view the the help pages."
1315 " Otherwise, press Cancel to continue."));
1317 if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm)))
1320 hildon_help_show(_osso, HELP_ID_INTRO, 0);
1322 ossohelp_show(_osso, HELP_ID_INTRO, 0);
1325 gtk_widget_destroy(confirm);
1327 /* Present the settings dialog. */
1329 popup_error(_window,
1330 _("OpenStreetMap.org provides public, free-to-use maps. "
1331 "You can also download a sample set of repositories from "
1332 " the internet by using the \"Download...\" button."));
1334 /* Present the repository dialog. */
1336 confirm = hildon_note_new_confirmation(GTK_WINDOW(_window),
1337 _("You will now see a blank screen. You can download"
1338 " maps using the \"Manage Maps\" menu item in the"
1339 " \"Maps\" menu. Or, press OK now to enable"
1340 " Auto-Download."));
1341 if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm)))
1343 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
1344 _menu_maps_auto_download_item), TRUE);
1346 gtk_widget_destroy(confirm);
1349 /* Connect to receiver. */
1353 ++done_here; /* Don't ask... */
1357 gtk_window_present(GTK_WINDOW(_window));
1358 g_timeout_add_full(G_PRIORITY_HIGH_IDLE,
1359 250, (GSourceFunc)banner_reset, NULL, NULL);
1362 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
1367 * "Set" the mark, which translates the current GPS position into on-screen
1368 * units in preparation for drawing the mark with map_draw_mark().
1373 gfloat sqrt_speed, tmp, vel_offset_devx, vel_offset_devy;
1374 printf("%s()\n", __PRETTY_FUNCTION__);
1376 tmp = deg2rad(_gps.heading);
1377 sqrt_speed = VELVEC_SIZE_FACTOR * sqrtf(10 + _gps.speed);
1378 gdk_pixbuf_rotate_vector(&vel_offset_devx, &vel_offset_devy,
1380 sqrt_speed * sinf(tmp), -sqrt_speed * cosf(tmp));
1382 unit2buf(_pos.unitx, _pos.unity, _mark_bufx1, _mark_bufy1);
1384 _mark_bufx2 = _mark_bufx1 + (_show_velvec ? (vel_offset_devx + 0.5f) : 0);
1385 _mark_bufy2 = _mark_bufy1 + (_show_velvec ? (vel_offset_devy + 0.5f) : 0);
1387 _mark_minx = MIN(_mark_bufx1, _mark_bufx2) - (2 * _draw_width);
1388 _mark_miny = MIN(_mark_bufy1, _mark_bufy2) - (2 * _draw_width);
1389 _mark_width = abs(_mark_bufx1 - _mark_bufx2) + (4 * _draw_width);
1390 _mark_height = abs(_mark_bufy1 - _mark_bufy2) + (4 * _draw_width);
1392 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
1397 * Force a redraw of the entire _map_pixmap, including fetching the
1398 * background maps from disk and redrawing the tracks on top of them.
1403 printf("%s()\n", __PRETTY_FUNCTION__);
1407 _map_widget->style->fg_gc[GTK_STATE_ACTIVE],
1411 _view_width_pixels, _view_height_pixels,
1412 GDK_RGB_DITHER_NONE, 0, 0);
1414 MACRO_MAP_RENDER_DATA();
1415 MACRO_QUEUE_DRAW_AREA();
1417 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
1421 map_calc_new_center(gint zoom)
1424 printf("%s()\n", __PRETTY_FUNCTION__);
1426 switch(_center_mode)
1430 gfloat tmp = deg2rad(_gps.heading);
1431 gfloat screen_pixels = _view_width_pixels
1432 + (((gint)_view_height_pixels
1433 - (gint)_view_width_pixels)
1434 * fabsf(cosf(deg2rad(
1435 ROTATE_DIR_ENUM_DEGREES[_rotate_dir] -
1437 : (_next_map_rotate_angle
1438 - (gint)(_gps.heading)))))));
1439 gfloat lead_pixels = 0.0025f
1440 * pixel2zunit((gint)screen_pixels, zoom)
1442 * VELVEC_SIZE_FACTOR
1443 * (_lead_is_fixed ? 7 : sqrtf(_gps.speed));
1445 new_center.unitx = _pos.unitx + (gint)(lead_pixels * sinf(tmp));
1446 new_center.unity = _pos.unity - (gint)(lead_pixels * cosf(tmp));
1450 new_center.unitx = _pos.unitx;
1451 new_center.unity = _pos.unity;
1454 new_center.unitx = _next_center.unitx;
1455 new_center.unity = _next_center.unity;
1458 vprintf("%s(): return (%d, %d)\n", __PRETTY_FUNCTION__,
1459 new_center.unitx, new_center.unity);
1464 * Center the view on the given unitx/unity.
1467 map_center_unit_full(Point new_center,
1468 gint zoom, gint rotate_angle)
1471 printf("%s(%d, %d)\n", __PRETTY_FUNCTION__,
1472 new_center.unitx, new_center.unity);
1476 /* Assure that _center.unitx/y are bounded. */
1477 BOUND(new_center.unitx, 0, WORLD_SIZE_UNITS);
1478 BOUND(new_center.unity, 0, WORLD_SIZE_UNITS);
1480 mrt = g_slice_new(MapRenderTask);
1481 mrt->repo = _curr_repo;
1482 mrt->old_offsetx = _map_offset_devx;
1483 mrt->old_offsety = _map_offset_devy;
1484 mrt->new_center = _next_center = new_center;
1485 mrt->screen_width_pixels = _view_width_pixels;
1486 mrt->screen_height_pixels = _view_height_pixels;
1487 mrt->zoom = _next_zoom = zoom;
1488 mrt->rotate_angle = _next_map_rotate_angle = rotate_angle;
1491 gtk_widget_queue_draw_area(
1493 _redraw_wait_bounds.x,
1494 _redraw_wait_bounds.y,
1495 _redraw_wait_bounds.width
1496 + (_redraw_count * HOURGLASS_SEPARATION),
1497 _redraw_wait_bounds.height);
1501 g_thread_pool_push(_mrt_thread_pool, mrt, NULL);
1504 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
1508 map_center_unit(Point new_center)
1510 map_center_unit_full(new_center, _next_zoom,
1511 _center_mode > 0 && _center_rotate
1512 ? _gps.heading : _next_map_rotate_angle);
1516 map_rotate(gint rotate_angle)
1518 if(_center_mode > 0 && gtk_check_menu_item_get_active(
1519 GTK_CHECK_MENU_ITEM(_menu_view_rotate_auto_item)))
1520 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
1521 _menu_view_rotate_auto_item), FALSE);
1523 map_center_unit_full(map_calc_new_center(_next_zoom), _next_zoom,
1524 (_next_map_rotate_angle + rotate_angle) % 360);
1528 map_center_zoom(gint zoom)
1530 map_center_unit_full(map_calc_new_center(zoom), zoom,
1531 _center_mode > 0 && _center_rotate
1532 ? _gps.heading : _next_map_rotate_angle);
1536 * Pan the view by the given number of units in the X and Y directions.
1539 map_pan(gint delta_unitx, gint delta_unity)
1542 printf("%s(%d, %d)\n", __PRETTY_FUNCTION__, delta_unitx, delta_unity);
1544 if(_center_mode > 0)
1545 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
1546 _menu_view_ac_none_item), TRUE);
1547 new_center.unitx = _center.unitx + delta_unitx;
1548 new_center.unity = _center.unity + delta_unity;
1549 map_center_unit_full(new_center, _next_zoom,
1550 _center_mode > 0 && _center_rotate
1551 ? _gps.heading : _next_map_rotate_angle);
1553 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
1557 * Initiate a move of the mark from the old location to the current
1558 * location. This function queues the draw area of the old mark (to force
1559 * drawing of the background map), then updates the mark, then queus the
1560 * draw area of the new mark.
1565 printf("%s()\n", __PRETTY_FUNCTION__);
1567 /* Just queue the old and new draw areas. */
1568 gtk_widget_queue_draw_area(_map_widget,
1569 _mark_minx + _map_offset_devx,
1570 _mark_miny + _map_offset_devy,
1574 gtk_widget_queue_draw_area(_map_widget,
1575 _mark_minx + _map_offset_devx,
1576 _mark_miny + _map_offset_devy,
1580 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
1584 * Make sure the mark is up-to-date. This function triggers a panning of
1585 * the view if the mark is appropriately close to the edge of the view.
1588 map_refresh_mark(gboolean force_redraw)
1590 printf("%s()\n", __PRETTY_FUNCTION__);
1592 gint new_center_devx, new_center_devy;
1594 Point new_center = map_calc_new_center(_next_zoom);
1596 unit2buf(new_center.unitx, new_center.unity,
1597 new_center_devx, new_center_devy);
1598 if(force_redraw || (_center_mode > 0
1599 && (UNITS_CONVERT[_units] * _gps.speed) >= _ac_min_speed &&
1600 (((unsigned)(new_center_devx - (_view_width_pixels * _center_ratio / 20))
1601 > ((10 - _center_ratio) * _view_width_pixels / 10))
1602 || ((unsigned)(new_center_devy - (_view_height_pixels * _center_ratio / 20))
1603 > ((10 - _center_ratio) * _view_height_pixels / 10))
1604 || (_center_rotate &&
1605 abs(_next_map_rotate_angle - _gps.heading)
1606 > (4*(10-_rotate_sens))))))
1609 map_center_unit(new_center);
1613 /* We're not changing the view - just move the mark. */
1617 /* Draw speed info */
1621 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
1625 map_download_refresh_idle(MapUpdateTask *mut)
1627 vprintf("%s(%p, %d, %d, %d)\n", __PRETTY_FUNCTION__, mut,
1628 mut->zoom, mut->tilex, mut->tiley);
1630 /* Test if download succeeded (only if retries != 0). */
1633 gint zoff = mut->zoom - _zoom;
1634 /* Update the UI to reflect the updated map database. */
1635 /* Only refresh at same or "lower" (more detailed) zoom level. */
1636 if(mut->update_type == MAP_UPDATE_AUTO && (unsigned)zoff <= 4)
1638 gfloat destx, desty;
1639 gint boundx, boundy, width, height;
1642 tile2pixel(mut->tilex << zoff)
1643 + ((TILE_SIZE_PIXELS << zoff) >> 1),
1644 tile2pixel(mut->tiley << zoff)
1645 + ((TILE_SIZE_PIXELS << zoff) >> 1),
1648 /* Multiply the matrix to cause blitting. */
1650 gdk_pixbuf_rotate_matrix_mult_number(
1651 _map_rotate_matrix, 1 << zoff);
1652 gdk_pixbuf_rotate(_map_pixbuf,
1653 /* Apply Map Correction. */
1654 destx - unit2pixel(_map_correction_unitx),
1655 desty - unit2pixel(_map_correction_unity),
1658 TILE_SIZE_PIXELS / 2,
1659 TILE_SIZE_PIXELS / 2,
1662 &boundx, &boundy, &width, &height);
1663 /* Un-multiply the matrix that we used for blitting. Good thing
1664 * we're multiplying by powers of two, or this wouldn't work
1665 * consistently... */
1667 gdk_pixbuf_rotate_matrix_mult_number(
1668 _map_rotate_matrix, 1.f / (1 << zoff));
1674 _map_widget->style->fg_gc[GTK_STATE_ACTIVE],
1679 GDK_RGB_DITHER_NONE, 0, 0);
1680 MACRO_MAP_RENDER_DATA();
1681 gtk_widget_queue_draw_area(
1682 _map_widget, boundx, boundy, width, height);
1685 g_object_unref(mut->pixbuf);
1687 else if(mut->vfs_result != GNOME_VFS_OK)
1692 if(++_curr_download == _num_downloads)
1694 if(_download_banner)
1696 gtk_widget_destroy(_download_banner);
1697 _download_banner = NULL;
1699 _num_downloads = _curr_download = 0;
1700 g_thread_pool_stop_unused_threads();
1701 #ifndef MAPDB_SQLITE
1703 gdbm_sync(_curr_repo->db);
1707 if (mut->repo->layer_level == 0) {
1708 gchar buffer[BUFFER_SIZE];
1709 snprintf(buffer, sizeof(buffer), "%d %s", _dl_errors,
1710 _("maps failed to download."));
1711 MACRO_BANNER_SHOW_INFO(_window, buffer);
1716 if(mut->update_type != MAP_UPDATE_AUTO || _refresh_map_after_download)
1718 /* Update the map. */
1719 map_refresh_mark(TRUE);
1722 else if(_download_banner)
1724 hildon_banner_set_fraction(HILDON_BANNER(_download_banner),
1725 _curr_download / (double)_num_downloads);
1728 g_mutex_lock(_mut_priority_mutex);
1729 g_hash_table_remove(_mut_exists_table, mut);
1730 g_mutex_unlock(_mut_priority_mutex);
1732 g_slice_free(MapUpdateTask, mut);
1734 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
1739 * Set the current zoom level. If the given zoom level is the same as the
1740 * current zoom level, or if the new zoom is invalid
1741 * (not MIN_ZOOM <= new_zoom < MAX_ZOOM), then this method does nothing.
1744 map_set_zoom(gint new_zoom)
1746 printf("%s(%d)\n", __PRETTY_FUNCTION__, _zoom);
1748 /* This if condition also checks for new_zoom >= 0. */
1749 if((unsigned)new_zoom > MAX_ZOOM)
1752 map_center_zoom(new_zoom / _curr_repo->view_zoom_steps
1753 * _curr_repo->view_zoom_steps);
1755 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
1759 map_replace_pixbuf_idle(MapRenderTask *mrt)
1761 printf("%s()\n", __PRETTY_FUNCTION__);
1763 if(!--_pending_replaces && !_mouse_is_down
1764 && mrt->screen_width_pixels == _view_width_pixels
1765 && mrt->screen_height_pixels == _view_height_pixels)
1767 g_object_unref(_map_pixbuf);
1768 _map_pixbuf = mrt->pixbuf;
1770 if(_center.unitx != mrt->new_center.unitx
1771 || _center.unity != mrt->new_center.unity
1772 || _zoom != mrt->zoom
1773 || _map_rotate_angle != mrt->rotate_angle)
1775 dbus_ifc_fire_view_position_changed(
1776 mrt->new_center, mrt->zoom, mrt->rotate_angle);
1779 _center = mrt->new_center;
1781 _map_rotate_angle = mrt->rotate_angle;
1783 gdk_pixbuf_rotate_matrix_fill_for_rotation(
1785 deg2rad(ROTATE_DIR_ENUM_DEGREES[_rotate_dir]
1786 - _map_rotate_angle));
1787 gdk_pixbuf_rotate_matrix_fill_for_rotation(
1788 _map_reverse_matrix,
1789 deg2rad(_map_rotate_angle
1790 - ROTATE_DIR_ENUM_DEGREES[_rotate_dir]));
1794 _map_offset_devx = 0;
1795 _map_offset_devy = 0;
1802 /* Ignore this new pixbuf. We have newer ones coming. */
1803 g_object_unref(mrt->pixbuf);
1807 g_slice_free(MapRenderTask, mrt);
1809 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
1814 /* Routine draws one partly-transparent pixbuf on top of the another (base map). For efficiency, we
1815 assume that base map's tile have no transparent pixels (because it should not have them). We also
1816 assume that pixbufs are have the same size. */
1818 combine_tiles (GdkPixbuf *dst_pixbuf, GdkPixbuf *src_pixbuf)
1820 gint s_n_channels = gdk_pixbuf_get_n_channels (src_pixbuf);
1821 gint d_n_channels = gdk_pixbuf_get_n_channels (dst_pixbuf);
1822 gint bps = gdk_pixbuf_get_bits_per_sample (dst_pixbuf);
1823 gint width, height, x, y, d_delta, s_delta;
1826 if (gdk_pixbuf_get_colorspace (dst_pixbuf) != gdk_pixbuf_get_colorspace (src_pixbuf)) {
1827 printf ("combine return (1)\n");
1830 if (gdk_pixbuf_get_colorspace (dst_pixbuf) != GDK_COLORSPACE_RGB) {
1831 printf ("combine return (2)\n");
1835 if (bps != gdk_pixbuf_get_bits_per_sample (src_pixbuf)) {
1836 printf ("combine return (5)\n");
1840 width = gdk_pixbuf_get_width (dst_pixbuf);
1841 height = gdk_pixbuf_get_height (dst_pixbuf);
1843 if (width != gdk_pixbuf_get_width (src_pixbuf)) {
1844 printf ("combine return (6)\n");
1847 if (height != gdk_pixbuf_get_height (src_pixbuf)) {
1848 printf ("combine return (7)\n");
1852 s_delta = (bps >> 3) * s_n_channels;
1853 d_delta = (bps >> 3) * d_n_channels;
1854 d_p = gdk_pixbuf_get_pixels (dst_pixbuf);
1855 s_p = gdk_pixbuf_get_pixels (src_pixbuf);
1857 /* ok, we're ready to combine */
1858 for (y = 0; y < height; y++) {
1859 for (x = 0; x < width; x++, d_p += d_delta, s_p += s_delta) {
1860 /* TODO: alpha blending? */
1861 if (s_n_channels == 3 || s_p[3]) {
1872 thread_render_map(MapRenderTask *mrt)
1875 gint start_tilex, start_tiley, stop_tilex, stop_tiley;
1876 gint x = 0, y, num_tilex, num_tiley;
1877 gint diag_halflength_units;
1879 gint tile_rothalf_pixels;
1880 gint curr_tile_to_draw, num_tiles_to_draw;
1882 ThreadLatch *refresh_latch = NULL;
1884 static gint8 auto_download_batch_id = INT8_MIN;
1885 printf("%s(%d, %d, %d, %d, %d, %d)\n", __PRETTY_FUNCTION__,
1886 mrt->screen_width_pixels, mrt->screen_height_pixels,
1887 mrt->new_center.unitx, mrt->new_center.unity, mrt->zoom,
1890 /* If there are more render tasks in the queue, skip this one. */
1891 if(g_thread_pool_unprocessed(_mrt_thread_pool))
1893 g_slice_free(MapRenderTask, mrt);
1895 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
1899 angle_rad = deg2rad(ROTATE_DIR_ENUM_DEGREES[_rotate_dir]
1900 - mrt->rotate_angle);
1902 gdk_pixbuf_rotate_matrix_fill_for_rotation(matrix, angle_rad);
1904 /* Determine (roughly) the tiles we might have to process.
1905 * Basically, we take the center unit and subtract the maximum dimension
1906 * of the screen plus the maximum additional pixels of a rotated tile.
1908 tile_rothalf_pixels = MAX(
1909 fabsf(TILE_HALFDIAG_PIXELS * sinf((PI / 4) - angle_rad)),
1910 fabsf(TILE_HALFDIAG_PIXELS * cosf((PI / 4) - angle_rad)));
1912 mrt->zoom = _next_zoom;
1914 if(mrt->repo->type != REPOTYPE_NONE && mrt->repo->db)
1915 cache_amount = _auto_download_precache;
1917 cache_amount = 1; /* No cache. */
1919 diag_halflength_units = pixel2zunit(TILE_HALFDIAG_PIXELS
1920 + MAX(mrt->screen_width_pixels, mrt->screen_height_pixels) / 2,
1922 start_tilex = unit2ztile(
1923 mrt->new_center.unitx - diag_halflength_units
1924 + _map_correction_unitx, mrt->zoom);
1925 start_tilex = MAX(start_tilex - (cache_amount - 1), 0);
1926 start_tiley = unit2ztile(
1927 mrt->new_center.unity - diag_halflength_units
1928 + _map_correction_unity, mrt->zoom);
1929 start_tiley = MAX(start_tiley - (cache_amount - 1), 0);
1930 stop_tilex = unit2ztile(mrt->new_center.unitx + diag_halflength_units
1931 + _map_correction_unitx, mrt->zoom);
1932 stop_tilex = MIN(stop_tilex + (cache_amount - 1),
1933 unit2ztile(WORLD_SIZE_UNITS, mrt->zoom));
1934 stop_tiley = unit2ztile(mrt->new_center.unity + diag_halflength_units
1935 + _map_correction_unity, mrt->zoom);
1936 stop_tiley = MIN(stop_tiley + (cache_amount - 1),
1937 unit2ztile(WORLD_SIZE_UNITS, mrt->zoom));
1939 num_tilex = (stop_tilex - start_tilex + 1);
1940 num_tiley = (stop_tiley - start_tiley + 1);
1941 tile_dev = g_new0(gfloat, num_tilex * num_tiley * 2);
1943 ++auto_download_batch_id;
1945 /* Iterate through the tiles and mark which ones need retrieval. */
1946 num_tiles_to_draw = 0;
1947 for(y = 0; y < num_tiley; ++y)
1949 for(x = 0; x < num_tilex; ++x)
1953 /* Find the device location of this tile's center. */
1955 tile2pixel(x + start_tilex) + (TILE_SIZE_PIXELS >> 1),
1956 tile2pixel(y + start_tiley) + (TILE_SIZE_PIXELS >> 1),
1958 mrt->new_center, mrt->zoom, matrix);
1960 /* Apply Map Correction. */
1961 devx -= unit2zpixel(_map_correction_unitx, mrt->zoom);
1962 devy -= unit2zpixel(_map_correction_unity, mrt->zoom);
1964 /* Skip this tile under the following conditions:
1965 * devx < -tile_rothalf_pixels
1966 * devx > _view_width_pixels + tile_rothalf_pixels
1967 * devy < -tile_rothalf_pixels
1968 * devy > _view_height_pixels + tile_rothalf_pixels
1970 if(((unsigned)(devx + tile_rothalf_pixels))
1971 < (_view_width_pixels + (2 * tile_rothalf_pixels))
1972 && ((unsigned)(devy + tile_rothalf_pixels))
1973 < (_view_height_pixels + (2 * tile_rothalf_pixels)))
1975 tile_dev[2 * (y * num_tilex + x)] = devx;
1976 tile_dev[2 * (y * num_tilex + x) + 1] = devy;
1977 ++num_tiles_to_draw;
1981 tile_dev[2 * (y * num_tilex + x)] = FLT_MAX;
1986 mrt->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8,
1987 mrt->screen_width_pixels, mrt->screen_height_pixels);
1988 _refresh_map_after_download = FALSE;
1990 /* Iterate through the tiles, get them (or queue a download if they're
1991 * not in the cache), and rotate them into the pixbuf. */
1992 for(y = curr_tile_to_draw = 0; y < num_tiley; ++y)
1994 gint tiley = y + start_tiley;
1995 for(x = 0; x < num_tilex; ++x)
1997 GdkPixbuf *tile_pixbuf = NULL, *layer_pixbuf = NULL;
1998 gboolean started_download = FALSE;
1999 gint zoff, zoff_base;
2001 RepoData* repo_p = mrt->repo;
2003 tilex = x + start_tilex;
2004 zoff_base = mrt->repo->double_size ? 1 : 0;
2006 /* iterating over tile and all it's layers */
2009 started_download = FALSE;
2011 /* for layers we must use resolution of underlying map */
2014 /* if this is not a bottom layer and layer not enabled, skip it */
2015 if (repo_p != mrt->repo && !repo_p->layer_enabled)
2017 repo_p = repo_p->layers;
2021 /* Iteratively try to retrieve a map to draw the tile. */
2022 while((mrt->zoom + zoff) <= MAX_ZOOM && zoff < 4)
2024 /* Check if we're actually going to draw this map. */
2025 if(tile_dev[2 * (y*num_tilex + x)] != FLT_MAX)
2027 if(NULL != (layer_pixbuf = mapdb_get(
2028 repo_p, mrt->zoom + zoff,
2032 /* Found a map. Check for it's age. */
2033 gint age = get_tile_age (layer_pixbuf);
2034 printf ("Tile age (%d)\n", age);
2036 /* throw away tile only if we can download something */
2037 if (!repo_p->layer_refresh_interval ||
2038 age < repo_p->layer_refresh_interval * 60 ||
2041 /* if this is a layer's tile, join with main tile */
2042 if (repo_p != mrt->repo)
2044 /* but only if main layer is exists */
2046 combine_tiles (tile_pixbuf, layer_pixbuf);
2047 g_object_unref (layer_pixbuf);
2050 tile_pixbuf = layer_pixbuf;
2056 g_object_unref (layer_pixbuf);
2060 _refresh_map_after_download = TRUE;
2062 /* Else we're not going to be drawing this map, so just check
2063 * if it's in the database. */
2064 else if(mapdb_exists(
2065 repo_p, mrt->zoom + zoff,
2073 /* No map; download, if we should. */
2074 if(!started_download && _auto_download
2075 && mrt->repo->type != REPOTYPE_NONE
2076 /* Make sure this map is within dl zoom limits. */
2077 && ((unsigned)(mrt->zoom + zoff - mrt->repo->min_zoom)
2078 <= (mrt->repo->max_zoom - mrt->repo->min_zoom))
2079 /* Make sure this map matches the dl_zoom_steps,
2080 * or that there currently is no cache. */
2081 && (!repo_p->db || !((mrt->zoom + zoff
2082 - (mrt->repo->double_size ? 1 : 0))
2083 % mrt->repo->dl_zoom_steps))
2084 /* Make sure this tile is even possible. */
2085 && ((unsigned)(tilex >> zoff)
2086 < unit2ztile(WORLD_SIZE_UNITS, mrt->zoom + zoff)
2087 && (unsigned)(tiley >> zoff)
2088 < unit2ztile(WORLD_SIZE_UNITS, mrt->zoom + zoff)))
2090 started_download = TRUE;
2094 refresh_latch = g_slice_new(ThreadLatch);
2095 refresh_latch->is_open = FALSE;
2096 refresh_latch->is_done_adding_tasks = FALSE;
2097 refresh_latch->num_tasks = 1;
2098 refresh_latch->num_done = 0;
2099 refresh_latch->mutex = g_mutex_new();
2100 refresh_latch->cond = g_cond_new();
2103 ++refresh_latch->num_tasks;
2105 mapdb_initiate_update(
2111 auto_download_batch_id,
2112 (abs((tilex >> zoff) - unit2ztile(
2113 mrt->new_center.unitx, mrt->zoom + zoff))
2114 + abs((tiley >> zoff) - unit2ztile(
2115 mrt->new_center.unity, mrt->zoom + zoff))),
2119 /* Try again at a coarser resolution. Only for underlying map.*/
2120 if (repo_p == mrt->repo && repo_p->type != REPOTYPE_NONE)
2126 repo_p = repo_p->layers;
2129 /* use zoom of the base map */
2134 gint boundx, boundy, width, height;
2137 gdk_pixbuf_rotate_matrix_mult_number(matrix, 1 << zoff);
2138 gdk_pixbuf_rotate(mrt->pixbuf,
2139 tile_dev[2 * (y * num_tilex + x)],
2140 tile_dev[2 * (y * num_tilex + x) + 1],
2143 ((tilex - ((tilex >> zoff) << zoff))
2144 << (TILE_SIZE_P2 - zoff))
2145 + (TILE_SIZE_PIXELS >> (1 + zoff)),
2146 ((tiley - ((tiley>>zoff) << zoff))
2147 << (TILE_SIZE_P2 - zoff))
2148 + (TILE_SIZE_PIXELS >> (1 + zoff)),
2149 TILE_SIZE_PIXELS >> zoff,
2150 TILE_SIZE_PIXELS >> zoff,
2151 &boundx, &boundy, &width, &height);
2152 g_object_unref(tile_pixbuf);
2153 /* Un-multiply the matrix that we used for blitting. Good
2154 * thing we're multiplying by powers of two, or this wouldn't
2155 * work consistently... */
2157 gdk_pixbuf_rotate_matrix_mult_number(
2158 matrix, 1.f / (1 << zoff));
2160 /* usleep(10000); DEBUG */
2164 /* Don't replace the pixbuf unless/until the mouse is released. */
2165 g_mutex_lock(_mouse_mutex);
2166 ++_pending_replaces;
2167 g_idle_add_full(G_PRIORITY_HIGH_IDLE + 20,
2168 (GSourceFunc)map_replace_pixbuf_idle, mrt, NULL);
2169 g_mutex_unlock(_mouse_mutex);
2171 /* Release the view-change lock. */
2174 g_mutex_lock(refresh_latch->mutex);
2175 if(refresh_latch->num_tasks == refresh_latch->num_done)
2177 /* Fast little workers, aren't they? */
2178 g_mutex_unlock(refresh_latch->mutex);
2179 g_cond_free(refresh_latch->cond);
2180 g_mutex_free(refresh_latch->mutex);
2181 g_slice_free(ThreadLatch, refresh_latch);
2185 refresh_latch->is_done_adding_tasks = TRUE;
2186 refresh_latch->is_open = TRUE;
2187 g_cond_signal(refresh_latch->cond);
2188 g_mutex_unlock(refresh_latch->mutex);
2194 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
2199 map_cb_configure(GtkWidget *widget, GdkEventConfigure *event)
2201 gint old_view_width_pixels, old_view_height_pixels;
2202 GdkPixbuf *old_map_pixbuf;
2203 printf("%s(%d, %d)\n", __PRETTY_FUNCTION__,
2204 _map_widget->allocation.width, _map_widget->allocation.height);
2206 if(_map_widget->allocation.width == 1
2207 && _map_widget->allocation.height == 1)
2208 /* Special case - first allocation - not persistent. */
2211 old_view_width_pixels = _view_width_pixels;
2212 old_view_height_pixels = _view_height_pixels;
2213 _view_width_pixels = _map_widget->allocation.width;
2214 _view_height_pixels = _map_widget->allocation.height;
2215 _view_halfwidth_pixels = _view_width_pixels / 2;
2216 _view_halfheight_pixels = _view_height_pixels / 2;
2218 g_object_unref(_map_pixmap);
2219 _map_pixmap = gdk_pixmap_new(
2220 _map_widget->window,
2221 _view_width_pixels, _view_height_pixels,
2222 -1); /* -1: use bit depth of widget->window. */
2224 old_map_pixbuf = _map_pixbuf;
2225 _map_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8,
2226 _view_width_pixels, _view_height_pixels);
2229 gint oldnew_diffx = (gint)(_view_width_pixels
2230 - old_view_width_pixels) / 2;
2231 gint oldnew_diffy = (gint)(_view_height_pixels
2232 - old_view_height_pixels) / 2;
2233 gdk_pixbuf_copy_area(old_map_pixbuf,
2234 MAX(0, -oldnew_diffx), MAX(0, -oldnew_diffy),
2235 MIN(_view_width_pixels, old_view_width_pixels),
2236 MIN(_view_height_pixels, old_view_height_pixels),
2238 MAX(0, oldnew_diffx), MAX(0, oldnew_diffy));
2241 g_object_unref(old_map_pixbuf);
2243 /* Set _scale_rect. */
2244 _scale_rect.x = (_view_width_pixels - SCALE_WIDTH) / 2;
2245 _scale_rect.width = SCALE_WIDTH;
2246 pango_layout_set_text(_scale_layout, "0", -1);
2247 pango_layout_get_pixel_size(_scale_layout, NULL, &_scale_rect.height);
2248 _scale_rect.y = _view_height_pixels - _scale_rect.height - 1;
2250 /* Set _zoom rect. */
2251 pango_layout_set_text(_zoom_layout, "00", -1);
2252 pango_layout_get_pixel_size(_zoom_layout, &_zoom_rect.width,
2253 &_zoom_rect.height);
2254 _zoom_rect.width *= 1.25;
2255 pango_layout_set_width(_zoom_layout, _zoom_rect.width);
2256 pango_layout_context_changed(_zoom_layout);
2257 _zoom_rect.x = _scale_rect.x - _zoom_rect.width;
2258 _zoom_rect.y = _view_height_pixels - _zoom_rect.height - 1;
2260 /* Set _comprose_rect. */
2261 _comprose_rect.x = _view_width_pixels - 25 - _comprose_rect.width;
2262 _comprose_rect.y = _view_height_pixels - 25 - _comprose_rect.height;
2267 /* Fire the screen_dimensions_changed DBUS signal. */
2268 dbus_ifc_fire_view_dimensions_changed(
2269 _view_width_pixels, _view_height_pixels);
2271 /* If Auto-Center is set to Lead, then recalc center. */
2272 if(_center_mode == CENTER_LEAD)
2273 map_center_unit(map_calc_new_center(_next_zoom));
2275 map_center_unit(_next_center);
2277 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2282 sat_panel_expose(GtkWidget *widget, GdkEventExpose *event)
2286 printf("%s()\n", __PRETTY_FUNCTION__);
2288 draw_sat_info(widget,
2290 widget->allocation.width,
2291 widget->allocation.height,
2294 /* Sat View/In Use */
2295 tmp = g_strdup_printf("%d/%d", _gps.satinuse, _gps.satinview);
2296 pango_layout_set_text(_sat_panel_layout, tmp, -1);
2297 pango_layout_set_alignment(_sat_panel_layout, PANGO_ALIGN_LEFT);
2298 gdk_draw_layout(widget->window,
2299 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
2307 case 3: tmp = g_strdup_printf("%dD fix", _gps.fix); break;
2308 default: tmp = g_strdup_printf("nofix"); break;
2310 pango_layout_set_text(_sat_panel_layout, tmp, -1);
2311 pango_layout_set_alignment(_sat_panel_layout, PANGO_ALIGN_RIGHT);
2312 pango_layout_get_pixel_size(_sat_panel_layout, &x, &y);
2313 gdk_draw_layout(widget->window,
2314 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
2315 widget->allocation.width - 20 - x, 2,
2319 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
2324 heading_panel_expose(GtkWidget *widget, GdkEventExpose *event)
2326 gint size, xoffset, yoffset, i, x, y;
2330 printf("%s()\n", __PRETTY_FUNCTION__);
2332 size = MIN(widget->allocation.width, widget->allocation.height);
2333 if(widget->allocation.width > widget->allocation.height)
2335 xoffset = (widget->allocation.width - widget->allocation.height) / 2;
2341 yoffset = (widget->allocation.height - widget->allocation.width) / 2;
2343 pango_font_description_set_size(_heading_panel_fontdesc,12*PANGO_SCALE);
2344 pango_layout_set_font_description(_heading_panel_layout,
2345 _heading_panel_fontdesc);
2346 pango_layout_set_alignment(_heading_panel_layout, PANGO_ALIGN_CENTER);
2348 text = g_strdup_printf("%3.0f°", _gps.heading);
2349 pango_layout_set_text(_heading_panel_layout, text, -1);
2350 pango_layout_get_pixel_size(_heading_panel_layout, &x, &y);
2352 gdk_draw_layout(widget->window,
2353 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
2354 xoffset + size/2 - x/2,
2355 yoffset + size - y - 2, _heading_panel_layout);
2358 gdk_draw_arc (widget->window,
2359 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
2361 xoffset, yoffset + size/2,
2365 /* Simple arrow for heading*/
2366 gdk_draw_line(widget->window,
2367 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
2368 xoffset + size/2 + 3,
2369 yoffset + size - y - 5,
2371 yoffset + size/2 + 5);
2373 gdk_draw_line(widget->window,
2374 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
2375 xoffset + size/2 - 3,
2376 yoffset + size - y - 5,
2378 yoffset + size/2 + 5);
2380 gdk_draw_line(widget->window,
2381 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
2382 xoffset + size/2 - 3,
2383 yoffset + size - y - 5,
2385 yoffset + size - y - 8);
2387 gdk_draw_line(widget->window,
2388 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
2389 xoffset + size/2 + 3,
2390 yoffset + size - y - 5,
2392 yoffset + size - y - 8);
2394 gint angle[5] = {-90,-45,0,45,90};
2395 gint fsize[5] = {0,4,10,4,0};
2396 for(i = 0; i < 5; i++)
2398 dir = (gint)(_gps.heading/45)*45 + angle[i];
2403 case 360: text = g_strdup("N"); break;
2406 text = g_strdup("NE"); break;
2408 text = g_strdup("E"); break;
2410 text = g_strdup("SE"); break;
2412 text = g_strdup("S"); break;
2414 text = g_strdup("SW"); break;
2417 text = g_strdup("W"); break;
2420 text = g_strdup("NW"); break;
2422 text = g_strdup("??");
2426 tmp = deg2rad(dir - _gps.heading);
2427 gdk_draw_line(widget->window,
2428 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
2429 xoffset + size/2 + ((size/2 - 5) * sinf(tmp)),
2430 yoffset + size - ((size/2 - 5) * cosf(tmp)),
2431 xoffset + size/2 + ((size/2 + 5) * sinf(tmp)),
2432 yoffset + size - ((size/2 + 5) * cosf(tmp)));
2435 if(abs((gint)(_gps.heading/45)*45 - _gps.heading)
2436 > abs((gint)(_gps.heading/45)*45 + 45 - _gps.heading)
2440 pango_font_description_set_size(_heading_panel_fontdesc,
2441 (10 + x)*PANGO_SCALE);
2442 pango_layout_set_font_description(_heading_panel_layout,
2443 _heading_panel_fontdesc);
2444 pango_layout_set_text(_heading_panel_layout, text, -1);
2445 pango_layout_get_pixel_size(_heading_panel_layout, &x, &y);
2446 x = xoffset + size/2 + ((size/2 + 15) * sinf(tmp)) - x/2,
2447 y = yoffset + size - ((size/2 + 15) * cosf(tmp)) - y/2,
2449 gdk_draw_layout(widget->window,
2450 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
2451 x, y, _heading_panel_layout);
2455 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
2460 map_cb_expose(GtkWidget *widget, GdkEventExpose *event)
2463 printf("%s(%d, %d, %d, %d)\n", __PRETTY_FUNCTION__,
2464 event->area.x, event->area.y,
2465 event->area.width, event->area.height);
2468 _map_widget->window,
2469 _gc[COLORABLE_MARK],
2471 event->area.x - _map_offset_devx, event->area.y - _map_offset_devy,
2472 event->area.x, event->area.y,
2473 event->area.width, event->area.height);
2475 /* Draw the mark. */
2476 if((((unsigned)(_mark_bufx1 + _draw_width)
2477 <= _view_width_pixels+2*_draw_width)
2478 &&((unsigned)(_mark_bufy1 + _draw_width)
2479 <= _view_height_pixels+2*_draw_width))
2480 || (((unsigned)(_mark_bufx2 + _draw_width)
2481 <= _view_width_pixels+2*_draw_width)
2482 &&((unsigned)(_mark_bufy2 + _draw_width)
2483 <= _view_height_pixels+2*_draw_width)))
2486 _map_widget->window,
2487 _gps_state == RCVR_FIXED
2488 ? _gc[COLORABLE_MARK] : _gc[COLORABLE_MARK_OLD],
2489 FALSE, /* not filled. */
2490 _mark_bufx1 - _draw_width + _map_offset_devx,
2491 _mark_bufy1 - _draw_width + _map_offset_devy,
2492 2 * _draw_width, 2 * _draw_width,
2495 _map_widget->window,
2496 _gps_state == RCVR_FIXED
2498 ? _gc[COLORABLE_MARK_VELOCITY] : _gc[COLORABLE_MARK])
2499 : _gc[COLORABLE_MARK_OLD],
2500 _mark_bufx1 + _map_offset_devx,
2501 _mark_bufy1 + _map_offset_devy,
2502 _mark_bufx2 + _map_offset_devx,
2503 _mark_bufy2 + _map_offset_devy);
2506 /* draw zoom box if so wanted */
2507 if(_show_zoomlevel) {
2508 gchar *buffer = g_strdup_printf("%d", _zoom);
2509 gdk_draw_rectangle(_map_widget->window,
2510 _map_widget->style->bg_gc[GTK_STATE_ACTIVE],
2512 _zoom_rect.x, _zoom_rect.y,
2513 _zoom_rect.width, _zoom_rect.height);
2514 gdk_draw_rectangle(_map_widget->window,
2515 _map_widget->style->fg_gc[GTK_STATE_ACTIVE],
2517 _zoom_rect.x, _zoom_rect.y,
2518 _zoom_rect.width, _zoom_rect.height);
2519 pango_layout_set_text(_zoom_layout, buffer, -1);
2520 gdk_draw_layout(_map_widget->window,
2521 _map_widget->style->fg_gc[GTK_STATE_ACTIVE],
2522 _zoom_rect.x + _zoom_rect.width / 2,
2523 _zoom_rect.y, _zoom_layout);
2526 /* Draw scale, if necessary. */
2529 gdk_rectangle_intersect(&event->area, &_scale_rect, &event->area);
2530 if(event->area.width && event->area.height)
2532 gdk_draw_rectangle(_map_widget->window,
2533 _map_widget->style->bg_gc[GTK_STATE_ACTIVE],
2535 _scale_rect.x, _scale_rect.y,
2536 _scale_rect.width, _scale_rect.height);
2537 gdk_draw_rectangle(_map_widget->window,
2538 _map_widget->style->fg_gc[GTK_STATE_ACTIVE],
2540 _scale_rect.x, _scale_rect.y,
2541 _scale_rect.width, _scale_rect.height);
2543 /* Now calculate and draw the distance. */
2547 gdouble lat1, lon1, lat2, lon2;
2550 unit2latlon(_center.unitx - pixel2unit(SCALE_WIDTH / 2 - 4),
2551 _center.unity, lat1, lon1);
2552 unit2latlon(_center.unitx + pixel2unit(SCALE_WIDTH / 2 - 4),
2553 _center.unity, lat2, lon2);
2554 distance = calculate_distance(lat1, lon1, lat2, lon2)
2555 * UNITS_CONVERT[_units];
2558 snprintf(buffer, sizeof(buffer), "%0.2f %s", distance,
2559 UNITS_ENUM_TEXT[_units]);
2560 else if(distance < 10.f)
2561 snprintf(buffer, sizeof(buffer), "%0.1f %s", distance,
2562 UNITS_ENUM_TEXT[_units]);
2564 snprintf(buffer, sizeof(buffer), "%0.f %s", distance,
2565 UNITS_ENUM_TEXT[_units]);
2566 pango_layout_set_text(_scale_layout, buffer, -1);
2568 pango_layout_get_pixel_size(_scale_layout, &width, NULL);
2570 /* Draw the layout itself. */
2571 gdk_draw_layout(_map_widget->window,
2572 _map_widget->style->fg_gc[GTK_STATE_ACTIVE],
2573 _scale_rect.x + (_scale_rect.width - width) / 2,
2574 _scale_rect.y, _scale_layout);
2576 /* Draw little hashes on the ends. */
2577 gdk_draw_line(_map_widget->window,
2578 _map_widget->style->fg_gc[GTK_STATE_ACTIVE],
2580 _scale_rect.y + _scale_rect.height / 2 - 4,
2582 _scale_rect.y + _scale_rect.height / 2 + 4);
2583 gdk_draw_line(_map_widget->window,
2584 _map_widget->style->fg_gc[GTK_STATE_ACTIVE],
2586 _scale_rect.y + _scale_rect.height / 2,
2587 _scale_rect.x + (_scale_rect.width - width) / 2 - 4,
2588 _scale_rect.y + _scale_rect.height / 2);
2589 gdk_draw_line(_map_widget->window,
2590 _map_widget->style->fg_gc[GTK_STATE_ACTIVE],
2591 _scale_rect.x + _scale_rect.width - 4,
2592 _scale_rect.y + _scale_rect.height / 2 - 4,
2593 _scale_rect.x + _scale_rect.width - 4,
2594 _scale_rect.y + _scale_rect.height / 2 + 4);
2595 gdk_draw_line(_map_widget->window,
2596 _map_widget->style->fg_gc[GTK_STATE_ACTIVE],
2597 _scale_rect.x + _scale_rect.width - 4,
2598 _scale_rect.y + _scale_rect.height / 2,
2599 _scale_rect.x + (_scale_rect.width + width) / 2 + 4,
2600 _scale_rect.y + _scale_rect.height / 2);
2605 /* Draw the compass rose, if necessary. */
2609 gint offsetx, offsety;
2612 offsetx = _comprose_rect.x;
2613 offsety = _comprose_rect.y;
2615 gdk_pixbuf_rotate_vector(&x, &y, _map_rotate_matrix, 0, 12);
2616 points[0].x = offsetx + x + 0.5f; points[0].y = offsety + y + 0.5f;
2617 gdk_pixbuf_rotate_vector(&x, &y, _map_rotate_matrix, 20, 30);
2618 points[1].x = offsetx + x + 0.5f; points[1].y = offsety + y + 0.5f;
2619 gdk_pixbuf_rotate_vector(&x, &y, _map_rotate_matrix, 0, -45);
2620 points[2].x = offsetx + x + 0.5f; points[2].y = offsety + y + 0.5f;
2621 gdk_pixbuf_rotate_vector(&x, &y, _map_rotate_matrix, -20, 30);
2622 points[3].x = offsetx + x + 0.5f; points[3].y = offsety + y + 0.5f;
2624 gdk_draw_polygon(_map_widget->window,
2625 _map_widget->style->bg_gc[GTK_STATE_ACTIVE],
2628 gdk_draw_polygon(_map_widget->window,
2629 _map_widget->style->fg_gc[GTK_STATE_ACTIVE],
2630 FALSE, /* NOT FILLED */
2633 gdk_draw_layout(_map_widget->window,
2634 _map_widget->style->fg_gc[GTK_STATE_ACTIVE],
2635 _comprose_rect.x - _comprose_rect.width / 2 + 1,
2636 _comprose_rect.y - _comprose_rect.height / 2 - 4,
2640 /* Draw a stopwatch if we're redrawing the map. */
2641 for(i = _redraw_count - 1; i >= 0; i--)
2644 _map_widget->window,
2645 _map_widget->style->fg_gc[GTK_STATE_ACTIVE],
2648 _redraw_wait_bounds.x + i
2649 * HOURGLASS_SEPARATION,
2650 _redraw_wait_bounds.y,
2651 _redraw_wait_bounds.width,
2652 _redraw_wait_bounds.height,
2653 GDK_RGB_DITHER_NONE, 0, 0);
2656 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2661 latlon_cb_copy_clicked(GtkWidget *widget, LatlonDialog *lld) {
2664 snprintf(buffer, sizeof(buffer),
2666 gtk_label_get_text(GTK_LABEL(lld->lat)),
2667 gtk_label_get_text(GTK_LABEL(lld->lon)));
2669 gtk_clipboard_set_text(
2670 gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), buffer, -1);
2674 latlon_cb_fmt_changed(GtkWidget *widget, LatlonDialog *lld) {
2677 fmt = gtk_combo_box_get_active(GTK_COMBO_BOX(lld->fmt_combo));
2680 gint old = _degformat; /* augh... */
2681 gchar buffer[LL_FMT_LEN];
2682 gchar buffer2[LL_FMT_LEN];
2686 format_lat_lon(lld->glat, lld->glon, buffer, buffer2);
2688 //lat_format(lld->glat, buffer);
2689 gtk_label_set_label(GTK_LABEL(lld->lat), buffer);
2690 //lon_format(lld->glon, buffer);
2692 if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use)
2693 gtk_label_set_label(GTK_LABEL(lld->lon), buffer2);
2695 gtk_label_set_label(GTK_LABEL(lld->lon), g_strdup(""));
2698 // And set the titles
2699 gtk_label_set_label(GTK_LABEL(lld->lat_title),
2700 DEG_FORMAT_ENUM_TEXT[_degformat].short_field_1 );
2702 if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use)
2703 gtk_label_set_label(GTK_LABEL(lld->lon_title),
2704 DEG_FORMAT_ENUM_TEXT[_degformat].short_field_2 );
2706 gtk_label_set_label(GTK_LABEL(lld->lon_title), g_strdup(""));
2714 latlon_dialog(gdouble lat, gdouble lon)
2720 GtkWidget *lbl_lon_title;
2721 GtkWidget *lbl_lat_title;
2724 GtkWidget *cmb_format;
2725 GtkWidget *btn_copy = NULL;
2726 gint prev_degformat = _degformat;
2727 gint fallback_deg_format = _degformat;
2729 printf("%s()\n", __PRETTY_FUNCTION__);
2731 // Check that the current coord system supports the select position
2732 if(!coord_system_check_lat_lon (lat, lon, &fallback_deg_format))
2734 _degformat = fallback_deg_format;
2738 dialog = gtk_dialog_new_with_buttons(_("Show Position"),
2739 GTK_WINDOW(_window), GTK_DIALOG_MODAL,
2740 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
2743 /* Set the lat/lon strings. */
2744 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
2745 table = gtk_table_new(5, 2, FALSE), TRUE, TRUE, 0);
2747 gtk_table_attach(GTK_TABLE(table),
2748 lbl_lat_title = gtk_label_new(/*_("Lat")*/ DEG_FORMAT_ENUM_TEXT[_degformat].short_field_1 ),
2749 0, 1, 0, 1, GTK_FILL, 0, 2, 4);
2750 gtk_misc_set_alignment(GTK_MISC(lbl_lat_title), 1.f, 0.5f);
2751 gtk_table_attach(GTK_TABLE(table),
2752 txt_lat = gtk_label_new(""),
2753 1, 2, 0, 1, GTK_FILL, 0, 2, 4);
2754 gtk_misc_set_alignment(GTK_MISC(txt_lat), 1.f, 0.5f);
2757 gtk_table_attach(GTK_TABLE(table),
2758 lbl_lon_title = gtk_label_new(/*_("Lon")*/ DEG_FORMAT_ENUM_TEXT[_degformat].short_field_2 ),
2759 0, 1, 1, 2, GTK_FILL, 0, 2, 4);
2760 gtk_misc_set_alignment(GTK_MISC(lbl_lon_title), 1.f, 0.5f);
2762 gtk_table_attach(GTK_TABLE(table),
2763 txt_lon = gtk_label_new(""),
2764 1, 2, 1, 2, GTK_FILL, 0, 2, 4);
2765 gtk_misc_set_alignment(GTK_MISC(txt_lon), 1.f, 0.5f);
2768 gtk_table_attach(GTK_TABLE(table),
2769 label = gtk_label_new(_("Format")),
2770 0, 1, 2, 3, GTK_FILL, 0, 2, 4);
2771 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
2772 gtk_table_attach(GTK_TABLE(table),
2773 label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
2774 1, 2, 2, 3, GTK_FILL, 0, 2, 4);
2775 gtk_container_add(GTK_CONTAINER(label),
2776 cmb_format = gtk_combo_box_new_text());
2777 gtk_table_attach(GTK_TABLE(table),
2778 btn_copy = gtk_button_new_with_label(_("Copy")),
2779 0, 2, 3, 4, GTK_FILL, 0, 2, 4);
2783 gchar buffer[LL_FMT_LEN];
2784 gchar buffer2[LL_FMT_LEN];
2786 format_lat_lon(lat, lon, buffer, buffer2);
2788 //lat_format(lat, buffer);
2789 gtk_label_set_label(GTK_LABEL(txt_lat), buffer);
2790 //lat_format(lon, buffer);
2791 if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use)
2792 gtk_label_set_label(GTK_LABEL(txt_lon), buffer2);
2794 gtk_label_set_label(GTK_LABEL(txt_lon), g_strdup(""));
2797 /* Fill in formats */
2801 for(i = 0; i < DEG_FORMAT_ENUM_COUNT; i++) {
2802 gtk_combo_box_append_text(GTK_COMBO_BOX(cmb_format),
2803 DEG_FORMAT_ENUM_TEXT[i].name);
2805 gtk_combo_box_set_active(GTK_COMBO_BOX(cmb_format), _degformat);
2809 /* setup cb context */
2810 lld.fmt_combo = cmb_format;
2816 lld.lat_title = lbl_lat_title;
2817 lld.lon_title = lbl_lon_title;
2819 /* Connect Signals */
2820 g_signal_connect(G_OBJECT(cmb_format), "changed",
2821 G_CALLBACK(latlon_cb_fmt_changed), &lld);
2822 g_signal_connect(G_OBJECT(btn_copy), "clicked",
2823 G_CALLBACK(latlon_cb_copy_clicked), &lld);
2825 gtk_widget_show_all(dialog);
2827 gtk_dialog_run(GTK_DIALOG(dialog));
2829 _degformat = prev_degformat; // Put back incase it had to be auto changed
2831 gtk_widget_hide(dialog);
2833 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2839 * This is a multi-purpose function for allowing the user to select a file
2840 * for either reading or writing. If chooser_action is
2841 * GTK_FILE_CHOOSER_ACTION_OPEN, then bytes_out and size_out must be
2842 * non-NULL. If chooser_action is GTK_FILE_CHOOSER_ACTION_SAVE, then
2843 * handle_out must be non-NULL. Either dir or file (or both) can be NULL.
2844 * This function returns TRUE if a file was successfully opened.
2847 display_open_file(GtkWindow *parent, gchar **bytes_out,
2848 GnomeVFSHandle **handle_out, gint *size_out,
2849 gchar **dir, gchar **file, GtkFileChooserAction chooser_action)
2852 gboolean success = FALSE;
2853 printf("%s()\n", __PRETTY_FUNCTION__);
2855 dialog = hildon_file_chooser_dialog_new(parent, chooser_action);
2858 gtk_file_chooser_set_current_folder_uri(
2859 GTK_FILE_CHOOSER(dialog), *dir);
2862 gtk_file_chooser_set_uri(
2863 GTK_FILE_CHOOSER(dialog), *file);
2864 if(chooser_action == GTK_FILE_CHOOSER_ACTION_SAVE)
2866 /* Work around a bug in HildonFileChooserDialog. */
2867 gchar *basename = g_path_get_basename(*file);
2868 g_object_set(G_OBJECT(dialog), "autonaming", FALSE, NULL);
2869 gtk_file_chooser_set_current_name(
2870 GTK_FILE_CHOOSER(dialog), basename);
2875 gtk_widget_show_all(dialog);
2877 while(!success && gtk_dialog_run(GTK_DIALOG(dialog))==GTK_RESPONSE_OK)
2879 gchar *file_uri_str;
2880 GnomeVFSResult vfs_result;
2882 /* Get the selected filename. */
2883 file_uri_str = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(dialog));
2885 if((chooser_action == GTK_FILE_CHOOSER_ACTION_OPEN
2886 && (GNOME_VFS_OK != (vfs_result = gnome_vfs_read_entire_file(
2887 file_uri_str, size_out, bytes_out))))
2888 || (chooser_action == GTK_FILE_CHOOSER_ACTION_SAVE
2889 && GNOME_VFS_OK != (vfs_result = gnome_vfs_create(
2890 handle_out, file_uri_str,
2891 GNOME_VFS_OPEN_WRITE, FALSE, 0664))))
2893 gchar buffer[BUFFER_SIZE];
2894 snprintf(buffer, sizeof(buffer),
2895 "%s:\n%s", chooser_action == GTK_FILE_CHOOSER_ACTION_OPEN
2896 ? _("Failed to open file for reading")
2897 : _("Failed to open file for writing"),
2898 gnome_vfs_result_to_string(vfs_result));
2899 popup_error(dialog, buffer);
2904 g_free(file_uri_str);
2913 *dir = gtk_file_chooser_get_current_folder_uri(
2914 GTK_FILE_CHOOSER(dialog));
2917 /* If desired, save the file for later. */
2921 *file = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(dialog));
2925 gtk_widget_destroy(dialog);
2927 vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, success);
2934 PangoContext *pango_context;
2935 PangoFontDescription *pango_font;
2937 printf("%s()\n", __PRETTY_FUNCTION__);
2939 /* Cache some pango and GCs for drawing. */
2940 pango_context = gtk_widget_get_pango_context(_map_widget);
2941 _scale_layout = pango_layout_new(pango_context);
2942 pango_font = pango_font_description_new();
2943 pango_font_description_set_size(pango_font, 12 * PANGO_SCALE);
2944 pango_layout_set_font_description(_scale_layout, pango_font);
2948 pango_context = gtk_widget_get_pango_context(_map_widget);
2949 _aprs_label_layout = pango_layout_new(pango_context);
2950 pango_font = pango_font_description_new();
2951 pango_font_description_set_size(pango_font, 10 * PANGO_SCALE);
2952 pango_font_description_set_family(pango_font,"Sans Serif");
2953 pango_layout_set_font_description(_aprs_label_layout, pango_font);
2954 #endif // INCLUDE_APRS
2957 pango_context = gtk_widget_get_pango_context(_map_widget);
2958 _zoom_layout = pango_layout_new(pango_context);
2959 pango_font = pango_font_description_new();
2960 pango_font_description_set_size(pango_font, 12 * PANGO_SCALE);
2961 pango_layout_set_font_description(_zoom_layout, pango_font);
2962 pango_layout_set_alignment(_zoom_layout, PANGO_ALIGN_CENTER);
2965 pango_context = gtk_widget_get_pango_context(_map_widget);
2966 _comprose_layout = pango_layout_new(pango_context);
2967 pango_font = pango_font_description_new();
2968 pango_font_description_set_size(pango_font, 16 * PANGO_SCALE);
2969 pango_font_description_set_weight(pango_font, PANGO_WEIGHT_BOLD);
2970 pango_layout_set_font_description(_comprose_layout, pango_font);
2971 pango_layout_set_alignment(_comprose_layout, PANGO_ALIGN_CENTER);
2972 pango_layout_set_text(_comprose_layout, "N", -1);
2974 PangoRectangle rect;
2975 pango_layout_get_pixel_extents(_comprose_layout, &rect, NULL);
2976 _comprose_rect.width = rect.width + 3;
2977 _comprose_rect.height = rect.height + 3;
2981 _speed_limit_gc1 = gdk_gc_new (_map_widget->window);
2985 gdk_gc_set_rgb_fg_color(_speed_limit_gc1, &color);
2989 _speed_limit_gc2 = gdk_gc_new(_map_widget->window);
2990 gdk_gc_set_rgb_fg_color(_speed_limit_gc2, &color);
2991 pango_context = gtk_widget_get_pango_context(_map_widget);
2992 _speed_limit_layout = pango_layout_new(pango_context);
2993 pango_font = pango_font_description_new();
2994 pango_font_description_set_size(pango_font, 64 * PANGO_SCALE);
2995 pango_layout_set_font_description(_speed_limit_layout,
2997 pango_layout_set_alignment(_speed_limit_layout, PANGO_ALIGN_CENTER);
2999 /* draw_sat_info() */
3000 _sat_info_gc1 = gdk_gc_new(_map_widget->window);
3004 gdk_gc_set_rgb_fg_color(_sat_info_gc1, &color);
3007 color.blue = 0xffff;
3008 _sat_info_gc2 = gdk_gc_new(_map_widget->window);
3009 gdk_gc_set_rgb_fg_color(_sat_info_gc2, &color);
3010 pango_context = gtk_widget_get_pango_context(_map_widget);
3011 _sat_info_layout = pango_layout_new(pango_context);
3012 pango_font = pango_font_description_new();
3013 pango_font_description_set_family(pango_font,"Sans Serif");
3014 pango_font_description_set_size(pango_font, 8*PANGO_SCALE);
3015 pango_layout_set_font_description(_sat_info_layout, pango_font);
3016 pango_layout_set_alignment(_sat_info_layout, PANGO_ALIGN_CENTER);
3018 /* sat_panel_expose() */
3019 pango_context = gtk_widget_get_pango_context(_map_widget);
3020 _sat_panel_layout = pango_layout_new(pango_context);
3021 pango_font = pango_font_description_new();
3022 pango_font_description_set_family(pango_font,"Sans Serif");
3023 pango_font_description_set_size(pango_font, 14*PANGO_SCALE);
3024 pango_layout_set_font_description (_sat_panel_layout, pango_font);
3026 /* heading_panel_expose() */
3027 pango_context = gtk_widget_get_pango_context(_map_widget);
3028 _heading_panel_layout = pango_layout_new(pango_context);
3029 _heading_panel_fontdesc = pango_font_description_new();
3030 pango_font_description_set_family(_heading_panel_fontdesc, "Sans Serif");
3032 /* draw_sat_details() */
3033 pango_context = gtk_widget_get_pango_context(_map_widget);
3034 _sat_details_layout = pango_layout_new(pango_context);
3035 pango_font = pango_font_description_new();
3036 pango_font_description_set_family(pango_font,"Sans Serif");
3037 pango_font_description_set_size(pango_font, 10*PANGO_SCALE);
3038 pango_layout_set_font_description(_sat_details_layout,
3040 pango_layout_set_alignment(_sat_details_layout, PANGO_ALIGN_CENTER);
3042 /* sat_details_panel_expose() */
3043 pango_context = gtk_widget_get_pango_context(_map_widget);
3044 _sat_details_expose_layout = pango_layout_new(pango_context);
3045 pango_font = pango_font_description_new();
3046 pango_font_description_set_family(
3047 pango_font,"Sans Serif");
3048 pango_layout_set_alignment(_sat_details_expose_layout,
3049 PANGO_ALIGN_CENTER);
3050 pango_font_description_set_size(pango_font,
3052 pango_layout_set_font_description(_sat_details_expose_layout,
3055 /* Load the _redraw_wait_icon. */
3057 GError *error = NULL;
3058 gchar *icon_path = "/usr/share/icons/hicolor/scalable/hildon"
3059 "/maemo-mapper-wait.png";
3060 _redraw_wait_bounds.x = 0;
3061 _redraw_wait_bounds.y = 0;
3062 _redraw_wait_icon = gdk_pixbuf_new_from_file(icon_path, &error);
3063 if(!_redraw_wait_icon || error)
3065 g_printerr("Error parsing pixbuf: %s\n",
3066 error ? error->message : icon_path);
3067 _redraw_wait_bounds.width = 0;
3068 _redraw_wait_bounds.height = 0;
3069 _redraw_wait_icon = NULL;
3073 _redraw_wait_bounds.width
3074 = gdk_pixbuf_get_width(_redraw_wait_icon);
3075 _redraw_wait_bounds.height
3076 = gdk_pixbuf_get_height(_redraw_wait_icon);
3080 g_signal_connect(G_OBJECT(_map_widget), "configure_event",
3081 G_CALLBACK(map_cb_configure), NULL);
3083 g_signal_connect(G_OBJECT(_map_widget), "expose_event",
3084 G_CALLBACK(map_cb_expose), NULL);
3085 g_signal_connect(G_OBJECT(_sat_panel), "expose_event",
3086 G_CALLBACK(sat_panel_expose), NULL);
3087 g_signal_connect(G_OBJECT(_heading_panel), "expose_event",
3088 G_CALLBACK(heading_panel_expose), NULL);
3090 vprintf("%s(): return\n", __PRETTY_FUNCTION__);