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();
1702 if(_curr_repo->gdbm_db && !_curr_repo->is_sqlite)
1703 gdbm_sync(_curr_repo->gdbm_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;
1825 printf("combine_tiles()\n");
1827 if (gdk_pixbuf_get_colorspace (dst_pixbuf) != gdk_pixbuf_get_colorspace (src_pixbuf)) {
1828 printf ("combine return (1)\n");
1831 if (gdk_pixbuf_get_colorspace (dst_pixbuf) != GDK_COLORSPACE_RGB) {
1832 printf ("combine return (2)\n");
1836 if (bps != gdk_pixbuf_get_bits_per_sample (src_pixbuf)) {
1837 printf ("combine return (5)\n");
1841 width = gdk_pixbuf_get_width (dst_pixbuf);
1842 height = gdk_pixbuf_get_height (dst_pixbuf);
1844 if (width != gdk_pixbuf_get_width (src_pixbuf)) {
1845 printf ("combine return (6)\n");
1848 if (height != gdk_pixbuf_get_height (src_pixbuf)) {
1849 printf ("combine return (7)\n");
1853 s_delta = (bps >> 3) * s_n_channels;
1854 d_delta = (bps >> 3) * d_n_channels;
1855 d_p = gdk_pixbuf_get_pixels (dst_pixbuf);
1856 s_p = gdk_pixbuf_get_pixels (src_pixbuf);
1858 /* ok, we're ready to combine */
1859 for (y = 0; y < height; y++) {
1860 for (x = 0; x < width; x++, d_p += d_delta, s_p += s_delta) {
1861 /* TODO: alpha blending? */
1862 if (s_n_channels == 3 || s_p[3]) {
1873 thread_render_map(MapRenderTask *mrt)
1876 gint start_tilex, start_tiley, stop_tilex, stop_tiley;
1877 gint x = 0, y, num_tilex, num_tiley;
1878 gint diag_halflength_units;
1880 gint tile_rothalf_pixels;
1881 gint curr_tile_to_draw, num_tiles_to_draw;
1883 ThreadLatch *refresh_latch = NULL;
1885 static gint8 auto_download_batch_id = INT8_MIN;
1886 printf("%s(%d, %d, %d, %d, %d, %d)\n", __PRETTY_FUNCTION__,
1887 mrt->screen_width_pixels, mrt->screen_height_pixels,
1888 mrt->new_center.unitx, mrt->new_center.unity, mrt->zoom,
1891 /* If there are more render tasks in the queue, skip this one. */
1892 if(g_thread_pool_unprocessed(_mrt_thread_pool))
1894 g_slice_free(MapRenderTask, mrt);
1896 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
1900 angle_rad = deg2rad(ROTATE_DIR_ENUM_DEGREES[_rotate_dir]
1901 - mrt->rotate_angle);
1903 gdk_pixbuf_rotate_matrix_fill_for_rotation(matrix, angle_rad);
1905 /* Determine (roughly) the tiles we might have to process.
1906 * Basically, we take the center unit and subtract the maximum dimension
1907 * of the screen plus the maximum additional pixels of a rotated tile.
1909 tile_rothalf_pixels = MAX(
1910 fabsf(TILE_HALFDIAG_PIXELS * sinf((PI / 4) - angle_rad)),
1911 fabsf(TILE_HALFDIAG_PIXELS * cosf((PI / 4) - angle_rad)));
1913 mrt->zoom = _next_zoom;
1915 if(mrt->repo->type != REPOTYPE_NONE && MAPDB_EXISTS(mrt->repo))
1916 cache_amount = _auto_download_precache;
1918 cache_amount = 1; /* No cache. */
1920 diag_halflength_units = pixel2zunit(TILE_HALFDIAG_PIXELS
1921 + MAX(mrt->screen_width_pixels, mrt->screen_height_pixels) / 2,
1923 start_tilex = unit2ztile(
1924 mrt->new_center.unitx - diag_halflength_units
1925 + _map_correction_unitx, mrt->zoom);
1926 start_tilex = MAX(start_tilex - (cache_amount - 1), 0);
1927 start_tiley = unit2ztile(
1928 mrt->new_center.unity - diag_halflength_units
1929 + _map_correction_unity, mrt->zoom);
1930 start_tiley = MAX(start_tiley - (cache_amount - 1), 0);
1931 stop_tilex = unit2ztile(mrt->new_center.unitx + diag_halflength_units
1932 + _map_correction_unitx, mrt->zoom);
1933 stop_tilex = MIN(stop_tilex + (cache_amount - 1),
1934 unit2ztile(WORLD_SIZE_UNITS, mrt->zoom));
1935 stop_tiley = unit2ztile(mrt->new_center.unity + diag_halflength_units
1936 + _map_correction_unity, mrt->zoom);
1937 stop_tiley = MIN(stop_tiley + (cache_amount - 1),
1938 unit2ztile(WORLD_SIZE_UNITS, mrt->zoom));
1940 num_tilex = (stop_tilex - start_tilex + 1);
1941 num_tiley = (stop_tiley - start_tiley + 1);
1942 tile_dev = g_new0(gfloat, num_tilex * num_tiley * 2);
1944 ++auto_download_batch_id;
1946 /* Iterate through the tiles and mark which ones need retrieval. */
1947 num_tiles_to_draw = 0;
1948 for(y = 0; y < num_tiley; ++y)
1950 for(x = 0; x < num_tilex; ++x)
1954 /* Find the device location of this tile's center. */
1956 tile2pixel(x + start_tilex) + (TILE_SIZE_PIXELS >> 1),
1957 tile2pixel(y + start_tiley) + (TILE_SIZE_PIXELS >> 1),
1959 mrt->new_center, mrt->zoom, matrix);
1961 /* Apply Map Correction. */
1962 devx -= unit2zpixel(_map_correction_unitx, mrt->zoom);
1963 devy -= unit2zpixel(_map_correction_unity, mrt->zoom);
1965 /* Skip this tile under the following conditions:
1966 * devx < -tile_rothalf_pixels
1967 * devx > _view_width_pixels + tile_rothalf_pixels
1968 * devy < -tile_rothalf_pixels
1969 * devy > _view_height_pixels + tile_rothalf_pixels
1971 if(((unsigned)(devx + tile_rothalf_pixels))
1972 < (_view_width_pixels + (2 * tile_rothalf_pixels))
1973 && ((unsigned)(devy + tile_rothalf_pixels))
1974 < (_view_height_pixels + (2 * tile_rothalf_pixels)))
1976 tile_dev[2 * (y * num_tilex + x)] = devx;
1977 tile_dev[2 * (y * num_tilex + x) + 1] = devy;
1978 ++num_tiles_to_draw;
1982 tile_dev[2 * (y * num_tilex + x)] = FLT_MAX;
1987 mrt->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8,
1988 mrt->screen_width_pixels, mrt->screen_height_pixels);
1989 _refresh_map_after_download = FALSE;
1991 /* Iterate through the tiles, get them (or queue a download if they're
1992 * not in the cache), and rotate them into the pixbuf. */
1993 for(y = curr_tile_to_draw = 0; y < num_tiley; ++y)
1995 gint tiley = y + start_tiley;
1996 for(x = 0; x < num_tilex; ++x)
1998 GdkPixbuf *tile_pixbuf = NULL, *layer_pixbuf = NULL;
1999 gboolean started_download = FALSE;
2000 gint zoff, zoff_base;
2002 RepoData* repo_p = mrt->repo;
2004 tilex = x + start_tilex;
2005 zoff_base = mrt->repo->double_size ? 1 : 0;
2007 /* iterating over tile and all it's layers */
2010 started_download = FALSE;
2012 /* for layers we must use resolution of underlying map */
2015 /* if this is not a bottom layer and layer not enabled, skip it */
2016 if (repo_p != mrt->repo && !repo_p->layer_enabled)
2018 repo_p = repo_p->layers;
2022 /* Iteratively try to retrieve a map to draw the tile. */
2023 while((mrt->zoom + zoff) <= MAX_ZOOM && zoff < 4)
2025 /* Check if we're actually going to draw this map. */
2026 if(tile_dev[2 * (y*num_tilex + x)] != FLT_MAX)
2028 if(NULL != (layer_pixbuf = mapdb_get(
2029 repo_p, mrt->zoom + zoff,
2033 /* if this is a layer's tile, join with main tile */
2034 if (repo_p != mrt->repo)
2036 /* but only if main layer is exists */
2038 combine_tiles (tile_pixbuf, layer_pixbuf);
2039 g_object_unref (layer_pixbuf);
2042 tile_pixbuf = layer_pixbuf;
2047 else if (repo_p->layers)
2048 _refresh_map_after_download = TRUE;
2050 /* Else we're not going to be drawing this map, so just check
2051 * if it's in the database. */
2052 else if(mapdb_exists(
2053 repo_p, mrt->zoom + zoff,
2061 /* No map; download, if we should. */
2062 if(!started_download && _auto_download
2063 && mrt->repo->type != REPOTYPE_NONE
2064 /* Make sure this map is within dl zoom limits. */
2065 && ((unsigned)(mrt->zoom + zoff - mrt->repo->min_zoom)
2066 <= (mrt->repo->max_zoom - mrt->repo->min_zoom))
2067 /* Make sure this map matches the dl_zoom_steps,
2068 * or that there currently is no cache. */
2069 && (!MAPDB_EXISTS(repo_p) || !((mrt->zoom + zoff
2070 - (mrt->repo->double_size ? 1 : 0))
2071 % mrt->repo->dl_zoom_steps))
2072 /* Make sure this tile is even possible. */
2073 && ((unsigned)(tilex >> zoff)
2074 < unit2ztile(WORLD_SIZE_UNITS, mrt->zoom + zoff)
2075 && (unsigned)(tiley >> zoff)
2076 < unit2ztile(WORLD_SIZE_UNITS, mrt->zoom + zoff)))
2078 started_download = TRUE;
2082 refresh_latch = g_slice_new(ThreadLatch);
2083 refresh_latch->is_open = FALSE;
2084 refresh_latch->is_done_adding_tasks = FALSE;
2085 refresh_latch->num_tasks = 1;
2086 refresh_latch->num_done = 0;
2087 refresh_latch->mutex = g_mutex_new();
2088 refresh_latch->cond = g_cond_new();
2091 ++refresh_latch->num_tasks;
2093 mapdb_initiate_update(
2099 auto_download_batch_id,
2100 (abs((tilex >> zoff) - unit2ztile(
2101 mrt->new_center.unitx, mrt->zoom + zoff))
2102 + abs((tiley >> zoff) - unit2ztile(
2103 mrt->new_center.unity, mrt->zoom + zoff))),
2107 /* Try again at a coarser resolution. Only for underlying map.*/
2108 if (repo_p == mrt->repo && MAPDB_EXISTS(repo_p))
2114 repo_p = repo_p->layers;
2117 /* use zoom of the base map */
2122 gint boundx, boundy, width, height;
2125 gdk_pixbuf_rotate_matrix_mult_number(matrix, 1 << zoff);
2126 gdk_pixbuf_rotate(mrt->pixbuf,
2127 tile_dev[2 * (y * num_tilex + x)],
2128 tile_dev[2 * (y * num_tilex + x) + 1],
2131 ((tilex - ((tilex >> zoff) << zoff))
2132 << (TILE_SIZE_P2 - zoff))
2133 + (TILE_SIZE_PIXELS >> (1 + zoff)),
2134 ((tiley - ((tiley>>zoff) << zoff))
2135 << (TILE_SIZE_P2 - zoff))
2136 + (TILE_SIZE_PIXELS >> (1 + zoff)),
2137 TILE_SIZE_PIXELS >> zoff,
2138 TILE_SIZE_PIXELS >> zoff,
2139 &boundx, &boundy, &width, &height);
2140 g_object_unref(tile_pixbuf);
2141 /* Un-multiply the matrix that we used for blitting. Good
2142 * thing we're multiplying by powers of two, or this wouldn't
2143 * work consistently... */
2145 gdk_pixbuf_rotate_matrix_mult_number(
2146 matrix, 1.f / (1 << zoff));
2148 /* usleep(10000); DEBUG */
2152 /* Don't replace the pixbuf unless/until the mouse is released. */
2153 g_mutex_lock(_mouse_mutex);
2154 ++_pending_replaces;
2155 g_idle_add_full(G_PRIORITY_HIGH_IDLE + 20,
2156 (GSourceFunc)map_replace_pixbuf_idle, mrt, NULL);
2157 g_mutex_unlock(_mouse_mutex);
2159 /* Release the view-change lock. */
2162 g_mutex_lock(refresh_latch->mutex);
2163 if(refresh_latch->num_tasks == refresh_latch->num_done)
2165 /* Fast little workers, aren't they? */
2166 g_mutex_unlock(refresh_latch->mutex);
2167 g_cond_free(refresh_latch->cond);
2168 g_mutex_free(refresh_latch->mutex);
2169 g_slice_free(ThreadLatch, refresh_latch);
2173 refresh_latch->is_done_adding_tasks = TRUE;
2174 refresh_latch->is_open = TRUE;
2175 g_cond_signal(refresh_latch->cond);
2176 g_mutex_unlock(refresh_latch->mutex);
2182 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
2187 map_cb_configure(GtkWidget *widget, GdkEventConfigure *event)
2189 gint old_view_width_pixels, old_view_height_pixels;
2190 GdkPixbuf *old_map_pixbuf;
2191 printf("%s(%d, %d)\n", __PRETTY_FUNCTION__,
2192 _map_widget->allocation.width, _map_widget->allocation.height);
2194 if(_map_widget->allocation.width == 1
2195 && _map_widget->allocation.height == 1)
2196 /* Special case - first allocation - not persistent. */
2199 old_view_width_pixels = _view_width_pixels;
2200 old_view_height_pixels = _view_height_pixels;
2201 _view_width_pixels = _map_widget->allocation.width;
2202 _view_height_pixels = _map_widget->allocation.height;
2203 _view_halfwidth_pixels = _view_width_pixels / 2;
2204 _view_halfheight_pixels = _view_height_pixels / 2;
2206 g_object_unref(_map_pixmap);
2207 _map_pixmap = gdk_pixmap_new(
2208 _map_widget->window,
2209 _view_width_pixels, _view_height_pixels,
2210 -1); /* -1: use bit depth of widget->window. */
2212 old_map_pixbuf = _map_pixbuf;
2213 _map_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8,
2214 _view_width_pixels, _view_height_pixels);
2217 gint oldnew_diffx = (gint)(_view_width_pixels
2218 - old_view_width_pixels) / 2;
2219 gint oldnew_diffy = (gint)(_view_height_pixels
2220 - old_view_height_pixels) / 2;
2221 gdk_pixbuf_copy_area(old_map_pixbuf,
2222 MAX(0, -oldnew_diffx), MAX(0, -oldnew_diffy),
2223 MIN(_view_width_pixels, old_view_width_pixels),
2224 MIN(_view_height_pixels, old_view_height_pixels),
2226 MAX(0, oldnew_diffx), MAX(0, oldnew_diffy));
2229 g_object_unref(old_map_pixbuf);
2231 /* Set _scale_rect. */
2232 _scale_rect.x = (_view_width_pixels - SCALE_WIDTH) / 2;
2233 _scale_rect.width = SCALE_WIDTH;
2234 pango_layout_set_text(_scale_layout, "0", -1);
2235 pango_layout_get_pixel_size(_scale_layout, NULL, &_scale_rect.height);
2236 _scale_rect.y = _view_height_pixels - _scale_rect.height - 1;
2238 /* Set _zoom rect. */
2239 pango_layout_set_text(_zoom_layout, "00", -1);
2240 pango_layout_get_pixel_size(_zoom_layout, &_zoom_rect.width,
2241 &_zoom_rect.height);
2242 _zoom_rect.width *= 1.25;
2243 pango_layout_set_width(_zoom_layout, _zoom_rect.width);
2244 pango_layout_context_changed(_zoom_layout);
2245 _zoom_rect.x = _scale_rect.x - _zoom_rect.width;
2246 _zoom_rect.y = _view_height_pixels - _zoom_rect.height - 1;
2248 /* Set _comprose_rect. */
2249 _comprose_rect.x = _view_width_pixels - 25 - _comprose_rect.width;
2250 _comprose_rect.y = _view_height_pixels - 25 - _comprose_rect.height;
2255 /* Fire the screen_dimensions_changed DBUS signal. */
2256 dbus_ifc_fire_view_dimensions_changed(
2257 _view_width_pixels, _view_height_pixels);
2259 /* If Auto-Center is set to Lead, then recalc center. */
2260 if(_center_mode == CENTER_LEAD)
2261 map_center_unit(map_calc_new_center(_next_zoom));
2263 map_center_unit(_next_center);
2265 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2270 sat_panel_expose(GtkWidget *widget, GdkEventExpose *event)
2274 printf("%s()\n", __PRETTY_FUNCTION__);
2276 draw_sat_info(widget,
2278 widget->allocation.width,
2279 widget->allocation.height,
2282 /* Sat View/In Use */
2283 tmp = g_strdup_printf("%d/%d", _gps.satinuse, _gps.satinview);
2284 pango_layout_set_text(_sat_panel_layout, tmp, -1);
2285 pango_layout_set_alignment(_sat_panel_layout, PANGO_ALIGN_LEFT);
2286 gdk_draw_layout(widget->window,
2287 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
2295 case 3: tmp = g_strdup_printf("%dD fix", _gps.fix); break;
2296 default: tmp = g_strdup_printf("nofix"); break;
2298 pango_layout_set_text(_sat_panel_layout, tmp, -1);
2299 pango_layout_set_alignment(_sat_panel_layout, PANGO_ALIGN_RIGHT);
2300 pango_layout_get_pixel_size(_sat_panel_layout, &x, &y);
2301 gdk_draw_layout(widget->window,
2302 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
2303 widget->allocation.width - 20 - x, 2,
2307 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
2312 heading_panel_expose(GtkWidget *widget, GdkEventExpose *event)
2314 gint size, xoffset, yoffset, i, x, y;
2318 printf("%s()\n", __PRETTY_FUNCTION__);
2320 size = MIN(widget->allocation.width, widget->allocation.height);
2321 if(widget->allocation.width > widget->allocation.height)
2323 xoffset = (widget->allocation.width - widget->allocation.height) / 2;
2329 yoffset = (widget->allocation.height - widget->allocation.width) / 2;
2331 pango_font_description_set_size(_heading_panel_fontdesc,12*PANGO_SCALE);
2332 pango_layout_set_font_description(_heading_panel_layout,
2333 _heading_panel_fontdesc);
2334 pango_layout_set_alignment(_heading_panel_layout, PANGO_ALIGN_CENTER);
2336 text = g_strdup_printf("%3.0f°", _gps.heading);
2337 pango_layout_set_text(_heading_panel_layout, text, -1);
2338 pango_layout_get_pixel_size(_heading_panel_layout, &x, &y);
2340 gdk_draw_layout(widget->window,
2341 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
2342 xoffset + size/2 - x/2,
2343 yoffset + size - y - 2, _heading_panel_layout);
2346 gdk_draw_arc (widget->window,
2347 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
2349 xoffset, yoffset + size/2,
2353 /* Simple arrow for heading*/
2354 gdk_draw_line(widget->window,
2355 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
2356 xoffset + size/2 + 3,
2357 yoffset + size - y - 5,
2359 yoffset + size/2 + 5);
2361 gdk_draw_line(widget->window,
2362 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
2363 xoffset + size/2 - 3,
2364 yoffset + size - y - 5,
2366 yoffset + size/2 + 5);
2368 gdk_draw_line(widget->window,
2369 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
2370 xoffset + size/2 - 3,
2371 yoffset + size - y - 5,
2373 yoffset + size - y - 8);
2375 gdk_draw_line(widget->window,
2376 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
2377 xoffset + size/2 + 3,
2378 yoffset + size - y - 5,
2380 yoffset + size - y - 8);
2382 gint angle[5] = {-90,-45,0,45,90};
2383 gint fsize[5] = {0,4,10,4,0};
2384 for(i = 0; i < 5; i++)
2386 dir = (gint)(_gps.heading/45)*45 + angle[i];
2391 case 360: text = g_strdup("N"); break;
2394 text = g_strdup("NE"); break;
2396 text = g_strdup("E"); break;
2398 text = g_strdup("SE"); break;
2400 text = g_strdup("S"); break;
2402 text = g_strdup("SW"); break;
2405 text = g_strdup("W"); break;
2408 text = g_strdup("NW"); break;
2410 text = g_strdup("??");
2414 tmp = deg2rad(dir - _gps.heading);
2415 gdk_draw_line(widget->window,
2416 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
2417 xoffset + size/2 + ((size/2 - 5) * sinf(tmp)),
2418 yoffset + size - ((size/2 - 5) * cosf(tmp)),
2419 xoffset + size/2 + ((size/2 + 5) * sinf(tmp)),
2420 yoffset + size - ((size/2 + 5) * cosf(tmp)));
2423 if(abs((gint)(_gps.heading/45)*45 - _gps.heading)
2424 > abs((gint)(_gps.heading/45)*45 + 45 - _gps.heading)
2428 pango_font_description_set_size(_heading_panel_fontdesc,
2429 (10 + x)*PANGO_SCALE);
2430 pango_layout_set_font_description(_heading_panel_layout,
2431 _heading_panel_fontdesc);
2432 pango_layout_set_text(_heading_panel_layout, text, -1);
2433 pango_layout_get_pixel_size(_heading_panel_layout, &x, &y);
2434 x = xoffset + size/2 + ((size/2 + 15) * sinf(tmp)) - x/2,
2435 y = yoffset + size - ((size/2 + 15) * cosf(tmp)) - y/2,
2437 gdk_draw_layout(widget->window,
2438 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
2439 x, y, _heading_panel_layout);
2443 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
2448 map_cb_expose(GtkWidget *widget, GdkEventExpose *event)
2451 printf("%s(%d, %d, %d, %d)\n", __PRETTY_FUNCTION__,
2452 event->area.x, event->area.y,
2453 event->area.width, event->area.height);
2456 _map_widget->window,
2457 _gc[COLORABLE_MARK],
2459 event->area.x - _map_offset_devx, event->area.y - _map_offset_devy,
2460 event->area.x, event->area.y,
2461 event->area.width, event->area.height);
2463 /* Draw the mark. */
2464 if((((unsigned)(_mark_bufx1 + _draw_width)
2465 <= _view_width_pixels+2*_draw_width)
2466 &&((unsigned)(_mark_bufy1 + _draw_width)
2467 <= _view_height_pixels+2*_draw_width))
2468 || (((unsigned)(_mark_bufx2 + _draw_width)
2469 <= _view_width_pixels+2*_draw_width)
2470 &&((unsigned)(_mark_bufy2 + _draw_width)
2471 <= _view_height_pixels+2*_draw_width)))
2474 _map_widget->window,
2475 _gps_state == RCVR_FIXED
2476 ? _gc[COLORABLE_MARK] : _gc[COLORABLE_MARK_OLD],
2477 FALSE, /* not filled. */
2478 _mark_bufx1 - _draw_width + _map_offset_devx,
2479 _mark_bufy1 - _draw_width + _map_offset_devy,
2480 2 * _draw_width, 2 * _draw_width,
2483 _map_widget->window,
2484 _gps_state == RCVR_FIXED
2486 ? _gc[COLORABLE_MARK_VELOCITY] : _gc[COLORABLE_MARK])
2487 : _gc[COLORABLE_MARK_OLD],
2488 _mark_bufx1 + _map_offset_devx,
2489 _mark_bufy1 + _map_offset_devy,
2490 _mark_bufx2 + _map_offset_devx,
2491 _mark_bufy2 + _map_offset_devy);
2494 /* draw zoom box if so wanted */
2495 if(_show_zoomlevel) {
2496 gchar *buffer = g_strdup_printf("%d", _zoom);
2497 gdk_draw_rectangle(_map_widget->window,
2498 _map_widget->style->bg_gc[GTK_STATE_ACTIVE],
2500 _zoom_rect.x, _zoom_rect.y,
2501 _zoom_rect.width, _zoom_rect.height);
2502 gdk_draw_rectangle(_map_widget->window,
2503 _map_widget->style->fg_gc[GTK_STATE_ACTIVE],
2505 _zoom_rect.x, _zoom_rect.y,
2506 _zoom_rect.width, _zoom_rect.height);
2507 pango_layout_set_text(_zoom_layout, buffer, -1);
2508 gdk_draw_layout(_map_widget->window,
2509 _map_widget->style->fg_gc[GTK_STATE_ACTIVE],
2510 _zoom_rect.x + _zoom_rect.width / 2,
2511 _zoom_rect.y, _zoom_layout);
2514 /* Draw scale, if necessary. */
2517 gdk_rectangle_intersect(&event->area, &_scale_rect, &event->area);
2518 if(event->area.width && event->area.height)
2520 gdk_draw_rectangle(_map_widget->window,
2521 _map_widget->style->bg_gc[GTK_STATE_ACTIVE],
2523 _scale_rect.x, _scale_rect.y,
2524 _scale_rect.width, _scale_rect.height);
2525 gdk_draw_rectangle(_map_widget->window,
2526 _map_widget->style->fg_gc[GTK_STATE_ACTIVE],
2528 _scale_rect.x, _scale_rect.y,
2529 _scale_rect.width, _scale_rect.height);
2531 /* Now calculate and draw the distance. */
2535 gdouble lat1, lon1, lat2, lon2;
2538 unit2latlon(_center.unitx - pixel2unit(SCALE_WIDTH / 2 - 4),
2539 _center.unity, lat1, lon1);
2540 unit2latlon(_center.unitx + pixel2unit(SCALE_WIDTH / 2 - 4),
2541 _center.unity, lat2, lon2);
2542 distance = calculate_distance(lat1, lon1, lat2, lon2)
2543 * UNITS_CONVERT[_units];
2546 snprintf(buffer, sizeof(buffer), "%0.2f %s", distance,
2547 UNITS_ENUM_TEXT[_units]);
2548 else if(distance < 10.f)
2549 snprintf(buffer, sizeof(buffer), "%0.1f %s", distance,
2550 UNITS_ENUM_TEXT[_units]);
2552 snprintf(buffer, sizeof(buffer), "%0.f %s", distance,
2553 UNITS_ENUM_TEXT[_units]);
2554 pango_layout_set_text(_scale_layout, buffer, -1);
2556 pango_layout_get_pixel_size(_scale_layout, &width, NULL);
2558 /* Draw the layout itself. */
2559 gdk_draw_layout(_map_widget->window,
2560 _map_widget->style->fg_gc[GTK_STATE_ACTIVE],
2561 _scale_rect.x + (_scale_rect.width - width) / 2,
2562 _scale_rect.y, _scale_layout);
2564 /* Draw little hashes on the ends. */
2565 gdk_draw_line(_map_widget->window,
2566 _map_widget->style->fg_gc[GTK_STATE_ACTIVE],
2568 _scale_rect.y + _scale_rect.height / 2 - 4,
2570 _scale_rect.y + _scale_rect.height / 2 + 4);
2571 gdk_draw_line(_map_widget->window,
2572 _map_widget->style->fg_gc[GTK_STATE_ACTIVE],
2574 _scale_rect.y + _scale_rect.height / 2,
2575 _scale_rect.x + (_scale_rect.width - width) / 2 - 4,
2576 _scale_rect.y + _scale_rect.height / 2);
2577 gdk_draw_line(_map_widget->window,
2578 _map_widget->style->fg_gc[GTK_STATE_ACTIVE],
2579 _scale_rect.x + _scale_rect.width - 4,
2580 _scale_rect.y + _scale_rect.height / 2 - 4,
2581 _scale_rect.x + _scale_rect.width - 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],
2585 _scale_rect.x + _scale_rect.width - 4,
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);
2593 /* Draw the compass rose, if necessary. */
2597 gint offsetx, offsety;
2600 offsetx = _comprose_rect.x;
2601 offsety = _comprose_rect.y;
2603 gdk_pixbuf_rotate_vector(&x, &y, _map_rotate_matrix, 0, 12);
2604 points[0].x = offsetx + x + 0.5f; points[0].y = offsety + y + 0.5f;
2605 gdk_pixbuf_rotate_vector(&x, &y, _map_rotate_matrix, 20, 30);
2606 points[1].x = offsetx + x + 0.5f; points[1].y = offsety + y + 0.5f;
2607 gdk_pixbuf_rotate_vector(&x, &y, _map_rotate_matrix, 0, -45);
2608 points[2].x = offsetx + x + 0.5f; points[2].y = offsety + y + 0.5f;
2609 gdk_pixbuf_rotate_vector(&x, &y, _map_rotate_matrix, -20, 30);
2610 points[3].x = offsetx + x + 0.5f; points[3].y = offsety + y + 0.5f;
2612 gdk_draw_polygon(_map_widget->window,
2613 _map_widget->style->bg_gc[GTK_STATE_ACTIVE],
2616 gdk_draw_polygon(_map_widget->window,
2617 _map_widget->style->fg_gc[GTK_STATE_ACTIVE],
2618 FALSE, /* NOT FILLED */
2621 gdk_draw_layout(_map_widget->window,
2622 _map_widget->style->fg_gc[GTK_STATE_ACTIVE],
2623 _comprose_rect.x - _comprose_rect.width / 2 + 1,
2624 _comprose_rect.y - _comprose_rect.height / 2 - 4,
2628 /* Draw a stopwatch if we're redrawing the map. */
2629 for(i = _redraw_count - 1; i >= 0; i--)
2632 _map_widget->window,
2633 _map_widget->style->fg_gc[GTK_STATE_ACTIVE],
2636 _redraw_wait_bounds.x + i
2637 * HOURGLASS_SEPARATION,
2638 _redraw_wait_bounds.y,
2639 _redraw_wait_bounds.width,
2640 _redraw_wait_bounds.height,
2641 GDK_RGB_DITHER_NONE, 0, 0);
2644 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2649 latlon_cb_copy_clicked(GtkWidget *widget, LatlonDialog *lld) {
2652 snprintf(buffer, sizeof(buffer),
2654 gtk_label_get_text(GTK_LABEL(lld->lat)),
2655 gtk_label_get_text(GTK_LABEL(lld->lon)));
2657 gtk_clipboard_set_text(
2658 gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), buffer, -1);
2662 latlon_cb_fmt_changed(GtkWidget *widget, LatlonDialog *lld) {
2665 fmt = gtk_combo_box_get_active(GTK_COMBO_BOX(lld->fmt_combo));
2668 gint old = _degformat; /* augh... */
2669 gchar buffer[LL_FMT_LEN];
2670 gchar buffer2[LL_FMT_LEN];
2674 format_lat_lon(lld->glat, lld->glon, buffer, buffer2);
2676 //lat_format(lld->glat, buffer);
2677 gtk_label_set_label(GTK_LABEL(lld->lat), buffer);
2678 //lon_format(lld->glon, buffer);
2680 if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use)
2681 gtk_label_set_label(GTK_LABEL(lld->lon), buffer2);
2683 gtk_label_set_label(GTK_LABEL(lld->lon), g_strdup(""));
2686 // And set the titles
2687 gtk_label_set_label(GTK_LABEL(lld->lat_title),
2688 DEG_FORMAT_ENUM_TEXT[_degformat].short_field_1 );
2690 if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use)
2691 gtk_label_set_label(GTK_LABEL(lld->lon_title),
2692 DEG_FORMAT_ENUM_TEXT[_degformat].short_field_2 );
2694 gtk_label_set_label(GTK_LABEL(lld->lon_title), g_strdup(""));
2702 latlon_dialog(gdouble lat, gdouble lon)
2708 GtkWidget *lbl_lon_title;
2709 GtkWidget *lbl_lat_title;
2712 GtkWidget *cmb_format;
2713 GtkWidget *btn_copy = NULL;
2714 gint prev_degformat = _degformat;
2715 gint fallback_deg_format = _degformat;
2717 printf("%s()\n", __PRETTY_FUNCTION__);
2719 // Check that the current coord system supports the select position
2720 if(!coord_system_check_lat_lon (lat, lon, &fallback_deg_format))
2722 _degformat = fallback_deg_format;
2726 dialog = gtk_dialog_new_with_buttons(_("Show Position"),
2727 GTK_WINDOW(_window), GTK_DIALOG_MODAL,
2728 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
2731 /* Set the lat/lon strings. */
2732 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
2733 table = gtk_table_new(5, 2, FALSE), TRUE, TRUE, 0);
2735 gtk_table_attach(GTK_TABLE(table),
2736 lbl_lat_title = gtk_label_new(/*_("Lat")*/ DEG_FORMAT_ENUM_TEXT[_degformat].short_field_1 ),
2737 0, 1, 0, 1, GTK_FILL, 0, 2, 4);
2738 gtk_misc_set_alignment(GTK_MISC(lbl_lat_title), 1.f, 0.5f);
2739 gtk_table_attach(GTK_TABLE(table),
2740 txt_lat = gtk_label_new(""),
2741 1, 2, 0, 1, GTK_FILL, 0, 2, 4);
2742 gtk_misc_set_alignment(GTK_MISC(txt_lat), 1.f, 0.5f);
2745 gtk_table_attach(GTK_TABLE(table),
2746 lbl_lon_title = gtk_label_new(/*_("Lon")*/ DEG_FORMAT_ENUM_TEXT[_degformat].short_field_2 ),
2747 0, 1, 1, 2, GTK_FILL, 0, 2, 4);
2748 gtk_misc_set_alignment(GTK_MISC(lbl_lon_title), 1.f, 0.5f);
2750 gtk_table_attach(GTK_TABLE(table),
2751 txt_lon = gtk_label_new(""),
2752 1, 2, 1, 2, GTK_FILL, 0, 2, 4);
2753 gtk_misc_set_alignment(GTK_MISC(txt_lon), 1.f, 0.5f);
2756 gtk_table_attach(GTK_TABLE(table),
2757 label = gtk_label_new(_("Format")),
2758 0, 1, 2, 3, GTK_FILL, 0, 2, 4);
2759 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
2760 gtk_table_attach(GTK_TABLE(table),
2761 label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
2762 1, 2, 2, 3, GTK_FILL, 0, 2, 4);
2763 gtk_container_add(GTK_CONTAINER(label),
2764 cmb_format = gtk_combo_box_new_text());
2765 gtk_table_attach(GTK_TABLE(table),
2766 btn_copy = gtk_button_new_with_label(_("Copy")),
2767 0, 2, 3, 4, GTK_FILL, 0, 2, 4);
2771 gchar buffer[LL_FMT_LEN];
2772 gchar buffer2[LL_FMT_LEN];
2774 format_lat_lon(lat, lon, buffer, buffer2);
2776 //lat_format(lat, buffer);
2777 gtk_label_set_label(GTK_LABEL(txt_lat), buffer);
2778 //lat_format(lon, buffer);
2779 if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use)
2780 gtk_label_set_label(GTK_LABEL(txt_lon), buffer2);
2782 gtk_label_set_label(GTK_LABEL(txt_lon), g_strdup(""));
2785 /* Fill in formats */
2789 for(i = 0; i < DEG_FORMAT_ENUM_COUNT; i++) {
2790 gtk_combo_box_append_text(GTK_COMBO_BOX(cmb_format),
2791 DEG_FORMAT_ENUM_TEXT[i].name);
2793 gtk_combo_box_set_active(GTK_COMBO_BOX(cmb_format), _degformat);
2797 /* setup cb context */
2798 lld.fmt_combo = cmb_format;
2804 lld.lat_title = lbl_lat_title;
2805 lld.lon_title = lbl_lon_title;
2807 /* Connect Signals */
2808 g_signal_connect(G_OBJECT(cmb_format), "changed",
2809 G_CALLBACK(latlon_cb_fmt_changed), &lld);
2810 g_signal_connect(G_OBJECT(btn_copy), "clicked",
2811 G_CALLBACK(latlon_cb_copy_clicked), &lld);
2813 gtk_widget_show_all(dialog);
2815 gtk_dialog_run(GTK_DIALOG(dialog));
2817 _degformat = prev_degformat; // Put back incase it had to be auto changed
2819 gtk_widget_hide(dialog);
2821 vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
2827 * This is a multi-purpose function for allowing the user to select a file
2828 * for either reading or writing. If chooser_action is
2829 * GTK_FILE_CHOOSER_ACTION_OPEN, then bytes_out and size_out must be
2830 * non-NULL. If chooser_action is GTK_FILE_CHOOSER_ACTION_SAVE, then
2831 * handle_out must be non-NULL. Either dir or file (or both) can be NULL.
2832 * This function returns TRUE if a file was successfully opened.
2835 display_open_file(GtkWindow *parent, gchar **bytes_out,
2836 GnomeVFSHandle **handle_out, gint *size_out,
2837 gchar **dir, gchar **file, GtkFileChooserAction chooser_action)
2840 gboolean success = FALSE;
2841 printf("%s()\n", __PRETTY_FUNCTION__);
2843 dialog = hildon_file_chooser_dialog_new(parent, chooser_action);
2846 gtk_file_chooser_set_current_folder_uri(
2847 GTK_FILE_CHOOSER(dialog), *dir);
2850 gtk_file_chooser_set_uri(
2851 GTK_FILE_CHOOSER(dialog), *file);
2852 if(chooser_action == GTK_FILE_CHOOSER_ACTION_SAVE)
2854 /* Work around a bug in HildonFileChooserDialog. */
2855 gchar *basename = g_path_get_basename(*file);
2856 g_object_set(G_OBJECT(dialog), "autonaming", FALSE, NULL);
2857 gtk_file_chooser_set_current_name(
2858 GTK_FILE_CHOOSER(dialog), basename);
2863 gtk_widget_show_all(dialog);
2865 while(!success && gtk_dialog_run(GTK_DIALOG(dialog))==GTK_RESPONSE_OK)
2867 gchar *file_uri_str;
2868 GnomeVFSResult vfs_result;
2870 /* Get the selected filename. */
2871 file_uri_str = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(dialog));
2873 if((chooser_action == GTK_FILE_CHOOSER_ACTION_OPEN
2874 && (GNOME_VFS_OK != (vfs_result = gnome_vfs_read_entire_file(
2875 file_uri_str, size_out, bytes_out))))
2876 || (chooser_action == GTK_FILE_CHOOSER_ACTION_SAVE
2877 && GNOME_VFS_OK != (vfs_result = gnome_vfs_create(
2878 handle_out, file_uri_str,
2879 GNOME_VFS_OPEN_WRITE, FALSE, 0664))))
2881 gchar buffer[BUFFER_SIZE];
2882 snprintf(buffer, sizeof(buffer),
2883 "%s:\n%s", chooser_action == GTK_FILE_CHOOSER_ACTION_OPEN
2884 ? _("Failed to open file for reading")
2885 : _("Failed to open file for writing"),
2886 gnome_vfs_result_to_string(vfs_result));
2887 popup_error(dialog, buffer);
2892 g_free(file_uri_str);
2901 *dir = gtk_file_chooser_get_current_folder_uri(
2902 GTK_FILE_CHOOSER(dialog));
2905 /* If desired, save the file for later. */
2909 *file = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(dialog));
2913 gtk_widget_destroy(dialog);
2915 vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, success);
2922 PangoContext *pango_context;
2923 PangoFontDescription *pango_font;
2925 printf("%s()\n", __PRETTY_FUNCTION__);
2927 /* Cache some pango and GCs for drawing. */
2928 pango_context = gtk_widget_get_pango_context(_map_widget);
2929 _scale_layout = pango_layout_new(pango_context);
2930 pango_font = pango_font_description_new();
2931 pango_font_description_set_size(pango_font, 12 * PANGO_SCALE);
2932 pango_layout_set_font_description(_scale_layout, pango_font);
2936 pango_context = gtk_widget_get_pango_context(_map_widget);
2937 _aprs_label_layout = pango_layout_new(pango_context);
2938 pango_font = pango_font_description_new();
2939 pango_font_description_set_size(pango_font, 10 * PANGO_SCALE);
2940 pango_font_description_set_family(pango_font,"Sans Serif");
2941 pango_layout_set_font_description(_aprs_label_layout, pango_font);
2942 #endif // INCLUDE_APRS
2945 pango_context = gtk_widget_get_pango_context(_map_widget);
2946 _zoom_layout = pango_layout_new(pango_context);
2947 pango_font = pango_font_description_new();
2948 pango_font_description_set_size(pango_font, 12 * PANGO_SCALE);
2949 pango_layout_set_font_description(_zoom_layout, pango_font);
2950 pango_layout_set_alignment(_zoom_layout, PANGO_ALIGN_CENTER);
2953 pango_context = gtk_widget_get_pango_context(_map_widget);
2954 _comprose_layout = pango_layout_new(pango_context);
2955 pango_font = pango_font_description_new();
2956 pango_font_description_set_size(pango_font, 16 * PANGO_SCALE);
2957 pango_font_description_set_weight(pango_font, PANGO_WEIGHT_BOLD);
2958 pango_layout_set_font_description(_comprose_layout, pango_font);
2959 pango_layout_set_alignment(_comprose_layout, PANGO_ALIGN_CENTER);
2960 pango_layout_set_text(_comprose_layout, "N", -1);
2962 PangoRectangle rect;
2963 pango_layout_get_pixel_extents(_comprose_layout, &rect, NULL);
2964 _comprose_rect.width = rect.width + 3;
2965 _comprose_rect.height = rect.height + 3;
2969 _speed_limit_gc1 = gdk_gc_new (_map_widget->window);
2973 gdk_gc_set_rgb_fg_color(_speed_limit_gc1, &color);
2977 _speed_limit_gc2 = gdk_gc_new(_map_widget->window);
2978 gdk_gc_set_rgb_fg_color(_speed_limit_gc2, &color);
2979 pango_context = gtk_widget_get_pango_context(_map_widget);
2980 _speed_limit_layout = pango_layout_new(pango_context);
2981 pango_font = pango_font_description_new();
2982 pango_font_description_set_size(pango_font, 64 * PANGO_SCALE);
2983 pango_layout_set_font_description(_speed_limit_layout,
2985 pango_layout_set_alignment(_speed_limit_layout, PANGO_ALIGN_CENTER);
2987 /* draw_sat_info() */
2988 _sat_info_gc1 = gdk_gc_new(_map_widget->window);
2992 gdk_gc_set_rgb_fg_color(_sat_info_gc1, &color);
2995 color.blue = 0xffff;
2996 _sat_info_gc2 = gdk_gc_new(_map_widget->window);
2997 gdk_gc_set_rgb_fg_color(_sat_info_gc2, &color);
2998 pango_context = gtk_widget_get_pango_context(_map_widget);
2999 _sat_info_layout = pango_layout_new(pango_context);
3000 pango_font = pango_font_description_new();
3001 pango_font_description_set_family(pango_font,"Sans Serif");
3002 pango_font_description_set_size(pango_font, 8*PANGO_SCALE);
3003 pango_layout_set_font_description(_sat_info_layout, pango_font);
3004 pango_layout_set_alignment(_sat_info_layout, PANGO_ALIGN_CENTER);
3006 /* sat_panel_expose() */
3007 pango_context = gtk_widget_get_pango_context(_map_widget);
3008 _sat_panel_layout = pango_layout_new(pango_context);
3009 pango_font = pango_font_description_new();
3010 pango_font_description_set_family(pango_font,"Sans Serif");
3011 pango_font_description_set_size(pango_font, 14*PANGO_SCALE);
3012 pango_layout_set_font_description (_sat_panel_layout, pango_font);
3014 /* heading_panel_expose() */
3015 pango_context = gtk_widget_get_pango_context(_map_widget);
3016 _heading_panel_layout = pango_layout_new(pango_context);
3017 _heading_panel_fontdesc = pango_font_description_new();
3018 pango_font_description_set_family(_heading_panel_fontdesc, "Sans Serif");
3020 /* draw_sat_details() */
3021 pango_context = gtk_widget_get_pango_context(_map_widget);
3022 _sat_details_layout = pango_layout_new(pango_context);
3023 pango_font = pango_font_description_new();
3024 pango_font_description_set_family(pango_font,"Sans Serif");
3025 pango_font_description_set_size(pango_font, 10*PANGO_SCALE);
3026 pango_layout_set_font_description(_sat_details_layout,
3028 pango_layout_set_alignment(_sat_details_layout, PANGO_ALIGN_CENTER);
3030 /* sat_details_panel_expose() */
3031 pango_context = gtk_widget_get_pango_context(_map_widget);
3032 _sat_details_expose_layout = pango_layout_new(pango_context);
3033 pango_font = pango_font_description_new();
3034 pango_font_description_set_family(
3035 pango_font,"Sans Serif");
3036 pango_layout_set_alignment(_sat_details_expose_layout,
3037 PANGO_ALIGN_CENTER);
3038 pango_font_description_set_size(pango_font,
3040 pango_layout_set_font_description(_sat_details_expose_layout,
3043 /* Load the _redraw_wait_icon. */
3045 GError *error = NULL;
3046 gchar *icon_path = "/usr/share/icons/hicolor/scalable/hildon"
3047 "/maemo-mapper-wait.png";
3048 _redraw_wait_bounds.x = 0;
3049 _redraw_wait_bounds.y = 0;
3050 _redraw_wait_icon = gdk_pixbuf_new_from_file(icon_path, &error);
3051 if(!_redraw_wait_icon || error)
3053 g_printerr("Error parsing pixbuf: %s\n",
3054 error ? error->message : icon_path);
3055 _redraw_wait_bounds.width = 0;
3056 _redraw_wait_bounds.height = 0;
3057 _redraw_wait_icon = NULL;
3061 _redraw_wait_bounds.width
3062 = gdk_pixbuf_get_width(_redraw_wait_icon);
3063 _redraw_wait_bounds.height
3064 = gdk_pixbuf_get_height(_redraw_wait_icon);
3068 g_signal_connect(G_OBJECT(_map_widget), "configure_event",
3069 G_CALLBACK(map_cb_configure), NULL);
3071 g_signal_connect(G_OBJECT(_map_widget), "expose_event",
3072 G_CALLBACK(map_cb_expose), NULL);
3073 g_signal_connect(G_OBJECT(_sat_panel), "expose_event",
3074 G_CALLBACK(sat_panel_expose), NULL);
3075 g_signal_connect(G_OBJECT(_heading_panel), "expose_event",
3076 G_CALLBACK(heading_panel_expose), NULL);
3078 vprintf("%s(): return\n", __PRETTY_FUNCTION__);