Codebase list osm-gps-map / a9010f5
Imported Upstream version 0.7.0 David Paleino 13 years ago
57 changed file(s) with 6782 addition(s) and 4199 deletion(s). Raw diff Collapse all Expand all
55 *.deps/
66 *.libs/
77 *.tar.gz
8 *.stamp
9 *.bak
810 INSTALL
911 Makefile
12 aclocal.m4
1013 autom4te.cache/
1114 compile
1215 config.guess
3134 src/mapviewer
3235 stamp-h1
3336 ChangeLog
34
(New empty file)
00 ## Process this file with automake to produce Makefile.in
1 ## Created by Anjuta
21
3 SUBDIRS = src
2 SUBDIRS = src examples docs
3 DISTCHECK_CONFIGURE_FLAGS = \
4 --enable-gtk-doc \
5 --enable-maintainer-flags \
6 --enable-introspection
7
8 ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
49
510 osm_gps_mapdocdir = ${prefix}/doc/osm-gps-map
611 osm_gps_mapdoc_DATA = \
1621
1722 EXTRA_DIST = $(openstreetmap_gps_mapdoc_DATA) \
1823 osmgpsmap.pc.in \
19 python/Makefile.am \
20 python/Makefile.in \
21 python/acinclude.m4 \
22 python/ChangeLog \
23 python/osmgpsmap.defs \
24 python/setup.py \
25 python/aclocal.m4 \
26 python/configure \
27 python/osmgpsmapmodule.c \
28 python/mapviewer.py \
29 python/AUTHORS \
30 python/configure.ac \
31 python/osmgpsmap.override \
32 python/NEWS \
33 python/README
24 gtk-doc.make \
25 m4/introspection.m4 \
26 m4/gtk-doc.m4
27
28 DISTCLEANFILES = gtk-doc.make
3429
3530 # ChangeLog generation from nautils
3631 distclean-local:
4136 ChangeLog:
4237 @echo Creating $@
4338 @if test -d "$(srcdir)/.git"; then \
44 (GIT_DIR=$(top_srcdir)/.git ./missing --run git log 0.5.. --stat -M -C --name-status --date=short --no-color) | fmt --split-only > $@.tmp \
39 (GIT_DIR=$(top_srcdir)/.git ./missing --run git log 0.6.0.. --stat -M -C --name-status --date=short --no-color) | fmt --split-only > $@.tmp \
4540 && mv -f $@.tmp $@ \
4641 || ($(RM) $@.tmp; \
4742 echo Failed to generate ChangeLog, your ChangeLog may be outdated >&2; \
0 Changes in 0.7.0
1 ======================
2 * Map auto center threshold is now adjustable via the auto-center-threshold
3 property.
4 * Build fixes
5 * Provide a notify signal for tiles-queued and zoom
6 * Improvements to changing source and tile-cache after map is constructed
7 * Drawing of the gps marker can now be completely controlled by applications
8 by implementing the draw_gps_point vfunc
9 * GPS marker visibility can also be controlled using the show-gps-point property
10 * GObject introspection support
11 * Documentation using gtk-doc
12 * Gtk-3.0 compatible (builds with -DGSEAL_ENABLE)
13 * Massive improvements to the Image and Track functions and additional
14 API cleanup. This release is not ABI compatible, however it is API compatible.
15 All users are advised to update to the new API.
16 A summary of these changes, and a porting guide follow;
17 * Replace coord_t -> OsmGpsMapPoint
18 * osm_gps_map_add_image -> osm_gps_map_image_add and now returns a
19 OsmGpsMapImage * type that should be used when removing or modifying images
20 * osm_gps_map_remove_image -> osm_gps_map_image_remove and now
21 accepts this returned OsmGpsMapImage * pointer
22 * osm_gps_map_clear_images -> osm_gps_map_image_remove_all
23 * Track management is now done using the OsmGpsMapTrack object. This
24 is a wrapper around a GSList of OsmGpsMapPoints. You should keep a
25 copy of this object around. You can add single points to the track by
26 calling osm_gps_map_track_add_point, and the map will update
27 accordingly. You can change the visual appearance of the track via
28 this object properties.
29 * osm_gps_map_add_track -> osm_gps_map_track_add
30 * osm_gps_map_replace_track. Modify the OsmGpsMapTrack object instead
31 * osm_gps_map_clear_tracks -> osm_gps_map_track_remove_all
32 * The gps functions are now just convenience wrappers around an
33 internal OsmGpsMapTrack object
34 * osm_gps_map_draw_gps -> osm_gps_map_gps_add
35 * osm_gps_map_clear_gps -> osm_gps_map_gps_clear
36 * osm_gps_map_screen_to_geographic -> osm_gps_map_convert_screen_to_geographic
37 * osm_gps_map_geographic_to_screen -> osm_gps_map_convert_geographic_to_screen
38 * osm_gps_map_get_co_ordinates -> osm_gps_map_get_event_location
39 * osm_gps_map_set_mapcenter -> osm_gps_map_set_center_and_zoom
40
041 Changes in 0.6.0
142 ======================
243 * Support libsoup-2.2 and libsoup-2.4
33 srcdir=`dirname $0`
44 test -z "$srcdir" && srcdir=.
55
6 DIE=0
7
8 if [ -n "$GNOME2_DIR" ]; then
9 ACLOCAL_FLAGS="-I $GNOME2_DIR/share/aclocal $ACLOCAL_FLAGS"
10 LD_LIBRARY_PATH="$GNOME2_DIR/lib:$LD_LIBRARY_PATH"
11 PATH="$GNOME2_DIR/bin:$PATH"
12 export PATH
13 export LD_LIBRARY_PATH
14 fi
6 PKG_NAME="osm-gps-map"
7 # REQUIRED_M4MACROS=introspection.m4
158
169 (test -f $srcdir/configure.ac) || {
1710 echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
18 echo " top-level package directory"
11 echo " top-level $PKG_NAME directory"
1912 exit 1
2013 }
2114
22 (autoconf --version) < /dev/null > /dev/null 2>&1 || {
23 echo
24 echo "**Error**: You must have \`autoconf' installed."
25 echo "Download the appropriate package for your distribution,"
26 echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
27 DIE=1
15 which gnome-autogen.sh || {
16 echo "You need to install gnome-common from the GNOME SVN"
17 exit 1
2818 }
2919
30 (grep "^IT_PROG_INTLTOOL" $srcdir/configure.ac >/dev/null) && {
31 (intltoolize --version) < /dev/null > /dev/null 2>&1 || {
32 echo
33 echo "**Error**: You must have \`intltool' installed."
34 echo "You can get it from:"
35 echo " ftp://ftp.gnome.org/pub/GNOME/"
36 DIE=1
37 }
38 }
20 . gnome-autogen.sh --enable-gtk-doc "$@"
3921
40 (grep "^AM_PROG_XML_I18N_TOOLS" $srcdir/configure.ac >/dev/null) && {
41 (xml-i18n-toolize --version) < /dev/null > /dev/null 2>&1 || {
42 echo
43 echo "**Error**: You must have \`xml-i18n-toolize' installed."
44 echo "You can get it from:"
45 echo " ftp://ftp.gnome.org/pub/GNOME/"
46 DIE=1
47 }
48 }
49
50 (grep "^AM_PROG_LIBTOOL" $srcdir/configure.ac >/dev/null) && {
51 (libtool --version) < /dev/null > /dev/null 2>&1 || {
52 echo
53 echo "**Error**: You must have \`libtool' installed."
54 echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/"
55 DIE=1
56 }
57 }
58
59 (grep "^AM_GLIB_GNU_GETTEXT" $srcdir/configure.ac >/dev/null) && {
60 (grep "sed.*POTFILES" $srcdir/configure.ac) > /dev/null || \
61 (glib-gettextize --version) < /dev/null > /dev/null 2>&1 || {
62 echo
63 echo "**Error**: You must have \`glib' installed."
64 echo "You can get it from: ftp://ftp.gtk.org/pub/gtk"
65 DIE=1
66 }
67 }
68
69 (automake --version) < /dev/null > /dev/null 2>&1 || {
70 echo
71 echo "**Error**: You must have \`automake' installed."
72 echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/"
73 DIE=1
74 NO_AUTOMAKE=yes
75 }
76
77
78 # if no automake, don't bother testing for aclocal
79 test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || {
80 echo
81 echo "**Error**: Missing \`aclocal'. The version of \`automake'"
82 echo "installed doesn't appear recent enough."
83 echo "You can get automake from ftp://ftp.gnu.org/pub/gnu/"
84 DIE=1
85 }
86
87 if test "$DIE" -eq 1; then
88 exit 1
89 fi
90
91 if test -z "$*"; then
92 echo "**Warning**: I am going to run \`configure' with no arguments."
93 echo "If you wish to pass any to it, please specify them on the"
94 echo \`$0\'" command line."
95 echo
96 fi
97
98 case $CC in
99 xlc )
100 am_opt=--include-deps;;
101 esac
102
103 for coin in `find $srcdir -path $srcdir/CVS -prune -o -name configure.ac -print`
104 do
105 dr=`dirname $coin`
106 if test -f $dr/NO-AUTO-GEN; then
107 echo skipping $dr -- flagged as no auto-gen
108 else
109 echo processing $dr
110 ( cd $dr
111
112 aclocalinclude="$ACLOCAL_FLAGS"
113
114 if grep "^AM_GLIB_GNU_GETTEXT" configure.ac >/dev/null; then
115 echo "Creating $dr/aclocal.m4 ..."
116 test -r $dr/aclocal.m4 || touch $dr/aclocal.m4
117 echo "Running glib-gettextize... Ignore non-fatal messages."
118 echo "no" | glib-gettextize --force --copy
119 echo "Making $dr/aclocal.m4 writable ..."
120 test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4
121 fi
122 if grep "^IT_PROG_INTLTOOL" configure.ac >/dev/null; then
123 echo "Running intltoolize..."
124 intltoolize --copy --force --automake
125 fi
126 if grep "^AM_PROG_XML_I18N_TOOLS" configure.ac >/dev/null; then
127 echo "Running xml-i18n-toolize..."
128 xml-i18n-toolize --copy --force --automake
129 fi
130 if grep "^AM_PROG_LIBTOOL" configure.ac >/dev/null; then
131 if test -z "$NO_LIBTOOLIZE" ; then
132 echo "Running libtoolize..."
133 libtoolize --force --copy
134 fi
135 fi
136 echo "Running aclocal $aclocalinclude ..."
137 aclocal $aclocalinclude
138 if grep "^AM_CONFIG_HEADER" configure.ac >/dev/null; then
139 echo "Running autoheader..."
140 autoheader
141 fi
142 echo "Running automake --gnu $am_opt ..."
143 automake --add-missing --gnu $am_opt
144 echo "Running autoconf ..."
145 autoconf
146 )
147 fi
148 done
149
150 conf_flags="--enable-maintainer-mode"
151
152 if test x$NOCONFIGURE = x; then
153 echo Running $srcdir/configure $conf_flags "$@" ...
154 $srcdir/configure $conf_flags "$@" \
155 && echo Now type \`make\' to compile. || exit 1
156 else
157 echo Skipping configure process.
158 fi
0 AC_INIT(osm-gps-map, 0.6.0)
1 AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
0 AC_PREREQ([2.62])
1 AC_INIT([osm-gps-map],
2 [0.7.0],
3 [http://github.com/nzjrs/osm-gps-map/issues],
4 [osm-gps-map])
5 AM_INIT_AUTOMAKE([1.10])
26
3 AC_CONFIG_SRCDIR(osmgpsmap.pc.in)
4 AM_CONFIG_HEADER(config.h)
7 AC_CONFIG_HEADER([config.h])
8 AC_CONFIG_SRCDIR([src/osm-gps-map.h])
9 AC_CONFIG_MACRO_DIR([m4])
510
611 AM_MAINTAINER_MODE
712
8 AC_ISC_POSIX
9 AC_PROG_CC
10 AM_PROG_CC_STDC
11 AC_HEADER_STDC
13 AM_PROG_CC_C_O
1214
1315 AC_LIBTOOL_WIN32_DLL
1416 AM_PROG_LIBTOOL
1517
1618 m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
1719
18 PKG_CHECK_MODULES(OPENSTREETMAP_GPS_MAP, [gtk+-2.0 glib-2.0 >= 2.18 cairo >= 1.8])
20 PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.16])
21 PKG_CHECK_MODULES(GTK, [gtk+-2.0])
22 PKG_CHECK_MODULES(CAIRO, [cairo >= 1.6])
1923
2024 PKG_CHECK_MODULES(SOUP24, libsoup-2.4,
2125 soup_ver=2.4, [
2327 soup_ver=2.2
2428 AC_DEFINE(USE_LIBSOUP22, 1, Use libsoup 2.2 instead of libsoup-2.4 to download tiles)],
2529 AC_ERROR([libsoup-2.4 (preferred) or libsoup-2.2 not found]))])
26
27 OPENSTREETMAP_GPS_MAP_CFLAGS="$OPENSTREETMAP_GPS_MAP_CFLAGS $SOUP24_CFLAGS $SOUP22_CFLAGS"
28 OPENSTREETMAP_GPS_MAP_LIBS="$OPENSTREETMAP_GPS_MAP_LIBS $SOUP24_LIBS $SOUP22_LIBS"
29
30 AC_SUBST(OPENSTREETMAP_GPS_MAP_CFLAGS)
31 AC_SUBST(OPENSTREETMAP_GPS_MAP_LIBS)
3230
3331 AC_MSG_CHECKING([for Win32])
3432 case "$host" in
4947 # - If binary compatibility has been broken (eg removed or changed interfaces)
5048 # change to C+1:0:0
5149 # - If the interface is the same as the previous version, change to C:R+1:A
52 LT_VERSION_INFO=1:0:1
50 LT_VERSION_INFO=2:0:0
5351 AC_SUBST(LT_VERSION_INFO)
5452
55 CFLAGS="$CFLAGS -Wall -Wswitch-enum"
53 GTK_DOC_CHECK([1.12])
54 GOBJECT_INTROSPECTION_CHECK([0.6.7])
55 GNOME_COMPILE_WARNINGS([maximum])
56 GNOME_MAINTAINER_MODE_DEFINES
5657
5758 AC_OUTPUT([
5859 osmgpsmap.pc
5960 Makefile
6061 src/Makefile
62 docs/Makefile
63 examples/Makefile
64 docs/reference/Makefile
65 docs/reference/version.xml
6166 ])
6267
6368 echo
0 SUBDIRS = reference
0 ## Process this file with automake to produce Makefile.in
1
2 # We require automake 1.6 at least.
3 AUTOMAKE_OPTIONS = 1.6
4
5 # This is a blank Makefile.am for using gtk-doc.
6 # Copy this to your project's API docs directory and modify the variables to
7 # suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples
8 # of using the various options.
9
10 # The name of the module, e.g. 'glib'.
11 DOC_MODULE=libosmgpsmap
12
13 # The top-level SGML file. You can change this if you want to.
14 DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.xml
15
16 # The directory containing the source code. Relative to $(srcdir).
17 # gtk-doc will search all .c & .h files beneath here for inline comments
18 # documenting the functions and macros.
19 # e.g. DOC_SOURCE_DIR=../../../gtk
20 DOC_SOURCE_DIR=../../src
21
22 # Extra options to pass to gtkdoc-scangobj. Not normally needed.
23 SCANGOBJ_OPTIONS=
24
25 # Extra options to supply to gtkdoc-scan.
26 # e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
27 SCAN_OPTIONS=
28
29 # Extra options to supply to gtkdoc-mkdb.
30 # e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml
31 MKDB_OPTIONS=--sgml-mode --output-format=xml --name-space=osm_gps_map_
32
33 # Extra options to supply to gtkdoc-mktmpl
34 # e.g. MKTMPL_OPTIONS=--only-section-tmpl
35 MKTMPL_OPTIONS=
36
37 # Extra options to supply to gtkdoc-fixref. Not normally needed.
38 # e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
39 FIXXREF_OPTIONS=
40
41 # Add the builddir to the HTML path so that version.xml is found
42 MKHTML_OPTIONS=--path="$(abs_builddir)"
43
44 # Used for dependencies. The docs will be rebuilt if any of these change.
45 # e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
46 # e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
47 HFILE_GLOB=$(top_srcdir)/src/*.h
48 CFILE_GLOB=$(top_srcdir)/src/*.c
49
50 # Header files to ignore when scanning.
51 # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h
52 IGNORE_HFILES= \
53 converter.h
54
55 # Images to copy into HTML directory.
56 # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
57 HTML_IMAGES=
58
59 # Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
60 # e.g. content_files=running.sgml building.sgml changes-2.0.sgml
61 content_files=version.xml
62
63 # SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
64 # These files must be listed here *and* in content_files
65 # e.g. expand_content_files=running.sgml
66 expand_content_files=
67
68 # CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
69 # Only needed if you are using gtkdoc-scangobj to dynamically query widget
70 # signals and properties.
71 # e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
72 # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
73 INCLUDES=-I$(top_srcdir) -I$(top_builddir) \
74 $(GLIB_CFLAGS) \
75 $(GTK_CFLAGS) \
76 $(CAIRO_CFLAGS) \
77 $(SOUP22_CFLAGS) $(SOUP24_CFLAGS)
78 GTKDOC_LIBS=$(top_builddir)/src/libosmgpsmap.la \
79 $(GLIB_LIBS) \
80 $(GTK_LIBS) \
81 $(CAIRO_LIBS) \
82 $(SOUP22_LIBS) $(SOUP24_LIBS)
83
84 # This includes the standard gtk-doc make rules, copied by gtkdocize.
85 include $(top_srcdir)/gtk-doc.make
86
87 # Other files to distribute
88 # e.g. EXTRA_DIST += version.xml.in
89 EXTRA_DIST += version.xml.in
90
91 if ENABLE_GTK_DOC
92 TESTS_ENVIRONMENT = cd $(srcdir) &&
93 TESTS = $(GTKDOC_CHECK)
94 endif
0 <?xml version="1.0"?>
1 <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
2 <!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
3 <!ENTITY version SYSTEM "version.xml">
4 <!ENTITY slash "/">
5 ]>
6 <book id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
7 <bookinfo>
8 <title>OsmGpsMap Reference Manual</title>
9 </bookinfo>
10
11 <chapter id="api-reference">
12 <title>API Reference</title>
13 <xi:include href="xml/osm-gps-map.xml"/>
14 <xi:include href="xml/osm-gps-map-layer.xml"/>
15 <xi:include href="xml/osm-gps-map-image.xml"/>
16 <xi:include href="xml/osm-gps-map-track.xml"/>
17 <xi:include href="xml/osm-gps-map-point.xml"/>
18 </chapter>
19
20 <chapter id="api-reference-deprecated">
21 <title>Deprecated API</title>
22 <xi:include href="xml/osm-gps-map-deprecated.xml"/>
23 </chapter>
24
25 <index id="api-index-full">
26 <title>Index of all symbols</title>
27 <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
28 </index>
29 <index id="api-index-deprecated" role="deprecated">
30 <title>Index of deprecated symbols</title>
31 <xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
32 </index>
33 <index id="annotation-glossary">
34 <title>Annotation glossary</title>
35 <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
36 </index>
37 </book>
0 <SECTION>
1 <FILE>osm-gps-map</FILE>
2 <TITLE>OsmGpsMap</TITLE>
3 OsmGpsMap
4 OsmGpsMapClass
5 OSM_GPS_MAP_INVALID
6 OSM_GPS_MAP_CACHE_DISABLED
7 OSM_GPS_MAP_CACHE_AUTO
8 OSM_GPS_MAP_CACHE_FRIENDLY
9 osm_gps_map_get_default_cache_directory
10 OsmGpsMapSource_t
11 osm_gps_map_source_get_friendly_name
12 osm_gps_map_source_get_repo_uri
13 osm_gps_map_source_get_image_format
14 osm_gps_map_source_get_min_zoom
15 osm_gps_map_source_get_max_zoom
16 osm_gps_map_source_is_valid
17 osm_gps_map_download_maps
18 osm_gps_map_get_bbox
19 osm_gps_map_set_center
20 osm_gps_map_set_center_and_zoom
21 osm_gps_map_set_zoom
22 osm_gps_map_zoom_in
23 osm_gps_map_zoom_out
24 osm_gps_map_scroll
25 osm_gps_map_get_scale
26 OsmGpsMapKey_t
27 osm_gps_map_set_keyboard_shortcut
28 osm_gps_map_get_event_location
29 osm_gps_map_convert_geographic_to_screen
30 osm_gps_map_convert_screen_to_geographic
31 osm_gps_map_gps_add
32 osm_gps_map_gps_clear
33 osm_gps_map_gps_get_track
34 osm_gps_map_track_add
35 osm_gps_map_track_remove
36 osm_gps_map_track_remove_all
37 osm_gps_map_image_add
38 osm_gps_map_image_add_with_alignment
39 osm_gps_map_image_remove
40 osm_gps_map_image_remove_all
41 osm_gps_map_layer_add
42 osm_gps_map_layer_remove
43 osm_gps_map_layer_remove_all
44 </SECTION>
45
46 <SECTION>
47 <FILE>osm-gps-map-deprecated</FILE>
48 <TITLE>OsmGpsMap Deprecated</TITLE>
49 osm_gps_map_draw_gps
50 osm_gps_map_clear_gps
51 osm_gps_map_add_track
52 osm_gps_map_replace_track
53 osm_gps_map_clear_tracks
54 osm_gps_map_add_image
55 osm_gps_map_add_image_with_alignment
56 osm_gps_map_remove_image
57 osm_gps_map_clear_images
58 osm_gps_map_add_layer
59 osm_gps_map_get_co_ordinates
60 osm_gps_map_screen_to_geographic
61 osm_gps_map_geographic_to_screen
62 osm_gps_map_set_mapcenter
63 </SECTION>
64
65 <SECTION>
66 <FILE>osm-gps-map-layer</FILE>
67 <TITLE>OsmGpsMapLayer</TITLE>
68 OsmGpsMapLayer
69 OsmGpsMapLayerClass
70 osm_gps_map_layer_render
71 osm_gps_map_layer_draw
72 osm_gps_map_layer_busy
73 osm_gps_map_layer_button_press
74 OsmGpsMapOsd
75 OsmGpsMapOsdClass
76 osm_gps_map_osd_new
77 </SECTION>
78
79 <SECTION>
80 <FILE>osm-gps-map-image</FILE>
81 <TITLE>OsmGpsMapImage</TITLE>
82 OsmGpsMapImage
83 OsmGpsMapImageClass
84 osm_gps_map_image_draw
85 osm_gps_map_image_get_point
86 osm_gps_map_image_get_type
87 osm_gps_map_image_new
88 </SECTION>
89
90 <SECTION>
91 <FILE>osm-gps-map-point</FILE>
92 <TITLE>OsmGpsMapPoint</TITLE>
93 OsmGpsMapPoint
94 osm_gps_map_point_get_degrees
95 osm_gps_map_point_get_radians
96 osm_gps_map_point_new_degrees
97 osm_gps_map_point_new_radians
98 osm_gps_map_point_set_degrees
99 osm_gps_map_point_set_radians
100 </SECTION>
101
102 <SECTION>
103 <FILE>osm-gps-map-track</FILE>
104 <TITLE>OsmGpsMapTrack</TITLE>
105 OsmGpsMapTrack
106 OsmGpsMapTrackClass
107 osm_gps_map_track_add_point
108 osm_gps_map_track_get_color
109 osm_gps_map_track_get_points
110 osm_gps_map_track_new
111 </SECTION>
0 osm_gps_map_get_type
1 osm_gps_map_layer_get_type
2 osm_gps_map_osd_get_type
3 osm_gps_map_image_get_type
4 osm_gps_map_track_get_type
5 osm_gps_map_point_get_type
0 @AC_PACKAGE_VERSION@
0 ## Process this file with automake to produce Makefile.in
1
2 OSMGPSMAP_CFLAGS = \
3 $(GLIB_CFLAGS) \
4 $(GTK_CFLAGS) \
5 $(CAIRO_CFLAGS) \
6 $(SOUP22_CFLAGS) \
7 $(SOUP24_CFLAGS)
8
9 OSMGPSMAP_LIBS = \
10 $(GLIB_LIBS) \
11 $(GTK_LIBS) \
12 $(CAIRO_LIBS) \
13 $(SOUP22_LIBS) \
14 $(SOUP24_LIBS)
15
16 ## Demo Application
17 bin_PROGRAMS = mapviewer
18
19 mapviewer_SOURCES = \
20 mapviewer.c
21
22 mapviewer_CFLAGS = \
23 -I$(top_srcdir)/src \
24 $(WARN_CFLAGS) \
25 $(DISABLE_DEPRECATED) \
26 $(OSMGPSMAP_CFLAGS)
27
28 mapviewer_LDADD = \
29 $(OSMGPSMAP_LIBS) \
30 $(top_builddir)/src/libosmgpsmap.la
31
32 ## Misc
33 EXTRA_DIST = poi.png mapviewer.ui mapviewer.js
34
0 export LD_LIBRARY_PATH=../src/.libs/
1 export GI_TYPELIB_PATH=$GI_TYPELIB_PATH:../src/
2 export PYTHONPATH=../python/
0 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */
1 /* vim:set et sw=4 ts=4 cino=t0,(0: */
2 /*
3 * main.c
4 * Copyright (C) John Stowers 2008 <john.stowers@gmail.com>
5 *
6 * This is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; version 2.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <stdlib.h>
20 #include <math.h>
21 #include <glib.h>
22 #include <gtk/gtk.h>
23 #include <gdk/gdkkeysyms.h>
24
25 #include "osm-gps-map.h"
26
27 static OsmGpsMapSource_t opt_map_provider = OSM_GPS_MAP_SOURCE_OPENSTREETMAP;
28 static gboolean opt_default_cache = FALSE;
29 static gboolean opt_no_cache = FALSE;
30 static gboolean opt_debug = FALSE;
31 static char *opt_cache_base_dir = NULL;
32 static GOptionEntry entries[] =
33 {
34 { "default-cache", 'D', 0, G_OPTION_ARG_NONE, &opt_default_cache, "Store maps using default cache style (md5)", NULL },
35 { "no-cache", 'n', 0, G_OPTION_ARG_NONE, &opt_no_cache, "Disable cache", NULL },
36 { "cache-basedir", 'b', 0, G_OPTION_ARG_FILENAME, &opt_cache_base_dir, "Cache basedir", NULL },
37 { "debug", 'd', 0, G_OPTION_ARG_NONE, &opt_debug, "Enable debugging", NULL },
38 { "map", 'm', 0, G_OPTION_ARG_INT, &opt_map_provider, "Map source", "N" },
39 { NULL }
40 };
41
42 static GdkPixbuf *g_star_image = NULL;
43 static OsmGpsMapImage *g_last_image = NULL;
44
45 static gboolean
46 on_button_press_event (GtkWidget *widget, GdkEventButton *event, gpointer user_data)
47 {
48 OsmGpsMapPoint coord;
49 float lat, lon;
50 OsmGpsMap *map = OSM_GPS_MAP(widget);
51 OsmGpsMapTrack *othertrack = OSM_GPS_MAP_TRACK(user_data);
52
53 if (event->type == GDK_3BUTTON_PRESS) {
54 if (event->button == 1) {
55 if (g_last_image)
56 osm_gps_map_image_remove (map, g_last_image);
57 }
58 if (event->button == 3) {
59 osm_gps_map_track_remove(map, othertrack);
60 }
61 }
62
63 if (event->type == GDK_2BUTTON_PRESS) {
64 osm_gps_map_convert_screen_to_geographic(map, event->x, event->y, &coord);
65 osm_gps_map_point_get_degrees(&coord, &lat, &lon);
66 if (event->button == 1) {
67 osm_gps_map_gps_add (map,
68 lat,
69 lon,
70 g_random_double_range(0,360));
71 }
72 if (event->button == 3) {
73 OsmGpsMapPoint *pt = g_boxed_copy(OSM_TYPE_GPS_MAP_POINT, &coord);
74 osm_gps_map_track_add_point(othertrack, pt);
75 }
76 }
77
78 if (event->type == GDK_BUTTON_PRESS) {
79 if (event->button == 2) {
80 osm_gps_map_convert_screen_to_geographic(map, event->x, event->y, &coord);
81 osm_gps_map_point_get_degrees(&coord, &lat, &lon);
82 g_last_image = osm_gps_map_image_add (
83 map,
84 lat,
85 lon,
86 g_star_image);
87 }
88 }
89 return FALSE;
90 }
91
92 static gboolean
93 on_button_release_event (GtkWidget *widget, GdkEventButton *event, gpointer user_data)
94 {
95 float lat,lon;
96 GtkEntry *entry = GTK_ENTRY(user_data);
97 OsmGpsMap *map = OSM_GPS_MAP(widget);
98
99 g_object_get(map, "latitude", &lat, "longitude", &lon, NULL);
100 gchar *msg = g_strdup_printf("%f,%f",lat,lon);
101 gtk_entry_set_text(entry, msg);
102 g_free(msg);
103
104 return FALSE;
105 }
106
107 static gboolean
108 on_zoom_in_clicked_event (GtkWidget *widget, gpointer user_data)
109 {
110 int zoom;
111 OsmGpsMap *map = OSM_GPS_MAP(user_data);
112 g_object_get(map, "zoom", &zoom, NULL);
113 osm_gps_map_set_zoom(map, zoom+1);
114 return FALSE;
115 }
116
117 static gboolean
118 on_zoom_out_clicked_event (GtkWidget *widget, gpointer user_data)
119 {
120 int zoom;
121 OsmGpsMap *map = OSM_GPS_MAP(user_data);
122 g_object_get(map, "zoom", &zoom, NULL);
123 osm_gps_map_set_zoom(map, zoom-1);
124 return FALSE;
125 }
126
127 static gboolean
128 on_home_clicked_event (GtkWidget *widget, gpointer user_data)
129 {
130 OsmGpsMap *map = OSM_GPS_MAP(user_data);
131 osm_gps_map_set_center_and_zoom(map, -43.5326,172.6362,12);
132 return FALSE;
133 }
134
135 static gboolean
136 on_cache_clicked_event (GtkWidget *widget, gpointer user_data)
137 {
138 OsmGpsMap *map = OSM_GPS_MAP(user_data);
139 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
140 int zoom,max_zoom;
141 OsmGpsMapPoint pt1, pt2;
142 osm_gps_map_get_bbox(map, &pt1, &pt2);
143 g_object_get(map, "zoom", &zoom, "max-zoom", &max_zoom, NULL);
144 osm_gps_map_download_maps(map, &pt1, &pt2, zoom, max_zoom);
145 } else {
146 osm_gps_map_download_cancel_all(map);
147 }
148 return FALSE;
149 }
150
151 static void
152 on_tiles_queued_changed (OsmGpsMap *image, GParamSpec *pspec, gpointer user_data)
153 {
154 gchar *s;
155 int tiles;
156 GtkLabel *label = GTK_LABEL(user_data);
157 g_object_get(image, "tiles-queued", &tiles, NULL);
158 s = g_strdup_printf("%d", tiles);
159 gtk_label_set_text(label, s);
160 g_free(s);
161 }
162
163 static void
164 on_gps_alpha_changed (GtkAdjustment *adjustment, gpointer user_data)
165 {
166 OsmGpsMap *map = OSM_GPS_MAP(user_data);
167 OsmGpsMapTrack *track = osm_gps_map_gps_get_track (map);
168 float f = gtk_adjustment_get_value(adjustment);
169 g_object_set (track, "alpha", f, NULL);}
170
171 static void
172 on_gps_width_changed (GtkAdjustment *adjustment, gpointer user_data)
173 {
174 OsmGpsMap *map = OSM_GPS_MAP(user_data);
175 OsmGpsMapTrack *track = osm_gps_map_gps_get_track (map);
176 float f = gtk_adjustment_get_value(adjustment);
177 g_object_set (track, "line-width", f, NULL);
178 }
179
180 static void
181 on_star_align_changed (GtkAdjustment *adjustment, gpointer user_data)
182 {
183 const char *propname = user_data;
184 float f = gtk_adjustment_get_value(adjustment);
185 if (g_last_image)
186 g_object_set (g_last_image, propname, f, NULL);
187 }
188
189 static void
190 on_gps_color_changed (GtkColorButton *widget, gpointer user_data)
191 {
192 GdkColor c;
193 OsmGpsMapTrack *track = OSM_GPS_MAP_TRACK(user_data);
194 gtk_color_button_get_color (widget, &c);
195 g_object_set(track, "color", &c, NULL);
196 }
197
198 static void
199 on_close (GtkWidget *widget, gpointer user_data)
200 {
201 gtk_widget_destroy(widget);
202 gtk_main_quit();
203 }
204
205 static void
206 usage (GOptionContext *context)
207 {
208 int i;
209
210 puts(g_option_context_get_help(context, TRUE, NULL));
211
212 printf("Valid map sources:\n");
213 for(i=OSM_GPS_MAP_SOURCE_NULL; i <= OSM_GPS_MAP_SOURCE_LAST; i++)
214 {
215 const char *name = osm_gps_map_source_get_friendly_name(i);
216 const char *uri = osm_gps_map_source_get_repo_uri(i);
217 if (uri != NULL)
218 printf("\t%d:\t%s\n",i,name);
219 }
220 }
221
222 int
223 main (int argc, char **argv)
224 {
225 GtkBuilder *builder;
226 GtkWidget *widget;
227 OsmGpsMap *map;
228 OsmGpsMapLayer *osd;
229 OsmGpsMapTrack *rightclicktrack;
230 const char *repo_uri;
231 const char *friendly_name;
232 char *cachedir, *cachebasedir;
233 GError *error = NULL;
234 GOptionContext *context;
235
236 g_thread_init(NULL);
237 gtk_init (&argc, &argv);
238
239 context = g_option_context_new ("- Map browser");
240 g_option_context_set_help_enabled(context, FALSE);
241 g_option_context_add_main_entries (context, entries, NULL);
242
243 if (!g_option_context_parse (context, &argc, &argv, &error)) {
244 usage(context);
245 return 1;
246 }
247
248 /* Only use the repo_uri to check if the user has supplied a
249 valid map source ID */
250 repo_uri = osm_gps_map_source_get_repo_uri(opt_map_provider);
251 if ( repo_uri == NULL ) {
252 usage(context);
253 return 2;
254 }
255
256 friendly_name = osm_gps_map_source_get_friendly_name(opt_map_provider);
257 cachebasedir = osm_gps_map_get_default_cache_directory();
258
259 if (opt_cache_base_dir && g_file_test(opt_cache_base_dir, G_FILE_TEST_IS_DIR)) {
260 cachedir = g_strdup(OSM_GPS_MAP_CACHE_AUTO);
261 cachebasedir = g_strdup(opt_cache_base_dir);
262 } else if (opt_default_cache) {
263 cachedir = g_strdup(OSM_GPS_MAP_CACHE_AUTO);
264 } else if (opt_no_cache) {
265 cachedir = g_strdup(OSM_GPS_MAP_CACHE_DISABLED);
266 } else {
267 cachedir = g_build_filename(cachebasedir,friendly_name,NULL);
268 }
269
270 if (opt_debug)
271 gdk_window_set_debug_updates(TRUE);
272
273 g_debug("Map Cache Dir: %s", cachedir);
274 g_debug("Map Provider: %s (%d)", friendly_name, opt_map_provider);
275
276 map = g_object_new (OSM_TYPE_GPS_MAP,
277 "map-source",opt_map_provider,
278 "tile-cache",cachedir,
279 "tile-cache-base", cachebasedir,
280 "proxy-uri",g_getenv("http_proxy"),
281 NULL);
282
283 osd = g_object_new (OSM_TYPE_GPS_MAP_OSD,
284 "show-scale",TRUE,
285 "show-coordinates",TRUE,
286 "show-crosshair",TRUE,
287 "show-dpad",TRUE,
288 "show-zoom",TRUE,
289 "show-gps-in-dpad",TRUE,
290 "show-gps-in-zoom",FALSE,
291 "dpad-radius", 30,
292 NULL);
293 osm_gps_map_layer_add(OSM_GPS_MAP(map), osd);
294 g_object_unref(G_OBJECT(osd));
295
296 //Add a second track for right clicks
297 rightclicktrack = osm_gps_map_track_new();
298 osm_gps_map_track_add(OSM_GPS_MAP(map), rightclicktrack);
299
300 g_free(cachedir);
301 g_free(cachebasedir);
302
303 //Enable keyboard navigation
304 osm_gps_map_set_keyboard_shortcut(map, OSM_GPS_MAP_KEY_FULLSCREEN, GDK_F11);
305 osm_gps_map_set_keyboard_shortcut(map, OSM_GPS_MAP_KEY_UP, GDK_Up);
306 osm_gps_map_set_keyboard_shortcut(map, OSM_GPS_MAP_KEY_DOWN, GDK_Down);
307 osm_gps_map_set_keyboard_shortcut(map, OSM_GPS_MAP_KEY_LEFT, GDK_Left);
308 osm_gps_map_set_keyboard_shortcut(map, OSM_GPS_MAP_KEY_RIGHT, GDK_Right);
309
310 //Build the UI
311 g_star_image = gdk_pixbuf_new_from_file_at_size ("poi.png", 24,24,NULL);
312
313 builder = gtk_builder_new();
314 gtk_builder_add_from_file (builder, "mapviewer.ui", &error);
315 if (error)
316 g_error ("ERROR: %s\n", error->message);
317
318 gtk_box_pack_start (
319 GTK_BOX(gtk_builder_get_object(builder, "map_box")),
320 GTK_WIDGET(map), TRUE, TRUE, 0);
321
322 //Init values
323 float lw,a;
324 GdkColor c;
325 OsmGpsMapTrack *gpstrack = osm_gps_map_gps_get_track (map);
326 g_object_get (gpstrack, "line-width", &lw, "alpha", &a, NULL);
327 osm_gps_map_track_get_color(gpstrack, &c);
328 gtk_adjustment_set_value (
329 GTK_ADJUSTMENT(gtk_builder_get_object(builder, "gps_width_adjustment")),
330 lw);
331 gtk_adjustment_set_value (
332 GTK_ADJUSTMENT(gtk_builder_get_object(builder, "gps_alpha_adjustment")),
333 a);
334 gtk_adjustment_set_value (
335 GTK_ADJUSTMENT(gtk_builder_get_object(builder, "star_xalign_adjustment")),
336 0.5);
337 gtk_adjustment_set_value (
338 GTK_ADJUSTMENT(gtk_builder_get_object(builder, "star_yalign_adjustment")),
339 0.5);
340 gtk_color_button_set_color (
341 GTK_COLOR_BUTTON(gtk_builder_get_object(builder, "gps_colorbutton")),
342 &c);
343
344 //Connect to signals
345 g_signal_connect (
346 gtk_builder_get_object(builder, "zoom_in_button"), "clicked",
347 G_CALLBACK (on_zoom_in_clicked_event), (gpointer) map);
348 g_signal_connect (
349 gtk_builder_get_object(builder, "zoom_out_button"), "clicked",
350 G_CALLBACK (on_zoom_out_clicked_event), (gpointer) map);
351 g_signal_connect (
352 gtk_builder_get_object(builder, "home_button"), "clicked",
353 G_CALLBACK (on_home_clicked_event), (gpointer) map);
354 g_signal_connect (
355 gtk_builder_get_object(builder, "cache_button"), "clicked",
356 G_CALLBACK (on_cache_clicked_event), (gpointer) map);
357 g_signal_connect (
358 gtk_builder_get_object(builder, "gps_alpha_adjustment"), "value-changed",
359 G_CALLBACK (on_gps_alpha_changed), (gpointer) map);
360 g_signal_connect (
361 gtk_builder_get_object(builder, "gps_width_adjustment"), "value-changed",
362 G_CALLBACK (on_gps_width_changed), (gpointer) map);
363 g_signal_connect (
364 gtk_builder_get_object(builder, "star_xalign_adjustment"), "value-changed",
365 G_CALLBACK (on_star_align_changed), (gpointer) "x-align");
366 g_signal_connect (
367 gtk_builder_get_object(builder, "star_yalign_adjustment"), "value-changed",
368 G_CALLBACK (on_star_align_changed), (gpointer) "y-align");
369 g_signal_connect (
370 gtk_builder_get_object(builder, "gps_colorbutton"), "color-set",
371 G_CALLBACK (on_gps_color_changed), (gpointer) gpstrack);
372 g_signal_connect (G_OBJECT (map), "button-press-event",
373 G_CALLBACK (on_button_press_event), (gpointer) rightclicktrack);
374 g_signal_connect (G_OBJECT (map), "button-release-event",
375 G_CALLBACK (on_button_release_event),
376 (gpointer) gtk_builder_get_object(builder, "text_entry"));
377 g_signal_connect (G_OBJECT (map), "notify::tiles-queued",
378 G_CALLBACK (on_tiles_queued_changed),
379 (gpointer) gtk_builder_get_object(builder, "cache_label"));
380
381 widget = GTK_WIDGET(gtk_builder_get_object(builder, "window1"));
382 g_signal_connect (widget, "destroy",
383 G_CALLBACK (on_close), (gpointer) map);
384 gtk_widget_show_all (widget);
385
386 g_log_set_handler ("OsmGpsMap", G_LOG_LEVEL_MASK, g_log_default_handler, NULL);
387 gtk_main ();
388
389 return 0;
390 }
0 #!/usr/bin/seed
1
2 const Gtk = imports.gi.Gtk;
3 const Osm = imports.gi.OsmGpsMap;
4
5 Gtk.init(0, null);
6
7 var win = new Gtk.Window({ type: Gtk.WindowType.TOPLEVEL });
8 win.set_border_width(10);
9 win.set_default_size(400,400);
10
11 // Fuck you GNOME
12 // GJS makes me do this
13 //win.connect("delete-event", Gtk.main_quit);
14 // Seed makes me do this
15 win.signal.delete_event.connect(Gtk.main_quit);
16
17 var map = new Osm.OsmGpsMap()
18 var osd = new Osm.Osd()
19
20 map.layer_add(osd)
21 win.add(map);
22
23 win.show_all();
24
25 Gtk.main();
26
27
0 #!/usr/bin/python
1
2 """
3 Copyright (C) Hadley Rich 2008 <hads@nice.net.nz>
4 based on main.c - with thanks to John Stowers
5
6 This is free software: you can redistribute it and/or modify it
7 under the terms of the GNU General Public License
8 as published by the Free Software Foundation; version 2.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, see <http://www.gnu.org/licenses/>.
17 """
18
19 import sys
20 import os.path
21 import gtk.gdk
22 import gobject
23
24 gobject.threads_init()
25 gtk.gdk.threads_init()
26
27 #Try static lib first
28 mydir = os.path.dirname(os.path.abspath(__file__))
29 libdir = os.path.abspath(os.path.join(mydir, "..", "python", ".libs"))
30 sys.path.insert(0, libdir)
31
32 import osmgpsmap
33 print "using library: %s (version %s)" % (osmgpsmap.__file__, osmgpsmap.__version__)
34
35 class DummyMapNoGpsPoint(osmgpsmap.GpsMap):
36 def do_draw_gps_point(self, drawable):
37 pass
38 gobject.type_register(DummyMapNoGpsPoint)
39
40 class DummyLayer(gobject.GObject, osmgpsmap.GpsMapLayer):
41 def __init__(self):
42 gobject.GObject.__init__(self)
43
44 def do_draw(self, gpsmap, gdkdrawable):
45 pass
46
47 def do_render(self, gpsmap):
48 pass
49
50 def do_busy(self):
51 return False
52
53 def do_button_press(self, gpsmap, gdkeventbutton):
54 return False
55 gobject.type_register(DummyLayer)
56
57 class UI(gtk.Window):
58 def __init__(self):
59 gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
60
61 self.set_default_size(500, 500)
62 self.connect('destroy', lambda x: gtk.main_quit())
63 self.set_title('OpenStreetMap GPS Mapper')
64
65 self.vbox = gtk.VBox(False, 0)
66 self.add(self.vbox)
67
68 if 0:
69 self.osm = DummyMapNoGpsPoint()
70 else:
71 self.osm = osmgpsmap.GpsMap()
72 self.osm.layer_add(
73 osmgpsmap.GpsMapOsd(
74 show_dpad=True,
75 show_zoom=True))
76 self.osm.layer_add(
77 DummyLayer())
78
79 self.osm.connect('button_release_event', self.map_clicked)
80
81 #connect keyboard shortcuts
82 self.osm.set_keyboard_shortcut(osmgpsmap.KEY_FULLSCREEN, gtk.gdk.keyval_from_name("F11"))
83 self.osm.set_keyboard_shortcut(osmgpsmap.KEY_UP, gtk.gdk.keyval_from_name("Up"))
84 self.osm.set_keyboard_shortcut(osmgpsmap.KEY_DOWN, gtk.gdk.keyval_from_name("Down"))
85 self.osm.set_keyboard_shortcut(osmgpsmap.KEY_LEFT, gtk.gdk.keyval_from_name("Left"))
86 self.osm.set_keyboard_shortcut(osmgpsmap.KEY_RIGHT, gtk.gdk.keyval_from_name("Right"))
87
88 self.latlon_entry = gtk.Entry()
89
90 zoom_in_button = gtk.Button(stock=gtk.STOCK_ZOOM_IN)
91 zoom_in_button.connect('clicked', self.zoom_in_clicked)
92 zoom_out_button = gtk.Button(stock=gtk.STOCK_ZOOM_OUT)
93 zoom_out_button.connect('clicked', self.zoom_out_clicked)
94 home_button = gtk.Button(stock=gtk.STOCK_HOME)
95 home_button.connect('clicked', self.home_clicked)
96 cache_button = gtk.Button('Cache')
97 cache_button.connect('clicked', self.cache_clicked)
98
99 self.vbox.pack_start(self.osm)
100 hbox = gtk.HBox(False, 0)
101 hbox.pack_start(zoom_in_button)
102 hbox.pack_start(zoom_out_button)
103 hbox.pack_start(home_button)
104 hbox.pack_start(cache_button)
105
106 #add ability to test custom map URIs
107 ex = gtk.Expander("<b>Map Repository URI</b>")
108 ex.props.use_markup = True
109 vb = gtk.VBox()
110 self.repouri_entry = gtk.Entry()
111 self.repouri_entry.set_text(self.osm.props.repo_uri)
112 self.image_format_entry = gtk.Entry()
113 self.image_format_entry.set_text(self.osm.props.image_format)
114
115 lbl = gtk.Label(
116 """
117 Enter an repository URL to fetch map tiles from in the box below. Special metacharacters may be included in this url
118
119 <i>Metacharacters:</i>
120 \t#X\tMax X location
121 \t#Y\tMax Y location
122 \t#Z\tMap zoom (0 = min zoom, fully zoomed out)
123 \t#S\tInverse zoom (max-zoom - #Z)
124 \t#Q\tQuadtree encoded tile (qrts)
125 \t#W\tQuadtree encoded tile (1234)
126 \t#U\tEncoding not implemeted
127 \t#R\tRandom integer, 0-4""")
128 lbl.props.xalign = 0
129 lbl.props.use_markup = True
130 lbl.props.wrap = True
131
132 ex.add(vb)
133 vb.pack_start(lbl, False)
134
135 hb = gtk.HBox()
136 hb.pack_start(gtk.Label("URI: "), False)
137 hb.pack_start(self.repouri_entry, True)
138 vb.pack_start(hb, False)
139
140 hb = gtk.HBox()
141 hb.pack_start(gtk.Label("Image Format: "), False)
142 hb.pack_start(self.image_format_entry, True)
143 vb.pack_start(hb, False)
144
145 gobtn = gtk.Button("Load Map URI")
146 gobtn.connect("clicked", self.load_map_clicked)
147 vb.pack_start(gobtn, False)
148
149 cb = gtk.CheckButton("Disable Cache")
150 cb.props.active = False
151 cb.connect("toggled", self.disable_cache_toggled)
152
153 self.vbox.pack_end(cb, False)
154 self.vbox.pack_end(ex, False)
155 self.vbox.pack_end(self.latlon_entry, False)
156 self.vbox.pack_end(hbox, False)
157
158 gobject.timeout_add(500, self.print_tiles)
159
160 def disable_cache_toggled(self, btn):
161 if btn.props.active:
162 self.osm.props.tile_cache = osmgpsmap.CACHE_DISABLED
163 else:
164 self.osm.props.tile_cache = osmgpsmap.CACHE_AUTO
165
166 def load_map_clicked(self, button):
167 uri = self.repouri_entry.get_text()
168 format = self.image_format_entry.get_text()
169 if uri and format:
170 if self.osm:
171 #remove old map
172 self.vbox.remove(self.osm)
173 try:
174 self.osm = osmgpsmap.GpsMap(
175 repo_uri=uri,
176 image_format=format
177 )
178 self.osm.connect('button_release_event', self.map_clicked)
179 except Exception, e:
180 print "ERROR:", e
181 self.osm = osm.GpsMap()
182
183 self.vbox.pack_start(self.osm, True)
184 self.osm.connect('button_release_event', self.map_clicked)
185 self.osm.show()
186
187 def print_tiles(self):
188 if self.osm.props.tiles_queued != 0:
189 print self.osm.props.tiles_queued, 'tiles queued'
190 return True
191
192 def zoom_in_clicked(self, button):
193 self.osm.set_zoom(self.osm.props.zoom + 1)
194
195 def zoom_out_clicked(self, button):
196 self.osm.set_zoom(self.osm.props.zoom - 1)
197
198 def home_clicked(self, button):
199 self.osm.set_center_and_zoom(-44.39, 171.25, 12)
200
201 def cache_clicked(self, button):
202 bbox = self.osm.get_bbox()
203 self.osm.download_maps(
204 *bbox,
205 zoom_start=self.osm.props.zoom,
206 zoom_end=self.osm.props.max_zoom
207 )
208
209 def map_clicked(self, osm, event):
210 if event.button == 1:
211 self.latlon_entry.set_text(
212 'Map Centre: latitude %s longitude %s' % (
213 self.osm.props.latitude,
214 self.osm.props.longitude
215 )
216 )
217 elif event.button == 2:
218 p = self.osm.get_event_location(event)
219 lat,lon = p.get_degrees()
220 self.osm.gps_add(lat, lon, heading=osmgpsmap.INVALID);
221
222 if __name__ == "__main__":
223 u = UI()
224 u.show_all()
225 if os.name == "nt": gtk.gdk.threads_enter()
226 gtk.main()
227 if os.name == "nt": gtk.gdk.threads_leave()
228
0 <?xml version="1.0"?>
1 <interface>
2 <requires lib="gtk+" version="2.16"/>
3 <!-- interface-naming-policy project-wide -->
4 <object class="GtkWindow" id="window1">
5 <property name="default_width">400</property>
6 <property name="default_height">400</property>
7 <child>
8 <object class="GtkAlignment" id="alignment1">
9 <property name="visible">True</property>
10 <property name="top_padding">4</property>
11 <property name="bottom_padding">4</property>
12 <property name="left_padding">4</property>
13 <property name="right_padding">4</property>
14 <child>
15 <object class="GtkVBox" id="vbox1">
16 <property name="visible">True</property>
17 <property name="spacing">4</property>
18 <child>
19 <object class="GtkHBox" id="map_box">
20 <property name="visible">True</property>
21 <child>
22 <placeholder/>
23 </child>
24 </object>
25 <packing>
26 <property name="position">0</property>
27 </packing>
28 </child>
29 <child>
30 <object class="GtkHBox" id="hbox3">
31 <property name="visible">True</property>
32 <property name="homogeneous">True</property>
33 <child>
34 <object class="GtkButton" id="zoom_in_button">
35 <property name="label">gtk-zoom-in</property>
36 <property name="visible">True</property>
37 <property name="can_focus">True</property>
38 <property name="receives_default">True</property>
39 <property name="use_stock">True</property>
40 </object>
41 <packing>
42 <property name="position">0</property>
43 </packing>
44 </child>
45 <child>
46 <object class="GtkButton" id="zoom_out_button">
47 <property name="label">gtk-zoom-out</property>
48 <property name="visible">True</property>
49 <property name="can_focus">True</property>
50 <property name="receives_default">True</property>
51 <property name="use_stock">True</property>
52 </object>
53 <packing>
54 <property name="position">1</property>
55 </packing>
56 </child>
57 <child>
58 <object class="GtkButton" id="home_button">
59 <property name="label">gtk-home</property>
60 <property name="visible">True</property>
61 <property name="can_focus">True</property>
62 <property name="receives_default">True</property>
63 <property name="use_stock">True</property>
64 </object>
65 <packing>
66 <property name="position">2</property>
67 </packing>
68 </child>
69 <child>
70 <object class="GtkToggleButton" id="cache_button">
71 <property name="label" translatable="yes">Cache</property>
72 <property name="visible">True</property>
73 <property name="can_focus">True</property>
74 <property name="receives_default">True</property>
75 </object>
76 <packing>
77 <property name="position">3</property>
78 </packing>
79 </child>
80 </object>
81 <packing>
82 <property name="expand">False</property>
83 <property name="position">1</property>
84 </packing>
85 </child>
86 <child>
87 <object class="GtkHBox" id="hbox2">
88 <property name="visible">True</property>
89 <property name="spacing">4</property>
90 <child>
91 <object class="GtkEntry" id="text_entry">
92 <property name="visible">True</property>
93 <property name="can_focus">True</property>
94 <property name="invisible_char">&#x2022;</property>
95 </object>
96 <packing>
97 <property name="position">0</property>
98 </packing>
99 </child>
100 <child>
101 <object class="GtkLabel" id="cache_label">
102 <property name="visible">True</property>
103 <property name="xalign">1</property>
104 <property name="label" translatable="yes">0</property>
105 <property name="width_chars">5</property>
106 </object>
107 <packing>
108 <property name="expand">False</property>
109 <property name="position">1</property>
110 </packing>
111 </child>
112 </object>
113 <packing>
114 <property name="expand">False</property>
115 <property name="position">2</property>
116 </packing>
117 </child>
118 <child>
119 <object class="GtkExpander" id="expander1">
120 <property name="visible">True</property>
121 <property name="can_focus">True</property>
122 <child>
123 <object class="GtkAlignment" id="alignment2">
124 <property name="visible">True</property>
125 <property name="left_padding">4</property>
126 <child>
127 <object class="GtkVBox" id="vbox2">
128 <property name="visible">True</property>
129 <child>
130 <object class="GtkHBox" id="hbox1">
131 <property name="visible">True</property>
132 <property name="spacing">4</property>
133 <child>
134 <object class="GtkLabel" id="label2">
135 <property name="visible">True</property>
136 <property name="xalign">0</property>
137 <property name="label" translatable="yes">Color</property>
138 </object>
139 <packing>
140 <property name="expand">False</property>
141 <property name="position">0</property>
142 </packing>
143 </child>
144 <child>
145 <object class="GtkColorButton" id="gps_colorbutton">
146 <property name="visible">True</property>
147 <property name="can_focus">True</property>
148 <property name="receives_default">True</property>
149 <property name="color">#000000000000</property>
150 </object>
151 <packing>
152 <property name="position">1</property>
153 </packing>
154 </child>
155 </object>
156 <packing>
157 <property name="expand">False</property>
158 <property name="position">0</property>
159 </packing>
160 </child>
161 <child>
162 <object class="GtkHBox" id="hbox4">
163 <property name="visible">True</property>
164 <property name="spacing">4</property>
165 <child>
166 <object class="GtkLabel" id="label3">
167 <property name="visible">True</property>
168 <property name="xalign">0</property>
169 <property name="label" translatable="yes">Alpha</property>
170 </object>
171 <packing>
172 <property name="expand">False</property>
173 <property name="position">0</property>
174 </packing>
175 </child>
176 <child>
177 <object class="GtkHScale" id="hscale1">
178 <property name="visible">True</property>
179 <property name="can_focus">True</property>
180 <property name="update_policy">delayed</property>
181 <property name="adjustment">gps_alpha_adjustment</property>
182 <property name="restrict_to_fill_level">False</property>
183 <property name="fill_level">0</property>
184 <property name="draw_value">False</property>
185 </object>
186 <packing>
187 <property name="position">1</property>
188 </packing>
189 </child>
190 </object>
191 <packing>
192 <property name="position">1</property>
193 </packing>
194 </child>
195 <child>
196 <object class="GtkHBox" id="hbox5">
197 <property name="visible">True</property>
198 <property name="spacing">4</property>
199 <child>
200 <object class="GtkLabel" id="label4">
201 <property name="visible">True</property>
202 <property name="xalign">0</property>
203 <property name="label" translatable="yes">Width</property>
204 </object>
205 <packing>
206 <property name="expand">False</property>
207 <property name="position">0</property>
208 </packing>
209 </child>
210 <child>
211 <object class="GtkHScale" id="hscale2">
212 <property name="visible">True</property>
213 <property name="can_focus">True</property>
214 <property name="update_policy">delayed</property>
215 <property name="adjustment">gps_width_adjustment</property>
216 <property name="restrict_to_fill_level">False</property>
217 <property name="fill_level">0</property>
218 <property name="draw_value">False</property>
219 </object>
220 <packing>
221 <property name="position">1</property>
222 </packing>
223 </child>
224 </object>
225 <packing>
226 <property name="expand">False</property>
227 <property name="position">2</property>
228 </packing>
229 </child>
230 </object>
231 </child>
232 </object>
233 </child>
234 <child type="label">
235 <object class="GtkLabel" id="label1">
236 <property name="visible">True</property>
237 <property name="label" translatable="yes">GPS Track Appearance</property>
238 </object>
239 </child>
240 </object>
241 <packing>
242 <property name="expand">False</property>
243 <property name="position">3</property>
244 </packing>
245 </child>
246 <child>
247 <object class="GtkExpander" id="expander2">
248 <property name="visible">True</property>
249 <property name="can_focus">True</property>
250 <child>
251 <object class="GtkAlignment" id="alignment3">
252 <property name="visible">True</property>
253 <property name="left_padding">4</property>
254 <child>
255 <object class="GtkVBox" id="vbox3">
256 <property name="visible">True</property>
257 <child>
258 <object class="GtkHBox" id="hbox6">
259 <property name="visible">True</property>
260 <property name="spacing">4</property>
261 <child>
262 <object class="GtkLabel" id="label6">
263 <property name="visible">True</property>
264 <property name="xalign">0</property>
265 <property name="label" translatable="yes">X Offset</property>
266 </object>
267 <packing>
268 <property name="expand">False</property>
269 <property name="position">0</property>
270 </packing>
271 </child>
272 <child>
273 <object class="GtkHScale" id="hscale3">
274 <property name="visible">True</property>
275 <property name="can_focus">True</property>
276 <property name="update_policy">delayed</property>
277 <property name="adjustment">star_xalign_adjustment</property>
278 <property name="restrict_to_fill_level">False</property>
279 <property name="fill_level">0</property>
280 <property name="draw_value">False</property>
281 </object>
282 <packing>
283 <property name="position">1</property>
284 </packing>
285 </child>
286 </object>
287 <packing>
288 <property name="position">0</property>
289 </packing>
290 </child>
291 <child>
292 <object class="GtkHBox" id="hbox7">
293 <property name="visible">True</property>
294 <property name="spacing">4</property>
295 <child>
296 <object class="GtkLabel" id="label7">
297 <property name="visible">True</property>
298 <property name="xalign">0</property>
299 <property name="label" translatable="yes">Y Offset</property>
300 </object>
301 <packing>
302 <property name="expand">False</property>
303 <property name="position">0</property>
304 </packing>
305 </child>
306 <child>
307 <object class="GtkHScale" id="hscale4">
308 <property name="visible">True</property>
309 <property name="can_focus">True</property>
310 <property name="update_policy">delayed</property>
311 <property name="adjustment">star_yalign_adjustment</property>
312 <property name="restrict_to_fill_level">False</property>
313 <property name="fill_level">0</property>
314 <property name="draw_value">False</property>
315 </object>
316 <packing>
317 <property name="position">1</property>
318 </packing>
319 </child>
320 </object>
321 <packing>
322 <property name="position">1</property>
323 </packing>
324 </child>
325 </object>
326 </child>
327 </object>
328 </child>
329 <child type="label">
330 <object class="GtkLabel" id="label5">
331 <property name="visible">True</property>
332 <property name="label" translatable="yes">Star Image Appearance</property>
333 </object>
334 </child>
335 </object>
336 <packing>
337 <property name="expand">False</property>
338 <property name="position">4</property>
339 </packing>
340 </child>
341 </object>
342 </child>
343 </object>
344 </child>
345 </object>
346 <object class="GtkAdjustment" id="gps_alpha_adjustment">
347 <property name="upper">1</property>
348 <property name="step_increment">0.10000000000000001</property>
349 <property name="page_increment">0.10000000000000001</property>
350 </object>
351 <object class="GtkAdjustment" id="gps_width_adjustment">
352 <property name="upper">10</property>
353 <property name="step_increment">0.5</property>
354 <property name="page_increment">0.5</property>
355 </object>
356 <object class="GtkSizeGroup" id="sizegroup1">
357 <widgets>
358 <widget name="label7"/>
359 <widget name="label6"/>
360 <widget name="label4"/>
361 <widget name="label3"/>
362 <widget name="label2"/>
363 </widgets>
364 </object>
365 <object class="GtkAdjustment" id="star_xalign_adjustment">
366 <property name="value">0.5</property>
367 <property name="upper">1</property>
368 <property name="step_increment">0.10000000000000001</property>
369 <property name="page_increment">0.10000000000000001</property>
370 </object>
371 <object class="GtkAdjustment" id="star_yalign_adjustment">
372 <property name="value">0.5</property>
373 <property name="upper">1</property>
374 <property name="step_increment">0.10000000000000001</property>
375 <property name="page_increment">0.10000000000000001</property>
376 </object>
377 </interface>
Binary diff not shown
0 dnl -*- mode: autoconf -*-
1
2 # serial 1
3
4 dnl Usage:
5 dnl GTK_DOC_CHECK([minimum-gtk-doc-version])
6 AC_DEFUN([GTK_DOC_CHECK],
7 [
8 AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first
9 AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first
10
11 dnl check for tools we added during development
12 AC_PATH_PROG([GTKDOC_CHECK],[gtkdoc-check])
13 AC_PATH_PROGS([GTKDOC_REBASE],[gtkdoc-rebase],[true])
14 AC_PATH_PROG([GTKDOC_MKPDF],[gtkdoc-mkpdf])
15
16 dnl for overriding the documentation installation directory
17 AC_ARG_WITH([html-dir],
18 AS_HELP_STRING([--with-html-dir=PATH], [path to installed docs]),,
19 [with_html_dir='${datadir}/gtk-doc/html'])
20 HTML_DIR="$with_html_dir"
21 AC_SUBST([HTML_DIR])
22
23 dnl enable/disable documentation building
24 AC_ARG_ENABLE([gtk-doc],
25 AS_HELP_STRING([--enable-gtk-doc],
26 [use gtk-doc to build documentation [[default=no]]]),,
27 [enable_gtk_doc=no])
28
29 if test x$enable_gtk_doc = xyes; then
30 ifelse([$1],[],
31 [PKG_CHECK_EXISTS([gtk-doc],,
32 AC_MSG_ERROR([gtk-doc not installed and --enable-gtk-doc requested]))],
33 [PKG_CHECK_EXISTS([gtk-doc >= $1],,
34 AC_MSG_ERROR([You need to have gtk-doc >= $1 installed to build $PACKAGE_NAME]))])
35 fi
36
37 AC_MSG_CHECKING([whether to build gtk-doc documentation])
38 AC_MSG_RESULT($enable_gtk_doc)
39
40 dnl enable/disable output formats
41 AC_ARG_ENABLE([gtk-doc-html],
42 AS_HELP_STRING([--enable-gtk-doc-html],
43 [build documentation in html format [[default=yes]]]),,
44 [enable_gtk_doc_html=yes])
45 AC_ARG_ENABLE([gtk-doc-pdf],
46 AS_HELP_STRING([--enable-gtk-doc-pdf],
47 [build documentation in pdf format [[default=no]]]),,
48 [enable_gtk_doc_pdf=no])
49
50 if test -z "$GTKDOC_MKPDF"; then
51 enable_gtk_doc_pdf=no
52 fi
53
54
55 AM_CONDITIONAL([ENABLE_GTK_DOC], [test x$enable_gtk_doc = xyes])
56 AM_CONDITIONAL([GTK_DOC_BUILD_HTML], [test x$enable_gtk_doc_html = xyes])
57 AM_CONDITIONAL([GTK_DOC_BUILD_PDF], [test x$enable_gtk_doc_pdf = xyes])
58 AM_CONDITIONAL([GTK_DOC_USE_LIBTOOL], [test -n "$LIBTOOL"])
59 AM_CONDITIONAL([GTK_DOC_USE_REBASE], [test -n "$GTKDOC_REBASE"])
60 ])
0 dnl -*- mode: autoconf -*-
1 dnl Copyright 2009 Johan Dahlin
2 dnl
3 dnl This file is free software; the author(s) gives unlimited
4 dnl permission to copy and/or distribute it, with or without
5 dnl modifications, as long as this notice is preserved.
6 dnl
7
8 # serial 1
9
10 m4_define([_GOBJECT_INTROSPECTION_CHECK_INTERNAL],
11 [
12 AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first
13 AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first
14 AC_BEFORE([LT_INIT],[$0])dnl setup libtool first
15
16 dnl enable/disable introspection
17 m4_if([$2], [require],
18 [dnl
19 enable_introspection=yes
20 ],[dnl
21 AC_ARG_ENABLE(introspection,
22 AS_HELP_STRING([--enable-introspection[=@<:@no/auto/yes@:>@]],
23 [Enable introspection for this build]),,
24 [enable_introspection=auto])
25 ])dnl
26
27 AC_MSG_CHECKING([for gobject-introspection])
28
29 dnl presence/version checking
30 AS_CASE([$enable_introspection],
31 [no], [dnl
32 found_introspection="no (disabled, use --enable-introspection to enable)"
33 ],dnl
34 [yes],[dnl
35 PKG_CHECK_EXISTS([gobject-introspection-1.0],,
36 AC_MSG_ERROR([gobject-introspection-1.0 is not installed]))
37 PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1],
38 found_introspection=yes,
39 AC_MSG_ERROR([You need to have gobject-introspection >= $1 installed to build AC_PACKAGE_NAME]))
40 ],dnl
41 [auto],[dnl
42 PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], found_introspection=yes, found_introspection=no)
43 ],dnl
44 [dnl
45 AC_MSG_ERROR([invalid argument passed to --enable-introspection, should be one of @<:@no/auto/yes@:>@])
46 ])dnl
47
48 AC_MSG_RESULT([$found_introspection])
49
50 INTROSPECTION_SCANNER=
51 INTROSPECTION_COMPILER=
52 INTROSPECTION_GENERATE=
53 INTROSPECTION_GIRDIR=
54 INTROSPECTION_TYPELIBDIR=
55 if test "x$found_introspection" = "xyes"; then
56 INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0`
57 INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0`
58 INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0`
59 INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0`
60 INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)"
61 INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0`
62 INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0`
63 INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection
64 fi
65 AC_SUBST(INTROSPECTION_SCANNER)
66 AC_SUBST(INTROSPECTION_COMPILER)
67 AC_SUBST(INTROSPECTION_GENERATE)
68 AC_SUBST(INTROSPECTION_GIRDIR)
69 AC_SUBST(INTROSPECTION_TYPELIBDIR)
70 AC_SUBST(INTROSPECTION_CFLAGS)
71 AC_SUBST(INTROSPECTION_LIBS)
72 AC_SUBST(INTROSPECTION_MAKEFILE)
73
74 AM_CONDITIONAL(HAVE_INTROSPECTION, test "x$found_introspection" = "xyes")
75 ])
76
77
78 dnl Usage:
79 dnl GOBJECT_INTROSPECTION_CHECK([minimum-g-i-version])
80
81 AC_DEFUN([GOBJECT_INTROSPECTION_CHECK],
82 [
83 _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1])
84 ])
85
86 dnl Usage:
87 dnl GOBJECT_INTROSPECTION_REQUIRE([minimum-g-i-version])
88
89
90 AC_DEFUN([GOBJECT_INTROSPECTION_REQUIRE],
91 [
92 _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1], [require])
93 ])
0 aclocal.m4
1 osmgpsmap-new.defs
0 /usr/share/automake-1.11/COPYING
0 ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
1
02 defsdir = $(datadir)/pygtk/2.0/defs
1 defs_DATA = osmgpsmap.defs
3 defs_DATA = osmgpsmap.defs osmgpsmap-compat.defs
24
35 INCLUDES = \
46 $(OSMGPSMAP_CFLAGS) \
7 $(SOUP24_CFLAGS) \
58 $(GTK_CFLAGS) \
69 $(PYGTK_CFLAGS) \
710 $(PYTHON_INCLUDES)
1114
1215 pkgpyexec_LTLIBRARIES = osmgpsmap.la
1316 osmgpsmap_la_LDFLAGS = -module -avoid-version -export-symbols-regex initosmgpsmap
14 osmgpsmap_la_LIBADD = $(OSMGPSMAP_LIBS) $(GTK_LIBS) $(PYGTK_LIBS)
17 osmgpsmap_la_LIBADD = $(OSMGPSMAP_LIBS) $(SOUP24_LIBS) $(GTK_LIBS) $(PYGTK_LIBS)
1518 osmgpsmap_la_SOURCES = osmgpsmapmodule.c osmgpsmap.c
1619 #nodist_osmgpsmap_la_SOURCES = osmgpsmap.c
1720
1821 CLEANFILES = osmgpsmap.c
19 EXTRA_DIST = \
20 setup.py \
21 mapviewer.py \
22 osmgpsmap.override \
22 EXTRA_DIST = \
23 setup.py \
24 osmgpsmap.override \
2325 $(defs_DATA)
2426
2527 osmgpsmap.c: osmgpsmap.defs osmgpsmap.override
2628 .defs.c:
2729 (cd $(srcdir)\
28 && pygtk-codegen-2.0 \
30 && $(PYTHON) $(CODEGENDIR)/codegen.py \
2931 --register $(PYGTK_DEFSDIR)/gtk-types.defs \
30 --register $(PYGTK_DEFSDIR)/gdk-base-types.defs \
32 --register $(PYGTK_DEFSDIR)/gdk-types.defs \
3133 --override $*.override \
3234 --prefix py$* $*.defs) > gen-$*.c \
3335 && cp gen-$*.c $*.c \
3436 && rm -f gen-$*.c
3537
3638 update-defs:
37 $(PYGTK_H2DEF) ../src/osm-gps-map.h ../src/osm-gps-map-osd.h ../src/osm-gps-map-layer.h > osmgpsmap-new.defs
39 $(PYTHON) $(CODEGENDIR)/h2def.py ../src/osm-gps-map-{widget,osd,image,layer,track,point,source}.h > osmgpsmap-new.defs
3840
3941 release: dist
4042 scp @PACKAGE@-@VERSION@.tar.gz root@greenbirdsystems.com:/var/www/johnstowers.co.nz/files/osm-gps-map/
+0
-66
python/acinclude.m4 less more
0 ## this one is commonly used with AM_PATH_PYTHONDIR ...
1 dnl AM_CHECK_PYMOD(MODNAME [,SYMBOL [,ACTION-IF-FOUND [,ACTION-IF-NOT-FOUND]]])
2 dnl Check if a module containing a given symbol is visible to python.
3 AC_DEFUN([AM_CHECK_PYMOD],
4 [AC_REQUIRE([AM_PATH_PYTHON])
5 py_mod_var=`echo $1['_']$2 | sed 'y%./+-%__p_%'`
6 AC_MSG_CHECKING(for ifelse([$2],[],,[$2 in ])python module $1)
7 AC_CACHE_VAL(py_cv_mod_$py_mod_var, [
8 ifelse([$2],[], [prog="
9 import sys
10 try:
11 import $1
12 except ImportError:
13 sys.exit(1)
14 except:
15 sys.exit(0)
16 sys.exit(0)"], [prog="
17 import $1
18 $1.$2"])
19 if $PYTHON -c "$prog" 1>&AC_FD_CC 2>&AC_FD_CC
20 then
21 eval "py_cv_mod_$py_mod_var=yes"
22 else
23 eval "py_cv_mod_$py_mod_var=no"
24 fi
25 ])
26 py_val=`eval "echo \`echo '$py_cv_mod_'$py_mod_var\`"`
27 if test "x$py_val" != xno; then
28 AC_MSG_RESULT(yes)
29 ifelse([$3], [],, [$3
30 ])dnl
31 else
32 AC_MSG_RESULT(no)
33 ifelse([$4], [],, [$4
34 ])dnl
35 fi
36 ])
37
38 dnl a macro to check for ability to create python extensions
39 dnl AM_CHECK_PYTHON_HEADERS([ACTION-IF-POSSIBLE], [ACTION-IF-NOT-POSSIBLE])
40 dnl function also defines PYTHON_INCLUDES
41 AC_DEFUN([AM_CHECK_PYTHON_HEADERS],
42 [AC_REQUIRE([AM_PATH_PYTHON])
43 AC_MSG_CHECKING(for headers required to compile python extensions)
44 dnl deduce PYTHON_INCLUDES
45 py_prefix=`$PYTHON -c "import sys; print sys.prefix"`
46 py_exec_prefix=`$PYTHON -c "import sys; print sys.exec_prefix"`
47 if test -x "$PYTHON-config"; then
48 PYTHON_INCLUDES=`$PYTHON-config --includes 2>/dev/null`
49 else
50 PYTHON_INCLUDES="-I${py_prefix}/include/python${PYTHON_VERSION}"
51 if test "$py_prefix" != "$py_exec_prefix"; then
52 PYTHON_INCLUDES="$PYTHON_INCLUDES -I${py_exec_prefix}/include/python${PYTHON_VERSION}"
53 fi
54 fi
55 AC_SUBST(PYTHON_INCLUDES)
56 dnl check if the headers exist:
57 save_CPPFLAGS="$CPPFLAGS"
58 CPPFLAGS="$CPPFLAGS $PYTHON_INCLUDES"
59 AC_TRY_CPP([#include <Python.h>],dnl
60 [AC_MSG_RESULT(found)
61 $1],dnl
62 [AC_MSG_RESULT(not found)
63 $2])
64 CPPFLAGS="$save_CPPFLAGS"
65 ])
0 AC_PREREQ(2.53)
1 AC_INIT(python-osmgpsmap, 0.6.0)
2 AC_CONFIG_SRCDIR(osmgpsmap.defs)
3 AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
0 AC_PREREQ([2.62])
1 AC_INIT([python-osmgpsmap],
2 [0.7.0],
3 [http://github.com/nzjrs/osm-gps-map/issues],
4 [python-osmgpsmap])
5 AM_INIT_AUTOMAKE([1.10])
6
7 AC_CONFIG_SRCDIR([osmgpsmap.defs])
8 AC_CONFIG_MACRO_DIR([m4])
49
510 AM_MAINTAINER_MODE
611 AC_PROG_MAKE_SET
712
813 AC_PROG_CC
9 AM_PROG_CC_STDC
10 AC_HEADER_STDC
14 AM_PROG_CC_C_O
1115
1216 AM_PROG_LIBTOOL
1317
2731 AM_PATH_PYTHON()
2832 AM_CHECK_PYTHON_HEADERS(,AC_MSG_ERROR([install python-devel]))
2933
30 PKG_CHECK_MODULES(PYGTK, [pygtk-2.0 >= 2.10.0])
34 PKG_CHECK_MODULES(PYGTK, [pygtk-2.0 >= 2.10.0 pygobject-2.0 >= 2.16.0])
3135
32 AC_MSG_CHECKING(for pygtk defs)
36 AC_MSG_CHECKING([for pygtk defs])
3337 PYGTK_DEFSDIR=`$PKG_CONFIG --variable=defsdir pygtk-2.0`
3438 AC_SUBST(PYGTK_DEFSDIR)
3539 AC_MSG_RESULT($PYGTK_DEFSDIR)
3640
37 AC_MSG_CHECKING(for pygtk codegen)
38 PYGTK_CODEGEN="$PYTHON `$PKG_CONFIG --variable=codegendir pygtk-2.0`/codegen.py"
39 AC_SUBST(PYGTK_CODEGEN)
40 AC_MSG_RESULT($PYGTK_CODEGEN)
41
42 AC_MSG_CHECKING(for pygtk h2def)
43 PYGTK_H2DEF="$PYTHON `$PKG_CONFIG --variable=codegendir pygtk-2.0`/h2def.py"
44 AC_SUBST(PYGTK_H2DEF)
45 AC_MSG_RESULT($PYGTK_H2DEF)
41 AC_MSG_CHECKING([for codegen])
42 CODEGENDIR=`$PKG_CONFIG --variable codegendir pygobject-2.0`
43 AC_SUBST([CODEGENDIR])
44 AC_MSG_RESULT($CODEGENDIR)
4645
4746 if test -f ../src/libosmgpsmap.la; then
4847 #Because we are building against a non installed lib, the pkgconfig
4948 #file cannot tell us to also include/link gtk/soup, so we must manually do it
50 PKG_CHECK_MODULES(OSMGPSMAP, [gtk+-2.0 libsoup-2.4])
49 PKG_CHECK_MODULES(GTK, [gtk+-2.0])
50 PKG_CHECK_MODULES(SOUP24, [libsoup-2.4])
5151
5252 #and we must link to the local lib
53 OSMGPSMAP_CFLAGS="$OSMGPSMAP_CFLAGS -I../src/"
54 OSMGPSMAP_LIBS="$OSMGPSMAP_LIBS -L../src/.libs/ -losmgpsmap"
53 OSMGPSMAP_CFLAGS="-I\$(top_srcdir)/../src/"
54 OSMGPSMAP_LIBS="\$(top_builddir)/../src/libosmgpsmap.la"
5555 else
56 PKG_CHECK_MODULES(OSMGPSMAP, osmgpsmap)
56 PKG_CHECK_MODULES(OSMGPSMAP, osmgpsmap = 0.7.0)
5757 fi
5858
5959 AC_OUTPUT([Makefile])
0 dnl a macro to check for ability to create python extensions
1 dnl AM_CHECK_PYTHON_HEADERS([ACTION-IF-POSSIBLE], [ACTION-IF-NOT-POSSIBLE])
2 dnl function also defines PYTHON_INCLUDES
3 AC_DEFUN([AM_CHECK_PYTHON_HEADERS],
4 [AC_REQUIRE([AM_PATH_PYTHON])
5 AC_MSG_CHECKING(for headers required to compile python extensions)
6 dnl deduce PYTHON_INCLUDES
7 py_prefix=`$PYTHON -c "import sys; print sys.prefix"`
8 py_exec_prefix=`$PYTHON -c "import sys; print sys.exec_prefix"`
9 if test -x "$PYTHON-config"; then
10 PYTHON_INCLUDES=`$PYTHON-config --includes 2>/dev/null`
11 else
12 PYTHON_INCLUDES="-I${py_prefix}/include/python${PYTHON_VERSION}"
13 if test "$py_prefix" != "$py_exec_prefix"; then
14 PYTHON_INCLUDES="$PYTHON_INCLUDES -I${py_exec_prefix}/include/python${PYTHON_VERSION}"
15 fi
16 fi
17 AC_SUBST(PYTHON_INCLUDES)
18 dnl check if the headers exist:
19 save_CPPFLAGS="$CPPFLAGS"
20 CPPFLAGS="$CPPFLAGS $PYTHON_INCLUDES"
21 AC_TRY_CPP([#include <Python.h>],dnl
22 [AC_MSG_RESULT(found)
23 $1],dnl
24 [AC_MSG_RESULT(not found)
25 $2])
26 CPPFLAGS="$save_CPPFLAGS"
27 ])
+0
-213
python/mapviewer.py less more
0 #!/usr/bin/python
1
2 """
3 Copyright (C) Hadley Rich 2008 <hads@nice.net.nz>
4 based on main.c - with thanks to John Stowers
5
6 This is free software: you can redistribute it and/or modify it
7 under the terms of the GNU General Public License
8 as published by the Free Software Foundation; version 2.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, see <http://www.gnu.org/licenses/>.
17 """
18
19 import math
20 import sys
21 import os.path
22 import gtk.gdk
23 import gobject
24
25 gobject.threads_init()
26 gtk.gdk.threads_init()
27
28 #Try static lib first
29 mydir = os.path.dirname(os.path.abspath(__file__))
30 libdir = os.path.join(mydir, ".libs")
31 sys.path.insert(0, libdir)
32
33 import osmgpsmap
34 print "using library: %s" % osmgpsmap.__file__
35
36 class DummyLayer(gobject.GObject, osmgpsmap.GpsMapLayer):
37 def __init__(self):
38 gobject.GObject.__init__(self)
39
40 def do_draw(self, gpsmap, gdkdrawable):
41 pass
42
43 def do_render(self, gpsmap):
44 pass
45
46 def do_busy(self):
47 return False
48
49 def do_button_press(self, gpsmap, gdkeventbutton):
50 return False
51 gobject.type_register(DummyLayer)
52
53 class UI(gtk.Window):
54 def __init__(self):
55 gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
56
57 self.set_default_size(500, 500)
58 self.connect('destroy', lambda x: gtk.main_quit())
59 self.set_title('OpenStreetMap GPS Mapper')
60
61 self.vbox = gtk.VBox(False, 0)
62 self.add(self.vbox)
63
64 self.osm = osmgpsmap.GpsMap()
65 self.osm.add_layer(
66 osmgpsmap.GpsMapOsd(
67 show_dpad=True,
68 show_zoom=True))
69 self.osm.add_layer(
70 DummyLayer())
71
72 self.osm.connect('button_release_event', self.map_clicked)
73
74 #connect keyboard shortcuts
75 self.osm.set_keyboard_shortcut(osmgpsmap.KEY_FULLSCREEN, gtk.gdk.keyval_from_name("F11"))
76 self.osm.set_keyboard_shortcut(osmgpsmap.KEY_UP, gtk.gdk.keyval_from_name("Up"))
77 self.osm.set_keyboard_shortcut(osmgpsmap.KEY_DOWN, gtk.gdk.keyval_from_name("Down"))
78 self.osm.set_keyboard_shortcut(osmgpsmap.KEY_LEFT, gtk.gdk.keyval_from_name("Left"))
79 self.osm.set_keyboard_shortcut(osmgpsmap.KEY_RIGHT, gtk.gdk.keyval_from_name("Right"))
80
81 self.latlon_entry = gtk.Entry()
82
83 zoom_in_button = gtk.Button(stock=gtk.STOCK_ZOOM_IN)
84 zoom_in_button.connect('clicked', self.zoom_in_clicked)
85 zoom_out_button = gtk.Button(stock=gtk.STOCK_ZOOM_OUT)
86 zoom_out_button.connect('clicked', self.zoom_out_clicked)
87 home_button = gtk.Button(stock=gtk.STOCK_HOME)
88 home_button.connect('clicked', self.home_clicked)
89 cache_button = gtk.Button('Cache')
90 cache_button.connect('clicked', self.cache_clicked)
91
92 self.vbox.pack_start(self.osm)
93 hbox = gtk.HBox(False, 0)
94 hbox.pack_start(zoom_in_button)
95 hbox.pack_start(zoom_out_button)
96 hbox.pack_start(home_button)
97 hbox.pack_start(cache_button)
98
99 #add ability to test custom map URIs
100 ex = gtk.Expander("<b>Map Repository URI</b>")
101 ex.props.use_markup = True
102 vb = gtk.VBox()
103 self.repouri_entry = gtk.Entry()
104 self.repouri_entry.set_text(self.osm.props.repo_uri)
105 self.image_format_entry = gtk.Entry()
106 self.image_format_entry.set_text(self.osm.props.image_format)
107 gobtn = gtk.Button("Load Map URI")
108 gobtn.connect("clicked", self.load_map_clicked)
109 exp = gtk.Label(
110 """
111 Enter an repository URL to fetch map tiles from in the box below. Special metacharacters may be included in this url
112
113 <i>Metacharacters:</i>
114 \t#X\tMax X location
115 \t#Y\tMax Y location
116 \t#Z\tMap zoom (0 = min zoom, fully zoomed out)
117 \t#S\tInverse zoom (max-zoom - #Z)
118 \t#Q\tQuadtree encoded tile (qrts)
119 \t#W\tQuadtree encoded tile (1234)
120 \t#U\tEncoding not implemeted
121 \t#R\tRandom integer, 0-4""")
122 exp.props.xalign = 0
123 exp.props.use_markup = True
124 exp.props.wrap = True
125
126 ex.add(vb)
127 vb.pack_start(exp, False)
128
129 hb = gtk.HBox()
130 hb.pack_start(gtk.Label("URI: "), False)
131 hb.pack_start(self.repouri_entry, True)
132 vb.pack_start(hb, False)
133
134 hb = gtk.HBox()
135 hb.pack_start(gtk.Label("Image Format: "), False)
136 hb.pack_start(self.image_format_entry, True)
137 vb.pack_start(hb, False)
138
139 vb.pack_start(gobtn, False)
140
141 self.vbox.pack_end(ex, False)
142 self.vbox.pack_end(self.latlon_entry, False)
143 self.vbox.pack_end(hbox, False)
144
145 gobject.timeout_add(500, self.print_tiles)
146
147 def load_map_clicked(self, button):
148 uri = self.repouri_entry.get_text()
149 format = self.image_format_entry.get_text()
150 if uri and format:
151 if self.osm:
152 #remove old map
153 self.vbox.remove(self.osm)
154 try:
155 self.osm = osmgpsmap.GpsMap(
156 repo_uri=uri,
157 image_format=format
158 )
159 self.osm.connect('button_release_event', self.map_clicked)
160 except Exception, e:
161 print "ERROR:", e
162 self.osm = osm.GpsMap()
163
164 self.vbox.pack_start(self.osm, True)
165 self.osm.connect('button_release_event', self.map_clicked)
166 self.osm.show()
167
168 def print_tiles(self):
169 if self.osm.props.tiles_queued != 0:
170 print self.osm.props.tiles_queued, 'tiles queued'
171 return True
172
173 def zoom_in_clicked(self, button):
174 self.osm.set_zoom(self.osm.props.zoom + 1)
175
176 def zoom_out_clicked(self, button):
177 self.osm.set_zoom(self.osm.props.zoom - 1)
178
179 def home_clicked(self, button):
180 self.osm.set_mapcenter(-44.39, 171.25, 12)
181
182 def cache_clicked(self, button):
183 bbox = self.osm.get_bbox()
184 self.osm.download_maps(
185 *bbox,
186 zoom_start=self.osm.props.zoom,
187 zoom_end=self.osm.props.max_zoom
188 )
189
190 def map_clicked(self, osm, event):
191 if event.button == 1:
192 self.latlon_entry.set_text(
193 'Map Centre: latitude %s longitude %s' % (
194 self.osm.props.latitude,
195 self.osm.props.longitude
196 )
197 )
198 elif event.button == 2:
199 rlat, rlon = self.osm.get_co_ordinates(event.x, event.y)
200 self.osm.draw_gps(
201 math.degrees(rlat),
202 math.degrees(rlon),
203 osmgpsmap.INVALID);
204
205
206 if __name__ == "__main__":
207 u = UI()
208 u.show_all()
209 if os.name == "nt": gtk.gdk.threads_enter()
210 gtk.main()
211 if os.name == "nt": gtk.gdk.threads_leave()
212
0 ;; -*- scheme -*-
1 (define-method add_track
2 (of-object "OsmGpsMap")
3 (c-name "osm_gps_map_add_track")
4 (return-type "none")
5 (parameters
6 '("GSList*" "track")
7 )
8 )
9
10 (define-method clear_tracks
11 (of-object "OsmGpsMap")
12 (c-name "osm_gps_map_clear_tracks")
13 (return-type "none")
14 )
15
16 (define-method add_image
17 (of-object "OsmGpsMap")
18 (c-name "osm_gps_map_add_image")
19 (return-type "none")
20 (parameters
21 '("float" "latitude")
22 '("float" "longitude")
23 '("GdkPixbuf*" "image")
24 )
25 )
26
27 (define-method remove_image
28 (of-object "OsmGpsMap")
29 (c-name "osm_gps_map_remove_image")
30 (return-type "gboolean")
31 (parameters
32 '("GdkPixbuf*" "image")
33 )
34 )
35
36 (define-method clear_images
37 (of-object "OsmGpsMap")
38 (c-name "osm_gps_map_clear_images")
39 (return-type "none")
40 )
41
42 (define-method draw_gps
43 (of-object "OsmGpsMap")
44 (c-name "osm_gps_map_draw_gps")
45 (return-type "none")
46 (parameters
47 '("float" "latitude")
48 '("float" "longitude")
49 '("float" "heading")
50 )
51 )
52
53 (define-method clear_gps
54 (of-object "OsmGpsMap")
55 (c-name "osm_gps_map_clear_gps")
56 (return-type "none")
57 )
58
59 (define-method add_layer
60 (of-object "OsmGpsMap")
61 (c-name "osm_gps_map_add_layer")
62 (return-type "none")
63 (parameters
64 '("OsmGpsMapLayer*" "layer")
65 )
66 )
67
68 (define-method get_co_ordinates
69 (of-object "OsmGpsMap")
70 (c-name "osm_gps_map_get_co_ordinates")
71 (return-type "coord_t")
72 (parameters
73 '("int" "pixel_x")
74 '("int" "pixel_y")
75 )
76 )
77
78 (define-method screen_to_geographic
79 (of-object "OsmGpsMap")
80 (c-name "osm_gps_map_screen_to_geographic")
81 (return-type "none")
82 (parameters
83 '("int" "pixel_x")
84 '("int" "pixel_y")
85 '("float*" "latitude")
86 '("float*" "longitude")
87 )
88 )
89
90 (define-method geographic_to_screen
91 (of-object "OsmGpsMap")
92 (c-name "osm_gps_map_geographic_to_screen")
93 (return-type "none")
94 (parameters
95 '("float" "latitude")
96 '("float" "longitude")
97 '("int*" "pixel_x")
98 '("int*" "pixel_y")
99 )
100 )
101
102 (define-method set_mapcenter
103 (of-object "OsmGpsMap")
104 (c-name "osm_gps_map_set_mapcenter")
105 (return-type "none")
106 (parameters
107 '("float" "latitude")
108 '("float" "longitude")
109 '("int" "zoom")
110 )
111 )
112
00 ;; -*- scheme -*-
1
2 (include "osmgpsmap-compat.defs")
3
14 ; object definitions ...
25 (define-object GpsMap
36 (in-module "Osm")
69 (gtype-id "OSM_TYPE_GPS_MAP")
710 )
811
12 (define-object GpsMapImage
13 (in-module "Osm")
14 (parent "GObject")
15 (c-name "OsmGpsMapImage")
16 (gtype-id "OSM_TYPE_GPS_MAP_IMAGE")
17 )
18
19 (define-interface GpsMapLayer
20 (in-module "Osm")
21 (c-name "OsmGpsMapLayer")
22 (gtype-id "OSM_TYPE_GPS_MAP_LAYER")
23 (prerequisite "GObject")
24 )
25
926 (define-object GpsMapOsd
1027 (in-module "Osm")
1128 (parent "GObject")
1229 (c-name "OsmGpsMapOsd")
1330 (gtype-id "OSM_TYPE_GPS_MAP_OSD")
1431 )
32
33 (define-object GpsMapTrack
34 (in-module "Osm")
35 (parent "GObject")
36 (c-name "OsmGpsMapTrack")
37 (gtype-id "OSM_TYPE_GPS_MAP_TRACK")
38 )
39
40 (define-boxed Point
41 (in-module "Osm")
42 (c-name "OsmGpsMapPoint")
43 (gtype-id "OSM_TYPE_GPS_MAP_POINT")
44 (copy-func "osm_gps_map_point_copy")
45 (release-func "g_free")
46 (fields
47 '("gfloat" "rlat")
48 '("gfloat" "rlon")
49 )
50 )
51
1552
1653 ;; Enumerations and flags ...
1754 (define-enum MapSource
4986 )
5087 )
5188
52 ;; From osm-gps-map.h
89 ;; From osm-gps-map-widget.h
5390
5491 (define-function osm_gps_map_get_type
5592 (c-name "osm_gps_map_get_type")
5693 (return-type "GType")
57 )
58
59 (define-function get_default_cache_directory
60 (c-name "osm_gps_map_get_default_cache_directory")
61 (return-type "char*")
62 )
63
64 (define-function source_get_friendly_name
65 (c-name "osm_gps_map_source_get_friendly_name")
66 (return-type "const-char*")
67 (parameters
68 '("OsmGpsMapSource_t" "source")
69 )
70 )
71
72 (define-function source_get_repo_uri
73 (c-name "osm_gps_map_source_get_repo_uri")
74 (return-type "const-char*")
75 (parameters
76 '("OsmGpsMapSource_t" "source")
77 )
78 )
79
80 (define-function source_get_image_format
81 (c-name "osm_gps_map_source_get_image_format")
82 (return-type "const-char*")
83 (parameters
84 '("OsmGpsMapSource_t" "source")
85 )
86 )
87
88 (define-function source_get_min_zoom
89 (c-name "osm_gps_map_source_get_min_zoom")
90 (return-type "int")
91 (parameters
92 '("OsmGpsMapSource_t" "source")
93 )
94 )
95
96 (define-function source_get_max_zoom
97 (c-name "osm_gps_map_source_get_max_zoom")
98 (return-type "int")
99 (parameters
100 '("OsmGpsMapSource_t" "source")
101 )
102 )
103
104 (define-function osm_gps_map_source_is_valid
105 (c-name "osm_gps_map_source_is_valid")
106 (return-type "gboolean")
107 (parameters
108 '("OsmGpsMapSource_t" "source")
109 )
110 )
111
112 (define-method download_maps
113 (of-object "OsmGpsMap")
114 (c-name "osm_gps_map_download_maps")
115 (return-type "none")
116 (parameters
117 '("coord_t*" "pt1")
118 '("coord_t*" "pt2")
119 '("int" "zoom_start")
120 '("int" "zoom_end")
121 )
122 )
123
124 (define-method get_bbox
125 (of-object "OsmGpsMap")
126 (c-name "osm_gps_map_get_bbox")
127 (return-type "none")
128 (parameters
129 '("coord_t*" "pt1")
130 '("coord_t*" "pt2")
131 )
132 )
133
134 (define-method set_mapcenter
135 (of-object "OsmGpsMap")
136 (c-name "osm_gps_map_set_mapcenter")
137 (return-type "none")
138 (parameters
139 '("float" "latitude")
140 '("float" "longitude")
141 '("int" "zoom")
142 )
143 )
144
145 (define-method set_center
146 (of-object "OsmGpsMap")
147 (c-name "osm_gps_map_set_center")
148 (return-type "none")
149 (parameters
150 '("float" "latitude")
151 '("float" "longitude")
152 )
153 )
154
155 (define-method set_zoom
156 (of-object "OsmGpsMap")
157 (c-name "osm_gps_map_set_zoom")
158 (return-type "int")
159 (parameters
160 '("int" "zoom")
161 )
162 )
163
164 (define-method zoom_in
165 (of-object "OsmGpsMap")
166 (c-name "osm_gps_map_zoom_in")
167 (return-type "int")
168 )
169
170 (define-method zoom_out
171 (of-object "OsmGpsMap")
172 (c-name "osm_gps_map_zoom_out")
173 (return-type "int")
174 )
175
176 (define-method add_track
177 (of-object "OsmGpsMap")
178 (c-name "osm_gps_map_add_track")
179 (return-type "none")
180 (parameters
181 '("GSList*" "track")
182 )
183 )
184
185 (define-method clear_tracks
186 (of-object "OsmGpsMap")
187 (c-name "osm_gps_map_clear_tracks")
188 (return-type "none")
189 )
190
191 (define-method add_image
192 (of-object "OsmGpsMap")
193 (c-name "osm_gps_map_add_image")
194 (return-type "none")
195 (parameters
196 '("float" "latitude")
197 '("float" "longitude")
198 '("GdkPixbuf*" "image")
199 )
200 )
201
202 (define-method remove_image
203 (of-object "OsmGpsMap")
204 (c-name "osm_gps_map_remove_image")
205 (return-type "gboolean")
206 (parameters
207 '("GdkPixbuf*" "image")
208 )
209 )
210
211 (define-method clear_images
212 (of-object "OsmGpsMap")
213 (c-name "osm_gps_map_clear_images")
214 (return-type "none")
215 )
216
217 (define-method draw_gps
218 (of-object "OsmGpsMap")
219 (c-name "osm_gps_map_draw_gps")
220 (return-type "none")
221 (parameters
222 '("float" "latitude")
223 '("float" "longitude")
224 '("float" "heading")
225 )
226 )
227
228 (define-method clear_gps
229 (of-object "OsmGpsMap")
230 (c-name "osm_gps_map_clear_gps")
231 (return-type "none")
232 )
233
234 (define-method get_co_ordinates
235 (of-object "OsmGpsMap")
236 (c-name "osm_gps_map_get_co_ordinates")
237 (return-type "coord_t")
238 (parameters
239 '("int" "pixel_x")
240 '("int" "pixel_y")
241 )
24294 )
24395
24496 (define-function osm_gps_map_new
24799 (return-type "GtkWidget*")
248100 (properties
249101 '("auto_center" (optional))
102 '("auto_center_threshold" (optional))
250103 '("record_trip_history" (optional))
251 '("show_trip-history" (optional))
104 '("show_trip_history" (optional))
105 '("show_gps_point" (optional))
252106 '("auto_download" (optional))
253107 '("repo_uri" (optional))
254108 '("proxy_uri" (optional))
269123 )
270124 )
271125
272 (define-method screen_to_geographic
273 (of-object "OsmGpsMap")
274 (c-name "osm_gps_map_screen_to_geographic")
275 (return-type "none")
276 (parameters
277 '("int" "pixel_x")
278 '("int" "pixel_y")
279 '("float*" "latitude")
280 '("float*" "longitude")
281 )
282 )
283
284 (define-method geographic_to_screen
285 (of-object "OsmGpsMap")
286 (c-name "osm_gps_map_geographic_to_screen")
126 (define-function get_default_cache_directory
127 (c-name "osm_gps_map_get_default_cache_directory")
128 (return-type "gchar*")
129 )
130
131 (define-virtual draw_gps_point
132 (of-object "OsmGpsMap")
133 (return-type "none")
134 (parameters
135 '("GdkDrawable*" "drawable")
136 )
137 )
138
139 (define-method download_maps
140 (of-object "OsmGpsMap")
141 (c-name "osm_gps_map_download_maps")
142 (return-type "none")
143 (parameters
144 '("OsmGpsMapPoint*" "pt1")
145 '("OsmGpsMapPoint*" "pt2")
146 '("int" "zoom_start")
147 '("int" "zoom_end")
148 )
149 )
150
151 (define-method download_cancel_all
152 (of-object "OsmGpsMap")
153 (c-name "osm_gps_map_download_cancel_all")
154 (return-type "none")
155 )
156
157 (define-method get_bbox
158 (of-object "OsmGpsMap")
159 (c-name "osm_gps_map_get_bbox")
160 (return-type "none")
161 (parameters
162 '("OsmGpsMapPoint*" "pt1")
163 '("OsmGpsMapPoint*" "pt2")
164 )
165 )
166
167 (define-method set_center_and_zoom
168 (of-object "OsmGpsMap")
169 (c-name "osm_gps_map_set_center_and_zoom")
287170 (return-type "none")
288171 (parameters
289172 '("float" "latitude")
290173 '("float" "longitude")
291 '("int*" "pixel_x")
292 '("int*" "pixel_y")
293 )
174 '("int" "zoom")
175 )
176 )
177
178 (define-method set_center
179 (of-object "OsmGpsMap")
180 (c-name "osm_gps_map_set_center")
181 (return-type "none")
182 (parameters
183 '("float" "latitude")
184 '("float" "longitude")
185 )
186 )
187
188 (define-method set_zoom
189 (of-object "OsmGpsMap")
190 (c-name "osm_gps_map_set_zoom")
191 (return-type "int")
192 (parameters
193 '("int" "zoom")
194 )
195 )
196
197 (define-method zoom_in
198 (of-object "OsmGpsMap")
199 (c-name "osm_gps_map_zoom_in")
200 (return-type "int")
201 )
202
203 (define-method zoom_out
204 (of-object "OsmGpsMap")
205 (c-name "osm_gps_map_zoom_out")
206 (return-type "int")
294207 )
295208
296209 (define-method scroll
319232 )
320233 )
321234
322 (define-method add_layer
323 (of-object "OsmGpsMap")
324 (c-name "osm_gps_map_add_layer")
235 (define-method track_add
236 (of-object "OsmGpsMap")
237 (c-name "osm_gps_map_track_add")
238 (return-type "none")
239 (parameters
240 '("OsmGpsMapTrack*" "track")
241 )
242 )
243
244 (define-method track_remove_all
245 (of-object "OsmGpsMap")
246 (c-name "osm_gps_map_track_remove_all")
247 (return-type "none")
248 )
249
250 (define-method track_remove
251 (of-object "OsmGpsMap")
252 (c-name "osm_gps_map_track_remove")
253 (return-type "gboolean")
254 (parameters
255 '("OsmGpsMapTrack*" "track")
256 )
257 )
258
259 (define-method gps_add
260 (of-object "OsmGpsMap")
261 (c-name "osm_gps_map_gps_add")
262 (return-type "none")
263 (parameters
264 '("float" "latitude")
265 '("float" "longitude")
266 '("float" "heading" (default "OSM_GPS_MAP_INVALID"))
267 )
268 )
269
270 (define-method gps_clear
271 (of-object "OsmGpsMap")
272 (c-name "osm_gps_map_gps_clear")
273 (return-type "none")
274 )
275
276 (define-method gps_get_track
277 (of-object "OsmGpsMap")
278 (c-name "osm_gps_map_gps_get_track")
279 (return-type "OsmGpsMapTrack*")
280 (caller-owns-return #f)
281 )
282
283 (define-method image_add
284 (of-object "OsmGpsMap")
285 (c-name "osm_gps_map_image_add")
286 (return-type "OsmGpsMapImage*")
287 (caller-owns-return #t)
288 (parameters
289 '("float" "latitude")
290 '("float" "longitude")
291 '("GdkPixbuf*" "image")
292 )
293 )
294
295 (define-method image_add_with_alignment
296 (of-object "OsmGpsMap")
297 (c-name "osm_gps_map_image_add_with_alignment")
298 (return-type "OsmGpsMapImage*")
299 (caller-owns-return #t)
300 (parameters
301 '("float" "latitude")
302 '("float" "longitude")
303 '("GdkPixbuf*" "image")
304 '("float" "xalign")
305 '("float" "yalign")
306 )
307 )
308
309 (define-method image_remove
310 (of-object "OsmGpsMap")
311 (c-name "osm_gps_map_image_remove")
312 (return-type "gboolean")
313 (parameters
314 '("OsmGpsMapImage*" "image")
315 )
316 )
317
318 (define-method image_remove_all
319 (of-object "OsmGpsMap")
320 (c-name "osm_gps_map_image_remove_all")
321 (return-type "none")
322 )
323
324 (define-method layer_add
325 (of-object "OsmGpsMap")
326 (c-name "osm_gps_map_layer_add")
325327 (return-type "none")
326328 (parameters
327329 '("OsmGpsMapLayer*" "layer")
330 )
331 )
332
333 (define-method layer_remove
334 (of-object "OsmGpsMap")
335 (c-name "osm_gps_map_layer_remove")
336 (return-type "gboolean")
337 (parameters
338 '("OsmGpsMapLayer*" "layer")
339 )
340 )
341
342 (define-method layer_remove_all
343 (of-object "OsmGpsMap")
344 (c-name "osm_gps_map_layer_remove_all")
345 (return-type "none")
346 )
347
348 (define-method convert_screen_to_geographic
349 (of-object "OsmGpsMap")
350 (c-name "osm_gps_map_convert_screen_to_geographic")
351 (return-type "none")
352 (parameters
353 '("gint" "pixel_x")
354 '("gint" "pixel_y")
355 '("OsmGpsMapPoint*" "pt")
356 )
357 )
358
359 (define-method convert_geographic_to_screen
360 (of-object "OsmGpsMap")
361 (c-name "osm_gps_map_convert_geographic_to_screen")
362 (return-type "none")
363 (parameters
364 '("OsmGpsMapPoint*" "pt")
365 '("gint*" "pixel_x")
366 '("gint*" "pixel_y")
367 )
368 )
369
370 (define-method get_event_location
371 (of-object "OsmGpsMap")
372 (c-name "osm_gps_map_get_event_location")
373 (return-type "OsmGpsMapPoint*")
374 (caller-owns-return #t)
375 (parameters
376 '("GdkEventButton*" "event")
328377 )
329378 )
330379
357406
358407
359408
409 ;; From osm-gps-map-image.h
410
411 (define-function osm_gps_map_image_get_type
412 (c-name "osm_gps_map_image_get_type")
413 (return-type "GType")
414 )
415
416 (define-function osm_gps_map_image_new
417 (c-name "osm_gps_map_image_new")
418 (is-constructor-of "OsmGpsMapImage")
419 (return-type "OsmGpsMapImage*")
420 )
421
422 (define-method draw
423 (of-object "OsmGpsMapImage")
424 (c-name "osm_gps_map_image_draw")
425 (return-type "none")
426 (parameters
427 '("GdkDrawable*" "drawable")
428 '("GdkGC*" "gc")
429 '("GdkRectangle*" "rect")
430 )
431 )
432
433 (define-method get_point
434 (of-object "OsmGpsMapImage")
435 (c-name "osm_gps_map_image_get_point")
436 (return-type "const-OsmGpsMapPoint*")
437 )
438
439
440
360441 ;; From osm-gps-map-layer.h
361
362 (define-interface GpsMapLayer
363 (in-module "Osm")
364 (c-name "OsmGpsMapLayer")
365 (gtype-id "OSM_TYPE_GPS_MAP_LAYER")
366 (prerequisite "GObject")
367 )
368442
369443 (define-function osm_gps_map_layer_get_type
370444 (c-name "osm_gps_map_layer_get_type")
405479 '("GdkEventButton*" "event")
406480 )
407481 )
482
483
484
485 ;; From osm-gps-map-track.h
486
487 (define-function osm_gps_map_track_get_type
488 (c-name "osm_gps_map_track_get_type")
489 (return-type "GType")
490 )
491
492 (define-function osm_gps_map_track_new
493 (c-name "osm_gps_map_track_new")
494 (is-constructor-of "OsmGpsMapTrack")
495 (return-type "OsmGpsMapTrack*")
496 )
497
498 (define-method add_point
499 (of-object "OsmGpsMapTrack")
500 (c-name "osm_gps_map_track_add_point")
501 (return-type "none")
502 (parameters
503 '("OsmGpsMapPoint*" "point")
504 )
505 )
506
507 (define-method get_points
508 (of-object "OsmGpsMapTrack")
509 (c-name "osm_gps_map_track_get_points")
510 (return-type "GSList*")
511 )
512
513 (define-method get_color
514 (of-object "OsmGpsMapTrack")
515 (c-name "osm_gps_map_track_get_color")
516 (return-type "none")
517 (parameters
518 '("GdkColor*" "color")
519 )
520 )
521
522
523
524 ;; From osm-gps-map-point.h
525
526 (define-function osm_gps_map_point_get_type
527 (c-name "osm_gps_map_point_get_type")
528 (return-type "GType")
529 )
530
531 (define-function point_new_degrees
532 (c-name "osm_gps_map_point_new_degrees")
533 (return-type "OsmGpsMapPoint*")
534 (parameters
535 '("float" "lat")
536 '("float" "lon")
537 )
538 )
539
540 (define-function point_new_radians
541 (c-name "osm_gps_map_point_new_radians")
542 (return-type "OsmGpsMapPoint*")
543 (parameters
544 '("float" "rlat")
545 '("float" "rlon")
546 )
547 )
548
549 (define-method get_degrees
550 (of-object "OsmGpsMapPoint")
551 (c-name "osm_gps_map_point_get_degrees")
552 (return-type "none")
553 (parameters
554 '("float*" "lat")
555 '("float*" "lon")
556 )
557 )
558
559 (define-method get_radians
560 (of-object "OsmGpsMapPoint")
561 (c-name "osm_gps_map_point_get_radians")
562 (return-type "none")
563 (parameters
564 '("float*" "rlat")
565 '("float*" "rlon")
566 )
567 )
568
569 (define-method set_degrees
570 (of-object "OsmGpsMapPoint")
571 (c-name "osm_gps_map_point_set_degrees")
572 (return-type "none")
573 (parameters
574 '("float" "lat")
575 '("float" "lon")
576 )
577 )
578
579 (define-method set_radians
580 (of-object "OsmGpsMapPoint")
581 (c-name "osm_gps_map_point_set_radians")
582 (return-type "none")
583 (parameters
584 '("float" "rlat")
585 '("float" "rlon")
586 )
587 )
588
589
590
591 ;; From osm-gps-map-source.h
592
593 (define-function source_get_friendly_name
594 (c-name "osm_gps_map_source_get_friendly_name")
595 (return-type "const-char*")
596 (parameters
597 '("OsmGpsMapSource_t" "source")
598 )
599 )
600
601 (define-function source_get_repo_uri
602 (c-name "osm_gps_map_source_get_repo_uri")
603 (return-type "const-char*")
604 (parameters
605 '("OsmGpsMapSource_t" "source")
606 )
607 )
608
609 (define-function source_get_image_format
610 (c-name "osm_gps_map_source_get_image_format")
611 (return-type "const-char*")
612 (parameters
613 '("OsmGpsMapSource_t" "source")
614 )
615 )
616
617 (define-function source_get_min_zoom
618 (c-name "osm_gps_map_source_get_min_zoom")
619 (return-type "int")
620 (parameters
621 '("OsmGpsMapSource_t" "source")
622 )
623 )
624
625 (define-function source_get_max_zoom
626 (c-name "osm_gps_map_source_get_max_zoom")
627 (return-type "int")
628 (parameters
629 '("OsmGpsMapSource_t" "source")
630 )
631 )
632
633 (define-function osm_gps_map_source_is_valid
634 (c-name "osm_gps_map_source_is_valid")
635 (return-type "gboolean")
636 (parameters
637 '("OsmGpsMapSource_t" "source")
638 )
639 )
640
641
00 %%
11 headers
22 #include <Python.h>
3 #include <pygobject.h>
4 #include <pygtk/pygtk.h>
35 #include "osm-gps-map.h"
4 #include "osm-gps-map-osd.h"
5 #include "osm-gps-map-layer.h"
6 #include "pygobject.h"
7 #include <stdio.h>
86 %%
97 modulename osmgpsmap
108 %%
1210 import gtk.DrawingArea as PyGtkDrawingArea_Type
1311 import gtk.gdk.Pixbuf as PyGdkPixbuf_Type
1412 import gtk.gdk.Drawable as PyGdkDrawable_Type
13 import gtk.gdk.GC as PyGdkGC_Type
14 import gtk.gdk.Rectangle as PyGtkRectangle_Type
1515 %%
1616 ignore-glob
1717 *_get_type
2020 static PyObject *
2121 _wrap_osm_gps_map_get_bbox(PyGObject *self)
2222 {
23 coord_t pt1,pt2;
23 OsmGpsMapPoint pt1,pt2;
2424
2525 osm_gps_map_get_bbox(OSM_GPS_MAP(self->obj), &pt1, &pt2);
2626
2727 return Py_BuildValue("(dddd)", pt1.rlat, pt1.rlon, pt2.rlat, pt2.rlon);
2828 }
29 %%
30 override osm_gps_map_set_center
31 static PyObject *
32 _wrap_osm_gps_map_set_center(PyGObject *self, PyObject *args)
33 {
34 double latitude, longitude;
35
36 if (PyTuple_Size(args) == 1)
37 args = PyTuple_GetItem(args, 0);
38 if (!PyArg_ParseTuple(args, "dd;OsmGpsMap.set_center takes two floats (also in a tuple)",
39 &latitude, &longitude))
40 return NULL;
41 osm_gps_map_set_center(OSM_GPS_MAP(self->obj), latitude, longitude);
42
43 Py_INCREF(Py_None);
44 return Py_None;
45 }
46 %%
47 override osm_gps_map_scroll
48 static PyObject *
49 _wrap_osm_gps_map_scroll(PyGObject *self, PyObject *args)
50 {
51 int dx, dy;
52
53 if (PyTuple_Size(args) == 1)
54 args = PyTuple_GetItem(args, 0);
55 if (!PyArg_ParseTuple(args, "ii:OsmGpsMap.scroll takes two "
56 "integers (also in a tuple)", &dx, &dy))
57 return NULL;
58
59 osm_gps_map_scroll(OSM_GPS_MAP(self->obj), dx, dy);
60
61 Py_INCREF(Py_None);
62 return Py_None;
63 }
64 %%
65 override osm_gps_map_download_maps kwargs
66 static PyObject *
67 _wrap_osm_gps_map_download_maps(PyGObject *self, PyObject *args,
68 PyObject *kwargs)
69 {
70 static char *kwlist[] = { "lat1", "lon1", "lat2", "lon2", "zoom_start", "zoom_end", NULL };
71 int zoom_start, zoom_end;
72 OsmGpsMapPoint pt1, pt2;
73
74 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
75 "ffffii:GpsMap.download_maps",
76 kwlist, &pt1.rlat,&pt1.rlon,&pt2.rlat, &pt2.rlon,
77 &zoom_start, &zoom_end))
78 return NULL;
79
80 osm_gps_map_download_maps(OSM_GPS_MAP(self->obj), &pt1, &pt2, zoom_start, zoom_end);
81
82 Py_RETURN_NONE;
83 }
84 %%
85 override osm_gps_map_convert_geographic_to_screen
86 static PyObject *
87 _wrap_osm_gps_map_convert_geographic_to_screen(PyGObject *self, PyObject *args, PyObject *kwargs)
88 {
89 static char *kwlist[] = { "pt", "pixel_x", "pixel_y", NULL };
90 int pixel_x, pixel_y;
91 PyObject *py_pt;
92 OsmGpsMapPoint *pt = NULL;
93
94 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"Oii:Osm.GpsMap.convert_geographic_to_screen", kwlist, &py_pt, &pixel_x, &pixel_y))
95 return NULL;
96 if (pyg_boxed_check(py_pt, OSM_TYPE_GPS_MAP_POINT))
97 pt = pyg_boxed_get(py_pt, OsmGpsMapPoint);
98 else {
99 PyErr_SetString(PyExc_TypeError, "pt should be a OsmGpsMapPoint");
100 return NULL;
101 }
102
103 osm_gps_map_convert_geographic_to_screen(OSM_GPS_MAP(self->obj), pt, &pixel_x, &pixel_y);
104
105 return Py_BuildValue("(ii)", pixel_x, pixel_y);
106 }
107 %%
108 override osm_gps_map_point_get_degrees noargs
109 static PyObject *
110 _wrap_osm_gps_map_point_get_degrees(PyGObject *self)
111 {
112 float lat, lon;
113
114 osm_gps_map_point_get_degrees(pyg_boxed_get(self, OsmGpsMapPoint), &lat, &lon);
115
116 return Py_BuildValue("(ff)", lat, lon);
117 }
118 %%
119 override osm_gps_map_point_get_radians noargs
120 static PyObject *
121 _wrap_osm_gps_map_point_get_radians(PyGObject *self)
122 {
123 float rlat, rlon;
124
125 osm_gps_map_point_get_radians(pyg_boxed_get(self, OsmGpsMapPoint), &rlat, &rlon);
126
127 return Py_BuildValue("(ff)", rlat, rlon);
128 }
129 %%
130 %%
131 %% DEPRECIATED WRAPPERS FOLLOW, THESE SHOULD BE IN ANOTHER FILE.
132 %% BUT I COULD NOT GET THE INCLUDE.override TO WORK
133 %%
29134 %%
30135 override osm_gps_map_get_co_ordinates kwargs
31136 static PyObject *
34139 {
35140 static char *kwlist[] = { "pixel_x", "pixel_y", NULL };
36141 int pixel_x = -1, pixel_y = -1;
37 coord_t coord;
142 OsmGpsMapPoint coord;
38143
39144 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
40145 "|ii:GpsMap.get_co_ordinates",
46151 return NULL;
47152 }
48153
49 coord = osm_gps_map_get_co_ordinates(OSM_GPS_MAP(self->obj), pixel_x, pixel_y);
154 osm_gps_map_convert_screen_to_geographic(OSM_GPS_MAP(self->obj), pixel_x, pixel_y, &coord);
50155
51156 return Py_BuildValue("(dd)", coord.rlat, coord.rlon);
52157 }
53158 %%
54 override osm_gps_map_set_center
55 static PyObject *
56 _wrap_osm_gps_map_set_center(PyGObject *self, PyObject *args)
57 {
58 double latitude, longitude;
59
60 if (PyTuple_Size(args) == 1)
61 args = PyTuple_GetItem(args, 0);
62 if (!PyArg_ParseTuple(args, "dd;OsmGpsMap.set_center takes two floats (also in a tuple)",
63 &latitude, &longitude))
64 return NULL;
65 osm_gps_map_set_center(OSM_GPS_MAP(self->obj), latitude, longitude);
66
67 Py_INCREF(Py_None);
68 return Py_None;
69 }
70 %%
71159 override osm_gps_map_screen_to_geographic
72160 static PyObject *
73161 _wrap_osm_gps_map_screen_to_geographic(PyGObject *self, PyObject *args)
74162 {
75163 int pixel_x, pixel_y;
76 gfloat latitude, longitude;
164 OsmGpsMapPoint coord;
165 gfloat lat, lon;
77166
78167 if (PyTuple_Size(args) == 1)
79168 args = PyTuple_GetItem(args, 0);
81170 "integers (also in a tuple)", &pixel_x, &pixel_y))
82171 return NULL;
83172
84 osm_gps_map_screen_to_geographic(OSM_GPS_MAP(self->obj), pixel_x, pixel_y,
85 &latitude, &longitude);
86
87 return Py_BuildValue("(ff)", latitude, longitude);
173 osm_gps_map_convert_screen_to_geographic(OSM_GPS_MAP(self->obj), pixel_x, pixel_y, &coord);
174 osm_gps_map_point_get_degrees(&coord, &lat, &lon);
175
176 return Py_BuildValue("(ff)", lat, lon);
88177 }
89178 %%
90179 override osm_gps_map_geographic_to_screen
92181 _wrap_osm_gps_map_geographic_to_screen(PyGObject *self, PyObject *args)
93182 {
94183 int pixel_x, pixel_y;
95 gfloat latitude, longitude;
184 gfloat lat, lon;
185 OsmGpsMapPoint coord;
96186
97187 if (PyTuple_Size(args) == 1)
98188 args = PyTuple_GetItem(args, 0);
99189 if (!PyArg_ParseTuple(args, "ff:OsmGpsMap.geographic_to_screen takes two"
100 "floats (also in a tuple)", &latitude, &longitude))
101 return NULL;
102
103 osm_gps_map_geographic_to_screen(OSM_GPS_MAP(self->obj),
104 latitude, longitude,
105 &pixel_x, &pixel_y);
190 "floats (also in a tuple)", &lat, &lon))
191 return NULL;
192
193 osm_gps_map_point_set_degrees(&coord, lat, lon);
194 osm_gps_map_convert_geographic_to_screen(OSM_GPS_MAP(self->obj), &coord, &pixel_x, &pixel_y);
106195
107196 return Py_BuildValue("(ii)", pixel_x, pixel_y);
108197 }
109 %%
110 override osm_gps_map_scroll
111 static PyObject *
112 _wrap_osm_gps_map_scroll(PyGObject *self, PyObject *args)
113 {
114 int dx, dy;
115
116 if (PyTuple_Size(args) == 1)
117 args = PyTuple_GetItem(args, 0);
118 if (!PyArg_ParseTuple(args, "ii:OsmGpsMap.scroll takes two "
119 "integers (also in a tuple)", &dx, &dy))
120 return NULL;
121
122 osm_gps_map_scroll(OSM_GPS_MAP(self->obj), dx, dy);
123
124 Py_INCREF(Py_None);
125 return Py_None;
126 }
127
128198 %%
129199 override osm_gps_map_add_track kwargs
130200 static PyObject *
148218 coords = PyList_GetItem(list,i);
149219 if(PyArg_ParseTuple(coords,"ff",&rlat,&rlon))
150220 {
151 coord_t *c = g_new0(coord_t, 1);
152 c->rlat = rlat;
153 c->rlon = rlon;
221 OsmGpsMapPoint *c = osm_gps_map_point_new_radians (rlat, rlon);
154222 track = g_slist_append(track, c);
155223 }
156224 else
176244 }
177245 Py_RETURN_NONE;
178246 }
179 %%
180 override osm_gps_map_download_maps kwargs
181 static PyObject *
182 _wrap_osm_gps_map_download_maps(PyGObject *self, PyObject *args,
183 PyObject *kwargs)
184 {
185 static char *kwlist[] = { "lat1", "lon1", "lat2", "lon2", "zoom_start", "zoom_end", NULL };
186 int zoom_start, zoom_end;
187 coord_t pt1, pt2;
188
189 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
190 "ffffii:GpsMap.download_maps",
191 kwlist, &pt1.rlat,&pt1.rlon,&pt2.rlat, &pt2.rlon,
192 &zoom_start, &zoom_end))
193 return NULL;
194
195 osm_gps_map_download_maps(OSM_GPS_MAP(self->obj), &pt1, &pt2, zoom_start, zoom_end);
196
197 Py_RETURN_NONE;
198 }
199
200247 // vim: filetype=c
1616 def get_libs(pkg):
1717 return pkg_config_parse(pkg,'--libs-only-l')
1818
19 #print get_libs('osmgpsmap pygobject-2.0')
20 #print get_libs('osmgpsmap pygobject-2.0')
21 #print get_libs('osmgpsmap pygobject-2.0')
19 VERSION = "0.7.0"
2220
2321 _osmgpsmap = Extension(name = 'osmgpsmap',
2422 sources= ['osmgpsmapmodule.c','osmgpsmap.c'],
2523 include_dirs = get_include('osmgpsmap pygobject-2.0'),
2624 library_dirs = get_lib_dirs('osmgpsmap pygobject-2.0'),
2725 libraries = get_libs('osmgpsmap pygobject-2.0'),
28 )
26 define_macros = [('VERSION', '"""%s"""' % VERSION)],
27 )
2928
3029 setup( name = "python-osmgpsmap",
31 version = "0.6.0",
30 version = VERSION,
3231 description = "python interface for osmgpsmap",
3332 ext_modules = [_osmgpsmap],
3433 )
0 OsmGpsMap-1.0.gir
1 OsmGpsMap-1.0.typelib
00 ## Process this file with automake to produce Makefile.in
1 lib_LTLIBRARIES = libosmgpsmap.la
12
2 ## Created by Anjuta
3 OSMGPSMAP_CFLAGS = \
4 $(GLIB_CFLAGS) \
5 $(GTK_CFLAGS) \
6 $(CAIRO_CFLAGS) \
7 $(SOUP22_CFLAGS) \
8 $(SOUP24_CFLAGS)
39
4 AM_CPPFLAGS = \
5 -DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
6 -DPACKAGE_SRC_DIR=\""$(srcdir)"\" \
7 -DPACKAGE_DATA_DIR=\""$(datadir)"\" $(OPENSTREETMAP_GPS_MAP_CFLAGS)
10 OSMGPSMAP_LIBS = \
11 $(GLIB_LIBS) \
12 $(GTK_LIBS) \
13 $(CAIRO_LIBS) \
14 $(SOUP22_LIBS) \
15 $(SOUP24_LIBS)
816
9 AM_CFLAGS =\
10 -Wall\
11 -g
12
13 bin_PROGRAMS = mapviewer
14
15 mapviewer_SOURCES = \
16 main.c
17
18 mapviewer_DEPENDENCIES = \
19 libosmgpsmap.la
20
21 mapviewer_LDFLAGS = \
22 -losmgpsmap -lgthread-2.0
23
24 mapviewer_LDADD = \
25 $(OPENSTREETMAP_GPS_MAP_LIBS)
26
27 lib_LTLIBRARIES = \
28 libosmgpsmap.la
29
30 libosmgpsmap_la_SOURCES = \
31 converter.c \
32 osm-gps-map.c \
33 osm-gps-map-osd.c \
34 osm-gps-map-layer.c \
35 osd-utils.c
36
37 libosmgpsmap_la_CFLAGS = \
17 ## Shared library
18 libosmgpsmap_la_CFLAGS = \
19 $(WARN_CFLAGS) \
20 $(DISABLE_DEPRECATED) \
21 $(OSMGPSMAP_CFLAGS) \
3822 -DG_LOG_DOMAIN=\"OsmGpsMap\"
3923
4024 if OS_WIN32
4529 -version-info $(LT_VERSION_INFO) \
4630 $(no_undefined)
4731
48 libosmgpsmap_la_LIBADD = \
49 $(OPENSTREETMAP_GPS_MAP_LIBS)
32 libosmgpsmap_la_LIBADD = \
33 $(OSMGPSMAP_LIBS)
34
35 sources_private_h = \
36 converter.h \
37 osd-utils.h \
38 osm-gps-map-types.h
39
40 sources_public_h = \
41 osm-gps-map.h \
42 osm-gps-map-osd.h \
43 osm-gps-map-layer.h \
44 osm-gps-map-track.h \
45 osm-gps-map-point.h \
46 osm-gps-map-image.h \
47 osm-gps-map-source.h \
48 osm-gps-map-widget.h \
49 osm-gps-map-compat.h
50
51 sources_c = \
52 converter.c \
53 osd-utils.c \
54 osm-gps-map-osd.c \
55 osm-gps-map-layer.c \
56 osm-gps-map-track.c \
57 osm-gps-map-point.c \
58 osm-gps-map-image.c \
59 osm-gps-map-source.c \
60 osm-gps-map-widget.c \
61 osm-gps-map-compat.c
62
63 libosmgpsmap_la_SOURCES = \
64 $(sources_public_h) \
65 $(sources_private_h) \
66 $(sources_c)
5067
5168 libosmgpsmapincdir = $(includedir)/osmgpsmap
52 libosmgpsmapinc_HEADERS = \
53 osm-gps-map.h \
54 osm-gps-map-layer.h \
55 osm-gps-map-osd.h
69 libosmgpsmapinc_HEADERS = $(sources_public_h)
5670
57 noinst_HEADERS = \
58 converter.h \
59 osd-utils.h \
60 osm-gps-map-types.h
71 ## Misc
72 CLEANFILES =
6173
62 EXTRA_DIST = \
63 poi.png
74 ## GObject Introspection Support
75 -include $(INTROSPECTION_MAKEFILE)
76 INTROSPECTION_GIRS =
77 INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir) --add-include-path=$(builddir)
78 INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir)
79
80 if HAVE_INTROSPECTION
81 introspection_sources = $(sources_c) $(sources_public_h)
82
83 OsmGpsMap-1.0.gir: libosmgpsmap.la
84 OsmGpsMap_1_0_gir_INCLUDES = GObject-2.0 Gtk-2.0
85 OsmGpsMap_1_0_gir_CFLAGS = $(OSMGPSMAP_CFLAGS)
86 OsmGpsMap_1_0_gir_LIBS = libosmgpsmap.la
87 OsmGpsMap_1_0_gir_FILES = $(introspection_sources)
88 INTROSPECTION_GIRS += OsmGpsMap-1.0.gir
89
90 girdir = $(datadir)/gir-1.0
91 dist_gir_DATA = $(INTROSPECTION_GIRS)
92
93 typelibdir = $(libdir)/girepository-1.0
94 typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
95
96 CLEANFILES += $(dist_gir_DATA) $(typelib_DATA)
97 endif
+0
-318
src/main.c less more
0 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */
1 /* vim:set et sw=4 ts=4 cino=t0,(0: */
2 /*
3 * main.c
4 * Copyright (C) John Stowers 2008 <john.stowers@gmail.com>
5 *
6 * This is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; version 2.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <stdlib.h>
20 #include <math.h>
21 #include <glib.h>
22 #include <gtk/gtk.h>
23 #include <gdk/gdkkeysyms.h>
24 #include "osm-gps-map.h"
25 #include "osm-gps-map-osd.h"
26
27 static OsmGpsMapSource_t map_provider = OSM_GPS_MAP_SOURCE_OPENSTREETMAP;
28 static gboolean default_cache = FALSE;
29 static gboolean no_cache = FALSE;
30 static gboolean debug = FALSE;
31 static GOptionEntry entries[] =
32 {
33 { "default-cache", 'D', 0, G_OPTION_ARG_NONE, &default_cache, "Store maps in default cache", NULL },
34 { "no-cache", 'n', 0, G_OPTION_ARG_NONE, &no_cache, "Disable cache", NULL },
35 { "debug", 'd', 0, G_OPTION_ARG_NONE, &debug, "Enable debugging", NULL },
36 { "map", 'm', 0, G_OPTION_ARG_INT, &map_provider, "Map source", "N" },
37 { NULL }
38 };
39
40 static GdkPixbuf *STAR_IMAGE;
41
42 typedef struct {
43 OsmGpsMap *map;
44 GtkWidget *entry;
45 } timeout_cb_t;
46
47 #define DEG2RAD(deg) (deg * M_PI / 180.0)
48 #define RAD2DEG(rad) (rad / M_PI * 180.0)
49
50 gboolean
51 on_timeout_check_tiles_in_queue(gpointer user_data)
52 {
53 gchar *msg;
54 int remaining;
55 timeout_cb_t *data = (timeout_cb_t *)user_data;
56 g_object_get(data->map, "tiles-queued", &remaining,NULL);
57
58 msg = g_strdup_printf("%d tiles queued",remaining);
59 gtk_entry_set_text(GTK_ENTRY(data->entry), msg);
60 g_free(msg);
61
62 return remaining > 0;
63 }
64
65 gboolean
66 on_button_press_event (GtkWidget *widget, GdkEventButton *event, gpointer user_data)
67 {
68 coord_t coord;
69 OsmGpsMap *map = OSM_GPS_MAP(widget);
70
71 if ( ((event->button == 1) || (event->button == 3))
72 && (event->type == GDK_2BUTTON_PRESS) )
73 {
74 g_debug("Double clicked %f %f", event->x, event->y);
75 coord = osm_gps_map_get_co_ordinates(map, (int)event->x, (int)event->y);
76 osm_gps_map_draw_gps (map,
77 RAD2DEG(coord.rlat),
78 RAD2DEG(coord.rlon),
79 (event->button == 1 ? OSM_GPS_MAP_INVALID : g_random_double_range(0,360)));
80 }
81
82 if ( (event->button == 2) && (event->type == GDK_BUTTON_PRESS) )
83 {
84 coord = osm_gps_map_get_co_ordinates(map, (int)event->x, (int)event->y);
85 osm_gps_map_add_image (map,
86 RAD2DEG(coord.rlat),
87 RAD2DEG(coord.rlon),
88 STAR_IMAGE);
89 }
90 return FALSE;
91 }
92
93 gboolean
94 on_button_release_event (GtkWidget *widget, GdkEventButton *event, gpointer user_data)
95 {
96 float lat,lon;
97 GtkEntry *entry = GTK_ENTRY(user_data);
98 OsmGpsMap *map = OSM_GPS_MAP(widget);
99
100 g_object_get(map, "latitude", &lat, "longitude", &lon, NULL);
101 gchar *msg = g_strdup_printf("%f,%f",lat,lon);
102 gtk_entry_set_text(entry, msg);
103 g_free(msg);
104
105 return FALSE;
106 }
107
108 gboolean
109 on_zoom_in_clicked_event (GtkWidget *widget, gpointer user_data)
110 {
111 int zoom;
112 OsmGpsMap *map = OSM_GPS_MAP(user_data);
113 g_object_get(map, "zoom", &zoom, NULL);
114 osm_gps_map_set_zoom(map, zoom+1);
115 return FALSE;
116 }
117
118 gboolean
119 on_zoom_out_clicked_event (GtkWidget *widget, gpointer user_data)
120 {
121 int zoom;
122 OsmGpsMap *map = OSM_GPS_MAP(user_data);
123 g_object_get(map, "zoom", &zoom, NULL);
124 osm_gps_map_set_zoom(map, zoom-1);
125 return FALSE;
126 }
127
128 gboolean
129 on_home_clicked_event (GtkWidget *widget, gpointer user_data)
130 {
131 OsmGpsMap *map = OSM_GPS_MAP(user_data);
132 osm_gps_map_set_mapcenter(map, -43.5326,172.6362,12);
133 return FALSE;
134 }
135
136 gboolean
137 on_cache_clicked_event (GtkWidget *widget, gpointer user_data)
138 {
139 int zoom,max_zoom;
140 coord_t pt1, pt2;
141 timeout_cb_t *data;
142
143 data = (timeout_cb_t *)user_data;
144 osm_gps_map_get_bbox(data->map, &pt1, &pt2);
145 g_object_get(data->map, "zoom", &zoom, "max-zoom", &max_zoom, NULL);
146 osm_gps_map_download_maps(data->map, &pt1, &pt2, zoom, max_zoom);
147 g_timeout_add(500, on_timeout_check_tiles_in_queue, user_data);
148
149 return FALSE;
150 }
151
152 void
153 on_close (GtkWidget *widget, gpointer user_data)
154 {
155 gtk_widget_destroy(widget);
156 gtk_main_quit();
157 }
158
159 void
160 usage (GOptionContext *context)
161 {
162 int i;
163
164 puts(g_option_context_get_help(context, TRUE, NULL));
165
166 printf("Valid map sources:\n");
167 for(i=OSM_GPS_MAP_SOURCE_NULL; i <= OSM_GPS_MAP_SOURCE_LAST; i++)
168 {
169 const char *name = osm_gps_map_source_get_friendly_name(i);
170 const char *uri = osm_gps_map_source_get_repo_uri(i);
171 if (uri != NULL)
172 printf("\t%d:\t%s\n",i,name);
173 }
174 }
175
176 int
177 main (int argc, char **argv)
178 {
179 GtkWidget *vbox;
180 GtkWidget *bbox;
181 GtkWidget *entry;
182 GtkWidget *window;
183 GtkWidget *zoomInbutton;
184 GtkWidget *zoomOutbutton;
185 GtkWidget *homeButton;
186 GtkWidget *cacheButton;
187 OsmGpsMap *map;
188 OsmGpsMapLayer *osd;
189 const char *repo_uri;
190 const char *friendly_name;
191 char *cachedir;
192 GError *error = NULL;
193 GOptionContext *context;
194 timeout_cb_t *data;
195
196 g_thread_init(NULL);
197 gtk_init (&argc, &argv);
198
199 context = g_option_context_new ("- Map browser");
200 g_option_context_set_help_enabled(context, FALSE);
201 g_option_context_add_main_entries (context, entries, NULL);
202
203 if (!g_option_context_parse (context, &argc, &argv, &error)) {
204 usage(context);
205 return 1;
206 }
207
208 /* Only use the repo_uri to check if the user has supplied a
209 valid map source ID */
210 repo_uri = osm_gps_map_source_get_repo_uri(map_provider);
211 if ( repo_uri == NULL ) {
212 usage(context);
213 return 2;
214 }
215
216 friendly_name = osm_gps_map_source_get_friendly_name(map_provider);
217
218 if (default_cache) {
219 cachedir = OSM_GPS_MAP_CACHE_AUTO;
220 } else if (no_cache) {
221 cachedir = OSM_GPS_MAP_CACHE_DISABLED;
222 } else {
223 char *mapcachedir;
224 mapcachedir = osm_gps_map_get_default_cache_directory();
225 cachedir = g_build_filename(mapcachedir,friendly_name,NULL);
226 g_free(mapcachedir);
227 }
228
229 if (debug)
230 gdk_window_set_debug_updates(TRUE);
231
232 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
233 gtk_window_set_default_size(GTK_WINDOW(window), 400, 400);
234
235 STAR_IMAGE = gdk_pixbuf_new_from_file_at_size ("poi.png", 24,24,NULL);
236
237 g_debug("Map Cache Dir: %s", cachedir);
238 g_debug("Map Provider: %s (%d)", friendly_name, map_provider);
239
240 map = g_object_new (OSM_TYPE_GPS_MAP,
241 "map-source",map_provider,
242 "tile-cache",cachedir,
243 "proxy-uri",g_getenv("http_proxy"),
244 NULL);
245
246 osd = g_object_new (OSM_TYPE_GPS_MAP_OSD,
247 "show-scale",TRUE,
248 "show-coordinates",TRUE,
249 "show-crosshair",TRUE,
250 "show-dpad",TRUE,
251 "show-zoom",TRUE,
252 "show-gps-in-dpad",TRUE,
253 "show-gps-in-zoom",FALSE,
254 "dpad-radius", 30,
255 NULL);
256 osm_gps_map_add_layer(OSM_GPS_MAP(map), osd);
257 g_object_unref(G_OBJECT(osd));
258
259 //Enable keyboard navigation
260 osm_gps_map_set_keyboard_shortcut(map, OSM_GPS_MAP_KEY_FULLSCREEN, GDK_F11);
261 osm_gps_map_set_keyboard_shortcut(map, OSM_GPS_MAP_KEY_UP, GDK_Up);
262 osm_gps_map_set_keyboard_shortcut(map, OSM_GPS_MAP_KEY_DOWN, GDK_Down);
263 osm_gps_map_set_keyboard_shortcut(map, OSM_GPS_MAP_KEY_LEFT, GDK_Left);
264 osm_gps_map_set_keyboard_shortcut(map, OSM_GPS_MAP_KEY_RIGHT, GDK_Right);
265
266 vbox = gtk_vbox_new (FALSE, 2);
267 gtk_container_add (GTK_CONTAINER (window), vbox);
268
269 //Add the map to the box
270 gtk_box_pack_start (GTK_BOX(vbox), GTK_WIDGET(map), TRUE, TRUE, 0);
271 //And add a box for the buttons
272 bbox = gtk_hbox_new (TRUE, 0);
273 gtk_box_pack_start (GTK_BOX(vbox), bbox, FALSE, TRUE, 0);
274 //And add the lat/long entry
275 entry = gtk_entry_new();
276 gtk_box_pack_start (GTK_BOX(vbox), entry, FALSE, TRUE, 0);
277
278 //Add buttons to the bbox
279 zoomInbutton = gtk_button_new_from_stock (GTK_STOCK_ZOOM_IN);
280 g_signal_connect (G_OBJECT (zoomInbutton), "clicked",
281 G_CALLBACK (on_zoom_in_clicked_event), (gpointer) map);
282 gtk_box_pack_start (GTK_BOX(bbox), zoomInbutton, FALSE, TRUE, 0);
283
284 zoomOutbutton = gtk_button_new_from_stock (GTK_STOCK_ZOOM_OUT);
285 g_signal_connect (G_OBJECT (zoomOutbutton), "clicked",
286 G_CALLBACK (on_zoom_out_clicked_event), (gpointer) map);
287 gtk_box_pack_start (GTK_BOX(bbox), zoomOutbutton, FALSE, TRUE, 0);
288
289 homeButton = gtk_button_new_from_stock (GTK_STOCK_HOME);
290 g_signal_connect (G_OBJECT (homeButton), "clicked",
291 G_CALLBACK (on_home_clicked_event), (gpointer) map);
292 gtk_box_pack_start (GTK_BOX(bbox), homeButton, FALSE, TRUE, 0);
293
294 data = g_new0(timeout_cb_t, 1);
295 data->map = map;
296 data->entry = entry;
297 cacheButton = gtk_button_new_with_label ("Cache");
298 g_signal_connect (G_OBJECT (cacheButton), "clicked",
299 G_CALLBACK (on_cache_clicked_event), (gpointer) data);
300 gtk_box_pack_start (GTK_BOX(bbox), cacheButton, FALSE, TRUE, 0);
301
302 //Connect to map events
303 g_signal_connect (G_OBJECT (map), "button-press-event",
304 G_CALLBACK (on_button_press_event), (gpointer) entry);
305 g_signal_connect (G_OBJECT (map), "button-release-event",
306 G_CALLBACK (on_button_release_event), (gpointer) entry);
307
308 g_signal_connect (window, "destroy",
309 G_CALLBACK (on_close), (gpointer) map);
310
311 gtk_widget_show_all (window);
312
313 g_log_set_handler ("OsmGpsMap", G_LOG_LEVEL_MASK, g_log_default_handler, NULL);
314 gtk_main ();
315
316 return 0;
317 }
0 #include "converter.h"
1 #include "osm-gps-map-compat.h"
2
3 /**
4 * osm_gps_map_draw_gps:
5 *
6 * Deprecated: 0.7.0: Use osm_gps_map_gps_add() instead.
7 **/
8 void
9 osm_gps_map_draw_gps (OsmGpsMap *map, float latitude, float longitude, float heading)
10 {
11 g_warning("%s is deprecated", G_STRFUNC);
12 osm_gps_map_gps_add (map, latitude, longitude, heading);
13 }
14
15 /**
16 * osm_gps_map_clear_gps:
17 *
18 * Deprecated: 0.7.0: Use osm_gps_map_gps_clear() instead.
19 **/
20 void
21 osm_gps_map_clear_gps (OsmGpsMap *map)
22 {
23 g_warning("%s is deprecated", G_STRFUNC);
24 osm_gps_map_gps_clear (map);
25 }
26
27 /**
28 * osm_gps_map_add_track:
29 *
30 * Deprecated: 0.7.0: Use osm_gps_map_track_add() instead.
31 **/
32 void
33 osm_gps_map_add_track (OsmGpsMap *map, GSList *list)
34 {
35 OsmGpsMapTrack *track;
36 g_warning("%s is deprecated", G_STRFUNC);
37 track = g_object_new (OSM_TYPE_GPS_MAP_TRACK, "track", list, NULL);
38 osm_gps_map_track_add (map, track);
39 }
40
41 /**
42 * osm_gps_map_clear_tracks:
43 *
44 * Deprecated: 0.7.0: Use osm_gps_map_track_remove_all() instead.
45 **/
46 void
47 osm_gps_map_clear_tracks (OsmGpsMap *map)
48 {
49 g_warning("%s is deprecated", G_STRFUNC);
50 osm_gps_map_track_remove_all (map);
51 }
52
53 /**
54 * osm_gps_map_add_image_with_alignment:
55 *
56 * Deprecated: 0.7.0: Use osm_gps_map_image_add_with_alignment() instead.
57 **/
58 void
59 osm_gps_map_add_image_with_alignment (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image, float xalign, float yalign)
60 {
61 g_warning("%s is deprecated", G_STRFUNC);
62 osm_gps_map_image_add_with_alignment (map, latitude, longitude, image, xalign, yalign);
63 }
64
65 /**
66 * osm_gps_map_add_image:
67 *
68 * Deprecated: 0.7.0: Use osm_gps_map_image_add() instead.
69 **/
70 void
71 osm_gps_map_add_image (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image)
72 {
73 g_warning("%s is deprecated", G_STRFUNC);
74 osm_gps_map_image_add_with_alignment (map, latitude, longitude, image, 0.5, 0.5);
75 }
76
77 /**
78 * osm_gps_map_clear_images:
79 *
80 * Deprecated: 0.7.0: Use osm_gps_map_image_remove_all() instead.
81 **/
82 void
83 osm_gps_map_clear_images (OsmGpsMap *map)
84 {
85 g_warning("%s is deprecated", G_STRFUNC);
86 osm_gps_map_image_remove_all (map);
87 }
88
89 /**
90 * osm_gps_map_add_layer:
91 *
92 * Deprecated: 0.7.0: Use osm_gps_map_layer_add() instead.
93 **/
94 void
95 osm_gps_map_add_layer (OsmGpsMap *map, OsmGpsMapLayer *layer)
96 {
97 g_warning("%s is deprecated", G_STRFUNC);
98 osm_gps_map_layer_add (map, layer);
99 }
100
101 /**
102 * osm_gps_map_screen_to_geographic:
103 *
104 * Deprecated: 0.7.0: Use osm_gps_map_convert_screen_to_geographic() instead.
105 **/
106 void
107 osm_gps_map_screen_to_geographic (OsmGpsMap *map, gint pixel_x, gint pixel_y,
108 gfloat *latitude, gfloat *longitude)
109 {
110 OsmGpsMapPoint p;
111 g_warning("%s is deprecated", G_STRFUNC);
112 osm_gps_map_convert_screen_to_geographic(map, pixel_x, pixel_y, &p);
113 if (latitude)
114 *latitude = rad2deg(p.rlat);
115 if (longitude)
116 *longitude = rad2deg(p.rlon);
117 }
118
119 /**
120 * osm_gps_map_geographic_to_screen:
121 *
122 * Deprecated: 0.7.0: Use osm_gps_map_convert_geographic_to_screen() instead.
123 **/
124 void
125 osm_gps_map_geographic_to_screen (OsmGpsMap *map,
126 gfloat latitude, gfloat longitude,
127 gint *pixel_x, gint *pixel_y)
128 {
129 OsmGpsMapPoint p;
130 g_warning("%s is deprecated", G_STRFUNC);
131 osm_gps_map_point_set_degrees(&p, latitude, longitude);
132 osm_gps_map_convert_geographic_to_screen(map, &p, pixel_x, pixel_y);
133 }
134
135 /**
136 * osm_gps_map_get_co_ordinates:
137 *
138 * Deprecated: 0.7.0: Use osm_gps_map_convert_screen_to_geographic() or
139 * osm_gps_map_get_event_location() instead.
140 **/
141 OsmGpsMapPoint
142 osm_gps_map_get_co_ordinates (OsmGpsMap *map, int pixel_x, int pixel_y)
143 {
144 OsmGpsMapPoint p;
145 g_warning("%s is deprecated", G_STRFUNC);
146 osm_gps_map_convert_screen_to_geographic(map, pixel_x, pixel_y, &p);
147 return p;
148 }
149
150 /**
151 * osm_gps_map_set_mapcenter:
152 *
153 * Deprecated: 0.7.0: Use osm_gps_map_set_center_and_zoom() instead.
154 **/
155 void
156 osm_gps_map_set_mapcenter (OsmGpsMap *map, float latitude, float longitude, int zoom)
157 {
158 g_warning("%s is deprecated", G_STRFUNC);
159 osm_gps_map_set_center_and_zoom (map, latitude, longitude, zoom);
160 }
161
162
0 #ifndef _OSM_GPS_MAP_COMPAT_H
1 #define _OSM_GPS_MAP_COMPAT_H
2
3 #include "osm-gps-map-widget.h"
4
5 G_BEGIN_DECLS
6
7 /* Depreciated Functions */
8 #define coord_t OsmGpsMapPoint
9 void osm_gps_map_add_track (OsmGpsMap *map, GSList *track) G_GNUC_DEPRECATED;
10 void osm_gps_map_replace_track (OsmGpsMap *map, GSList *old_track, GSList *new_track) G_GNUC_DEPRECATED;
11 void osm_gps_map_clear_tracks (OsmGpsMap *map) G_GNUC_DEPRECATED;
12 void osm_gps_map_draw_gps (OsmGpsMap *map, float latitude, float longitude, float heading) G_GNUC_DEPRECATED;
13 void osm_gps_map_clear_gps (OsmGpsMap *map) G_GNUC_DEPRECATED;
14 void osm_gps_map_add_image (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image) G_GNUC_DEPRECATED;
15 void osm_gps_map_add_image_with_alignment (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image, float xalign, float yalign) G_GNUC_DEPRECATED;
16 gboolean osm_gps_map_remove_image (OsmGpsMap *map, GdkPixbuf *image) G_GNUC_DEPRECATED;
17 void osm_gps_map_clear_images (OsmGpsMap *map) G_GNUC_DEPRECATED;
18 void osm_gps_map_add_layer (OsmGpsMap *map, OsmGpsMapLayer *layer) G_GNUC_DEPRECATED;
19 void osm_gps_map_screen_to_geographic (OsmGpsMap *map, gint pixel_x, gint pixel_y, gfloat *latitude, gfloat *longitude) G_GNUC_DEPRECATED;
20 void osm_gps_map_geographic_to_screen (OsmGpsMap *map, gfloat latitude, gfloat longitude, gint *pixel_x, gint *pixel_y) G_GNUC_DEPRECATED;
21 OsmGpsMapPoint osm_gps_map_get_co_ordinates (OsmGpsMap *map, int pixel_x, int pixel_y) G_GNUC_DEPRECATED;
22 void osm_gps_map_set_mapcenter (OsmGpsMap *map, float latitude, float longitude, int zoom) G_GNUC_DEPRECATED;
23
24 G_END_DECLS
25
26 #endif /* _OSM_GPS_MAP_COMPAT_H */
0 /* osm-gps-map-image.c */
1
2 #include <gdk-pixbuf/gdk-pixbuf.h>
3
4 #include "converter.h"
5 #include "osm-gps-map-track.h"
6 #include "osm-gps-map-image.h"
7
8 G_DEFINE_TYPE (OsmGpsMapImage, osm_gps_map_image, G_TYPE_OBJECT)
9
10 enum
11 {
12 PROP_0,
13 PROP_PIXBUF,
14 PROP_X_ALIGN,
15 PROP_Y_ALIGN,
16 PROP_POINT,
17 };
18
19 struct _OsmGpsMapImagePrivate
20 {
21 OsmGpsMapPoint *pt;
22 GdkPixbuf *pixbuf;
23 int w;
24 int h;
25 gfloat xalign;
26 gfloat yalign;
27 };
28
29 static void
30 osm_gps_map_image_get_property (GObject *object,
31 guint property_id,
32 GValue *value,
33 GParamSpec *pspec)
34 {
35 OsmGpsMapImagePrivate *priv = OSM_GPS_MAP_IMAGE(object)->priv;
36 switch (property_id)
37 {
38 case PROP_PIXBUF:
39 g_value_set_object (value, priv->pixbuf);
40 break;
41 case PROP_X_ALIGN:
42 g_value_set_float (value, priv->xalign);
43 break;
44 case PROP_Y_ALIGN:
45 g_value_set_float (value, priv->yalign);
46 break;
47 case PROP_POINT:
48 g_value_set_boxed (value, priv->pt);
49 break;
50 default:
51 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
52 }
53 }
54
55 static void
56 osm_gps_map_image_set_property (GObject *object,
57 guint property_id,
58 const GValue *value,
59 GParamSpec *pspec)
60 {
61 OsmGpsMapImagePrivate *priv = OSM_GPS_MAP_IMAGE(object)->priv;
62 switch (property_id)
63 {
64 case PROP_PIXBUF:
65 if (priv->pixbuf)
66 g_object_unref (priv->pixbuf);
67 priv->pixbuf = g_value_dup_object (value);
68 priv->w = gdk_pixbuf_get_width(priv->pixbuf);
69 priv->h = gdk_pixbuf_get_width(priv->pixbuf);
70 break;
71 case PROP_X_ALIGN:
72 priv->xalign = g_value_get_float (value);
73 break;
74 case PROP_Y_ALIGN:
75 priv->yalign = g_value_get_float (value);
76 break;
77 case PROP_POINT:
78 priv->pt = g_value_dup_boxed (value);
79 break;
80 default:
81 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
82 }
83 }
84
85 static void
86 osm_gps_map_image_dispose (GObject *object)
87 {
88 OsmGpsMapImagePrivate *priv = OSM_GPS_MAP_IMAGE(object)->priv;
89
90 if (priv->pixbuf)
91 g_object_unref (priv->pixbuf);
92
93 G_OBJECT_CLASS (osm_gps_map_image_parent_class)->dispose (object);
94 }
95
96 static void
97 osm_gps_map_image_finalize (GObject *object)
98 {
99 G_OBJECT_CLASS (osm_gps_map_image_parent_class)->finalize (object);
100 }
101
102 static void
103 osm_gps_map_image_class_init (OsmGpsMapImageClass *klass)
104 {
105 GObjectClass *object_class = G_OBJECT_CLASS (klass);
106
107 g_type_class_add_private (klass, sizeof (OsmGpsMapImagePrivate));
108
109 object_class->get_property = osm_gps_map_image_get_property;
110 object_class->set_property = osm_gps_map_image_set_property;
111 object_class->dispose = osm_gps_map_image_dispose;
112 object_class->finalize = osm_gps_map_image_finalize;
113
114 g_object_class_install_property (object_class,
115 PROP_PIXBUF,
116 g_param_spec_object ("pixbuf",
117 "pixbuf",
118 "the pixbuf for this image",
119 GDK_TYPE_PIXBUF,
120 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
121
122 g_object_class_install_property (object_class,
123 PROP_X_ALIGN,
124 g_param_spec_float ("x-align",
125 "x-align",
126 "image x-alignment",
127 0.0, /* minimum property value */
128 1.0, /* maximum property value */
129 0.5,
130 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
131
132 g_object_class_install_property (object_class,
133 PROP_Y_ALIGN,
134 g_param_spec_float ("y-align",
135 "y-align",
136 "image y-alignment",
137 0.0, /* minimum property value */
138 1.0, /* maximum property value */
139 0.5,
140 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
141
142 g_object_class_install_property (object_class,
143 PROP_POINT,
144 g_param_spec_boxed ("point",
145 "point",
146 "location point",
147 OSM_TYPE_GPS_MAP_POINT,
148 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
149 }
150
151 static void
152 osm_gps_map_image_init (OsmGpsMapImage *self)
153 {
154 self->priv = G_TYPE_INSTANCE_GET_PRIVATE ((self), OSM_TYPE_GPS_MAP_IMAGE, OsmGpsMapImagePrivate);
155 }
156
157 OsmGpsMapImage *
158 osm_gps_map_image_new (void)
159 {
160 return g_object_new (OSM_TYPE_GPS_MAP_IMAGE, NULL);
161 }
162
163 void
164 osm_gps_map_image_draw (OsmGpsMapImage *object, GdkDrawable *drawable, GdkGC *gc, GdkRectangle *rect)
165 {
166 OsmGpsMapImagePrivate *priv;
167 int xoffset, yoffset;
168
169 g_return_if_fail (OSM_IS_GPS_MAP_IMAGE (object));
170 priv = OSM_GPS_MAP_IMAGE(object)->priv;
171 xoffset = priv->xalign * priv->w;
172 yoffset = priv->yalign * priv->h;
173
174 gdk_draw_pixbuf (
175 drawable,
176 gc,
177 priv->pixbuf,
178 0,0,
179 rect->x - xoffset,
180 rect->y - yoffset,
181 priv->w,
182 priv->h,
183 GDK_RGB_DITHER_NONE, 0, 0);
184 rect->width = priv->w;
185 rect->height = priv->w;
186 }
187
188 const OsmGpsMapPoint *
189 osm_gps_map_image_get_point(OsmGpsMapImage *object)
190 {
191 g_return_val_if_fail (OSM_IS_GPS_MAP_IMAGE (object), NULL);
192 return object->priv->pt;
193 }
0 /* osm-gps-map-image.h */
1
2 #ifndef _OSM_GPS_MAP_IMAGE_H
3 #define _OSM_GPS_MAP_IMAGE_H
4
5 #include <glib-object.h>
6 #include <gdk/gdk.h>
7
8 #include "osm-gps-map-point.h"
9
10 G_BEGIN_DECLS
11
12 #define OSM_TYPE_GPS_MAP_IMAGE osm_gps_map_image_get_type()
13 #define OSM_GPS_MAP_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), OSM_TYPE_GPS_MAP_IMAGE, OsmGpsMapImage))
14 #define OSM_GPS_MAP_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), OSM_TYPE_GPS_MAP_IMAGE, OsmGpsMapImageClass))
15 #define OSM_IS_GPS_MAP_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OSM_TYPE_GPS_MAP_IMAGE))
16 #define OSM_IS_GPS_MAP_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OSM_TYPE_GPS_MAP_IMAGE))
17 #define OSM_GPS_MAP_IMAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OSM_TYPE_GPS_MAP_IMAGE, OsmGpsMapImageClass))
18
19 typedef struct _OsmGpsMapImage OsmGpsMapImage;
20 typedef struct _OsmGpsMapImageClass OsmGpsMapImageClass;
21 typedef struct _OsmGpsMapImagePrivate OsmGpsMapImagePrivate;
22
23 struct _OsmGpsMapImage
24 {
25 GObject parent;
26
27 OsmGpsMapImagePrivate *priv;
28 };
29
30 struct _OsmGpsMapImageClass
31 {
32 GObjectClass parent_class;
33 };
34
35 GType osm_gps_map_image_get_type (void) G_GNUC_CONST;
36
37 OsmGpsMapImage *osm_gps_map_image_new (void);
38 void osm_gps_map_image_draw (OsmGpsMapImage *object, GdkDrawable *drawable, GdkGC *gc, GdkRectangle *rect);
39 const OsmGpsMapPoint *osm_gps_map_image_get_point(OsmGpsMapImage *object);
40
41 G_END_DECLS
42
43 #endif /* _OSM_GPS_MAP_IMAGE_H */
3838 typedef struct _OsmGpsMapLayer OsmGpsMapLayer; /* dummy object */
3939 typedef struct _OsmGpsMapLayerIface OsmGpsMapLayerIface;
4040
41 #include "osm-gps-map.h"
41 #include "osm-gps-map-widget.h"
4242
4343 struct _OsmGpsMapLayerIface {
4444 GTypeInterface parent;
4545 typedef struct _OsdScale {
4646 cairo_surface_t *surface;
4747 int zoom;
48 float lat;
4849 } OsdScale_t;
4950
5051 typedef struct _OsdCoordinates {
246247 priv->scale = g_new0(OsdScale_t, 1);
247248 priv->scale->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, OSD_SCALE_W, OSD_SCALE_H);
248249 priv->scale->zoom = -1;
250 priv->scale->lat = 360.0; /* init to an invalid lat so we get re-rendered */
249251
250252 priv->coordinates = g_new0(OsdCoordinates_t, 1);
251253 priv->coordinates->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, OSD_COORDINATES_W, OSD_COORDINATES_H);
463465 cairo_t *cr;
464466 OsmGpsMapOsd *self;
465467 OsmGpsMapOsdPrivate *priv;
466 GtkAllocation *allocation;
468 GtkAllocation allocation;
467469
468470 g_return_if_fail(OSM_IS_GPS_MAP_OSD(osd));
469471
470472 self = OSM_GPS_MAP_OSD(osd);
471473 priv = self->priv;
472 allocation = &(GTK_WIDGET(map)->allocation);
473
474
475 gtk_widget_get_allocation(GTK_WIDGET(map), &allocation);
474476 cr = gdk_cairo_create(drawable);
475477
476478 if (priv->show_scale)
477 scale_draw(self, allocation, cr);
479 scale_draw(self, &allocation, cr);
478480 if (priv->show_coordinates)
479 coordinates_draw(self, allocation, cr);
481 coordinates_draw(self, &allocation, cr);
480482 if (priv->show_crosshair)
481 crosshair_draw(self, allocation, cr);
483 crosshair_draw(self, &allocation, cr);
482484 if (priv->show_zoom || priv->show_dpad)
483 controls_draw(self, allocation, cr);
485 controls_draw(self, &allocation, cr);
484486
485487 cairo_destroy(cr);
486488 }
500502 OsdControlPress_t but = OSD_NONE;
501503 OsmGpsMapOsd *self;
502504 OsmGpsMapOsdPrivate *priv;
503 GtkAllocation *allocation;
505 GtkAllocation allocation;
504506
505507 g_return_val_if_fail(OSM_IS_GPS_MAP_OSD(osd), FALSE);
506508
507509 self = OSM_GPS_MAP_OSD(osd);
508510 priv = self->priv;
509 allocation = &(GTK_WIDGET(map)->allocation);
511 gtk_widget_get_allocation(GTK_WIDGET(map), &allocation);
510512
511513 if ((event->button == 1) && (event->type == GDK_BUTTON_PRESS)) {
512514 gint mx = event->x - priv->osd_x;
513515 gint my = event->y - priv->osd_y;
514516
515517 if(priv->osd_x < 0)
516 mx -= (allocation->width - priv->osd_w);
518 mx -= (allocation.width - priv->osd_w);
517519
518520 if(priv->osd_y < 0)
519 my -= (allocation->height - priv->osd_h);
521 my -= (allocation.height - priv->osd_h);
520522
521523 /* first do a rough test for the OSD area. */
522524 /* this is just to avoid an unnecessary detailed test */
587589 if(!scale->surface)
588590 return;
589591
590 /* this only needs to be rendered if the zoom has changed */
592 /* this only needs to be rendered if the zoom or latitude has changed */
591593 gint zoom;
592 g_object_get(G_OBJECT(map), "zoom", &zoom, NULL);
593 if(zoom == scale->zoom)
594 gfloat lat;
595 g_object_get(G_OBJECT(map), "zoom", &zoom, "latitude", &lat, NULL);
596 if(zoom == scale->zoom && lat == scale->lat)
594597 return;
595598
596599 scale->zoom = zoom;
600 scale->lat = lat;
597601
598602 float m_per_pix = osm_gps_map_get_scale(map);
599603
851855
852856 controls->rendered = TRUE;
853857
854 GdkColor bg = GTK_WIDGET(map)->style->bg[GTK_STATE_NORMAL];
855 GdkColor fg = GTK_WIDGET(map)->style->fg[GTK_STATE_NORMAL];
858 GtkStyle *style = gtk_widget_get_style(GTK_WIDGET(map));
859 GdkColor bg = style->bg[GTK_STATE_NORMAL];
860 GdkColor fg = style->fg[GTK_STATE_NORMAL];
856861 //GdkColor da = GTK_WIDGET(map)->style->fg[GTK_STATE_INSENSITIVE];
857862
858863 /* first fill with transparency */
0 /* osm-gps-map-point.c */
1
2 #include "converter.h"
3 #include "osm-gps-map-point.h"
4
5 OsmGpsMapPoint *
6 osm_gps_map_point_new_degrees(float lat, float lon)
7 {
8 OsmGpsMapPoint *p = g_new0(OsmGpsMapPoint, 1);
9 p->rlat = deg2rad(lat);
10 p->rlon = deg2rad(lon);
11 return p;
12 }
13
14 OsmGpsMapPoint *
15 osm_gps_map_point_new_radians(float rlat, float rlon)
16 {
17 OsmGpsMapPoint *p = g_new0(OsmGpsMapPoint, 1);
18 p->rlat = rlat;
19 p->rlon = rlon;
20 return p;
21 }
22
23 void
24 osm_gps_map_point_get_degrees(OsmGpsMapPoint *point, float *lat, float *lon)
25 {
26 *lat = rad2deg(point->rlat);
27 *lon = rad2deg(point->rlon);
28 }
29
30 void
31 osm_gps_map_point_get_radians(OsmGpsMapPoint *point, float *rlat, float *rlon)
32 {
33 *rlat = point->rlat;
34 *rlon = point->rlon;
35 }
36
37 void
38 osm_gps_map_point_set_degrees(OsmGpsMapPoint *point, float lat, float lon)
39 {
40 point->rlat = deg2rad(lat);
41 point->rlon = deg2rad(lon);
42 }
43
44 void
45 osm_gps_map_point_set_radians(OsmGpsMapPoint *point, float rlat, float rlon)
46 {
47 point->rlat = rlat;
48 point->rlon = rlon;
49 }
50
51 static OsmGpsMapPoint *
52 osm_gps_map_point_copy (const OsmGpsMapPoint *point)
53 {
54 OsmGpsMapPoint *result = g_new (OsmGpsMapPoint, 1);
55 *result = *point;
56
57 return result;
58 }
59
60 GType
61 osm_gps_map_point_get_type (void)
62 {
63 static GType our_type = 0;
64
65 if (our_type == 0)
66 our_type = g_boxed_type_register_static (g_intern_static_string ("OsmGpsMapPoint"),
67 (GBoxedCopyFunc)osm_gps_map_point_copy,
68 (GBoxedFreeFunc)g_free);
69 return our_type;
70 }
0 /* osm-gps-map-point.h */
1
2 #ifndef _OSM_GPS_MAP_POINT_H
3 #define _OSM_GPS_MAP_POINT_H
4
5 #include <glib.h>
6 #include <glib-object.h>
7
8 G_BEGIN_DECLS
9
10 #define OSM_TYPE_GPS_MAP_POINT osm_gps_map_point_get_type()
11
12 typedef struct _OsmGpsMapPoint OsmGpsMapPoint;
13
14 struct _OsmGpsMapPoint
15 {
16 /* radians */
17 float rlat;
18 float rlon;
19 };
20
21 GType osm_gps_map_point_get_type (void) G_GNUC_CONST;
22
23 OsmGpsMapPoint * osm_gps_map_point_new_degrees (float lat, float lon);
24 OsmGpsMapPoint * osm_gps_map_point_new_radians (float rlat, float rlon);
25 void osm_gps_map_point_get_degrees (OsmGpsMapPoint *point, float *lat, float *lon);
26 void osm_gps_map_point_get_radians (OsmGpsMapPoint *point, float *rlat, float *rlon);
27 void osm_gps_map_point_set_degrees (OsmGpsMapPoint *point, float lat, float lon);
28 void osm_gps_map_point_set_radians (OsmGpsMapPoint *point, float rlat, float rlon);
29
30 G_END_DECLS
31
32 #endif /* _OSM_GPS_MAP_POINT_H */
0 #include "osm-gps-map-source.h"
1 #include "osm-gps-map-types.h"
2
3 const char*
4 osm_gps_map_source_get_friendly_name(OsmGpsMapSource_t source)
5 {
6 switch(source)
7 {
8 case OSM_GPS_MAP_SOURCE_NULL:
9 return "None";
10 case OSM_GPS_MAP_SOURCE_OPENSTREETMAP:
11 return "OpenStreetMap I";
12 case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER:
13 return "OpenStreetMap II";
14 case OSM_GPS_MAP_SOURCE_OPENAERIALMAP:
15 return "OpenAerialMap";
16 case OSM_GPS_MAP_SOURCE_OPENCYCLEMAP:
17 return "OpenCycleMap";
18 case OSM_GPS_MAP_SOURCE_OSM_PUBLIC_TRANSPORT:
19 return "Public Transport";
20 case OSM_GPS_MAP_SOURCE_OSMC_TRAILS:
21 return "OSMC Trails";
22 case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE:
23 return "Maps-For-Free";
24 case OSM_GPS_MAP_SOURCE_GOOGLE_STREET:
25 return "Google Maps";
26 case OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE:
27 return "Google Satellite";
28 case OSM_GPS_MAP_SOURCE_GOOGLE_HYBRID:
29 return "Google Hybrid";
30 case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_STREET:
31 return "Virtual Earth";
32 case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_SATELLITE:
33 return "Virtual Earth Satellite";
34 case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_HYBRID:
35 return "Virtual Earth Hybrid";
36 case OSM_GPS_MAP_SOURCE_YAHOO_STREET:
37 return "Yahoo Maps";
38 case OSM_GPS_MAP_SOURCE_YAHOO_SATELLITE:
39 return "Yahoo Satellite";
40 case OSM_GPS_MAP_SOURCE_YAHOO_HYBRID:
41 return "Yahoo Hybrid";
42 case OSM_GPS_MAP_SOURCE_LAST:
43 default:
44 return NULL;
45 }
46 return NULL;
47 }
48
49 //http://www.internettablettalk.com/forums/showthread.php?t=5209
50 //https://garage.maemo.org/plugins/scmsvn/viewcvs.php/trunk/src/maps.c?root=maemo-mapper&view=markup
51 //http://www.ponies.me.uk/maps/GoogleTileUtils.java
52 //http://www.mgmaps.com/cache/MapTileCacher.perl
53 const char*
54 osm_gps_map_source_get_repo_uri(OsmGpsMapSource_t source)
55 {
56 switch(source)
57 {
58 case OSM_GPS_MAP_SOURCE_NULL:
59 return "none://";
60 case OSM_GPS_MAP_SOURCE_OPENSTREETMAP:
61 return OSM_REPO_URI;
62 case OSM_GPS_MAP_SOURCE_OPENAERIALMAP:
63 /* OpenAerialMap is down, offline till furthur notice
64 http://openaerialmap.org/pipermail/talk_openaerialmap.org/2008-December/000055.html */
65 return NULL;
66 case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER:
67 return "http://tah.openstreetmap.org/Tiles/tile/#Z/#X/#Y.png";
68 case OSM_GPS_MAP_SOURCE_OPENCYCLEMAP:
69 return "http://c.andy.sandbox.cloudmade.com/tiles/cycle/#Z/#X/#Y.png";
70 case OSM_GPS_MAP_SOURCE_OSM_PUBLIC_TRANSPORT:
71 return "http://tile.xn--pnvkarte-m4a.de/tilegen/#Z/#X/#Y.png";
72 case OSM_GPS_MAP_SOURCE_OSMC_TRAILS:
73 return "http://topo.geofabrik.de/trails/#Z/#X/#Y.png";
74 case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE:
75 return "http://maps-for-free.com/layer/relief/z#Z/row#Y/#Z_#X-#Y.jpg";
76 case OSM_GPS_MAP_SOURCE_GOOGLE_STREET:
77 return "http://mt#R.google.com/vt/lyrs=m@126&hl=en&x=#X&s=&y=#Y&z=#Z";
78 case OSM_GPS_MAP_SOURCE_GOOGLE_HYBRID:
79 return "http://mt#R.google.com/vt/lyrs=h@126&hl=en&x=#X&s=&y=#Y&z=#Z";
80 case OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE:
81 return "http://khm#R.google.com/kh/v=61&x=#X&y=#Y&z=#Z";
82 case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_STREET:
83 return "http://a#R.ortho.tiles.virtualearth.net/tiles/r#W.jpeg?g=50";
84 case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_SATELLITE:
85 return "http://a#R.ortho.tiles.virtualearth.net/tiles/a#W.jpeg?g=50";
86 case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_HYBRID:
87 return "http://a#R.ortho.tiles.virtualearth.net/tiles/h#W.jpeg?g=50";
88 case OSM_GPS_MAP_SOURCE_YAHOO_STREET:
89 case OSM_GPS_MAP_SOURCE_YAHOO_SATELLITE:
90 case OSM_GPS_MAP_SOURCE_YAHOO_HYBRID:
91 /* TODO: Implement signed Y, aka U
92 * http://us.maps3.yimg.com/aerial.maps.yimg.com/ximg?v=1.7&t=a&s=256&x=%d&y=%-d&z=%d
93 * x = tilex,
94 * y = (1 << (MAX_ZOOM - zoom)) - tiley - 1,
95 * z = zoom - (MAX_ZOOM - 17));
96 */
97 return NULL;
98 case OSM_GPS_MAP_SOURCE_LAST:
99 default:
100 return NULL;
101 }
102 return NULL;
103 }
104
105 const char *
106 osm_gps_map_source_get_image_format(OsmGpsMapSource_t source)
107 {
108 switch(source) {
109 case OSM_GPS_MAP_SOURCE_NULL:
110 case OSM_GPS_MAP_SOURCE_OPENSTREETMAP:
111 case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER:
112 case OSM_GPS_MAP_SOURCE_OPENCYCLEMAP:
113 case OSM_GPS_MAP_SOURCE_OSM_PUBLIC_TRANSPORT:
114 case OSM_GPS_MAP_SOURCE_OSMC_TRAILS:
115 return "png";
116 case OSM_GPS_MAP_SOURCE_OPENAERIALMAP:
117 case OSM_GPS_MAP_SOURCE_GOOGLE_STREET:
118 case OSM_GPS_MAP_SOURCE_GOOGLE_HYBRID:
119 case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_STREET:
120 case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_SATELLITE:
121 case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_HYBRID:
122 case OSM_GPS_MAP_SOURCE_YAHOO_STREET:
123 case OSM_GPS_MAP_SOURCE_YAHOO_SATELLITE:
124 case OSM_GPS_MAP_SOURCE_YAHOO_HYBRID:
125 case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE:
126 case OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE:
127 return "jpg";
128 case OSM_GPS_MAP_SOURCE_LAST:
129 default:
130 return "bin";
131 }
132 return "bin";
133 }
134
135
136 int
137 osm_gps_map_source_get_min_zoom(OsmGpsMapSource_t source)
138 {
139 return 1;
140 }
141
142 int
143 osm_gps_map_source_get_max_zoom(OsmGpsMapSource_t source)
144 {
145 switch(source) {
146 case OSM_GPS_MAP_SOURCE_NULL:
147 return 18;
148 case OSM_GPS_MAP_SOURCE_OPENSTREETMAP:
149 case OSM_GPS_MAP_SOURCE_OPENCYCLEMAP:
150 case OSM_GPS_MAP_SOURCE_OSM_PUBLIC_TRANSPORT:
151 return OSM_MAX_ZOOM;
152 case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER:
153 case OSM_GPS_MAP_SOURCE_OPENAERIALMAP:
154 case OSM_GPS_MAP_SOURCE_GOOGLE_STREET:
155 case OSM_GPS_MAP_SOURCE_GOOGLE_HYBRID:
156 case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_STREET:
157 case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_SATELLITE:
158 case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_HYBRID:
159 case OSM_GPS_MAP_SOURCE_YAHOO_STREET:
160 case OSM_GPS_MAP_SOURCE_YAHOO_SATELLITE:
161 case OSM_GPS_MAP_SOURCE_YAHOO_HYBRID:
162 return 17;
163 case OSM_GPS_MAP_SOURCE_OSMC_TRAILS:
164 return 15;
165 case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE:
166 return 11;
167 case OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE:
168 return 18;
169 case OSM_GPS_MAP_SOURCE_LAST:
170 default:
171 return 17;
172 }
173 return 17;
174 }
175
176 gboolean
177 osm_gps_map_source_is_valid(OsmGpsMapSource_t source)
178 {
179 return osm_gps_map_source_get_repo_uri(source) != NULL;
180 }
181
0 #ifndef _OSM_GPS_MAP_SOURCE_H_
1 #define _OSM_GPS_MAP_SOURCE_H_
2
3 #include <glib.h>
4
5 G_BEGIN_DECLS
6
7 typedef enum {
8 OSM_GPS_MAP_SOURCE_NULL,
9 OSM_GPS_MAP_SOURCE_OPENSTREETMAP,
10 OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER,
11 OSM_GPS_MAP_SOURCE_OPENAERIALMAP,
12 OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE,
13 OSM_GPS_MAP_SOURCE_OPENCYCLEMAP,
14 OSM_GPS_MAP_SOURCE_OSM_PUBLIC_TRANSPORT,
15 OSM_GPS_MAP_SOURCE_GOOGLE_STREET,
16 OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE,
17 OSM_GPS_MAP_SOURCE_GOOGLE_HYBRID,
18 OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_STREET,
19 OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_SATELLITE,
20 OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_HYBRID,
21 OSM_GPS_MAP_SOURCE_YAHOO_STREET,
22 OSM_GPS_MAP_SOURCE_YAHOO_SATELLITE,
23 OSM_GPS_MAP_SOURCE_YAHOO_HYBRID,
24 OSM_GPS_MAP_SOURCE_OSMC_TRAILS,
25
26 OSM_GPS_MAP_SOURCE_LAST
27 } OsmGpsMapSource_t;
28
29 const char* osm_gps_map_source_get_friendly_name (OsmGpsMapSource_t source);
30 const char* osm_gps_map_source_get_repo_uri (OsmGpsMapSource_t source);
31 const char* osm_gps_map_source_get_image_format (OsmGpsMapSource_t source);
32 int osm_gps_map_source_get_min_zoom (OsmGpsMapSource_t source);
33 int osm_gps_map_source_get_max_zoom (OsmGpsMapSource_t source);
34 gboolean osm_gps_map_source_is_valid (OsmGpsMapSource_t source);
35
36 G_END_DECLS
37
38 #endif /* _OSM_GPS_MAP_SOURCE_H_ */
0 /* osm-gps-map-track.c */
1
2 #include <gdk/gdk.h>
3
4 #include "converter.h"
5 #include "osm-gps-map-track.h"
6
7 G_DEFINE_TYPE (OsmGpsMapTrack, osm_gps_map_track, G_TYPE_OBJECT)
8
9 enum
10 {
11 PROP_0,
12 PROP_VISIBLE,
13 PROP_TRACK,
14 PROP_LINE_WIDTH,
15 PROP_ALPHA,
16 PROP_COLOR
17 };
18
19 enum
20 {
21 POINT_ADDED,
22 LAST_SIGNAL
23 };
24
25 static guint signals[LAST_SIGNAL] = {0,};
26
27 struct _OsmGpsMapTrackPrivate
28 {
29 GSList *track;
30 gboolean visible;
31 gfloat linewidth;
32 gfloat alpha;
33 GdkColor color;
34 };
35
36 #define DEFAULT_R (60000)
37 #define DEFAULT_G (0)
38 #define DEFAULT_B (0)
39 #define DEFAULT_A (0.6)
40
41 static void
42 osm_gps_map_track_get_property (GObject *object,
43 guint property_id,
44 GValue *value,
45 GParamSpec *pspec)
46 {
47 OsmGpsMapTrackPrivate *priv = OSM_GPS_MAP_TRACK(object)->priv;
48
49 switch (property_id)
50 {
51 case PROP_VISIBLE:
52 g_value_set_boolean(value, priv->visible);
53 break;
54 case PROP_TRACK:
55 g_value_set_pointer(value, priv->track);
56 break;
57 case PROP_LINE_WIDTH:
58 g_value_set_float(value, priv->linewidth);
59 break;
60 case PROP_ALPHA:
61 g_value_set_float(value, priv->alpha);
62 break;
63 case PROP_COLOR:
64 g_value_set_boxed(value, &priv->color);
65 break;
66 default:
67 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
68 }
69 }
70
71 static void
72 osm_gps_map_track_set_property (GObject *object,
73 guint property_id,
74 const GValue *value,
75 GParamSpec *pspec)
76 {
77 OsmGpsMapTrackPrivate *priv = OSM_GPS_MAP_TRACK(object)->priv;
78
79 switch (property_id)
80 {
81 case PROP_VISIBLE:
82 priv->visible = g_value_get_boolean (value);
83 break;
84 case PROP_TRACK:
85 priv->track = g_value_get_pointer (value);
86 break;
87 case PROP_LINE_WIDTH:
88 priv->linewidth = g_value_get_float (value);
89 break;
90 case PROP_ALPHA:
91 priv->alpha = g_value_get_float (value);
92 break;
93 case PROP_COLOR: {
94 GdkColor *c = g_value_get_boxed (value);
95 priv->color.red = c->red;
96 priv->color.green = c->green;
97 priv->color.blue = c->blue;
98 } break;
99 default:
100 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
101 }
102 }
103
104 static void
105 osm_gps_map_track_dispose (GObject *object)
106 {
107 g_return_if_fail (OSM_IS_GPS_MAP_TRACK (object));
108 OsmGpsMapTrackPrivate *priv = OSM_GPS_MAP_TRACK(object)->priv;
109
110 if (priv->track) {
111 g_slist_foreach(priv->track, (GFunc) g_free, NULL);
112 g_slist_free(priv->track);
113 priv->track = NULL;
114 }
115
116 G_OBJECT_CLASS (osm_gps_map_track_parent_class)->dispose (object);
117 }
118
119 static void
120 osm_gps_map_track_finalize (GObject *object)
121 {
122 G_OBJECT_CLASS (osm_gps_map_track_parent_class)->finalize (object);
123 }
124
125 static void
126 osm_gps_map_track_class_init (OsmGpsMapTrackClass *klass)
127 {
128 GObjectClass *object_class = G_OBJECT_CLASS (klass);
129
130 g_type_class_add_private (klass, sizeof (OsmGpsMapTrackPrivate));
131
132 object_class->get_property = osm_gps_map_track_get_property;
133 object_class->set_property = osm_gps_map_track_set_property;
134 object_class->dispose = osm_gps_map_track_dispose;
135 object_class->finalize = osm_gps_map_track_finalize;
136
137 g_object_class_install_property (object_class,
138 PROP_VISIBLE,
139 g_param_spec_boolean ("visible",
140 "visible",
141 "should this track be visible",
142 TRUE,
143 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
144
145 g_object_class_install_property (object_class,
146 PROP_TRACK,
147 g_param_spec_pointer ("track",
148 "track",
149 "list of points for the track",
150 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
151
152 g_object_class_install_property (object_class,
153 PROP_LINE_WIDTH,
154 g_param_spec_float ("line-width",
155 "line-width",
156 "width of the lines drawn for the track",
157 0.0, /* minimum property value */
158 100.0, /* maximum property value */
159 4.0,
160 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
161
162 g_object_class_install_property (object_class,
163 PROP_ALPHA,
164 g_param_spec_float ("alpha",
165 "alpha",
166 "alpha transparency of the track",
167 0.0, /* minimum property value */
168 1.0, /* maximum property value */
169 DEFAULT_A,
170 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
171
172 g_object_class_install_property (object_class,
173 PROP_COLOR,
174 g_param_spec_boxed ("color",
175 "color",
176 "color of the track",
177 GDK_TYPE_COLOR,
178 G_PARAM_READABLE | G_PARAM_WRITABLE));
179
180 /**
181 * OsmGpsMapTrack::point-added:
182 * @self: A #OsmGpsMapTrack
183 *
184 * The point-added signal.
185 */
186 signals [POINT_ADDED] = g_signal_new ("point-added",
187 OSM_TYPE_GPS_MAP_TRACK,
188 G_SIGNAL_RUN_FIRST,
189 0,
190 NULL,
191 NULL,
192 g_cclosure_marshal_VOID__BOXED,
193 G_TYPE_NONE,
194 1,
195 OSM_TYPE_GPS_MAP_POINT);
196 }
197
198 static void
199 osm_gps_map_track_init (OsmGpsMapTrack *self)
200 {
201 self->priv = G_TYPE_INSTANCE_GET_PRIVATE((self), OSM_TYPE_GPS_MAP_TRACK, OsmGpsMapTrackPrivate);
202
203 self->priv->color.red = DEFAULT_R;
204 self->priv->color.green = DEFAULT_G;
205 self->priv->color.blue = DEFAULT_B;
206 }
207
208 void
209 osm_gps_map_track_add_point (OsmGpsMapTrack *track, OsmGpsMapPoint *point)
210 {
211 g_return_if_fail (OSM_IS_GPS_MAP_TRACK (track));
212 OsmGpsMapTrackPrivate *priv = track->priv;
213
214 priv->track = g_slist_append (priv->track, point);
215 g_signal_emit (track, signals[POINT_ADDED], 0, point);
216 }
217
218 GSList *
219 osm_gps_map_track_get_points (OsmGpsMapTrack *track)
220 {
221 g_return_val_if_fail (OSM_IS_GPS_MAP_TRACK (track), NULL);
222 return track->priv->track;
223 }
224
225 void
226 osm_gps_map_track_get_color (OsmGpsMapTrack *track, GdkColor *color)
227 {
228 g_return_if_fail (OSM_IS_GPS_MAP_TRACK (track));
229 color->red = track->priv->color.red;
230 color->green = track->priv->color.green;
231 color->blue = track->priv->color.blue;
232 }
233
234
235 OsmGpsMapTrack *
236 osm_gps_map_track_new (void)
237 {
238 return g_object_new (OSM_TYPE_GPS_MAP_TRACK, NULL);
239 }
240
0 /* osm-gps-map-track.h */
1
2 #ifndef _OSM_GPS_MAP_TRACK_H
3 #define _OSM_GPS_MAP_TRACK_H
4
5 #include <glib.h>
6 #include <glib-object.h>
7 #include <gdk/gdk.h>
8
9 #include "osm-gps-map-point.h"
10
11 G_BEGIN_DECLS
12
13 #define OSM_TYPE_GPS_MAP_TRACK osm_gps_map_track_get_type()
14 #define OSM_GPS_MAP_TRACK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), OSM_TYPE_GPS_MAP_TRACK, OsmGpsMapTrack))
15 #define OSM_GPS_MAP_TRACK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), OSM_TYPE_GPS_MAP_TRACK, OsmGpsMapTrackClass))
16 #define OSM_IS_GPS_MAP_TRACK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OSM_TYPE_GPS_MAP_TRACK))
17 #define OSM_IS_GPS_MAP_TRACK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OSM_TYPE_GPS_MAP_TRACK))
18 #define OSM_GPS_MAP_TRACK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OSM_TYPE_GPS_MAP_TRACK, OsmGpsMapTrackClass))
19
20 typedef struct _OsmGpsMapTrack OsmGpsMapTrack;
21 typedef struct _OsmGpsMapTrackClass OsmGpsMapTrackClass;
22 typedef struct _OsmGpsMapTrackPrivate OsmGpsMapTrackPrivate;
23
24 struct _OsmGpsMapTrack
25 {
26 GObject parent;
27
28 OsmGpsMapTrackPrivate *priv;
29 };
30
31 struct _OsmGpsMapTrackClass
32 {
33 GObjectClass parent_class;
34 };
35
36 GType osm_gps_map_track_get_type (void) G_GNUC_CONST;
37
38 OsmGpsMapTrack * osm_gps_map_track_new (void);
39 void osm_gps_map_track_add_point (OsmGpsMapTrack *track, OsmGpsMapPoint *point);
40 GSList * osm_gps_map_track_get_points (OsmGpsMapTrack *track);
41 void osm_gps_map_track_get_color (OsmGpsMapTrack *track, GdkColor *color);
42
43 G_END_DECLS
44
45 #endif /* _OSM_GPS_MAP_TRACK_H */
2323 #ifndef _OSM_GPS_MAP_TYPES_H_
2424 #define _OSM_GPS_MAP_TYPES_H_
2525
26 #include "config.h"
27
26 #include <glib.h>
2827 #include <gdk/gdk.h>
28 #include <gtk/gtk.h>
2929 #if USE_LIBSOUP22
3030 #include <libsoup/soup.h>
3131 #endif
32 #include "osm-gps-map.h"
32 #include "osm-gps-map-widget.h"
3333
3434 #define TILESIZE 256
3535 #define MAX_ZOOM 20
6363 /* equatorial radius in meters */
6464 #define OSM_EQ_RADIUS (6378137.0)
6565
66 typedef struct {
67 int x1;
68 int y1;
69 int x2;
70 int y2;
71 } bbox_pixel_t;
66 #if !GLIB_CHECK_VERSION (2, 16, 0)
67 int g_strcmp0(const char *str1, const char *str2)
68 {
69 if( str1 == NULL && str2 == NULL ) return 0;
70 if( str1 == NULL ) return -1;
71 if( str2 == NULL ) return 1;
72 return strcmp(str1, str2);
73 }
74 #endif
7275
73 typedef struct {
74 /* The details of the tile to download */
75 char *uri;
76 char *folder;
77 char *filename;
78 OsmGpsMap *map;
79 /* whether to redraw the map when the tile arrives */
80 gboolean redraw;
81 #if USE_LIBSOUP22
82 SoupSession *session;
83 #endif
84 } tile_download_t;
76 #if !GTK_CHECK_VERSION (2, 20, 0)
77 #define gtk_widget_get_realized(widget) (GTK_WIDGET_REALIZED (widget))
78 #define gtk_widget_get_mapped(widget) (GTK_WIDGET_MAPPED (widget))
79 #endif /* GTK < 2.20.0 */
8580
86 typedef struct {
87 int x;
88 int y;
89 int zoom;
90 } tile_t;
91
92 typedef struct {
93 coord_t pt;
94 GdkPixbuf *image;
95 int w;
96 int h;
97 int xoffset;
98 int yoffset;
99 } image_t;
81 #if !GTK_CHECK_VERSION (2, 18, 0)
82 #define gtk_cell_renderer_get_alignment(cell, xalign, yalign) g_object_get (cell, "xalign", xalign, "yalign", yalign, NULL);
83 #define gtk_cell_renderer_get_padding(cell, xpad, ypad) g_object_get (cell, "xpad", xpad, "ypad", ypad, NULL);
84 #define gtk_cell_renderer_set_padding(cell, xpad, ypad) g_object_set (cell, "xpad", xpad, "ypad", ypad, NULL);
85 #define gtk_widget_get_allocation(widget, alloc) (*(alloc) = (widget)->allocation)
86 #define gtk_widget_set_allocation(widget, alloc) ((widget)->allocation = *(alloc))
87 #define gtk_widget_get_app_paintable(widget) (GTK_WIDGET_APP_PAINTABLE (widget))
88 #define gtk_widget_set_can_default(widget, can_default) ((can_default) ? (GTK_WIDGET_SET_FLAGS (w, GTK_CAN_DEFAULT)) : (GTK_WIDGET_UNSET_FLAGS (w, GTK_CAN_DEFAULT)))
89 #define gtk_widget_set_can_focus(widget, can_focus) ((can_focus) ? (GTK_WIDGET_SET_FLAGS (w, GTK_CAN_FOCUS)) : (GTK_WIDGET_UNSET_FLAGS (w, GTK_CAN_FOCUS)))
90 #define gtk_widget_set_double_buffered(widget, double_buffered) ((double_buffered) ? (GTK_WIDGET_SET_FLAGS (w, GTK_DOUBLE_BUFFERED)) : (GTK_WIDGET_UNSET_FLAGS (w, GTK_DOUBLE_BUFFERED)))
91 #define gtk_widget_is_drawable(widget) (GTK_WIDGET_DRAWABLE (widget))
92 #define gtk_widget_has_focus(widget) (GTK_WIDGET_HAS_FOCUS (widget))
93 #define gtk_widget_get_has_window(widget) (!GTK_WIDGET_NO_WINDOW (widget))
94 #define gtk_widget_get_state(widget) ((widget)->state)
95 #define gtk_widget_get_visible(widget) (GTK_WIDGET_VISIBLE (widget))
96 #define gtk_widget_set_window(widget, _window) ((widget)->window = _window)
97 #endif /* GTK+ < 2.18.0 */
10098
10199 #endif /* _OSM_GPS_MAP_TYPES_H_ */
0 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */
1 /* vim:set et sw=4 ts=4 cino=t0,(0: */
2 /*
3 * osm-gps-map.c
4 * Copyright (C) Marcus Bauer 2008 <marcus.bauer@gmail.com>
5 * Copyright (C) John Stowers 2009 <john.stowers@gmail.com>
6 * Copyright (C) Till Harbaum 2009 <till@harbaum.org>
7 *
8 * Contributions by
9 * Everaldo Canuto 2009 <everaldo.canuto@gmail.com>
10 *
11 * osm-gps-map.c is free software: you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; version 2.
14 *
15 * This program 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.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "config.h"
25
26 #include <fcntl.h>
27 #include <math.h>
28 #include <unistd.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include <gdk/gdk.h>
34 #include <glib.h>
35 #include <glib/gstdio.h>
36 #include <glib/gprintf.h>
37 #include <libsoup/soup.h>
38 #include <cairo.h>
39
40 #include "converter.h"
41 #include "osm-gps-map-source.h"
42 #include "osm-gps-map-types.h"
43 #include "osm-gps-map-widget.h"
44 #include "osm-gps-map-compat.h"
45
46 #define ENABLE_DEBUG (0)
47 #define EXTRA_BORDER (TILESIZE / 2)
48 #define OSM_GPS_MAP_SCROLL_STEP (10)
49 #define USER_AGENT "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11"
50
51 struct _OsmGpsMapPrivate
52 {
53 GHashTable *tile_queue;
54 GHashTable *missing_tiles;
55 GHashTable *tile_cache;
56
57 int map_zoom;
58 int max_zoom;
59 int min_zoom;
60 int map_x;
61 int map_y;
62
63 /* Controls auto centering the map when a new GPS position arrives */
64 gfloat map_auto_center_threshold;
65
66 /* Latitude and longitude of the center of the map, in radians */
67 gfloat center_rlat;
68 gfloat center_rlon;
69
70 guint max_tile_cache_size;
71 /* Incremented at each redraw */
72 guint redraw_cycle;
73 /* ID of the idle redraw operation */
74 guint idle_map_redraw;
75
76 //how we download tiles
77 SoupSession *soup_session;
78 char *proxy_uri;
79
80 //where downloaded tiles are cached
81 char *tile_dir;
82 char *tile_base_dir;
83 char *cache_dir;
84
85 //contains flags indicating the various special characters
86 //the uri string contains, that will be replaced when calculating
87 //the uri to download.
88 OsmGpsMapSource_t map_source;
89 char *repo_uri;
90 char *image_format;
91 int uri_format;
92
93 //gps tracking state
94 GSList *trip_history;
95 float gps_heading;
96
97 OsmGpsMapPoint *gps;
98 OsmGpsMapTrack *gps_track;
99 gboolean gps_track_used;
100
101 #ifdef OSD_DOUBLE_BUFFER
102 GdkPixmap *dbuf_pixmap;
103 #endif
104 //additional images or tracks added to the map
105 GSList *tracks;
106 GSList *images;
107
108 //Used for storing the joined tiles
109 GdkPixmap *pixmap;
110 GdkGC *gc_map;
111
112 //The tile painted when one cannot be found
113 GdkPixbuf *null_tile;
114
115 //A list of OsmGpsMapLayer* layers, such as the OSD
116 GSList *layers;
117
118 //For tracking click and drag
119 int drag_counter;
120 int drag_mouse_dx;
121 int drag_mouse_dy;
122 int drag_start_mouse_x;
123 int drag_start_mouse_y;
124 int drag_start_map_x;
125 int drag_start_map_y;
126 int drag_limit;
127 guint drag_expose_source;
128
129 /* for customizing the redering of the gps track */
130 int ui_gps_point_inner_radius;
131 int ui_gps_point_outer_radius;
132
133 /* For storing keybindings */
134 guint keybindings[OSM_GPS_MAP_KEY_MAX];
135
136 /* flags controlling which features are enabled */
137 guint keybindings_enabled : 1;
138 guint map_auto_download_enabled : 1;
139 guint map_auto_center_enabled : 1;
140 guint trip_history_record_enabled : 1;
141 guint trip_history_show_enabled : 1;
142 guint gps_point_enabled : 1;
143
144 /* state flags */
145 guint is_disposed : 1;
146 guint is_constructed : 1;
147 guint is_dragging : 1;
148 guint is_button_down : 1;
149 guint is_fullscreen : 1;
150 guint is_google : 1;
151 };
152
153 #define OSM_GPS_MAP_PRIVATE(o) (OSM_GPS_MAP (o)->priv)
154
155 typedef struct
156 {
157 GdkPixbuf *pixbuf;
158 /* We keep track of the number of the redraw cycle this tile was last used,
159 * so that osm_gps_map_purge_cache() can remove the older ones */
160 guint redraw_cycle;
161 } OsmCachedTile;
162
163 typedef struct {
164 /* The details of the tile to download */
165 char *uri;
166 char *folder;
167 char *filename;
168 OsmGpsMap *map;
169 /* whether to redraw the map when the tile arrives */
170 gboolean redraw;
171 #if USE_LIBSOUP22
172 SoupSession *session;
173 #endif
174 } OsmTileDownload;
175
176 enum
177 {
178 PROP_0,
179 PROP_AUTO_CENTER,
180 PROP_RECORD_TRIP_HISTORY,
181 PROP_SHOW_TRIP_HISTORY,
182 PROP_AUTO_DOWNLOAD,
183 PROP_REPO_URI,
184 PROP_PROXY_URI,
185 PROP_TILE_CACHE_DIR,
186 PROP_TILE_CACHE_BASE_DIR,
187 PROP_TILE_CACHE_DIR_IS_FULL_PATH,
188 PROP_ZOOM,
189 PROP_MAX_ZOOM,
190 PROP_MIN_ZOOM,
191 PROP_LATITUDE,
192 PROP_LONGITUDE,
193 PROP_MAP_X,
194 PROP_MAP_Y,
195 PROP_TILES_QUEUED,
196 PROP_GPS_TRACK_WIDTH,
197 PROP_GPS_POINT_R1,
198 PROP_GPS_POINT_R2,
199 PROP_MAP_SOURCE,
200 PROP_IMAGE_FORMAT,
201 PROP_DRAG_LIMIT,
202 PROP_AUTO_CENTER_THRESHOLD,
203 PROP_SHOW_GPS_POINT
204 };
205
206 G_DEFINE_TYPE (OsmGpsMap, osm_gps_map, GTK_TYPE_DRAWING_AREA);
207
208 /*
209 * Drawing function forward defintions
210 */
211 static gchar *replace_string(const gchar *src, const gchar *from, const gchar *to);
212 static gchar *replace_map_uri(OsmGpsMap *map, const gchar *uri, int zoom, int x, int y);
213 static void osm_gps_map_blit_tile(OsmGpsMap *map, GdkPixbuf *pixbuf, int offset_x, int offset_y);
214 #if USE_LIBSOUP22
215 static void osm_gps_map_tile_download_complete (SoupMessage *msg, gpointer user_data);
216 #else
217 static void osm_gps_map_tile_download_complete (SoupSession *session, SoupMessage *msg, gpointer user_data);
218 #endif
219 static void osm_gps_map_download_tile (OsmGpsMap *map, int zoom, int x, int y, gboolean redraw);
220 static void osm_gps_map_load_tile (OsmGpsMap *map, int zoom, int x, int y, int offset_x, int offset_y);
221 static void osm_gps_map_fill_tiles_pixel (OsmGpsMap *map);
222 static gboolean osm_gps_map_map_redraw (OsmGpsMap *map);
223 static void osm_gps_map_map_redraw_idle (OsmGpsMap *map);
224
225 static void
226 cached_tile_free (OsmCachedTile *tile)
227 {
228 g_object_unref (tile->pixbuf);
229 g_slice_free (OsmCachedTile, tile);
230 }
231
232 /*
233 * Description:
234 * Find and replace text within a string.
235 *
236 * Parameters:
237 * src (in) - pointer to source string
238 * from (in) - pointer to search text
239 * to (in) - pointer to replacement text
240 *
241 * Returns:
242 * Returns a pointer to dynamically-allocated memory containing string
243 * with occurences of the text pointed to by 'from' replaced by with the
244 * text pointed to by 'to'.
245 */
246 static gchar *
247 replace_string(const gchar *src, const gchar *from, const gchar *to)
248 {
249 size_t size = strlen(src) + 1;
250 size_t fromlen = strlen(from);
251 size_t tolen = strlen(to);
252
253 /* Allocate the first chunk with enough for the original string. */
254 gchar *value = g_malloc(size);
255
256
257 /* We need to return 'value', so let's make a copy to mess around with. */
258 gchar *dst = value;
259
260 if ( value != NULL )
261 {
262 for ( ;; )
263 {
264 /* Try to find the search text. */
265 const gchar *match = g_strstr_len(src, size, from);
266 if ( match != NULL )
267 {
268 gchar *temp;
269 /* Find out how many characters to copy up to the 'match'. */
270 size_t count = match - src;
271
272
273 /* Calculate the total size the string will be after the
274 * replacement is performed. */
275 size += tolen - fromlen;
276
277 temp = g_realloc(value, size);
278 if ( temp == NULL )
279 {
280 g_free(value);
281 return NULL;
282 }
283
284 /* we'll want to return 'value' eventually, so let's point it
285 * to the memory that we are now working with.
286 * And let's not forget to point to the right location in
287 * the destination as well. */
288 dst = temp + (dst - value);
289 value = temp;
290
291 /*
292 * Copy from the source to the point where we matched. Then
293 * move the source pointer ahead by the amount we copied. And
294 * move the destination pointer ahead by the same amount.
295 */
296 g_memmove(dst, src, count);
297 src += count;
298 dst += count;
299
300 /* Now copy in the replacement text 'to' at the position of
301 * the match. Adjust the source pointer by the text we replaced.
302 * Adjust the destination pointer by the amount of replacement
303 * text. */
304 g_memmove(dst, to, tolen);
305 src += fromlen;
306 dst += tolen;
307 }
308 else
309 {
310 /*
311 * Copy any remaining part of the string. This includes the null
312 * termination character.
313 */
314 strcpy(dst, src);
315 break;
316 }
317 }
318 }
319 return value;
320 }
321
322 static void
323 map_convert_coords_to_quadtree_string(OsmGpsMap *map, gint x, gint y, gint zoomlevel,
324 gchar *buffer, const gchar initial,
325 const gchar *const quadrant)
326 {
327 gchar *ptr = buffer;
328 gint n;
329
330 if (initial)
331 *ptr++ = initial;
332
333 for(n = zoomlevel-1; n >= 0; n--)
334 {
335 gint xbit = (x >> n) & 1;
336 gint ybit = (y >> n) & 1;
337 *ptr++ = quadrant[xbit + 2 * ybit];
338 }
339
340 *ptr++ = '\0';
341 }
342
343
344 static void
345 inspect_map_uri(OsmGpsMapPrivate *priv)
346 {
347 priv->uri_format = 0;
348 priv->is_google = FALSE;
349
350 if (g_strrstr(priv->repo_uri, URI_MARKER_X))
351 priv->uri_format |= URI_HAS_X;
352
353 if (g_strrstr(priv->repo_uri, URI_MARKER_Y))
354 priv->uri_format |= URI_HAS_Y;
355
356 if (g_strrstr(priv->repo_uri, URI_MARKER_Z))
357 priv->uri_format |= URI_HAS_Z;
358
359 if (g_strrstr(priv->repo_uri, URI_MARKER_S))
360 priv->uri_format |= URI_HAS_S;
361
362 if (g_strrstr(priv->repo_uri, URI_MARKER_Q))
363 priv->uri_format |= URI_HAS_Q;
364
365 if (g_strrstr(priv->repo_uri, URI_MARKER_Q0))
366 priv->uri_format |= URI_HAS_Q0;
367
368 if (g_strrstr(priv->repo_uri, URI_MARKER_YS))
369 priv->uri_format |= URI_HAS_YS;
370
371 if (g_strrstr(priv->repo_uri, URI_MARKER_R))
372 priv->uri_format |= URI_HAS_R;
373
374 if (g_strrstr(priv->repo_uri, "google.com"))
375 priv->is_google = TRUE;
376
377 g_debug("URI Format: 0x%X (google: %X)", priv->uri_format, priv->is_google);
378
379 }
380
381 static gchar *
382 replace_map_uri(OsmGpsMap *map, const gchar *uri, int zoom, int x, int y)
383 {
384 OsmGpsMapPrivate *priv = map->priv;
385 char *url;
386 unsigned int i;
387 char location[22];
388
389 i = 1;
390 url = g_strdup(uri);
391 while (i < URI_FLAG_END)
392 {
393 char *s = NULL;
394 char *old;
395
396 old = url;
397 switch(i & priv->uri_format)
398 {
399 case URI_HAS_X:
400 s = g_strdup_printf("%d", x);
401 url = replace_string(url, URI_MARKER_X, s);
402 break;
403 case URI_HAS_Y:
404 s = g_strdup_printf("%d", y);
405 url = replace_string(url, URI_MARKER_Y, s);
406 break;
407 case URI_HAS_Z:
408 s = g_strdup_printf("%d", zoom);
409 url = replace_string(url, URI_MARKER_Z, s);
410 break;
411 case URI_HAS_S:
412 s = g_strdup_printf("%d", priv->max_zoom-zoom);
413 url = replace_string(url, URI_MARKER_S, s);
414 break;
415 case URI_HAS_Q:
416 map_convert_coords_to_quadtree_string(map,x,y,zoom,location,'t',"qrts");
417 s = g_strdup_printf("%s", location);
418 url = replace_string(url, URI_MARKER_Q, s);
419 break;
420 case URI_HAS_Q0:
421 map_convert_coords_to_quadtree_string(map,x,y,zoom,location,'\0', "0123");
422 s = g_strdup_printf("%s", location);
423 url = replace_string(url, URI_MARKER_Q0, s);
424 //g_debug("FOUND " URI_MARKER_Q0);
425 break;
426 case URI_HAS_YS:
427 // s = g_strdup_printf("%d", y);
428 // url = replace_string(url, URI_MARKER_YS, s);
429 g_warning("FOUND " URI_MARKER_YS " NOT IMPLEMENTED");
430 // retval = g_strdup_printf(repo->url,
431 // tilex,
432 // (1 << (MAX_ZOOM - zoom)) - tiley - 1,
433 // zoom - (MAX_ZOOM - 17));
434 break;
435 case URI_HAS_R:
436 s = g_strdup_printf("%d", g_random_int_range(0,4));
437 url = replace_string(url, URI_MARKER_R, s);
438 break;
439 default:
440 s = NULL;
441 break;
442 }
443
444 if (s) {
445 g_free(s);
446 g_free(old);
447 }
448
449 i = (i << 1);
450
451 }
452
453 return url;
454 }
455
456 static void
457 my_log_handler (const gchar * log_domain, GLogLevelFlags log_level, const gchar * message, gpointer user_data)
458 {
459 if (!(log_level & G_LOG_LEVEL_DEBUG) || ENABLE_DEBUG)
460 g_log_default_handler (log_domain, log_level, message, user_data);
461 }
462
463 static float
464 osm_gps_map_get_scale_at_point(int zoom, float rlat, float rlon)
465 {
466 /* world at zoom 1 == 512 pixels */
467 return cos(rlat) * M_PI * OSM_EQ_RADIUS / (1<<(7+zoom));
468 }
469
470 static GSList *
471 gslist_remove_one_gobject(GSList **list, GObject *gobj)
472 {
473 GSList *data = g_slist_find(*list, gobj);
474 if (data) {
475 g_object_unref(gobj);
476 *list = g_slist_delete_link(*list, data);
477 }
478 return data;
479 }
480
481 static void
482 gslist_of_gobjects_free(GSList **list)
483 {
484 if (list) {
485 g_slist_foreach(*list, (GFunc) g_object_unref, NULL);
486 g_slist_free(*list);
487 *list = NULL;
488 }
489 }
490
491 static void
492 gslist_of_data_free (GSList **list)
493 {
494 if (list) {
495 g_slist_foreach(*list, (GFunc) g_free, NULL);
496 g_slist_free(*list);
497 *list = NULL;
498 }
499 }
500
501 static void
502 osm_gps_map_print_images (OsmGpsMap *map)
503 {
504 GSList *list;
505 int min_x = 0,min_y = 0,max_x = 0,max_y = 0;
506 int map_x0, map_y0;
507 OsmGpsMapPrivate *priv = map->priv;
508
509 map_x0 = priv->map_x - EXTRA_BORDER;
510 map_y0 = priv->map_y - EXTRA_BORDER;
511 for(list = priv->images; list != NULL; list = list->next)
512 {
513 GdkRectangle loc;
514 OsmGpsMapImage *im = OSM_GPS_MAP_IMAGE(list->data);
515 const OsmGpsMapPoint *pt = osm_gps_map_image_get_point(im);
516
517 /* pixel_x,y, offsets */
518 loc.x = lon2pixel(priv->map_zoom, pt->rlon) - map_x0;
519 loc.y = lat2pixel(priv->map_zoom, pt->rlat) - map_y0;
520
521 osm_gps_map_image_draw (
522 im,
523 priv->pixmap,
524 priv->gc_map,
525 &loc);
526
527 max_x = MAX(loc.x + loc.width, max_x);
528 min_x = MIN(loc.x - loc.width, min_x);
529 max_y = MAX(loc.y + loc.height, max_y);
530 min_y = MIN(loc.y - loc.height, min_y);
531 }
532
533 gtk_widget_queue_draw_area (
534 GTK_WIDGET(map),
535 min_x + EXTRA_BORDER, min_y + EXTRA_BORDER,
536 max_x + EXTRA_BORDER, max_y + EXTRA_BORDER);
537
538 }
539
540 static void
541 osm_gps_map_draw_gps_point (OsmGpsMap *map, GdkDrawable *drawable)
542 {
543 OsmGpsMapPrivate *priv = map->priv;
544 cairo_t *cr;
545 int map_x0, map_y0;
546 int x, y;
547 int r, r2, mr;
548
549 r = priv->ui_gps_point_inner_radius;
550 r2 = priv->ui_gps_point_outer_radius;
551 mr = MAX(3*r,r2);
552 map_x0 = priv->map_x - EXTRA_BORDER;
553 map_y0 = priv->map_y - EXTRA_BORDER;
554 x = lon2pixel(priv->map_zoom, priv->gps->rlon) - map_x0;
555 y = lat2pixel(priv->map_zoom, priv->gps->rlat) - map_y0;
556
557 cr = gdk_cairo_create(drawable);
558
559 /* draw transparent area */
560 if (r2 > 0) {
561 cairo_set_line_width (cr, 1.5);
562 cairo_set_source_rgba (cr, 0.75, 0.75, 0.75, 0.4);
563 cairo_arc (cr, x, y, r2, 0, 2 * M_PI);
564 cairo_fill (cr);
565 /* draw transparent area border */
566 cairo_set_source_rgba (cr, 0.55, 0.55, 0.55, 0.4);
567 cairo_arc (cr, x, y, r2, 0, 2 * M_PI);
568 cairo_stroke(cr);
569 }
570
571 /* draw ball gradient */
572 if (r > 0) {
573 cairo_pattern_t *pat;
574 /* draw direction arrow */
575 if(!isnan(priv->gps_heading)) {
576 cairo_move_to (cr, x-r*cos(priv->gps_heading), y-r*sin(priv->gps_heading));
577 cairo_line_to (cr, x+3*r*sin(priv->gps_heading), y-3*r*cos(priv->gps_heading));
578 cairo_line_to (cr, x+r*cos(priv->gps_heading), y+r*sin(priv->gps_heading));
579 cairo_close_path (cr);
580
581 cairo_set_source_rgba (cr, 0.3, 0.3, 1.0, 0.5);
582 cairo_fill_preserve (cr);
583
584 cairo_set_line_width (cr, 1.0);
585 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.5);
586 cairo_stroke(cr);
587 }
588
589 pat = cairo_pattern_create_radial (x-(r/5), y-(r/5), (r/5), x, y, r);
590 cairo_pattern_add_color_stop_rgba (pat, 0, 1, 1, 1, 1.0);
591 cairo_pattern_add_color_stop_rgba (pat, 1, 0, 0, 1, 1.0);
592 cairo_set_source (cr, pat);
593 cairo_arc (cr, x, y, r, 0, 2 * M_PI);
594 cairo_fill (cr);
595 cairo_pattern_destroy (pat);
596 /* draw ball border */
597 cairo_set_line_width (cr, 1.0);
598 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
599 cairo_arc (cr, x, y, r, 0, 2 * M_PI);
600 cairo_stroke(cr);
601 }
602
603 cairo_destroy(cr);
604 gtk_widget_queue_draw_area (GTK_WIDGET(map),
605 x-mr,
606 y-mr,
607 mr*2,
608 mr*2);
609 }
610
611 static void
612 osm_gps_map_blit_tile(OsmGpsMap *map, GdkPixbuf *pixbuf, int offset_x, int offset_y)
613 {
614 OsmGpsMapPrivate *priv = map->priv;
615
616 g_debug("Queing redraw @ %d,%d (w:%d h:%d)", offset_x,offset_y, TILESIZE,TILESIZE);
617
618 /* draw pixbuf onto pixmap */
619 gdk_draw_pixbuf (priv->pixmap,
620 priv->gc_map,
621 pixbuf,
622 0,0,
623 offset_x,offset_y,
624 TILESIZE,TILESIZE,
625 GDK_RGB_DITHER_NONE, 0, 0);
626 }
627
628 /* libsoup-2.2 and libsoup-2.4 use different ways to store the body data */
629 #if USE_LIBSOUP22
630 #define soup_message_headers_append(a,b,c) soup_message_add_header(a,b,c)
631 #define MSG_RESPONSE_BODY(a) ((a)->response.body)
632 #define MSG_RESPONSE_LEN(a) ((a)->response.length)
633 #define MSG_RESPONSE_LEN_FORMAT "%u"
634 #else
635 #define MSG_RESPONSE_BODY(a) ((a)->response_body->data)
636 #define MSG_RESPONSE_LEN(a) ((a)->response_body->length)
637 #define MSG_RESPONSE_LEN_FORMAT "%lld"
638 #endif
639
640 #if USE_LIBSOUP22
641 static void
642 osm_gps_map_tile_download_complete (SoupMessage *msg, gpointer user_data)
643 #else
644 static void
645 osm_gps_map_tile_download_complete (SoupSession *session, SoupMessage *msg, gpointer user_data)
646 #endif
647 {
648 FILE *file;
649 OsmTileDownload *dl = (OsmTileDownload *)user_data;
650 OsmGpsMap *map = OSM_GPS_MAP(dl->map);
651 OsmGpsMapPrivate *priv = map->priv;
652 gboolean file_saved = FALSE;
653
654 if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
655 /* save tile into cachedir if one has been specified */
656 if (priv->cache_dir) {
657 if (g_mkdir_with_parents(dl->folder,0700) == 0) {
658 file = g_fopen(dl->filename, "wb");
659 if (file != NULL) {
660 fwrite (MSG_RESPONSE_BODY(msg), 1, MSG_RESPONSE_LEN(msg), file);
661 file_saved = TRUE;
662 g_debug("Wrote "MSG_RESPONSE_LEN_FORMAT" bytes to %s", MSG_RESPONSE_LEN(msg), dl->filename);
663 fclose (file);
664
665 }
666 } else {
667 g_warning("Error creating tile download directory: %s", dl->folder);
668 perror("perror:");
669 }
670 }
671
672 if (dl->redraw) {
673 GdkPixbuf *pixbuf = NULL;
674
675 /* if the file was actually stored on disk, we can simply */
676 /* load and decode it from that file */
677 if (priv->cache_dir) {
678 if (file_saved) {
679 pixbuf = gdk_pixbuf_new_from_file (dl->filename, NULL);
680 }
681 } else {
682 GdkPixbufLoader *loader;
683 char *extension = strrchr (dl->filename, '.');
684
685 /* parse file directly from memory */
686 if (extension) {
687 loader = gdk_pixbuf_loader_new_with_type (extension+1, NULL);
688 if (!gdk_pixbuf_loader_write (loader, (unsigned char*)MSG_RESPONSE_BODY(msg), MSG_RESPONSE_LEN(msg), NULL))
689 {
690 g_warning("Error: Decoding of image failed");
691 }
692 gdk_pixbuf_loader_close(loader, NULL);
693
694 pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
695
696 /* give up loader but keep the pixbuf */
697 g_object_ref(pixbuf);
698 g_object_unref(loader);
699 } else {
700 g_warning("Error: Unable to determine image file format");
701 }
702 }
703
704 /* Store the tile into the cache */
705 if (G_LIKELY (pixbuf)) {
706 OsmCachedTile *tile = g_slice_new (OsmCachedTile);
707 tile->pixbuf = pixbuf;
708 tile->redraw_cycle = priv->redraw_cycle;
709 /* if the tile is already in the cache (it could be one
710 * rendered from another zoom level), it will be
711 * overwritten */
712 g_hash_table_insert (priv->tile_cache, dl->filename, tile);
713 /* NULL-ify dl->filename so that it won't be freed, as
714 * we are using it as a key in the hash table */
715 dl->filename = NULL;
716 }
717 osm_gps_map_map_redraw_idle (map);
718 }
719 g_hash_table_remove(priv->tile_queue, dl->uri);
720 g_object_notify(G_OBJECT(map), "tiles-queued");
721
722 g_free(dl->folder);
723 g_free(dl->filename);
724 g_free(dl);
725 } else {
726 if (msg->status_code == SOUP_STATUS_NOT_FOUND) {
727 g_hash_table_insert(priv->missing_tiles, dl->uri, NULL);
728 g_hash_table_remove(priv->tile_queue, dl->uri);
729 g_object_notify(G_OBJECT(map), "tiles-queued");
730 } else if (msg->status_code == SOUP_STATUS_CANCELLED) {
731 /* called as application exit or after osm_gps_map_download_cancel_all */
732 g_hash_table_remove(priv->tile_queue, dl->uri);
733 g_object_notify(G_OBJECT(map), "tiles-queued");
734 } else {
735 g_warning("Error downloading tile: %d - %s", msg->status_code, msg->reason_phrase);
736 #if USE_LIBSOUP22
737 soup_session_requeue_message(dl->session, msg);
738 #else
739 soup_session_requeue_message(session, msg);
740 #endif
741 return;
742 }
743 }
744
745
746 }
747
748 static void
749 osm_gps_map_download_tile (OsmGpsMap *map, int zoom, int x, int y, gboolean redraw)
750 {
751 SoupMessage *msg;
752 OsmGpsMapPrivate *priv = map->priv;
753 OsmTileDownload *dl = g_new0(OsmTileDownload,1);
754
755 //calculate the uri to download
756 dl->uri = replace_map_uri(map, priv->repo_uri, zoom, x, y);
757
758 #if USE_LIBSOUP22
759 dl->session = priv->soup_session;
760 #endif
761
762 //check the tile has not already been queued for download,
763 //or has been attempted, and its missing
764 if (g_hash_table_lookup_extended(priv->tile_queue, dl->uri, NULL, NULL) ||
765 g_hash_table_lookup_extended(priv->missing_tiles, dl->uri, NULL, NULL) )
766 {
767 g_debug("Tile already downloading (or missing)");
768 g_free(dl->uri);
769 g_free(dl);
770 } else {
771 dl->folder = g_strdup_printf("%s%c%d%c%d%c",
772 priv->cache_dir, G_DIR_SEPARATOR,
773 zoom, G_DIR_SEPARATOR,
774 x, G_DIR_SEPARATOR);
775 dl->filename = g_strdup_printf("%s%c%d%c%d%c%d.%s",
776 priv->cache_dir, G_DIR_SEPARATOR,
777 zoom, G_DIR_SEPARATOR,
778 x, G_DIR_SEPARATOR,
779 y,
780 priv->image_format);
781 dl->map = map;
782 dl->redraw = redraw;
783
784 g_debug("Download tile: %d,%d z:%d\n\t%s --> %s", x, y, zoom, dl->uri, dl->filename);
785
786 msg = soup_message_new (SOUP_METHOD_GET, dl->uri);
787 if (msg) {
788 if (priv->is_google) {
789 //Set maps.google.com as the referrer
790 g_debug("Setting Google Referrer");
791 soup_message_headers_append(msg->request_headers, "Referer", "http://maps.google.com/");
792 //For google satelite also set the appropriate cookie value
793 if (priv->uri_format & URI_HAS_Q) {
794 const char *cookie = g_getenv("GOOGLE_COOKIE");
795 if (cookie) {
796 g_debug("Adding Google Cookie");
797 soup_message_headers_append(msg->request_headers, "Cookie", cookie);
798 }
799 }
800 }
801
802 #if USE_LIBSOUP22
803 soup_message_headers_append(msg->request_headers,
804 "User-Agent", USER_AGENT);
805 #endif
806
807 g_hash_table_insert (priv->tile_queue, dl->uri, msg);
808 g_object_notify (G_OBJECT (map), "tiles-queued");
809 /* the soup session unrefs the message when the download finishes */
810 soup_session_queue_message (priv->soup_session, msg, osm_gps_map_tile_download_complete, dl);
811 } else {
812 g_warning("Could not create soup message");
813 g_free(dl->uri);
814 g_free(dl->folder);
815 g_free(dl->filename);
816 g_free(dl);
817 }
818 }
819 }
820
821 static GdkPixbuf *
822 osm_gps_map_load_cached_tile (OsmGpsMap *map, int zoom, int x, int y)
823 {
824 OsmGpsMapPrivate *priv = map->priv;
825 gchar *filename;
826 GdkPixbuf *pixbuf = NULL;
827 OsmCachedTile *tile;
828
829 filename = g_strdup_printf("%s%c%d%c%d%c%d.%s",
830 priv->cache_dir, G_DIR_SEPARATOR,
831 zoom, G_DIR_SEPARATOR,
832 x, G_DIR_SEPARATOR,
833 y,
834 priv->image_format);
835
836 tile = g_hash_table_lookup (priv->tile_cache, filename);
837 if (tile)
838 {
839 g_free (filename);
840 }
841 else
842 {
843 pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
844 if (pixbuf)
845 {
846 tile = g_slice_new (OsmCachedTile);
847 tile->pixbuf = pixbuf;
848 g_hash_table_insert (priv->tile_cache, filename, tile);
849 }
850 else
851 {
852 g_free (filename);
853 }
854 }
855
856 /* set/update the redraw_cycle timestamp on the tile */
857 if (tile)
858 {
859 tile->redraw_cycle = priv->redraw_cycle;
860 pixbuf = g_object_ref (tile->pixbuf);
861 }
862
863 return pixbuf;
864 }
865
866 static GdkPixbuf *
867 osm_gps_map_find_bigger_tile (OsmGpsMap *map, int zoom, int x, int y,
868 int *zoom_found)
869 {
870 GdkPixbuf *pixbuf;
871 int next_zoom, next_x, next_y;
872
873 if (zoom == 0) return NULL;
874 next_zoom = zoom - 1;
875 next_x = x / 2;
876 next_y = y / 2;
877 pixbuf = osm_gps_map_load_cached_tile (map, next_zoom, next_x, next_y);
878 if (pixbuf)
879 *zoom_found = next_zoom;
880 else
881 pixbuf = osm_gps_map_find_bigger_tile (map, next_zoom, next_x, next_y,
882 zoom_found);
883 return pixbuf;
884 }
885
886 static GdkPixbuf *
887 osm_gps_map_render_missing_tile_upscaled (OsmGpsMap *map, int zoom,
888 int x, int y)
889 {
890 GdkPixbuf *pixbuf, *big, *area;
891 int zoom_big, zoom_diff, area_size, area_x, area_y;
892 int modulo;
893
894 big = osm_gps_map_find_bigger_tile (map, zoom, x, y, &zoom_big);
895 if (!big) return NULL;
896
897 g_debug ("Found bigger tile (zoom = %d, wanted = %d)", zoom_big, zoom);
898
899 /* get a Pixbuf for the area to magnify */
900 zoom_diff = zoom - zoom_big;
901 area_size = TILESIZE >> zoom_diff;
902 modulo = 1 << zoom_diff;
903 area_x = (x % modulo) * area_size;
904 area_y = (y % modulo) * area_size;
905 area = gdk_pixbuf_new_subpixbuf (big, area_x, area_y,
906 area_size, area_size);
907 g_object_unref (big);
908 pixbuf = gdk_pixbuf_scale_simple (area, TILESIZE, TILESIZE,
909 GDK_INTERP_NEAREST);
910 g_object_unref (area);
911 return pixbuf;
912 }
913
914 static GdkPixbuf *
915 osm_gps_map_render_missing_tile (OsmGpsMap *map, int zoom, int x, int y)
916 {
917 /* maybe TODO: render from downscaled tiles, if the following fails */
918 return osm_gps_map_render_missing_tile_upscaled (map, zoom, x, y);
919 }
920
921 static void
922 osm_gps_map_load_tile (OsmGpsMap *map, int zoom, int x, int y, int offset_x, int offset_y)
923 {
924 OsmGpsMapPrivate *priv = map->priv;
925 gchar *filename;
926 GdkPixbuf *pixbuf;
927
928 g_debug("Load tile %d,%d (%d,%d) z:%d", x, y, offset_x, offset_y, zoom);
929
930 if (priv->map_source == OSM_GPS_MAP_SOURCE_NULL) {
931 osm_gps_map_blit_tile(map, priv->null_tile, offset_x,offset_y);
932 return;
933 }
934
935 filename = g_strdup_printf("%s%c%d%c%d%c%d.%s",
936 priv->cache_dir, G_DIR_SEPARATOR,
937 zoom, G_DIR_SEPARATOR,
938 x, G_DIR_SEPARATOR,
939 y,
940 priv->image_format);
941
942 /* try to get file from internal cache first */
943 if(!(pixbuf = osm_gps_map_load_cached_tile(map, zoom, x, y)))
944 pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
945
946 if(pixbuf) {
947 g_debug("Found tile %s", filename);
948 osm_gps_map_blit_tile(map, pixbuf, offset_x,offset_y);
949 g_object_unref (pixbuf);
950 } else {
951 if (priv->map_auto_download_enabled) {
952 osm_gps_map_download_tile(map, zoom, x, y, TRUE);
953 }
954
955 /* try to render the tile by scaling cached tiles from other zoom
956 * levels */
957 pixbuf = osm_gps_map_render_missing_tile (map, zoom, x, y);
958 if (pixbuf) {
959 gdk_draw_pixbuf (priv->pixmap,
960 priv->gc_map,
961 pixbuf,
962 0,0,
963 offset_x,offset_y,
964 TILESIZE,TILESIZE,
965 GDK_RGB_DITHER_NONE, 0, 0);
966 g_object_unref (pixbuf);
967 } else {
968 /* prevent some artifacts when drawing not yet loaded areas. */
969 GtkStyle *style = gtk_widget_get_style(GTK_WIDGET(map));
970 gdk_draw_rectangle (priv->pixmap,
971 style->white_gc,
972 TRUE,
973 offset_x, offset_y, TILESIZE, TILESIZE);
974 }
975 }
976 g_free(filename);
977 }
978
979 static void
980 osm_gps_map_fill_tiles_pixel (OsmGpsMap *map)
981 {
982 OsmGpsMapPrivate *priv = map->priv;
983 GtkAllocation allocation;
984 GtkStyle *style;
985 int i,j, tile_x0, tile_y0, tiles_nx, tiles_ny;
986 int offset_xn = 0;
987 int offset_yn = 0;
988 int offset_x;
989 int offset_y;
990
991 g_debug("Fill tiles: %d,%d z:%d", priv->map_x, priv->map_y, priv->map_zoom);
992
993 gtk_widget_get_allocation(GTK_WIDGET(map), &allocation);
994 style = gtk_widget_get_style(GTK_WIDGET(map));
995
996 offset_x = - priv->map_x % TILESIZE;
997 offset_y = - priv->map_y % TILESIZE;
998 if (offset_x > 0) offset_x -= TILESIZE;
999 if (offset_y > 0) offset_y -= TILESIZE;
1000
1001 offset_xn = offset_x + EXTRA_BORDER;
1002 offset_yn = offset_y + EXTRA_BORDER;
1003
1004 tiles_nx = (allocation.width - offset_x) / TILESIZE + 1;
1005 tiles_ny = (allocation.height - offset_y) / TILESIZE + 1;
1006
1007 tile_x0 = floor((float)priv->map_x / (float)TILESIZE);
1008 tile_y0 = floor((float)priv->map_y / (float)TILESIZE);
1009
1010 //TODO: implement wrap around
1011 for (i=tile_x0; i<(tile_x0+tiles_nx);i++)
1012 {
1013 for (j=tile_y0; j<(tile_y0+tiles_ny); j++)
1014 {
1015 if( j<0 || i<0 || i>=exp(priv->map_zoom * M_LN2) || j>=exp(priv->map_zoom * M_LN2))
1016 {
1017 gdk_draw_rectangle (priv->pixmap,
1018 style->white_gc,
1019 TRUE,
1020 offset_xn, offset_yn,
1021 TILESIZE,TILESIZE);
1022 }
1023 else
1024 {
1025 osm_gps_map_load_tile(map,
1026 priv->map_zoom,
1027 i,j,
1028 offset_xn,offset_yn);
1029 }
1030 offset_yn += TILESIZE;
1031 }
1032 offset_xn += TILESIZE;
1033 offset_yn = offset_y + EXTRA_BORDER;
1034 }
1035 }
1036
1037 static void
1038 osm_gps_map_print_track (OsmGpsMap *map, OsmGpsMapTrack *track)
1039 {
1040 OsmGpsMapPrivate *priv = map->priv;
1041
1042 GSList *pt,*points;
1043 int x,y;
1044 int min_x = 0,min_y = 0,max_x = 0,max_y = 0;
1045 gfloat lw, alpha;
1046 int map_x0, map_y0;
1047 cairo_t *cr;
1048 GdkColor color;
1049
1050 g_object_get (track,
1051 "track", &points,
1052 "line-width", &lw,
1053 "alpha", &alpha,
1054 NULL);
1055 osm_gps_map_track_get_color(track, &color);
1056
1057 if (points == NULL)
1058 return;
1059
1060 cr = gdk_cairo_create(priv->pixmap);
1061 cairo_set_line_width (cr, lw);
1062 cairo_set_source_rgba (cr, color.red/65535.0, color.green/65535.0, color.blue/65535.0, alpha);
1063 cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
1064 cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
1065
1066 map_x0 = priv->map_x - EXTRA_BORDER;
1067 map_y0 = priv->map_y - EXTRA_BORDER;
1068 for(pt = points; pt != NULL; pt = pt->next)
1069 {
1070 OsmGpsMapPoint *tp = pt->data;
1071
1072 x = lon2pixel(priv->map_zoom, tp->rlon) - map_x0;
1073 y = lat2pixel(priv->map_zoom, tp->rlat) - map_y0;
1074
1075 /* first time through loop */
1076 if (pt == points) {
1077 cairo_move_to(cr, x, y);
1078 }
1079
1080 cairo_line_to(cr, x, y);
1081
1082 max_x = MAX(x,max_x);
1083 min_x = MIN(x,min_x);
1084 max_y = MAX(y,max_y);
1085 min_y = MIN(y,min_y);
1086 }
1087
1088 gtk_widget_queue_draw_area (
1089 GTK_WIDGET(map),
1090 min_x - lw,
1091 min_y - lw,
1092 max_x + (lw * 2),
1093 max_y + (lw * 2));
1094
1095 cairo_stroke(cr);
1096 cairo_destroy(cr);
1097 }
1098
1099 /* Prints the gps trip history, and any other tracks */
1100 static void
1101 osm_gps_map_print_tracks (OsmGpsMap *map)
1102 {
1103 GSList *tmp;
1104 OsmGpsMapPrivate *priv = map->priv;
1105
1106 if (priv->trip_history_show_enabled) {
1107 osm_gps_map_print_track (map, priv->gps_track);
1108 }
1109
1110 if (priv->tracks) {
1111 tmp = priv->tracks;
1112 while (tmp != NULL) {
1113 osm_gps_map_print_track (map, OSM_GPS_MAP_TRACK(tmp->data));
1114 tmp = g_slist_next(tmp);
1115 }
1116 }
1117 }
1118
1119 static gboolean
1120 osm_gps_map_purge_cache_check(gpointer key, gpointer value, gpointer user)
1121 {
1122 return (((OsmCachedTile*)value)->redraw_cycle != ((OsmGpsMapPrivate*)user)->redraw_cycle);
1123 }
1124
1125 static void
1126 osm_gps_map_purge_cache (OsmGpsMap *map)
1127 {
1128 OsmGpsMapPrivate *priv = map->priv;
1129
1130 if (g_hash_table_size (priv->tile_cache) < priv->max_tile_cache_size)
1131 return;
1132
1133 /* run through the cache, and remove the tiles which have not been used
1134 * during the last redraw operation */
1135 g_hash_table_foreach_remove(priv->tile_cache, osm_gps_map_purge_cache_check, priv);
1136 }
1137
1138 static gboolean
1139 osm_gps_map_map_redraw (OsmGpsMap *map)
1140 {
1141 GtkStyle *style;
1142 GtkAllocation allocation;
1143 OsmGpsMapPrivate *priv = map->priv;
1144
1145 priv->idle_map_redraw = 0;
1146
1147 /* don't redraw the entire map while the OSD is doing */
1148 /* some animation or the like. This is to keep the animation */
1149 /* fluid */
1150 if (priv->layers) {
1151 GSList *list;
1152 for(list = priv->layers; list != NULL; list = list->next) {
1153 OsmGpsMapLayer *layer = list->data;
1154 if (osm_gps_map_layer_busy(layer))
1155 return FALSE;
1156 }
1157 }
1158
1159 /* the motion_notify handler uses priv->pixmap to redraw the area; if we
1160 * change it while we are dragging, we will end up showing it in the wrong
1161 * place. This could be fixed by carefully recompute the coordinates, but
1162 * for now it's easier just to disable redrawing the map while dragging */
1163 if (priv->is_dragging)
1164 return FALSE;
1165
1166 /* undo all offsets that may have happened when dragging */
1167 priv->drag_mouse_dx = 0;
1168 priv->drag_mouse_dy = 0;
1169
1170 priv->redraw_cycle++;
1171
1172 /* draw white background to initialise pixmap */
1173 gtk_widget_get_allocation(GTK_WIDGET(map), &allocation);
1174 style = gtk_widget_get_style(GTK_WIDGET(map));
1175 gdk_draw_rectangle (priv->pixmap,
1176 style->white_gc,
1177 TRUE,
1178 0, 0,
1179 allocation.width + EXTRA_BORDER * 2,
1180 allocation.height + EXTRA_BORDER * 2);
1181
1182 osm_gps_map_fill_tiles_pixel(map);
1183
1184 osm_gps_map_print_tracks(map);
1185 osm_gps_map_print_images(map);
1186
1187 /* draw the gps point using the appropriate virtual private method */
1188 if (priv->gps_track_used && priv->gps_point_enabled) {
1189 OsmGpsMapClass *klass = OSM_GPS_MAP_GET_CLASS(map);
1190 if (klass->draw_gps_point)
1191 klass->draw_gps_point (map, priv->pixmap);
1192 }
1193
1194 if (priv->layers) {
1195 GSList *list;
1196 for(list = priv->layers; list != NULL; list = list->next) {
1197 OsmGpsMapLayer *layer = list->data;
1198 osm_gps_map_layer_render (layer, map);
1199 }
1200 }
1201
1202 osm_gps_map_purge_cache(map);
1203 gtk_widget_queue_draw (GTK_WIDGET (map));
1204
1205 return FALSE;
1206 }
1207
1208 static void
1209 osm_gps_map_map_redraw_idle (OsmGpsMap *map)
1210 {
1211 OsmGpsMapPrivate *priv = map->priv;
1212
1213 if (priv->idle_map_redraw == 0)
1214 priv->idle_map_redraw = g_idle_add ((GSourceFunc)osm_gps_map_map_redraw, map);
1215 }
1216
1217 /* call this to update center_rlat and center_rlon after
1218 * changin map_x or map_y */
1219 static void
1220 center_coord_update(OsmGpsMap *map) {
1221
1222 GtkWidget *widget = GTK_WIDGET(map);
1223 OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(map);
1224 GtkAllocation allocation;
1225
1226 gtk_widget_get_allocation(widget, &allocation);
1227 gint pixel_x = priv->map_x + allocation.width/2;
1228 gint pixel_y = priv->map_y + allocation.height/2;
1229
1230 priv->center_rlon = pixel2lon(priv->map_zoom, pixel_x);
1231 priv->center_rlat = pixel2lat(priv->map_zoom, pixel_y);
1232
1233 g_signal_emit_by_name(widget, "changed");
1234 }
1235
1236 /* Automatically center the map if the current point, i.e the most recent
1237 * gps point, approaches the edge, and map_auto_center is set. Does not
1238 * request the map be redrawn */
1239 static void
1240 maybe_autocenter_map (OsmGpsMap *map)
1241 {
1242 OsmGpsMapPrivate *priv;
1243 GtkAllocation allocation;
1244
1245 g_return_if_fail (OSM_IS_GPS_MAP (map));
1246 priv = map->priv;
1247 gtk_widget_get_allocation(GTK_WIDGET(map), &allocation);
1248
1249 if(priv->map_auto_center_enabled) {
1250 int pixel_x = lon2pixel(priv->map_zoom, priv->gps->rlon);
1251 int pixel_y = lat2pixel(priv->map_zoom, priv->gps->rlat);
1252 int x = pixel_x - priv->map_x;
1253 int y = pixel_y - priv->map_y;
1254 int width = allocation.width;
1255 int height = allocation.height;
1256 if( x < (width/2 - width/8) || x > (width/2 + width/8) ||
1257 y < (height/2 - height/8) || y > (height/2 + height/8)) {
1258
1259 priv->map_x = pixel_x - allocation.width/2;
1260 priv->map_y = pixel_y - allocation.height/2;
1261 center_coord_update(map);
1262 }
1263 }
1264 }
1265
1266 static gboolean
1267 on_window_key_press(GtkWidget *widget, GdkEventKey *event, OsmGpsMapPrivate *priv)
1268 {
1269 int i;
1270 int step;
1271 gboolean handled;
1272 GtkAllocation allocation;
1273 OsmGpsMap *map = OSM_GPS_MAP(widget);
1274
1275 /* if no keybindings are set, let the app handle them... */
1276 if (!priv->keybindings_enabled)
1277 return FALSE;
1278
1279 handled = FALSE;
1280 gtk_widget_get_allocation(GTK_WIDGET(map), &allocation);
1281 step = allocation.width/OSM_GPS_MAP_SCROLL_STEP;
1282
1283 /* the map handles some keys on its own */
1284 for (i = 0; i < OSM_GPS_MAP_KEY_MAX; i++) {
1285 /* not the key we have a binding for */
1286 if (map->priv->keybindings[i] != event->keyval)
1287 continue;
1288
1289 switch(i) {
1290 case OSM_GPS_MAP_KEY_FULLSCREEN: {
1291 GtkWidget *toplevel = gtk_widget_get_toplevel(GTK_WIDGET(widget));
1292 if(!priv->is_fullscreen)
1293 gtk_window_fullscreen(GTK_WINDOW(toplevel));
1294 else
1295 gtk_window_unfullscreen(GTK_WINDOW(toplevel));
1296
1297 priv->is_fullscreen = !priv->is_fullscreen;
1298 handled = TRUE;
1299 } break;
1300 case OSM_GPS_MAP_KEY_ZOOMIN:
1301 osm_gps_map_zoom_in(map);
1302 handled = TRUE;
1303 break;
1304 case OSM_GPS_MAP_KEY_ZOOMOUT:
1305 osm_gps_map_zoom_out(map);
1306 handled = TRUE;
1307 break;
1308 case OSM_GPS_MAP_KEY_UP:
1309 priv->map_y -= step;
1310 center_coord_update(map);
1311 osm_gps_map_map_redraw_idle(map);
1312 handled = TRUE;
1313 break;
1314 case OSM_GPS_MAP_KEY_DOWN:
1315 priv->map_y += step;
1316 center_coord_update(map);
1317 osm_gps_map_map_redraw_idle(map);
1318 handled = TRUE;
1319 break;
1320 case OSM_GPS_MAP_KEY_LEFT:
1321 priv->map_x -= step;
1322 center_coord_update(map);
1323 osm_gps_map_map_redraw_idle(map);
1324 handled = TRUE;
1325 break;
1326 case OSM_GPS_MAP_KEY_RIGHT:
1327 priv->map_x += step;
1328 center_coord_update(map);
1329 osm_gps_map_map_redraw_idle(map);
1330 handled = TRUE;
1331 break;
1332 default:
1333 break;
1334 }
1335 }
1336
1337 return handled;
1338 }
1339
1340 static void
1341 on_gps_point_added (OsmGpsMapTrack *track, OsmGpsMapPoint *point, OsmGpsMap *map)
1342 {
1343 osm_gps_map_map_redraw_idle (map);
1344 maybe_autocenter_map (map);
1345 }
1346
1347 static void
1348 on_track_changed (OsmGpsMapTrack *track, GParamSpec *pspec, OsmGpsMap *map)
1349 {
1350 osm_gps_map_map_redraw_idle (map);
1351 }
1352
1353 static void
1354 osm_gps_map_init (OsmGpsMap *object)
1355 {
1356 int i;
1357 OsmGpsMapPrivate *priv;
1358
1359 priv = G_TYPE_INSTANCE_GET_PRIVATE (object, OSM_TYPE_GPS_MAP, OsmGpsMapPrivate);
1360 object->priv = priv;
1361
1362 priv->pixmap = NULL;
1363
1364 priv->trip_history = NULL;
1365 priv->gps = osm_gps_map_point_new_radians(0.0, 0.0);
1366 priv->gps_track_used = FALSE;
1367 priv->gps_heading = OSM_GPS_MAP_INVALID;
1368
1369 priv->gps_track = osm_gps_map_track_new();
1370 g_signal_connect(priv->gps_track, "point-added",
1371 G_CALLBACK(on_gps_point_added), object);
1372 g_signal_connect(priv->gps_track, "notify",
1373 G_CALLBACK(on_track_changed), object);
1374
1375 priv->tracks = NULL;
1376 priv->images = NULL;
1377 priv->layers = NULL;
1378
1379 priv->drag_counter = 0;
1380 priv->drag_mouse_dx = 0;
1381 priv->drag_mouse_dy = 0;
1382 priv->drag_start_mouse_x = 0;
1383 priv->drag_start_mouse_y = 0;
1384
1385 priv->uri_format = 0;
1386 priv->is_google = FALSE;
1387
1388 priv->map_source = -1;
1389
1390 priv->keybindings_enabled = FALSE;
1391 for (i = 0; i < OSM_GPS_MAP_KEY_MAX; i++)
1392 priv->keybindings[i] = 0;
1393
1394
1395 #if USE_LIBSOUP22
1396 /* libsoup-2.2 has no special way to set the user agent, so we */
1397 /* set it seperately as an extra header field for each reuest */
1398 priv->soup_session = soup_session_async_new();
1399 #else
1400 /* set the user agent */
1401 priv->soup_session =
1402 soup_session_async_new_with_options(SOUP_SESSION_USER_AGENT,
1403 USER_AGENT, NULL);
1404
1405 #endif
1406 /* Hash table which maps tile d/l URIs to SoupMessage requests, the hashtable
1407 must free the key, the soup session unrefs the message */
1408 priv->tile_queue = g_hash_table_new_full (g_str_hash, g_str_equal,
1409 g_free, NULL);
1410
1411 //Some mapping providers (Google) have varying degrees of tiles at multiple
1412 //zoom levels
1413 priv->missing_tiles = g_hash_table_new (g_str_hash, g_str_equal);
1414
1415 /* memory cache for most recently used tiles */
1416 priv->tile_cache = g_hash_table_new_full (g_str_hash, g_str_equal,
1417 g_free, (GDestroyNotify)cached_tile_free);
1418 priv->max_tile_cache_size = 20;
1419
1420 gtk_widget_add_events (GTK_WIDGET (object),
1421 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
1422 GDK_POINTER_MOTION_MASK |
1423 GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
1424 gtk_widget_set_can_focus (GTK_WIDGET (object), TRUE);
1425
1426 g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MASK, my_log_handler, NULL);
1427
1428 /* setup signal handlers */
1429 g_signal_connect(object, "key_press_event",
1430 G_CALLBACK(on_window_key_press), priv);
1431 }
1432
1433 static char*
1434 osm_gps_map_get_cache_base_dir(OsmGpsMapPrivate *priv)
1435 {
1436 if (priv->tile_base_dir)
1437 return g_strdup(priv->tile_base_dir);
1438 return osm_gps_map_get_default_cache_directory();
1439 }
1440
1441 static void
1442 osm_gps_map_setup(OsmGpsMap *map)
1443 {
1444 const char *uri;
1445 OsmGpsMapPrivate *priv = map->priv;
1446
1447 /* user can specify a map source ID, or a repo URI as the map source */
1448 uri = osm_gps_map_source_get_repo_uri(OSM_GPS_MAP_SOURCE_NULL);
1449 if ( (priv->map_source == 0) || (strcmp(priv->repo_uri, uri) == 0) ) {
1450 g_debug("Using null source");
1451 priv->map_source = OSM_GPS_MAP_SOURCE_NULL;
1452
1453 priv->null_tile = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, 256, 256);
1454 gdk_pixbuf_fill(priv->null_tile, 0xcccccc00);
1455 }
1456 else if (priv->map_source >= 0) {
1457 /* check if the source given is valid */
1458 uri = osm_gps_map_source_get_repo_uri(priv->map_source);
1459 if (uri) {
1460 g_debug("Setting map source from ID");
1461 g_free(priv->repo_uri);
1462
1463 priv->repo_uri = g_strdup(uri);
1464 priv->image_format = g_strdup(
1465 osm_gps_map_source_get_image_format(priv->map_source));
1466 priv->max_zoom = osm_gps_map_source_get_max_zoom(priv->map_source);
1467 priv->min_zoom = osm_gps_map_source_get_min_zoom(priv->map_source);
1468 }
1469 }
1470 /* parse the source uri */
1471 inspect_map_uri(priv);
1472
1473 /* setup the tile cache */
1474 if ( g_strcmp0(priv->tile_dir, OSM_GPS_MAP_CACHE_DISABLED) == 0 ) {
1475 priv->cache_dir = NULL;
1476 } else if ( g_strcmp0(priv->tile_dir, OSM_GPS_MAP_CACHE_AUTO) == 0 ) {
1477 char *base = osm_gps_map_get_cache_base_dir(priv);
1478 #if GLIB_CHECK_VERSION (2, 16, 0)
1479 char *md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, priv->repo_uri, -1);
1480 #else
1481 char *md5 = g_strdup(osm_gps_map_source_get_friendly_name(priv->map_source));
1482 #endif
1483 priv->cache_dir = g_strdup_printf("%s%c%s", base, G_DIR_SEPARATOR, md5);
1484 g_free(base);
1485 g_free(md5);
1486 } else if ( g_strcmp0(priv->tile_dir, OSM_GPS_MAP_CACHE_FRIENDLY) == 0 ) {
1487 char *base = osm_gps_map_get_cache_base_dir(priv);
1488 const char *fname = osm_gps_map_source_get_friendly_name(priv->map_source);
1489 priv->cache_dir = g_strdup_printf("%s%c%s", base, G_DIR_SEPARATOR, fname);
1490 g_free(base);
1491 } else {
1492 /* the simple case is handled in g_object_set(PROP_TILE_CACHE_DIR) */
1493 }
1494 g_debug("Cache dir: %s", priv->cache_dir);
1495
1496 /* check if we are being called for a second (or more) time in the lifetime
1497 of the object, and if so, do some extra cleanup */
1498 if ( priv->is_constructed ) {
1499 g_debug("Setup called again in map lifetime");
1500 /* flush the ram cache */
1501 g_hash_table_remove_all(priv->tile_cache);
1502
1503 /* adjust zoom if necessary */
1504 if(priv->map_zoom > priv->max_zoom)
1505 osm_gps_map_set_zoom(map, priv->max_zoom);
1506
1507 if(priv->map_zoom < priv->min_zoom)
1508 osm_gps_map_set_zoom(map, priv->min_zoom);
1509
1510 osm_gps_map_map_redraw_idle(map);
1511 }
1512 }
1513
1514 static GObject *
1515 osm_gps_map_constructor (GType gtype, guint n_properties, GObjectConstructParam *properties)
1516 {
1517 GObject *object;
1518 OsmGpsMap *map;
1519
1520 /* always chain up to the parent constructor */
1521 object = G_OBJECT_CLASS(osm_gps_map_parent_class)->constructor(gtype, n_properties, properties);
1522
1523 map = OSM_GPS_MAP(object);
1524
1525 osm_gps_map_setup(map);
1526 map->priv->is_constructed = TRUE;
1527
1528 return object;
1529 }
1530
1531 static void
1532 osm_gps_map_dispose (GObject *object)
1533 {
1534 OsmGpsMap *map = OSM_GPS_MAP(object);
1535 OsmGpsMapPrivate *priv = map->priv;
1536
1537 if (priv->is_disposed)
1538 return;
1539
1540 priv->is_disposed = TRUE;
1541
1542 soup_session_abort(priv->soup_session);
1543 g_object_unref(priv->soup_session);
1544
1545 g_object_unref(priv->gps_track);
1546
1547 g_hash_table_destroy(priv->tile_queue);
1548 g_hash_table_destroy(priv->missing_tiles);
1549 g_hash_table_destroy(priv->tile_cache);
1550
1551 /* images and layers contain GObjects which need unreffing, so free here */
1552 gslist_of_gobjects_free(&priv->images);
1553 gslist_of_gobjects_free(&priv->layers);
1554 gslist_of_gobjects_free(&priv->tracks);
1555
1556 if(priv->pixmap)
1557 g_object_unref (priv->pixmap);
1558
1559 if (priv->null_tile)
1560 g_object_unref (priv->null_tile);
1561
1562 if(priv->gc_map)
1563 g_object_unref(priv->gc_map);
1564
1565 if (priv->idle_map_redraw != 0)
1566 g_source_remove (priv->idle_map_redraw);
1567
1568 if (priv->drag_expose_source != 0)
1569 g_source_remove (priv->drag_expose_source);
1570
1571 g_free(priv->gps);
1572
1573
1574 #ifdef OSD_DOUBLE_BUFFER
1575 if(priv->dbuf_pixmap)
1576 g_object_unref (priv->dbuf_pixmap);
1577 #endif
1578
1579 G_OBJECT_CLASS (osm_gps_map_parent_class)->dispose (object);
1580 }
1581
1582 static void
1583 osm_gps_map_finalize (GObject *object)
1584 {
1585 OsmGpsMap *map = OSM_GPS_MAP(object);
1586 OsmGpsMapPrivate *priv = map->priv;
1587
1588 if (priv->tile_dir)
1589 g_free(priv->tile_dir);
1590
1591 if (priv->cache_dir)
1592 g_free(priv->cache_dir);
1593
1594 g_free(priv->repo_uri);
1595 g_free(priv->image_format);
1596
1597 /* trip and tracks contain simple non GObject types, so free them here */
1598 gslist_of_data_free(&priv->trip_history);
1599
1600 G_OBJECT_CLASS (osm_gps_map_parent_class)->finalize (object);
1601 }
1602
1603 static void
1604 osm_gps_map_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
1605 {
1606 g_return_if_fail (OSM_IS_GPS_MAP (object));
1607 OsmGpsMap *map = OSM_GPS_MAP(object);
1608 OsmGpsMapPrivate *priv = map->priv;
1609
1610 switch (prop_id)
1611 {
1612 case PROP_AUTO_CENTER:
1613 priv->map_auto_center_enabled = g_value_get_boolean (value);
1614 break;
1615 case PROP_RECORD_TRIP_HISTORY:
1616 priv->trip_history_record_enabled = g_value_get_boolean (value);
1617 break;
1618 case PROP_SHOW_TRIP_HISTORY:
1619 priv->trip_history_show_enabled = g_value_get_boolean (value);
1620 break;
1621 case PROP_AUTO_DOWNLOAD:
1622 priv->map_auto_download_enabled = g_value_get_boolean (value);
1623 break;
1624 case PROP_REPO_URI:
1625 priv->repo_uri = g_value_dup_string (value);
1626 break;
1627 case PROP_PROXY_URI:
1628 if ( g_value_get_string(value) ) {
1629 priv->proxy_uri = g_value_dup_string (value);
1630 g_debug("Setting proxy server: %s", priv->proxy_uri);
1631
1632 #if USE_LIBSOUP22
1633 SoupUri* uri = soup_uri_new(priv->proxy_uri);
1634 g_object_set(G_OBJECT(priv->soup_session), SOUP_SESSION_PROXY_URI, uri, NULL);
1635 #else
1636 GValue val = {0};
1637 SoupURI* uri = soup_uri_new(priv->proxy_uri);
1638 g_value_init(&val, SOUP_TYPE_URI);
1639 g_value_take_boxed(&val, uri);
1640 g_object_set_property(G_OBJECT(priv->soup_session),SOUP_SESSION_PROXY_URI,&val);
1641 #endif
1642 } else {
1643 priv->proxy_uri = NULL;
1644 }
1645 break;
1646 case PROP_TILE_CACHE_DIR:
1647 if ( g_value_get_string(value) ) {
1648 priv->tile_dir = g_value_dup_string (value);
1649 if ((g_strcmp0(priv->tile_dir, OSM_GPS_MAP_CACHE_DISABLED) == 0) ||
1650 (g_strcmp0(priv->tile_dir, OSM_GPS_MAP_CACHE_AUTO) == 0) ||
1651 (g_strcmp0(priv->tile_dir, OSM_GPS_MAP_CACHE_FRIENDLY) == 0)) {
1652 /* this case is handled by osm_gps_map_setup */
1653 } else {
1654 priv->cache_dir = g_strdup(priv->tile_dir);
1655 g_debug("Cache dir: %s", priv->cache_dir);
1656 }
1657 } else {
1658 priv->tile_dir = g_strdup(OSM_GPS_MAP_CACHE_DISABLED);
1659 }
1660 break;
1661 case PROP_TILE_CACHE_BASE_DIR:
1662 priv->tile_base_dir = g_value_dup_string (value);
1663 break;
1664 case PROP_TILE_CACHE_DIR_IS_FULL_PATH:
1665 break;
1666 case PROP_ZOOM:
1667 priv->map_zoom = g_value_get_int (value);
1668 break;
1669 case PROP_MAX_ZOOM:
1670 priv->max_zoom = g_value_get_int (value);
1671 break;
1672 case PROP_MIN_ZOOM:
1673 priv->min_zoom = g_value_get_int (value);
1674 break;
1675 case PROP_MAP_X:
1676 priv->map_x = g_value_get_int (value);
1677 center_coord_update(map);
1678 break;
1679 case PROP_MAP_Y:
1680 priv->map_y = g_value_get_int (value);
1681 center_coord_update(map);
1682 break;
1683 case PROP_GPS_TRACK_WIDTH:
1684 g_object_set (priv->gps_track,
1685 "line-width", g_value_get_float (value),
1686 NULL);
1687 break;
1688 case PROP_GPS_POINT_R1:
1689 priv->ui_gps_point_inner_radius = g_value_get_int (value);
1690 break;
1691 case PROP_GPS_POINT_R2:
1692 priv->ui_gps_point_outer_radius = g_value_get_int (value);
1693 break;
1694 case PROP_MAP_SOURCE: {
1695 gint old = priv->map_source;
1696 priv->map_source = g_value_get_int (value);
1697 if(old >= OSM_GPS_MAP_SOURCE_NULL &&
1698 priv->map_source != old &&
1699 priv->map_source >= OSM_GPS_MAP_SOURCE_NULL &&
1700 priv->map_source <= OSM_GPS_MAP_SOURCE_LAST) {
1701
1702 if (!priv->is_constructed)
1703 g_critical("Map source setup called twice");
1704
1705 /* we now have to switch the entire map */
1706 osm_gps_map_setup(map);
1707
1708 } } break;
1709 case PROP_IMAGE_FORMAT:
1710 priv->image_format = g_value_dup_string (value);
1711 break;
1712 case PROP_DRAG_LIMIT:
1713 priv->drag_limit = g_value_get_int (value);
1714 break;
1715 case PROP_AUTO_CENTER_THRESHOLD:
1716 priv->map_auto_center_threshold = g_value_get_float (value);
1717 break;
1718 case PROP_SHOW_GPS_POINT:
1719 priv->gps_point_enabled = g_value_get_boolean (value);
1720 break;
1721 default:
1722 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1723 break;
1724 }
1725 }
1726
1727 static void
1728 osm_gps_map_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
1729 {
1730 g_return_if_fail (OSM_IS_GPS_MAP (object));
1731 OsmGpsMap *map = OSM_GPS_MAP(object);
1732 OsmGpsMapPrivate *priv = map->priv;
1733
1734 switch (prop_id)
1735 {
1736 case PROP_AUTO_CENTER:
1737 g_value_set_boolean(value, priv->map_auto_center_enabled);
1738 break;
1739 case PROP_RECORD_TRIP_HISTORY:
1740 g_value_set_boolean(value, priv->trip_history_record_enabled);
1741 break;
1742 case PROP_SHOW_TRIP_HISTORY:
1743 g_value_set_boolean(value, priv->trip_history_show_enabled);
1744 break;
1745 case PROP_AUTO_DOWNLOAD:
1746 g_value_set_boolean(value, priv->map_auto_download_enabled);
1747 break;
1748 case PROP_REPO_URI:
1749 g_value_set_string(value, priv->repo_uri);
1750 break;
1751 case PROP_PROXY_URI:
1752 g_value_set_string(value, priv->proxy_uri);
1753 break;
1754 case PROP_TILE_CACHE_DIR:
1755 g_value_set_string(value, priv->cache_dir);
1756 break;
1757 case PROP_TILE_CACHE_BASE_DIR:
1758 g_value_set_string(value, priv->tile_base_dir);
1759 break;
1760 case PROP_TILE_CACHE_DIR_IS_FULL_PATH:
1761 g_value_set_boolean(value, FALSE);
1762 break;
1763 case PROP_ZOOM:
1764 g_value_set_int(value, priv->map_zoom);
1765 break;
1766 case PROP_MAX_ZOOM:
1767 g_value_set_int(value, priv->max_zoom);
1768 break;
1769 case PROP_MIN_ZOOM:
1770 g_value_set_int(value, priv->min_zoom);
1771 break;
1772 case PROP_LATITUDE:
1773 g_value_set_float(value, rad2deg(priv->center_rlat));
1774 break;
1775 case PROP_LONGITUDE:
1776 g_value_set_float(value, rad2deg(priv->center_rlon));
1777 break;
1778 case PROP_MAP_X:
1779 g_value_set_int(value, priv->map_x);
1780 break;
1781 case PROP_MAP_Y:
1782 g_value_set_int(value, priv->map_y);
1783 break;
1784 case PROP_TILES_QUEUED:
1785 g_value_set_int(value, g_hash_table_size(priv->tile_queue));
1786 break;
1787 case PROP_GPS_TRACK_WIDTH: {
1788 gfloat f;
1789 g_object_get (priv->gps_track, "line-width", &f, NULL);
1790 g_value_set_float (value, f);
1791 } break;
1792 case PROP_GPS_POINT_R1:
1793 g_value_set_int(value, priv->ui_gps_point_inner_radius);
1794 break;
1795 case PROP_GPS_POINT_R2:
1796 g_value_set_int(value, priv->ui_gps_point_outer_radius);
1797 break;
1798 case PROP_MAP_SOURCE:
1799 g_value_set_int(value, priv->map_source);
1800 break;
1801 case PROP_IMAGE_FORMAT:
1802 g_value_set_string(value, priv->image_format);
1803 break;
1804 case PROP_DRAG_LIMIT:
1805 g_value_set_int(value, priv->drag_limit);
1806 break;
1807 case PROP_AUTO_CENTER_THRESHOLD:
1808 g_value_set_float(value, priv->map_auto_center_threshold);
1809 break;
1810 case PROP_SHOW_GPS_POINT:
1811 g_value_set_boolean(value, priv->gps_point_enabled);
1812 break;
1813 default:
1814 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1815 break;
1816 }
1817 }
1818
1819 static gboolean
1820 osm_gps_map_scroll_event (GtkWidget *widget, GdkEventScroll *event)
1821 {
1822 OsmGpsMap *map = OSM_GPS_MAP(widget);
1823
1824 if (event->direction == GDK_SCROLL_UP)
1825 osm_gps_map_zoom_in(map);
1826 else if (event->direction == GDK_SCROLL_DOWN)
1827 osm_gps_map_zoom_out(map);
1828
1829 return FALSE;
1830 }
1831
1832 static gboolean
1833 osm_gps_map_button_press (GtkWidget *widget, GdkEventButton *event)
1834 {
1835 OsmGpsMap *map = OSM_GPS_MAP(widget);
1836 OsmGpsMapPrivate *priv = map->priv;
1837
1838 if (priv->layers) {
1839 GSList *list;
1840 for(list = priv->layers; list != NULL; list = list->next) {
1841 OsmGpsMapLayer *layer = list->data;
1842 if (osm_gps_map_layer_button_press(layer, map, event))
1843 return FALSE;
1844 }
1845 }
1846
1847 priv->is_button_down = TRUE;
1848 priv->drag_counter = 0;
1849 priv->drag_start_mouse_x = (int) event->x;
1850 priv->drag_start_mouse_y = (int) event->y;
1851 priv->drag_start_map_x = priv->map_x;
1852 priv->drag_start_map_y = priv->map_y;
1853
1854 return FALSE;
1855 }
1856
1857 static gboolean
1858 osm_gps_map_button_release (GtkWidget *widget, GdkEventButton *event)
1859 {
1860 OsmGpsMap *map = OSM_GPS_MAP(widget);
1861 OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);
1862
1863 if(!priv->is_button_down)
1864 return FALSE;
1865
1866 if (priv->is_dragging)
1867 {
1868 priv->is_dragging = FALSE;
1869
1870 priv->map_x = priv->drag_start_map_x;
1871 priv->map_y = priv->drag_start_map_y;
1872
1873 priv->map_x += (priv->drag_start_mouse_x - (int) event->x);
1874 priv->map_y += (priv->drag_start_mouse_y - (int) event->y);
1875
1876 center_coord_update(map);
1877
1878 osm_gps_map_map_redraw_idle(map);
1879 }
1880
1881 priv->drag_counter = -1;
1882 priv->is_button_down = FALSE;
1883
1884 return FALSE;
1885 }
1886
1887 static gboolean
1888 osm_gps_map_expose (GtkWidget *widget, GdkEventExpose *event);
1889
1890 static gboolean
1891 osm_gps_map_map_expose (GtkWidget *widget)
1892 {
1893 OsmGpsMapPrivate *priv = OSM_GPS_MAP(widget)->priv;
1894
1895 priv->drag_expose_source = 0;
1896 osm_gps_map_expose (widget, NULL);
1897 return FALSE;
1898 }
1899
1900 static gboolean
1901 osm_gps_map_motion_notify (GtkWidget *widget, GdkEventMotion *event)
1902 {
1903 int x, y;
1904 GdkModifierType state;
1905 OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);
1906
1907 if(!priv->is_button_down)
1908 return FALSE;
1909
1910 if (event->is_hint)
1911 gdk_window_get_pointer (event->window, &x, &y, &state);
1912 else
1913 {
1914 x = event->x;
1915 y = event->y;
1916 state = event->state;
1917 }
1918
1919 // are we being dragged
1920 if (!(state & GDK_BUTTON1_MASK))
1921 return FALSE;
1922
1923 if (priv->drag_counter < 0)
1924 return FALSE;
1925
1926 /* not yet dragged far enough? */
1927 if(!priv->drag_counter &&
1928 ( (x - priv->drag_start_mouse_x) * (x - priv->drag_start_mouse_x) +
1929 (y - priv->drag_start_mouse_y) * (y - priv->drag_start_mouse_y) <
1930 priv->drag_limit*priv->drag_limit))
1931 return FALSE;
1932
1933 priv->drag_counter++;
1934
1935 priv->is_dragging = TRUE;
1936
1937 if (priv->map_auto_center_enabled)
1938 g_object_set(G_OBJECT(widget), "auto-center", FALSE, NULL);
1939
1940 priv->drag_mouse_dx = x - priv->drag_start_mouse_x;
1941 priv->drag_mouse_dy = y - priv->drag_start_mouse_y;
1942
1943 /* instead of redrawing directly just add an idle function */
1944 if (!priv->drag_expose_source)
1945 priv->drag_expose_source =
1946 g_idle_add ((GSourceFunc)osm_gps_map_map_expose, widget);
1947
1948 return FALSE;
1949 }
1950
1951 static gboolean
1952 osm_gps_map_configure (GtkWidget *widget, GdkEventConfigure *event)
1953 {
1954 GtkAllocation allocation;
1955 OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);
1956 GdkWindow *window;
1957
1958 /* create pixmap */
1959 if (priv->pixmap)
1960 g_object_unref (priv->pixmap);
1961
1962 gtk_widget_get_allocation(widget, &allocation);
1963 window = gtk_widget_get_window(widget);
1964 priv->pixmap = gdk_pixmap_new (
1965 window,
1966 allocation.width + EXTRA_BORDER * 2,
1967 allocation.height + EXTRA_BORDER * 2,
1968 -1);
1969
1970 // pixel_x,y, offsets
1971 gint pixel_x = lon2pixel(priv->map_zoom, priv->center_rlon);
1972 gint pixel_y = lat2pixel(priv->map_zoom, priv->center_rlat);
1973
1974 priv->map_x = pixel_x - allocation.width/2;
1975 priv->map_y = pixel_y - allocation.height/2;
1976
1977 #ifdef OSD_DOUBLE_BUFFER
1978 if (priv->dbuf_pixmap)
1979 g_object_unref (priv->dbuf_pixmap);
1980
1981 priv->dbuf_pixmap = gdk_pixmap_new (
1982 window,
1983 allocation.width,
1984 allocation.height,
1985 -1);
1986 #endif
1987
1988
1989 /* and gc, used for clipping (I think......) */
1990 if(priv->gc_map)
1991 g_object_unref(priv->gc_map);
1992
1993 priv->gc_map = gdk_gc_new(priv->pixmap);
1994
1995 osm_gps_map_map_redraw(OSM_GPS_MAP(widget));
1996
1997 g_signal_emit_by_name(widget, "changed");
1998
1999 return FALSE;
2000 }
2001
2002 static gboolean
2003 osm_gps_map_expose (GtkWidget *widget, GdkEventExpose *event)
2004 {
2005 OsmGpsMap *map = OSM_GPS_MAP(widget);
2006 OsmGpsMapPrivate *priv = map->priv;
2007 GtkAllocation allocation;
2008 GtkStateType state;
2009 GtkStyle *style;
2010 GdkWindow *window;
2011 GdkDrawable *drawable;
2012
2013 window = gtk_widget_get_window (widget);
2014 #ifdef OSD_DOUBLE_BUFFER
2015 drawable = priv->dbuf_pixmap;
2016 #else
2017 drawable = window;
2018 #endif
2019 state = gtk_widget_get_state (widget);
2020 gtk_widget_get_allocation (widget, &allocation);
2021 style = gtk_widget_get_style (widget);
2022
2023 if (!priv->drag_mouse_dx && !priv->drag_mouse_dy && event)
2024 {
2025 gdk_draw_drawable (drawable,
2026 style->fg_gc[state],
2027 priv->pixmap,
2028 event->area.x + EXTRA_BORDER, event->area.y + EXTRA_BORDER,
2029 event->area.x, event->area.y,
2030 event->area.width, event->area.height);
2031 }
2032 else
2033 {
2034 gdk_draw_drawable (drawable,
2035 style->fg_gc[state],
2036 priv->pixmap,
2037 0,0,
2038 priv->drag_mouse_dx - EXTRA_BORDER,
2039 priv->drag_mouse_dy - EXTRA_BORDER,
2040 -1,-1);
2041
2042 /* Paint white outside of the map if dragging. Its less
2043 ugly than painting the corrupted map */
2044 if(priv->drag_mouse_dx>EXTRA_BORDER) {
2045 gdk_draw_rectangle (drawable,
2046 style->white_gc,
2047 TRUE,
2048 0, 0,
2049 priv->drag_mouse_dx - EXTRA_BORDER,
2050 allocation.height);
2051 }
2052 else if (-priv->drag_mouse_dx > EXTRA_BORDER)
2053 {
2054 gdk_draw_rectangle (drawable,
2055 style->white_gc,
2056 TRUE,
2057 priv->drag_mouse_dx + allocation.width + EXTRA_BORDER, 0,
2058 -priv->drag_mouse_dx - EXTRA_BORDER,
2059 allocation.height);
2060 }
2061
2062 if (priv->drag_mouse_dy>EXTRA_BORDER) {
2063 gdk_draw_rectangle (drawable,
2064 style->white_gc,
2065 TRUE,
2066 0, 0,
2067 allocation.width,
2068 priv->drag_mouse_dy - EXTRA_BORDER);
2069 }
2070 else if (-priv->drag_mouse_dy > EXTRA_BORDER)
2071 {
2072 gdk_draw_rectangle (drawable,
2073 style->white_gc,
2074 TRUE,
2075 0, priv->drag_mouse_dy + allocation.height + EXTRA_BORDER,
2076 allocation.width,
2077 -priv->drag_mouse_dy - EXTRA_BORDER);
2078 }
2079 }
2080
2081 if (priv->layers) {
2082 GSList *list;
2083 for(list = priv->layers; list != NULL; list = list->next) {
2084 OsmGpsMapLayer *layer = list->data;
2085 osm_gps_map_layer_draw(layer, map, drawable);
2086 #ifdef OSD_DOUBLE_BUFFER
2087 gdk_draw_drawable (widget->window,
2088 style->fg_gc[state],
2089 priv->dbuf_pixmap,
2090 0,0,0,0,-1,-1);
2091 #endif
2092 }
2093 }
2094
2095 return FALSE;
2096 }
2097
2098 static void
2099 osm_gps_map_class_init (OsmGpsMapClass *klass)
2100 {
2101 GObjectClass* object_class = G_OBJECT_CLASS (klass);
2102 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
2103
2104 g_type_class_add_private (klass, sizeof (OsmGpsMapPrivate));
2105
2106 object_class->dispose = osm_gps_map_dispose;
2107 object_class->finalize = osm_gps_map_finalize;
2108 object_class->constructor = osm_gps_map_constructor;
2109 object_class->set_property = osm_gps_map_set_property;
2110 object_class->get_property = osm_gps_map_get_property;
2111
2112 widget_class->expose_event = osm_gps_map_expose;
2113 widget_class->configure_event = osm_gps_map_configure;
2114 widget_class->button_press_event = osm_gps_map_button_press;
2115 widget_class->button_release_event = osm_gps_map_button_release;
2116 widget_class->motion_notify_event = osm_gps_map_motion_notify;
2117 widget_class->scroll_event = osm_gps_map_scroll_event;
2118
2119 /* default implementation of draw_gps_point */
2120 klass->draw_gps_point = osm_gps_map_draw_gps_point;
2121
2122 g_object_class_install_property (object_class,
2123 PROP_AUTO_CENTER,
2124 g_param_spec_boolean ("auto-center",
2125 "auto center",
2126 "map auto center",
2127 TRUE,
2128 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
2129
2130 g_object_class_install_property (object_class,
2131 PROP_AUTO_CENTER_THRESHOLD,
2132 g_param_spec_float ("auto-center-threshold",
2133 "auto center threshold",
2134 "the amount of the window the gps point must move before auto centering",
2135 0.0, /* minimum property value */
2136 1.0, /* maximum property value */
2137 0.25,
2138 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
2139
2140 g_object_class_install_property (object_class,
2141 PROP_RECORD_TRIP_HISTORY,
2142 g_param_spec_boolean ("record-trip-history",
2143 "record trip history",
2144 "should all gps points be recorded in a trip history",
2145 TRUE,
2146 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
2147
2148 g_object_class_install_property (object_class,
2149 PROP_SHOW_TRIP_HISTORY,
2150 g_param_spec_boolean ("show-trip-history",
2151 "show trip history",
2152 "should the recorded trip history be shown on the map",
2153 TRUE,
2154 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
2155
2156 /**
2157 * OsmGpsMap:show-gps-point:
2158 *
2159 * Controls whether the current gps point is shown on the map. Note that
2160 * for derived classes that implement the draw_gps_point vfunc, if this
2161 * property is %FALSE
2162 **/
2163 g_object_class_install_property (object_class,
2164 PROP_SHOW_GPS_POINT,
2165 g_param_spec_boolean ("show-gps-point",
2166 "show gps point",
2167 "should the current gps point be shown on the map",
2168 TRUE,
2169 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
2170
2171 g_object_class_install_property (object_class,
2172 PROP_AUTO_DOWNLOAD,
2173 g_param_spec_boolean ("auto-download",
2174 "auto download",
2175 "map auto download",
2176 TRUE,
2177 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
2178
2179 /**
2180 * OsmGpsMap:repo-uri:
2181 *
2182 * A URI string which defines the location and format to fetch tiles
2183 * for the map. The string is of the format
2184 * "http://tile.openstreetmap.org/&num;Z/&num;X/&num;Y.png". Characters
2185 * that begin with &num; are treated as tokens and replaced according to
2186 * the following rules;
2187 *
2188 * <itemizedlist>
2189 * <listitem>
2190 * <para>
2191 * \#X - X-tile, slippy map format
2192 * </para>
2193 * </listitem>
2194 * <listitem>
2195 * <para>
2196 * \#Y - Y-tile, slippy map format, mercator projection
2197 * </para>
2198 * </listitem>
2199 * <listitem>
2200 * <para>
2201 * \#Z - Zoom level, where min_zoom &gt;= zoom &lt;= max_zoom
2202 * </para>
2203 * </listitem>
2204 * <listitem>
2205 * <para>
2206 * \#S - Zoom level, where -max_zoom &gt;= (zoom-max_zoom) &lt;= min_zoom
2207 * </para>
2208 * </listitem>
2209 * <listitem>
2210 * <para>
2211 * \#Q - Quad tree format, set of "qrts"
2212 * </para>
2213 * </listitem>
2214 * <listitem>
2215 * <para>
2216 * \#Q0 - Quad tree format, set of "0123"
2217 * </para>
2218 * </listitem>
2219 * <listitem>
2220 * <para>
2221 * \#YS - Not Implemented
2222 * </para>
2223 * </listitem>
2224 * <listitem>
2225 * <para>
2226 * \#R - Random integer in range [0,4]
2227 * </para>
2228 * </listitem>
2229 * </itemizedlist>
2230 *
2231 * <note>
2232 * <para>
2233 * If you do not wish to use the default map tiles (provided by OpenStreeMap)
2234 * it is recommened that you use one of the predefined map sources, and thus
2235 * you should construct the map by setting #OsmGpsMap:map-source and not
2236 * #OsmGpsMap:repo-uri. The #OsmGpsMap:repo-uri property is primarily
2237 * designed for applications that wish complete control of tile repository
2238 * management, or wish to use #OsmGpsMap with a tile repository it does not
2239 * explicitly support.
2240 * </para>
2241 * </note>
2242 **/
2243 g_object_class_install_property (object_class,
2244 PROP_REPO_URI,
2245 g_param_spec_string ("repo-uri",
2246 "repo uri",
2247 "Map source tile repository uri",
2248 OSM_REPO_URI,
2249 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
2250
2251 g_object_class_install_property (object_class,
2252 PROP_PROXY_URI,
2253 g_param_spec_string ("proxy-uri",
2254 "proxy uri",
2255 "HTTP proxy uri or NULL",
2256 NULL,
2257 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
2258
2259
2260 /**
2261 * OsmGpsMap:tile-cache:
2262 *
2263 * Either a full path or one of the special format URIs
2264 * #OSM_GPS_MAP_CACHE_DISABLED, #OSM_GPS_MAP_CACHE_AUTO,
2265 * #OSM_GPS_MAP_CACHE_FRIENDLY. Also see #OsmGpsMap:tile-cache-base for a
2266 * full understanding.
2267 *
2268 * #OSM_GPS_MAP_CACHE_DISABLED disables the on disk tile cache (so all tiles
2269 * are fetched from the network. #OSM_GPS_MAP_CACHE_AUTO causes the tile
2270 * cache to be /tile-cache-base/md5(repo-uri), where md5 is the md5sum
2271 * of #OsmGpsMap:repo-uri. #OSM_GPS_MAP_CACHE_FRIENDLY
2272 * causes the tile cache to be /tile-cache-base/friendlyname(repo-uri).
2273 *
2274 * Any other string is interpreted as a local path, i.e. /path/to/cache
2275 **/
2276 g_object_class_install_property (object_class,
2277 PROP_TILE_CACHE_DIR,
2278 g_param_spec_string ("tile-cache",
2279 "tile cache",
2280 "Tile cache dir",
2281 OSM_GPS_MAP_CACHE_AUTO,
2282 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
2283
2284 /**
2285 * OsmGpsMap:tile-cache-base:
2286 *
2287 * The base directory of the tile cache when you have constructed
2288 * the map with #OsmGpsMap:tile-cache set to #OSM_GPS_MAP_CACHE_AUTO or
2289 * #OSM_GPS_MAP_CACHE_FRIENDLY
2290 *
2291 * The string is interpreted as a local path, i.e. /path/to/cache
2292 **/
2293 g_object_class_install_property (object_class,
2294 PROP_TILE_CACHE_BASE_DIR,
2295 g_param_spec_string ("tile-cache-base",
2296 "tile cache-base",
2297 "Base directory to which friendly and auto paths are appended",
2298 NULL,
2299 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
2300
2301 /**
2302 * OsmGpsMap:tile-cache-is-full-path:
2303 *
2304 * Deprecated: Use #OsmGpsMap:tile-cache and #OsmGpsMap:tile-cache-base instead
2305 **/
2306 g_object_class_install_property (object_class,
2307 PROP_TILE_CACHE_DIR_IS_FULL_PATH,
2308 g_param_spec_boolean ("tile-cache-is-full-path",
2309 "tile cache is full path",
2310 "",
2311 FALSE,
2312 G_PARAM_READABLE | G_PARAM_WRITABLE));
2313
2314 /**
2315 * OsmGpsMap:zoom:
2316 *
2317 * The map zoom level. Connect to ::notify::zoom if you want to be informed
2318 * when this changes.
2319 **/
2320 g_object_class_install_property (object_class,
2321 PROP_ZOOM,
2322 g_param_spec_int ("zoom",
2323 "zoom",
2324 "Map zoom level",
2325 MIN_ZOOM, /* minimum property value */
2326 MAX_ZOOM, /* maximum property value */
2327 3,
2328 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
2329
2330 g_object_class_install_property (object_class,
2331 PROP_MAX_ZOOM,
2332 g_param_spec_int ("max-zoom",
2333 "max zoom",
2334 "Maximum zoom level",
2335 MIN_ZOOM, /* minimum property value */
2336 MAX_ZOOM, /* maximum property value */
2337 OSM_MAX_ZOOM,
2338 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
2339
2340 g_object_class_install_property (object_class,
2341 PROP_MIN_ZOOM,
2342 g_param_spec_int ("min-zoom",
2343 "min zoom",
2344 "Minimum zoom level",
2345 MIN_ZOOM, /* minimum property value */
2346 MAX_ZOOM, /* maximum property value */
2347 OSM_MIN_ZOOM,
2348 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
2349
2350 g_object_class_install_property (object_class,
2351 PROP_LATITUDE,
2352 g_param_spec_float ("latitude",
2353 "latitude",
2354 "Latitude in degrees",
2355 -90.0, /* minimum property value */
2356 90.0, /* maximum property value */
2357 0,
2358 G_PARAM_READABLE));
2359
2360 g_object_class_install_property (object_class,
2361 PROP_LONGITUDE,
2362 g_param_spec_float ("longitude",
2363 "longitude",
2364 "Longitude in degrees",
2365 -180.0, /* minimum property value */
2366 180.0, /* maximum property value */
2367 0,
2368 G_PARAM_READABLE));
2369
2370 g_object_class_install_property (object_class,
2371 PROP_MAP_X,
2372 g_param_spec_int ("map-x",
2373 "map-x",
2374 "Initial map x location",
2375 G_MININT, /* minimum property value */
2376 G_MAXINT, /* maximum property value */
2377 890,
2378 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
2379
2380 g_object_class_install_property (object_class,
2381 PROP_MAP_Y,
2382 g_param_spec_int ("map-y",
2383 "map-y",
2384 "Initial map y location",
2385 G_MININT, /* minimum property value */
2386 G_MAXINT, /* maximum property value */
2387 515,
2388 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
2389
2390 /**
2391 * OsmGpsMap:tiles-queued:
2392 *
2393 * The number of tiles currently waiting to download. Connect to
2394 * ::notify::tiles-queued if you want to be informed when this changes
2395 **/
2396 g_object_class_install_property (object_class,
2397 PROP_TILES_QUEUED,
2398 g_param_spec_int ("tiles-queued",
2399 "tiles-queued",
2400 "The number of tiles currently waiting to download",
2401 G_MININT, /* minimum property value */
2402 G_MAXINT, /* maximum property value */
2403 0,
2404 G_PARAM_READABLE));
2405
2406 g_object_class_install_property (object_class,
2407 PROP_GPS_TRACK_WIDTH,
2408 g_param_spec_float ("gps-track-width",
2409 "gps-track-width",
2410 "The width of the lines drawn for the gps track",
2411 1.0, /* minimum property value */
2412 100.0, /* maximum property value */
2413 4.0,
2414 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
2415
2416 g_object_class_install_property (object_class,
2417 PROP_GPS_POINT_R1,
2418 g_param_spec_int ("gps-track-point-radius",
2419 "gps-track-point-radius",
2420 "The radius of the gps point inner circle",
2421 0, /* minimum property value */
2422 G_MAXINT, /* maximum property value */
2423 5,
2424 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
2425
2426 g_object_class_install_property (object_class,
2427 PROP_GPS_POINT_R2,
2428 g_param_spec_int ("gps-track-highlight-radius",
2429 "gps-track-highlight-radius",
2430 "The radius of the gps point highlight circle",
2431 0, /* minimum property value */
2432 G_MAXINT, /* maximum property value */
2433 20,
2434 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
2435
2436 /**
2437 * OsmGpsMap:map-source:
2438 *
2439 * A #OsmGpsMapSource_t representing the tile repository to use
2440 *
2441 * <note>
2442 * <para>
2443 * If you do not wish to use the default map tiles (provided by OpenStreeMap)
2444 * it is recommened that you set this property at construction, instead
2445 * of setting #OsmGpsMap:repo-uri.
2446 * </para>
2447 * </note>
2448 **/
2449 g_object_class_install_property (object_class,
2450 PROP_MAP_SOURCE,
2451 g_param_spec_int ("map-source",
2452 "map source",
2453 "The map source ID",
2454 -1, /* minimum property value */
2455 G_MAXINT, /* maximum property value */
2456 -1,
2457 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
2458
2459 g_object_class_install_property (object_class,
2460 PROP_IMAGE_FORMAT,
2461 g_param_spec_string ("image-format",
2462 "image format",
2463 "The map source tile repository image format (jpg, png)",
2464 OSM_IMAGE_FORMAT,
2465 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
2466
2467 g_object_class_install_property (object_class,
2468 PROP_DRAG_LIMIT,
2469 g_param_spec_int ("drag-limit",
2470 "drag limit",
2471 "The number of pixels the user has to move the pointer in order to start dragging",
2472 0, /* minimum property value */
2473 G_MAXINT, /* maximum property value */
2474 10,
2475 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
2476
2477 /**
2478 * OsmGpsMap::changed:
2479 *
2480 * The #OsmGpsMap::changed signal is emitted any time the map zoom or map center
2481 * is chaged (such as by dragging or zooming).
2482 *
2483 * <note>
2484 * <para>
2485 * If you are only interested in the map zoom, then you can simply connect
2486 * to ::notify::zoom
2487 * </para>
2488 * </note>
2489 **/
2490 g_signal_new ("changed", OSM_TYPE_GPS_MAP,
2491 G_SIGNAL_RUN_FIRST, 0, NULL, NULL,
2492 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2493 }
2494
2495 /**
2496 * osm_gps_map_download_maps:
2497 *
2498 * Downloads all tiles over the supplied zoom range in the rectangular
2499 * region specified by pt1 (north west corner) to pt2 (south east corner)
2500 *
2501 **/
2502 void
2503 osm_gps_map_download_maps (OsmGpsMap *map, OsmGpsMapPoint *pt1, OsmGpsMapPoint *pt2, int zoom_start, int zoom_end)
2504 {
2505 OsmGpsMapPrivate *priv = map->priv;
2506
2507 if (pt1 && pt2) {
2508 gchar *filename;
2509 int i,j,zoom;
2510 int num_tiles = 0;
2511 zoom_end = CLAMP(zoom_end, priv->min_zoom, priv->max_zoom);
2512
2513 for(zoom=zoom_start; zoom<=zoom_end; zoom++) {
2514 int x1,y1,x2,y2;
2515
2516 x1 = (int)floor((float)lon2pixel(zoom, pt1->rlon) / (float)TILESIZE);
2517 y1 = (int)floor((float)lat2pixel(zoom, pt1->rlat) / (float)TILESIZE);
2518
2519 x2 = (int)floor((float)lon2pixel(zoom, pt2->rlon) / (float)TILESIZE);
2520 y2 = (int)floor((float)lat2pixel(zoom, pt2->rlat) / (float)TILESIZE);
2521
2522 /* loop x1-x2 */
2523 for(i=x1; i<=x2; i++) {
2524 /* loop y1 - y2 */
2525 for(j=y1; j<=y2; j++) {
2526 /* x = i, y = j */
2527 filename = g_strdup_printf("%s%c%d%c%d%c%d.%s",
2528 priv->cache_dir, G_DIR_SEPARATOR,
2529 zoom, G_DIR_SEPARATOR,
2530 i, G_DIR_SEPARATOR,
2531 j,
2532 priv->image_format);
2533 if (!g_file_test(filename, G_FILE_TEST_EXISTS)) {
2534 osm_gps_map_download_tile(map, zoom, i, j, FALSE);
2535 num_tiles++;
2536 }
2537 g_free(filename);
2538 }
2539 }
2540 g_debug("DL @Z:%d = %d tiles", zoom, num_tiles);
2541 }
2542 }
2543 }
2544
2545 static void
2546 cancel_message (char *key, SoupMessage *value, SoupSession *user_data)
2547 {
2548 soup_session_cancel_message (user_data, value, SOUP_STATUS_CANCELLED);
2549 }
2550
2551 /**
2552 * osm_gps_map_download_cancel_all:
2553 *
2554 * Cancels all tiles currently being downloaded. Typically used if you wish to
2555 * cacel a large number of tiles queued using osm_gps_map_download_maps()
2556 *
2557 * Since: 0.7.0
2558 **/
2559 void
2560 osm_gps_map_download_cancel_all (OsmGpsMap *map)
2561 {
2562 OsmGpsMapPrivate *priv = map->priv;
2563 g_hash_table_foreach (priv->tile_queue, (GHFunc)cancel_message, priv->soup_session);
2564 }
2565
2566 /**
2567 * osm_gps_map_get_bbox:
2568 * @pt1: point to be filled with the top left location
2569 * @pt2: point to be filled with the bottom right location
2570 *
2571 * Returns the geographic locations of the bounding box describing the contents
2572 * of the current window, i.e the top left and bottom right corners.
2573 **/
2574 void
2575 osm_gps_map_get_bbox (OsmGpsMap *map, OsmGpsMapPoint *pt1, OsmGpsMapPoint *pt2)
2576 {
2577 GtkAllocation allocation;
2578 OsmGpsMapPrivate *priv = map->priv;
2579
2580 if (pt1 && pt2) {
2581 gtk_widget_get_allocation(GTK_WIDGET(map), &allocation);
2582 pt1->rlat = pixel2lat(priv->map_zoom, priv->map_y);
2583 pt1->rlon = pixel2lon(priv->map_zoom, priv->map_x);
2584 pt2->rlat = pixel2lat(priv->map_zoom, priv->map_y + allocation.height);
2585 pt2->rlon = pixel2lon(priv->map_zoom, priv->map_x + allocation.width);
2586 }
2587 }
2588
2589 /**
2590 * osm_gps_map_set_center_and_zoom:
2591 *
2592 * Since: 0.7.0
2593 **/
2594 void osm_gps_map_set_center_and_zoom (OsmGpsMap *map, float latitude, float longitude, int zoom)
2595 {
2596 osm_gps_map_set_center (map, latitude, longitude);
2597 osm_gps_map_set_zoom (map, zoom);
2598 }
2599
2600 /**
2601 * osm_gps_map_set_center:
2602 *
2603 **/
2604 void
2605 osm_gps_map_set_center (OsmGpsMap *map, float latitude, float longitude)
2606 {
2607 int pixel_x, pixel_y;
2608 OsmGpsMapPrivate *priv;
2609 GtkAllocation allocation;
2610
2611 g_return_if_fail (OSM_IS_GPS_MAP (map));
2612
2613 priv = map->priv;
2614 gtk_widget_get_allocation(GTK_WIDGET(map), &allocation);
2615 g_object_set(G_OBJECT(map), "auto-center", FALSE, NULL);
2616
2617 priv->center_rlat = deg2rad(latitude);
2618 priv->center_rlon = deg2rad(longitude);
2619
2620 pixel_x = lon2pixel(priv->map_zoom, priv->center_rlon);
2621 pixel_y = lat2pixel(priv->map_zoom, priv->center_rlat);
2622
2623 priv->map_x = pixel_x - allocation.width/2;
2624 priv->map_y = pixel_y - allocation.height/2;
2625
2626 osm_gps_map_map_redraw_idle(map);
2627
2628 g_signal_emit_by_name(map, "changed");
2629 }
2630
2631 /**
2632 * osm_gps_map_set_zoom:
2633 *
2634 **/
2635 int
2636 osm_gps_map_set_zoom (OsmGpsMap *map, int zoom)
2637 {
2638 int width_center, height_center;
2639 OsmGpsMapPrivate *priv;
2640 GtkAllocation allocation;
2641
2642 g_return_val_if_fail (OSM_IS_GPS_MAP (map), 0);
2643 priv = map->priv;
2644
2645 if (zoom != priv->map_zoom)
2646 {
2647 gtk_widget_get_allocation(GTK_WIDGET(map), &allocation);
2648 width_center = allocation.width / 2;
2649 height_center = allocation.height / 2;
2650
2651 /* update zoom but constrain [min_zoom..max_zoom] */
2652 priv->map_zoom = CLAMP(zoom, priv->min_zoom, priv->max_zoom);
2653 priv->map_x = lon2pixel(priv->map_zoom, priv->center_rlon) - width_center;
2654 priv->map_y = lat2pixel(priv->map_zoom, priv->center_rlat) - height_center;
2655
2656 osm_gps_map_map_redraw_idle(map);
2657
2658 g_signal_emit_by_name(map, "changed");
2659 g_object_notify(G_OBJECT(map), "zoom");
2660 }
2661 return priv->map_zoom;
2662 }
2663
2664 /**
2665 * osm_gps_map_zoom_in:
2666 *
2667 **/
2668 int
2669 osm_gps_map_zoom_in (OsmGpsMap *map)
2670 {
2671 g_return_val_if_fail (OSM_IS_GPS_MAP (map), 0);
2672 return osm_gps_map_set_zoom(map, map->priv->map_zoom+1);
2673 }
2674
2675 /**
2676 * osm_gps_map_zoom_out:
2677 *
2678 **/
2679 int
2680 osm_gps_map_zoom_out (OsmGpsMap *map)
2681 {
2682 g_return_val_if_fail (OSM_IS_GPS_MAP (map), 0);
2683 return osm_gps_map_set_zoom(map, map->priv->map_zoom-1);
2684 }
2685
2686 GtkWidget *
2687 osm_gps_map_new (void)
2688 {
2689 return g_object_new (OSM_TYPE_GPS_MAP, NULL);
2690 }
2691
2692 /**
2693 * osm_gps_map_scroll:
2694 * @map:
2695 * @dx:
2696 * @dy:
2697 *
2698 * Scrolls the map by @dx, @dy pixels (positive north, east)
2699 *
2700 **/
2701 void
2702 osm_gps_map_scroll (OsmGpsMap *map, gint dx, gint dy)
2703 {
2704 OsmGpsMapPrivate *priv;
2705
2706 g_return_if_fail (OSM_IS_GPS_MAP (map));
2707 priv = map->priv;
2708
2709 priv->map_x += dx;
2710 priv->map_y += dy;
2711 center_coord_update(map);
2712
2713 osm_gps_map_map_redraw_idle (map);
2714 }
2715
2716 /**
2717 * osm_gps_map_get_scale:
2718 * @map:
2719 *
2720 * Returns: the scale of the map at the center, in meters/pixel.
2721 *
2722 **/
2723 float
2724 osm_gps_map_get_scale (OsmGpsMap *map)
2725 {
2726 OsmGpsMapPrivate *priv;
2727
2728 g_return_val_if_fail (OSM_IS_GPS_MAP (map), OSM_GPS_MAP_INVALID);
2729 priv = map->priv;
2730
2731 return osm_gps_map_get_scale_at_point(priv->map_zoom, priv->center_rlat, priv->center_rlon);
2732 }
2733
2734 /**
2735 * osm_gps_map_get_default_cache_directory:
2736 *
2737 * Returns: the default cache directory for the library, that is the base
2738 * directory to which the full cache path is appended. If
2739 * #OsmGpsMap:tile-cache-base is omitted from the constructor then this value
2740 * is used.
2741 *
2742 **/
2743 gchar *
2744 osm_gps_map_get_default_cache_directory (void)
2745 {
2746 return g_build_filename(
2747 g_get_user_cache_dir(),
2748 "osmgpsmap",
2749 NULL);
2750 }
2751
2752 /**
2753 * osm_gps_map_set_keyboard_shortcut:
2754 * @key: a #OsmGpsMapKey_t
2755 * @keyval:
2756 *
2757 * Associates a keyboard shortcut with the supplied @keyval
2758 * (as returned by #gdk_keyval_from_name or simiar). The action given in @key
2759 * will be triggered when the corresponding @keyval is pressed. By default
2760 * no keyboard shortcuts are associated.
2761 *
2762 **/
2763 void
2764 osm_gps_map_set_keyboard_shortcut (OsmGpsMap *map, OsmGpsMapKey_t key, guint keyval)
2765 {
2766 g_return_if_fail (OSM_IS_GPS_MAP (map));
2767 g_return_if_fail(key < OSM_GPS_MAP_KEY_MAX);
2768
2769 map->priv->keybindings[key] = keyval;
2770 map->priv->keybindings_enabled = TRUE;
2771 }
2772
2773 /**
2774 * osm_gps_map_track_add:
2775 *
2776 * Since: 0.7.0
2777 **/
2778 void
2779 osm_gps_map_track_add (OsmGpsMap *map, OsmGpsMapTrack *track)
2780 {
2781 OsmGpsMapPrivate *priv;
2782
2783 g_return_if_fail (OSM_IS_GPS_MAP (map));
2784 priv = map->priv;
2785
2786 g_object_ref(track);
2787 g_signal_connect(track, "point-added",
2788 G_CALLBACK(on_gps_point_added), map);
2789 g_signal_connect(track, "notify",
2790 G_CALLBACK(on_track_changed), map);
2791
2792 priv->tracks = g_slist_append(priv->tracks, track);
2793 osm_gps_map_map_redraw_idle(map);
2794 }
2795
2796 /**
2797 * osm_gps_map_track_remove_all:
2798 *
2799 * Since: 0.7.0
2800 **/
2801 void
2802 osm_gps_map_track_remove_all (OsmGpsMap *map)
2803 {
2804 g_return_if_fail (OSM_IS_GPS_MAP (map));
2805
2806 gslist_of_gobjects_free(&map->priv->tracks);
2807 osm_gps_map_map_redraw_idle(map);
2808 }
2809
2810 /**
2811 * osm_gps_map_track_remove:
2812 *
2813 * Since: 0.7.0
2814 **/
2815 gboolean
2816 osm_gps_map_track_remove (OsmGpsMap *map, OsmGpsMapTrack *track)
2817 {
2818 GSList *data;
2819
2820 g_return_val_if_fail (OSM_IS_GPS_MAP (map), FALSE);
2821 g_return_val_if_fail (track != NULL, FALSE);
2822
2823 data = gslist_remove_one_gobject (&map->priv->tracks, G_OBJECT(track));
2824 osm_gps_map_map_redraw_idle(map);
2825 return data != NULL;
2826 }
2827
2828 /**
2829 * osm_gps_map_gps_clear:
2830 *
2831 * Since: 0.7.0
2832 **/
2833 void
2834 osm_gps_map_gps_clear (OsmGpsMap *map)
2835 {
2836 OsmGpsMapPrivate *priv;
2837
2838 g_return_if_fail (OSM_IS_GPS_MAP (map));
2839 priv = map->priv;
2840
2841 g_object_unref(priv->gps_track);
2842 priv->gps_track = osm_gps_map_track_new();
2843 g_signal_connect(priv->gps_track, "point-added",
2844 G_CALLBACK(on_gps_point_added), map);
2845 g_signal_connect(priv->gps_track, "notify",
2846 G_CALLBACK(on_track_changed), map);
2847 osm_gps_map_map_redraw_idle(map);
2848 }
2849
2850 /**
2851 * osm_gps_map_gps_get_track:
2852 *
2853 * Returns: (transfer none): The #OsmGpsMapTrack of the internal GPS track,
2854 * i.e. that which is modified when calling osm_gps_map_gps_add(). You must
2855 * not free this.
2856 * Since: 0.7.0
2857 **/
2858 OsmGpsMapTrack *
2859 osm_gps_map_gps_get_track (OsmGpsMap *map)
2860 {
2861 g_return_val_if_fail (OSM_IS_GPS_MAP (map), NULL);
2862 return map->priv->gps_track;
2863 }
2864
2865 /**
2866 * osm_gps_map_gps_add:
2867 * @latitude: degrees
2868 * @longitude: degrees
2869 * @heading: degrees or #OSM_GPS_MAP_INVALID to disable showing heading
2870 *
2871 * Since: 0.7.0
2872 **/
2873 void
2874 osm_gps_map_gps_add (OsmGpsMap *map, float latitude, float longitude, float heading)
2875 {
2876 OsmGpsMapPoint *point;
2877 OsmGpsMapPrivate *priv;
2878
2879 g_return_if_fail (OSM_IS_GPS_MAP (map));
2880 priv = map->priv;
2881
2882 /* update the current point */
2883 priv->gps->rlat = deg2rad(latitude);
2884 priv->gps->rlon = deg2rad(longitude);
2885 priv->gps_track_used = TRUE;
2886 priv->gps_heading = deg2rad(heading);
2887
2888 /* If trip marker add to list of gps points */
2889 if (priv->trip_history_record_enabled) {
2890 point = osm_gps_map_point_new_degrees(latitude, longitude);
2891 /* this will cause a redraw to be scheduled */
2892 osm_gps_map_track_add_point (priv->gps_track, point);
2893 } else {
2894 osm_gps_map_map_redraw_idle (map);
2895 maybe_autocenter_map (map);
2896 }
2897 }
2898
2899 /**
2900 * osm_gps_map_image_add:
2901 *
2902 * Returns: (transfer full): A #OsmGpsMapImage representing the added pixbuf
2903 * Since: 0.7.0
2904 **/
2905 OsmGpsMapImage *
2906 osm_gps_map_image_add (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image)
2907 {
2908 return osm_gps_map_image_add_with_alignment (map, latitude, longitude, image, 0.5, 0.5);
2909 }
2910
2911 static void
2912 on_image_changed (OsmGpsMapImage *image, GParamSpec *pspec, OsmGpsMap *map)
2913 {
2914 osm_gps_map_map_redraw_idle (map);
2915 }
2916
2917 /**
2918 * osm_gps_map_image_add_with_alignment:
2919 *
2920 * Returns: (transfer full): A #OsmGpsMapImage representing the added pixbuf
2921 * Since: 0.7.0
2922 **/
2923 OsmGpsMapImage *
2924 osm_gps_map_image_add_with_alignment (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image, float xalign, float yalign)
2925 {
2926 OsmGpsMapImage *im;
2927 OsmGpsMapPoint pt;
2928
2929 g_return_val_if_fail (OSM_IS_GPS_MAP (map), NULL);
2930 pt.rlat = deg2rad(latitude);
2931 pt.rlon = deg2rad(longitude);
2932
2933 im = g_object_new (OSM_TYPE_GPS_MAP_IMAGE, "pixbuf", image, "x-align", xalign, "y-align", yalign, "point", &pt, NULL);
2934 g_signal_connect(im, "notify",
2935 G_CALLBACK(on_image_changed), map);
2936
2937 map->priv->images = g_slist_append(map->priv->images, im);
2938 osm_gps_map_map_redraw_idle(map);
2939 return im;
2940 }
2941
2942 /**
2943 * osm_gps_map_image_remove:
2944 *
2945 * Since: 0.7.0
2946 **/
2947 gboolean
2948 osm_gps_map_image_remove (OsmGpsMap *map, OsmGpsMapImage *image)
2949 {
2950 GSList *data;
2951
2952 g_return_val_if_fail (OSM_IS_GPS_MAP (map), FALSE);
2953 g_return_val_if_fail (image != NULL, FALSE);
2954
2955 data = gslist_remove_one_gobject (&map->priv->images, G_OBJECT(image));
2956 osm_gps_map_map_redraw_idle(map);
2957 return data != NULL;
2958 }
2959
2960 /**
2961 * osm_gps_map_image_remove_all:
2962 *
2963 * Since: 0.7.0
2964 **/
2965 void
2966 osm_gps_map_image_remove_all (OsmGpsMap *map)
2967 {
2968 g_return_if_fail (OSM_IS_GPS_MAP (map));
2969
2970 gslist_of_gobjects_free(&map->priv->images);
2971 osm_gps_map_map_redraw_idle(map);
2972 }
2973
2974 /**
2975 * osm_gps_map_layer_add:
2976 * @layer: a #OsmGpsMapLayer object
2977 *
2978 * Since: 0.7.0
2979 **/
2980 void
2981 osm_gps_map_layer_add (OsmGpsMap *map, OsmGpsMapLayer *layer)
2982 {
2983 g_return_if_fail (OSM_IS_GPS_MAP (map));
2984 g_return_if_fail (OSM_GPS_MAP_IS_LAYER (layer));
2985
2986 g_object_ref(G_OBJECT(layer));
2987 map->priv->layers = g_slist_append(map->priv->layers, layer);
2988 }
2989
2990 /**
2991 * osm_gps_map_layer_remove:
2992 * @layer: a #OsmGpsMapLayer object
2993 *
2994 * Since: 0.7.0
2995 **/
2996 gboolean
2997 osm_gps_map_layer_remove (OsmGpsMap *map, OsmGpsMapLayer *layer)
2998 {
2999 GSList *data;
3000
3001 g_return_val_if_fail (OSM_IS_GPS_MAP (map), FALSE);
3002 g_return_val_if_fail (layer != NULL, FALSE);
3003
3004 data = gslist_remove_one_gobject (&map->priv->layers, G_OBJECT(layer));
3005 osm_gps_map_map_redraw_idle(map);
3006 return data != NULL;
3007 }
3008
3009 /**
3010 * osm_gps_map_layer_remove:
3011 * @layer: a #OsmGpsMapLayer object
3012 *
3013 * Since: 0.7.0
3014 **/
3015 void
3016 osm_gps_map_layer_remove_all (OsmGpsMap *map)
3017 {
3018 g_return_if_fail (OSM_IS_GPS_MAP (map));
3019
3020 gslist_of_gobjects_free(&map->priv->layers);
3021 osm_gps_map_map_redraw_idle(map);
3022 }
3023
3024 /**
3025 * osm_gps_map_convert_screen_to_geographic:
3026 * @map:
3027 * @pixel_x: pixel location on map, x axis
3028 * @pixel_y: pixel location on map, y axis
3029 * @pt: (out): location
3030 *
3031 * Convert the given pixel location on the map into corresponding
3032 * location on the globe
3033 *
3034 * Since: 0.7.0
3035 **/
3036 void
3037 osm_gps_map_convert_screen_to_geographic(OsmGpsMap *map, gint pixel_x, gint pixel_y, OsmGpsMapPoint *pt)
3038 {
3039 OsmGpsMapPrivate *priv;
3040
3041 g_return_if_fail (OSM_IS_GPS_MAP (map));
3042 g_return_if_fail (pt);
3043 priv = map->priv;
3044
3045 pt->rlat = pixel2lat(priv->map_zoom, priv->map_y + pixel_y);
3046 pt->rlon = pixel2lon(priv->map_zoom, priv->map_x + pixel_x);
3047 }
3048
3049 /**
3050 * osm_gps_map_convert_geographic_to_screen:
3051 * @map:
3052 * @pt: location
3053 * @pixel_x: (out): pixel location on map, x axis
3054 * @pixel_y: (out): pixel location on map, y axis
3055 *
3056 * Convert the given location on the globe to the corresponding
3057 * pixel locations on the map.
3058 *
3059 * Since: 0.7.0
3060 **/
3061 void
3062 osm_gps_map_convert_geographic_to_screen(OsmGpsMap *map, OsmGpsMapPoint *pt, gint *pixel_x, gint *pixel_y)
3063 {
3064 OsmGpsMapPrivate *priv;
3065
3066 g_return_if_fail (OSM_IS_GPS_MAP (map));
3067 g_return_if_fail (pt);
3068 priv = map->priv;
3069
3070 if (pixel_x)
3071 *pixel_x = lon2pixel(priv->map_zoom, pt->rlon) - priv->map_x + priv->drag_mouse_dx;
3072 if (pixel_y)
3073 *pixel_y = lat2pixel(priv->map_zoom, pt->rlat) - priv->map_y + priv->drag_mouse_dy;
3074 }
3075
3076 /**
3077 * osm_gps_map_get_event_location:
3078 * @map:
3079 * @event: A #GtkEventButton that occured on the map
3080 *
3081 * A convenience function for getting the geographic location of events,
3082 * such as mouse clicks, on the map
3083 *
3084 * Returns: (transfer full): The point on the globe corresponding to the click
3085 * Since: 0.7.0
3086 **/
3087 OsmGpsMapPoint *
3088 osm_gps_map_get_event_location (OsmGpsMap *map, GdkEventButton *event)
3089 {
3090 OsmGpsMapPoint *p = osm_gps_map_point_new_degrees(0.0,0.0);
3091 osm_gps_map_convert_screen_to_geographic(map, event->x, event->y, p);
3092 return p;
3093 }
3094
3095 /**
3096 * osm_gps_map_remove_image:
3097 *
3098 * Deprecated: 0.7.0: Use osm_gps_map_image_remove() instead.
3099 **/
3100 gboolean
3101 osm_gps_map_remove_image (OsmGpsMap *map, GdkPixbuf *image)
3102 {
3103 GSList *tmp;
3104 OsmGpsMapImage *im;
3105
3106 g_critical("%s is deprecated", G_STRFUNC);
3107
3108 im = NULL;
3109 tmp = map->priv->images;
3110 while (tmp != NULL) {
3111 GdkPixbuf *p;
3112 im = tmp->data;
3113 /* g_object_get ref's the pixbuf */
3114 g_object_get (im, "pixbuf", &p, NULL);
3115 if (p == image) {
3116 g_object_unref (p);
3117 break;
3118 }
3119 g_object_unref (p);
3120 tmp = g_slist_next(tmp);
3121 }
3122
3123 /* we found the image */
3124 if (tmp && im)
3125 return osm_gps_map_image_remove (map, im);
3126
3127 return FALSE;
3128 }
3129
3130 /**
3131 * osm_gps_map_replace_track:
3132 *
3133 * Deprecated: 0.7.0: Use osm_gps_map_track_remove() and osm_gps_map_track_add()
3134 * or just edit the #OsmGpsMapTrack object directly
3135 **/
3136 void
3137 osm_gps_map_replace_track (OsmGpsMap *map, GSList *old_track, GSList *new_track)
3138 {
3139 GSList *tmp;
3140 OsmGpsMapTrack *track;
3141
3142 g_critical("%s is deprecated", G_STRFUNC);
3143
3144 track = NULL;
3145 tmp = map->priv->tracks;
3146 while (tmp != NULL) {
3147 GSList *l;
3148 track = tmp->data;
3149 g_object_get (track, "track", &l, NULL);
3150 if (l == old_track)
3151 break;
3152 tmp = g_slist_next(tmp);
3153 }
3154
3155 /* we found the track */
3156 if (tmp && track) {
3157 osm_gps_map_track_remove (map, track);
3158 track = g_object_new (OSM_TYPE_GPS_MAP_TRACK, "track", new_track, NULL);
3159 osm_gps_map_track_add (map, track);
3160 }
3161 }
3162
0 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */
1 /* vim:set et sw=4 ts=4 cino=t0,(0: */
2 /*
3 * osm-gps-map-widget.h
4 * Copyright (C) Marcus Bauer 2008 <marcus.bauer@gmail.com>
5 * Copyright (C) John Stowers 2009 <john.stowers@gmail.com>
6 * Copyright (C) Till Harbaum 2009 <till@harbaum.org>
7 *
8 * Contributions by
9 * Everaldo Canuto 2009 <everaldo.canuto@gmail.com>
10 *
11 * This is free software: you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; version 2.
14 *
15 * This program 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.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #ifndef _OSM_GPS_MAP_WIDGET_H_
25 #define _OSM_GPS_MAP_WIDGET_H_
26
27 #include <glib.h>
28 #include <glib-object.h>
29 #include <gtk/gtk.h>
30 #include <gdk-pixbuf/gdk-pixbuf.h>
31
32 G_BEGIN_DECLS
33
34 #define OSM_TYPE_GPS_MAP (osm_gps_map_get_type ())
35 #define OSM_GPS_MAP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), OSM_TYPE_GPS_MAP, OsmGpsMap))
36 #define OSM_GPS_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), OSM_TYPE_GPS_MAP, OsmGpsMapClass))
37 #define OSM_IS_GPS_MAP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OSM_TYPE_GPS_MAP))
38 #define OSM_IS_GPS_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OSM_TYPE_GPS_MAP))
39 #define OSM_GPS_MAP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OSM_TYPE_GPS_MAP, OsmGpsMapClass))
40
41 typedef struct _OsmGpsMapClass OsmGpsMapClass;
42 typedef struct _OsmGpsMap OsmGpsMap;
43 typedef struct _OsmGpsMapPrivate OsmGpsMapPrivate;
44
45 #include "osm-gps-map-layer.h"
46 #include "osm-gps-map-point.h"
47 #include "osm-gps-map-track.h"
48 #include "osm-gps-map-image.h"
49
50 struct _OsmGpsMapClass
51 {
52 GtkDrawingAreaClass parent_class;
53
54 void (*draw_gps_point) (OsmGpsMap *map, GdkDrawable *drawable);
55 };
56
57 struct _OsmGpsMap
58 {
59 GtkDrawingArea parent_instance;
60 OsmGpsMapPrivate *priv;
61 };
62
63 typedef enum {
64 OSM_GPS_MAP_KEY_FULLSCREEN,
65 OSM_GPS_MAP_KEY_ZOOMIN,
66 OSM_GPS_MAP_KEY_ZOOMOUT,
67 OSM_GPS_MAP_KEY_UP,
68 OSM_GPS_MAP_KEY_DOWN,
69 OSM_GPS_MAP_KEY_LEFT,
70 OSM_GPS_MAP_KEY_RIGHT,
71 OSM_GPS_MAP_KEY_MAX
72 } OsmGpsMapKey_t;
73
74 #define OSM_GPS_MAP_INVALID (0.0/0.0)
75 #define OSM_GPS_MAP_CACHE_DISABLED "none://"
76 #define OSM_GPS_MAP_CACHE_AUTO "auto://"
77 #define OSM_GPS_MAP_CACHE_FRIENDLY "friendly://"
78
79 GType osm_gps_map_get_type (void) G_GNUC_CONST;
80
81 GtkWidget* osm_gps_map_new (void);
82
83 gchar* osm_gps_map_get_default_cache_directory (void);
84
85 void osm_gps_map_download_maps (OsmGpsMap *map, OsmGpsMapPoint *pt1, OsmGpsMapPoint *pt2, int zoom_start, int zoom_end);
86 void osm_gps_map_download_cancel_all (OsmGpsMap *map);
87 void osm_gps_map_get_bbox (OsmGpsMap *map, OsmGpsMapPoint *pt1, OsmGpsMapPoint *pt2);
88 void osm_gps_map_set_center_and_zoom (OsmGpsMap *map, float latitude, float longitude, int zoom);
89 void osm_gps_map_set_center (OsmGpsMap *map, float latitude, float longitude);
90 int osm_gps_map_set_zoom (OsmGpsMap *map, int zoom);
91 int osm_gps_map_zoom_in (OsmGpsMap *map);
92 int osm_gps_map_zoom_out (OsmGpsMap *map);
93 void osm_gps_map_scroll (OsmGpsMap *map, gint dx, gint dy);
94 float osm_gps_map_get_scale (OsmGpsMap *map);
95 void osm_gps_map_set_keyboard_shortcut (OsmGpsMap *map, OsmGpsMapKey_t key, guint keyval);
96 void osm_gps_map_track_add (OsmGpsMap *map, OsmGpsMapTrack *track);
97 void osm_gps_map_track_remove_all (OsmGpsMap *map);
98 gboolean osm_gps_map_track_remove (OsmGpsMap *map, OsmGpsMapTrack *track);
99 void osm_gps_map_gps_add (OsmGpsMap *map, float latitude, float longitude, float heading);
100 void osm_gps_map_gps_clear (OsmGpsMap *map);
101 OsmGpsMapTrack *osm_gps_map_gps_get_track (OsmGpsMap *map);
102 OsmGpsMapImage *osm_gps_map_image_add (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image);
103 OsmGpsMapImage *osm_gps_map_image_add_with_alignment (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image, float xalign, float yalign);
104 gboolean osm_gps_map_image_remove (OsmGpsMap *map, OsmGpsMapImage *image);
105 void osm_gps_map_image_remove_all (OsmGpsMap *map);
106 void osm_gps_map_layer_add (OsmGpsMap *map, OsmGpsMapLayer *layer);
107 gboolean osm_gps_map_layer_remove (OsmGpsMap *map, OsmGpsMapLayer *layer);
108 void osm_gps_map_layer_remove_all (OsmGpsMap *map);
109 void osm_gps_map_convert_screen_to_geographic(OsmGpsMap *map, gint pixel_x, gint pixel_y, OsmGpsMapPoint *pt);
110 void osm_gps_map_convert_geographic_to_screen(OsmGpsMap *map, OsmGpsMapPoint *pt, gint *pixel_x, gint *pixel_y);
111 OsmGpsMapPoint *osm_gps_map_get_event_location (OsmGpsMap *map, GdkEventButton *event);
112
113 G_END_DECLS
114
115 #endif /* _OSM_GPS_MAP_WIDGET_H_ */
116
+0
-2859
src/osm-gps-map.c less more
0 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */
1 /* vim:set et sw=4 ts=4 cino=t0,(0: */
2 /*
3 * osm-gps-map.c
4 * Copyright (C) Marcus Bauer 2008 <marcus.bauer@gmail.com>
5 * Copyright (C) John Stowers 2009 <john.stowers@gmail.com>
6 * Copyright (C) Till Harbaum 2009 <till@harbaum.org>
7 *
8 * Contributions by
9 * Everaldo Canuto 2009 <everaldo.canuto@gmail.com>
10 *
11 * osm-gps-map.c is free software: you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; version 2.
14 *
15 * This program 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.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "config.h"
25
26 #include <fcntl.h>
27 #include <math.h>
28 #include <unistd.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include <gdk/gdk.h>
34 #include <glib.h>
35 #include <glib/gstdio.h>
36 #include <glib/gprintf.h>
37 #include <libsoup/soup.h>
38 #include <cairo.h>
39
40 #include "converter.h"
41 #include "osm-gps-map-types.h"
42 #include "osm-gps-map.h"
43
44 #define ENABLE_DEBUG (0)
45 #define EXTRA_BORDER (TILESIZE / 2)
46 #define OSM_GPS_MAP_SCROLL_STEP (10)
47 #define USER_AGENT "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11"
48
49 struct _OsmGpsMapPrivate
50 {
51 GHashTable *tile_queue;
52 GHashTable *missing_tiles;
53 GHashTable *tile_cache;
54
55 int map_zoom;
56 int max_zoom;
57 int min_zoom;
58 gboolean map_auto_center;
59 gboolean map_auto_download;
60 int map_x;
61 int map_y;
62
63 /* Latitude and longitude of the center of the map, in radians */
64 gfloat center_rlat;
65 gfloat center_rlon;
66
67 guint max_tile_cache_size;
68 /* Incremented at each redraw */
69 guint redraw_cycle;
70 /* ID of the idle redraw operation */
71 guint idle_map_redraw;
72
73 //how we download tiles
74 SoupSession *soup_session;
75 char *proxy_uri;
76
77 //where downloaded tiles are cached
78 char *tile_dir;
79 char *tile_base_dir;
80 char *cache_dir;
81
82 //contains flags indicating the various special characters
83 //the uri string contains, that will be replaced when calculating
84 //the uri to download.
85 OsmGpsMapSource_t map_source;
86 char *repo_uri;
87 char *image_format;
88 int uri_format;
89 //flag indicating if the map source is located on the google
90 gboolean the_google;
91
92 //gps tracking state
93 gboolean record_trip_history;
94 gboolean show_trip_history;
95 GSList *trip_history;
96 coord_t *gps;
97 float gps_heading;
98 gboolean gps_valid;
99
100 #ifdef OSD_DOUBLE_BUFFER
101 GdkPixmap *dbuf_pixmap;
102 #endif
103 //additional images or tracks added to the map
104 GSList *tracks;
105 GSList *images;
106
107 //Used for storing the joined tiles
108 GdkPixmap *pixmap;
109 GdkGC *gc_map;
110
111 //The tile painted when one cannot be found
112 GdkPixbuf *null_tile;
113
114 //A list of OsmGpsMapLayer* layers, such as the OSD
115 GSList *layers;
116
117 //For tracking click and drag
118 int drag_counter;
119 int drag_mouse_dx;
120 int drag_mouse_dy;
121 int drag_start_mouse_x;
122 int drag_start_mouse_y;
123 int drag_start_map_x;
124 int drag_start_map_y;
125 int drag_limit;
126 guint drag_expose;
127
128 //for customizing the redering of the gps track
129 int ui_gps_track_width;
130 int ui_gps_point_inner_radius;
131 int ui_gps_point_outer_radius;
132
133 //For storing keybindings
134 guint keybindings[OSM_GPS_MAP_KEY_MAX];
135
136 guint fullscreen : 1;
137 guint keybindings_enabled : 1;
138 guint is_disposed : 1;
139 guint dragging : 1;
140 guint button_down : 1;
141 };
142
143 #define OSM_GPS_MAP_PRIVATE(o) (OSM_GPS_MAP (o)->priv)
144
145 typedef struct
146 {
147 GdkPixbuf *pixbuf;
148 /* We keep track of the number of the redraw cycle this tile was last used,
149 * so that osm_gps_map_purge_cache() can remove the older ones */
150 guint redraw_cycle;
151 } OsmCachedTile;
152
153 enum
154 {
155 PROP_0,
156
157 PROP_AUTO_CENTER,
158 PROP_RECORD_TRIP_HISTORY,
159 PROP_SHOW_TRIP_HISTORY,
160 PROP_AUTO_DOWNLOAD,
161 PROP_REPO_URI,
162 PROP_PROXY_URI,
163 PROP_TILE_CACHE_DIR,
164 PROP_TILE_CACHE_BASE_DIR,
165 PROP_TILE_CACHE_DIR_IS_FULL_PATH,
166 PROP_ZOOM,
167 PROP_MAX_ZOOM,
168 PROP_MIN_ZOOM,
169 PROP_LATITUDE,
170 PROP_LONGITUDE,
171 PROP_MAP_X,
172 PROP_MAP_Y,
173 PROP_TILES_QUEUED,
174 PROP_GPS_TRACK_WIDTH,
175 PROP_GPS_POINT_R1,
176 PROP_GPS_POINT_R2,
177 PROP_MAP_SOURCE,
178 PROP_IMAGE_FORMAT,
179 PROP_DRAG_LIMIT,
180 };
181
182 G_DEFINE_TYPE (OsmGpsMap, osm_gps_map, GTK_TYPE_DRAWING_AREA);
183
184 /*
185 * Drawing function forward defintions
186 */
187 static gchar *replace_string(const gchar *src, const gchar *from, const gchar *to);
188 static void inspect_map_uri(OsmGpsMap *map);
189 static gchar *replace_map_uri(OsmGpsMap *map, const gchar *uri, int zoom, int x, int y);
190 static void osm_gps_map_print_images (OsmGpsMap *map);
191 static void osm_gps_map_draw_gps_point (OsmGpsMap *map);
192 static void osm_gps_map_blit_tile(OsmGpsMap *map, GdkPixbuf *pixbuf, int offset_x, int offset_y);
193 #if USE_LIBSOUP22
194 static void osm_gps_map_tile_download_complete (SoupMessage *msg, gpointer user_data);
195 #else
196 static void osm_gps_map_tile_download_complete (SoupSession *session, SoupMessage *msg, gpointer user_data);
197 #endif
198 static void osm_gps_map_download_tile (OsmGpsMap *map, int zoom, int x, int y, gboolean redraw);
199 static void osm_gps_map_load_tile (OsmGpsMap *map, int zoom, int x, int y, int offset_x, int offset_y);
200 static void osm_gps_map_fill_tiles_pixel (OsmGpsMap *map);
201 static gboolean osm_gps_map_map_redraw (OsmGpsMap *map);
202 static void osm_gps_map_map_redraw_idle (OsmGpsMap *map);
203
204 static void
205 cached_tile_free (OsmCachedTile *tile)
206 {
207 g_object_unref (tile->pixbuf);
208 g_slice_free (OsmCachedTile, tile);
209 }
210
211 /*
212 * Description:
213 * Find and replace text within a string.
214 *
215 * Parameters:
216 * src (in) - pointer to source string
217 * from (in) - pointer to search text
218 * to (in) - pointer to replacement text
219 *
220 * Returns:
221 * Returns a pointer to dynamically-allocated memory containing string
222 * with occurences of the text pointed to by 'from' replaced by with the
223 * text pointed to by 'to'.
224 */
225 static gchar *
226 replace_string(const gchar *src, const gchar *from, const gchar *to)
227 {
228 size_t size = strlen(src) + 1;
229 size_t fromlen = strlen(from);
230 size_t tolen = strlen(to);
231
232 /* Allocate the first chunk with enough for the original string. */
233 gchar *value = g_malloc(size);
234
235
236 /* We need to return 'value', so let's make a copy to mess around with. */
237 gchar *dst = value;
238
239 if ( value != NULL )
240 {
241 for ( ;; )
242 {
243 /* Try to find the search text. */
244 const gchar *match = g_strstr_len(src, size, from);
245 if ( match != NULL )
246 {
247 gchar *temp;
248 /* Find out how many characters to copy up to the 'match'. */
249 size_t count = match - src;
250
251
252 /* Calculate the total size the string will be after the
253 * replacement is performed. */
254 size += tolen - fromlen;
255
256 temp = g_realloc(value, size);
257 if ( temp == NULL )
258 {
259 g_free(value);
260 return NULL;
261 }
262
263 /* we'll want to return 'value' eventually, so let's point it
264 * to the memory that we are now working with.
265 * And let's not forget to point to the right location in
266 * the destination as well. */
267 dst = temp + (dst - value);
268 value = temp;
269
270 /*
271 * Copy from the source to the point where we matched. Then
272 * move the source pointer ahead by the amount we copied. And
273 * move the destination pointer ahead by the same amount.
274 */
275 g_memmove(dst, src, count);
276 src += count;
277 dst += count;
278
279 /* Now copy in the replacement text 'to' at the position of
280 * the match. Adjust the source pointer by the text we replaced.
281 * Adjust the destination pointer by the amount of replacement
282 * text. */
283 g_memmove(dst, to, tolen);
284 src += fromlen;
285 dst += tolen;
286 }
287 else
288 {
289 /*
290 * Copy any remaining part of the string. This includes the null
291 * termination character.
292 */
293 strcpy(dst, src);
294 break;
295 }
296 }
297 }
298 return value;
299 }
300
301 static void
302 map_convert_coords_to_quadtree_string(OsmGpsMap *map, gint x, gint y, gint zoomlevel,
303 gchar *buffer, const gchar initial,
304 const gchar *const quadrant)
305 {
306 gchar *ptr = buffer;
307 gint n;
308
309 if (initial)
310 *ptr++ = initial;
311
312 for(n = zoomlevel-1; n >= 0; n--)
313 {
314 gint xbit = (x >> n) & 1;
315 gint ybit = (y >> n) & 1;
316 *ptr++ = quadrant[xbit + 2 * ybit];
317 }
318
319 *ptr++ = '\0';
320 }
321
322
323 static void
324 inspect_map_uri(OsmGpsMap *map)
325 {
326 OsmGpsMapPrivate *priv = map->priv;
327 priv->uri_format = 0;
328 priv->the_google = FALSE;
329
330 if (g_strrstr(priv->repo_uri, URI_MARKER_X))
331 priv->uri_format |= URI_HAS_X;
332
333 if (g_strrstr(priv->repo_uri, URI_MARKER_Y))
334 priv->uri_format |= URI_HAS_Y;
335
336 if (g_strrstr(priv->repo_uri, URI_MARKER_Z))
337 priv->uri_format |= URI_HAS_Z;
338
339 if (g_strrstr(priv->repo_uri, URI_MARKER_S))
340 priv->uri_format |= URI_HAS_S;
341
342 if (g_strrstr(priv->repo_uri, URI_MARKER_Q))
343 priv->uri_format |= URI_HAS_Q;
344
345 if (g_strrstr(priv->repo_uri, URI_MARKER_Q0))
346 priv->uri_format |= URI_HAS_Q0;
347
348 if (g_strrstr(priv->repo_uri, URI_MARKER_YS))
349 priv->uri_format |= URI_HAS_YS;
350
351 if (g_strrstr(priv->repo_uri, URI_MARKER_R))
352 priv->uri_format |= URI_HAS_R;
353
354 if (g_strrstr(priv->repo_uri, "google.com"))
355 priv->the_google = TRUE;
356
357 g_debug("URI Format: 0x%X (google: %X)", priv->uri_format, priv->the_google);
358
359 }
360
361 static gchar *
362 replace_map_uri(OsmGpsMap *map, const gchar *uri, int zoom, int x, int y)
363 {
364 OsmGpsMapPrivate *priv = map->priv;
365 char *url;
366 unsigned int i;
367 char location[22];
368
369 i = 1;
370 url = g_strdup(uri);
371 while (i < URI_FLAG_END)
372 {
373 char *s = NULL;
374 char *old;
375
376 old = url;
377 switch(i & priv->uri_format)
378 {
379 case URI_HAS_X:
380 s = g_strdup_printf("%d", x);
381 url = replace_string(url, URI_MARKER_X, s);
382 //g_debug("FOUND " URI_MARKER_X);
383 break;
384 case URI_HAS_Y:
385 s = g_strdup_printf("%d", y);
386 url = replace_string(url, URI_MARKER_Y, s);
387 //g_debug("FOUND " URI_MARKER_Y);
388 break;
389 case URI_HAS_Z:
390 s = g_strdup_printf("%d", zoom);
391 url = replace_string(url, URI_MARKER_Z, s);
392 //g_debug("FOUND " URI_MARKER_Z);
393 break;
394 case URI_HAS_S:
395 s = g_strdup_printf("%d", priv->max_zoom-zoom);
396 url = replace_string(url, URI_MARKER_S, s);
397 //g_debug("FOUND " URI_MARKER_S);
398 break;
399 case URI_HAS_Q:
400 map_convert_coords_to_quadtree_string(map,x,y,zoom,location,'t',"qrts");
401 s = g_strdup_printf("%s", location);
402 url = replace_string(url, URI_MARKER_Q, s);
403 //g_debug("FOUND " URI_MARKER_Q);
404 break;
405 case URI_HAS_Q0:
406 map_convert_coords_to_quadtree_string(map,x,y,zoom,location,'\0', "0123");
407 s = g_strdup_printf("%s", location);
408 url = replace_string(url, URI_MARKER_Q0, s);
409 //g_debug("FOUND " URI_MARKER_Q0);
410 break;
411 case URI_HAS_YS:
412 // s = g_strdup_printf("%d", y);
413 // url = replace_string(url, URI_MARKER_YS, s);
414 g_warning("FOUND " URI_MARKER_YS " NOT IMPLEMENTED");
415 // retval = g_strdup_printf(repo->url,
416 // tilex,
417 // (1 << (MAX_ZOOM - zoom)) - tiley - 1,
418 // zoom - (MAX_ZOOM - 17));
419 break;
420 case URI_HAS_R:
421 s = g_strdup_printf("%d", g_random_int_range(0,4));
422 url = replace_string(url, URI_MARKER_R, s);
423 //g_debug("FOUND " URI_MARKER_R);
424 break;
425 default:
426 s = NULL;
427 break;
428 }
429
430 if (s) {
431 g_free(s);
432 g_free(old);
433 }
434
435 i = (i << 1);
436
437 }
438
439 return url;
440 }
441
442 static void
443 my_log_handler (const gchar * log_domain, GLogLevelFlags log_level, const gchar * message, gpointer user_data)
444 {
445 if (!(log_level & G_LOG_LEVEL_DEBUG) || ENABLE_DEBUG)
446 g_log_default_handler (log_domain, log_level, message, user_data);
447 }
448
449 static float
450 osm_gps_map_get_scale_at_point(int zoom, float rlat, float rlon)
451 {
452 /* world at zoom 1 == 512 pixels */
453 return cos(rlat) * M_PI * OSM_EQ_RADIUS / (1<<(7+zoom));
454 }
455
456 /* clears the trip list and all resources */
457 static void
458 osm_gps_map_free_trip (OsmGpsMap *map)
459 {
460 OsmGpsMapPrivate *priv = map->priv;
461 if (priv->trip_history) {
462 g_slist_foreach(priv->trip_history, (GFunc) g_free, NULL);
463 g_slist_free(priv->trip_history);
464 priv->trip_history = NULL;
465 }
466 }
467
468 /* clears the tracks and all resources */
469 static void
470 osm_gps_map_free_tracks (OsmGpsMap *map)
471 {
472 OsmGpsMapPrivate *priv = map->priv;
473 if (priv->tracks)
474 {
475 GSList* tmp = priv->tracks;
476 while (tmp != NULL)
477 {
478 g_slist_foreach(tmp->data, (GFunc) g_free, NULL);
479 g_slist_free(tmp->data);
480 tmp = g_slist_next(tmp);
481 }
482 g_slist_free(priv->tracks);
483 priv->tracks = NULL;
484 }
485 }
486
487 /* free the poi image lists */
488 static void
489 osm_gps_map_free_images (OsmGpsMap *map)
490 {
491 OsmGpsMapPrivate *priv = map->priv;
492 if (priv->images) {
493 GSList *list;
494 for(list = priv->images; list != NULL; list = list->next)
495 {
496 image_t *im = list->data;
497 g_object_unref(im->image);
498 g_free(im);
499 }
500 g_slist_free(priv->images);
501 priv->images = NULL;
502 }
503 }
504
505 static void
506 osm_gps_map_free_layers(OsmGpsMap *map)
507 {
508 OsmGpsMapPrivate *priv = map->priv;
509 if (priv->layers) {
510 g_slist_foreach(priv->layers, (GFunc) g_object_unref, NULL);
511 g_slist_free(priv->layers);
512 priv->layers = NULL;
513 }
514 }
515
516 static void
517 osm_gps_map_print_images (OsmGpsMap *map)
518 {
519 GSList *list;
520 int x,y,pixel_x,pixel_y;
521 int min_x = 0,min_y = 0,max_x = 0,max_y = 0;
522 int map_x0, map_y0;
523 OsmGpsMapPrivate *priv = map->priv;
524
525 map_x0 = priv->map_x - EXTRA_BORDER;
526 map_y0 = priv->map_y - EXTRA_BORDER;
527 for(list = priv->images; list != NULL; list = list->next)
528 {
529 image_t *im = list->data;
530
531 // pixel_x,y, offsets
532 pixel_x = lon2pixel(priv->map_zoom, im->pt.rlon);
533 pixel_y = lat2pixel(priv->map_zoom, im->pt.rlat);
534
535 g_debug("Image %dx%d @: %f,%f (%d,%d)",
536 im->w, im->h,
537 im->pt.rlat, im->pt.rlon,
538 pixel_x, pixel_y);
539
540 x = pixel_x - map_x0;
541 y = pixel_y - map_y0;
542
543 gdk_draw_pixbuf (
544 priv->pixmap,
545 priv->gc_map,
546 im->image,
547 0,0,
548 x-im->xoffset,y-im->yoffset,
549 im->w,im->h,
550 GDK_RGB_DITHER_NONE, 0, 0);
551
552 max_x = MAX(x+im->w,max_x);
553 min_x = MIN(x-im->w,min_x);
554 max_y = MAX(y+im->h,max_y);
555 min_y = MIN(y-im->h,min_y);
556 }
557
558 gtk_widget_queue_draw_area (
559 GTK_WIDGET(map),
560 min_x + EXTRA_BORDER, min_y + EXTRA_BORDER,
561 max_x + EXTRA_BORDER, max_y + EXTRA_BORDER);
562
563 }
564
565 static void
566 osm_gps_map_draw_gps_point (OsmGpsMap *map)
567 {
568 OsmGpsMapPrivate *priv = map->priv;
569
570 //incase we get called before we have got a gps point
571 if (priv->gps_valid) {
572 int map_x0, map_y0;
573 int x, y;
574 int r = priv->ui_gps_point_inner_radius;
575 int r2 = priv->ui_gps_point_outer_radius;
576 int mr = MAX(3*r,r2);
577
578 map_x0 = priv->map_x - EXTRA_BORDER;
579 map_y0 = priv->map_y - EXTRA_BORDER;
580 x = lon2pixel(priv->map_zoom, priv->gps->rlon) - map_x0;
581 y = lat2pixel(priv->map_zoom, priv->gps->rlat) - map_y0;
582 cairo_t *cr;
583 cairo_pattern_t *pat;
584
585 cr = gdk_cairo_create(priv->pixmap);
586
587 // draw transparent area
588 if (r2 > 0) {
589 cairo_set_line_width (cr, 1.5);
590 cairo_set_source_rgba (cr, 0.75, 0.75, 0.75, 0.4);
591 cairo_arc (cr, x, y, r2, 0, 2 * M_PI);
592 cairo_fill (cr);
593 // draw transparent area border
594 cairo_set_source_rgba (cr, 0.55, 0.55, 0.55, 0.4);
595 cairo_arc (cr, x, y, r2, 0, 2 * M_PI);
596 cairo_stroke(cr);
597 }
598
599 // draw ball gradient
600 if (r > 0) {
601 // draw direction arrow
602 if(!isnan(priv->gps_heading))
603 {
604 cairo_move_to (cr, x-r*cos(priv->gps_heading), y-r*sin(priv->gps_heading));
605 cairo_line_to (cr, x+3*r*sin(priv->gps_heading), y-3*r*cos(priv->gps_heading));
606 cairo_line_to (cr, x+r*cos(priv->gps_heading), y+r*sin(priv->gps_heading));
607 cairo_close_path (cr);
608
609 cairo_set_source_rgba (cr, 0.3, 0.3, 1.0, 0.5);
610 cairo_fill_preserve (cr);
611
612 cairo_set_line_width (cr, 1.0);
613 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.5);
614 cairo_stroke(cr);
615 }
616
617 pat = cairo_pattern_create_radial (x-(r/5), y-(r/5), (r/5), x, y, r);
618 cairo_pattern_add_color_stop_rgba (pat, 0, 1, 1, 1, 1.0);
619 cairo_pattern_add_color_stop_rgba (pat, 1, 0, 0, 1, 1.0);
620 cairo_set_source (cr, pat);
621 cairo_arc (cr, x, y, r, 0, 2 * M_PI);
622 cairo_fill (cr);
623 cairo_pattern_destroy (pat);
624 // draw ball border
625 cairo_set_line_width (cr, 1.0);
626 cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
627 cairo_arc (cr, x, y, r, 0, 2 * M_PI);
628 cairo_stroke(cr);
629 }
630
631 cairo_destroy(cr);
632 gtk_widget_queue_draw_area (GTK_WIDGET(map),
633 x-mr,
634 y-mr,
635 mr*2,
636 mr*2);
637 }
638 }
639
640 static void
641 osm_gps_map_blit_tile(OsmGpsMap *map, GdkPixbuf *pixbuf, int offset_x, int offset_y)
642 {
643 OsmGpsMapPrivate *priv = map->priv;
644
645 g_debug("Queing redraw @ %d,%d (w:%d h:%d)", offset_x,offset_y, TILESIZE,TILESIZE);
646
647 /* draw pixbuf onto pixmap */
648 gdk_draw_pixbuf (priv->pixmap,
649 priv->gc_map,
650 pixbuf,
651 0,0,
652 offset_x,offset_y,
653 TILESIZE,TILESIZE,
654 GDK_RGB_DITHER_NONE, 0, 0);
655 }
656
657 /* libsoup-2.2 and libsoup-2.4 use different ways to store the body data */
658 #if USE_LIBSOUP22
659 #define soup_message_headers_append(a,b,c) soup_message_add_header(a,b,c)
660 #define MSG_RESPONSE_BODY(a) ((a)->response.body)
661 #define MSG_RESPONSE_LEN(a) ((a)->response.length)
662 #define MSG_RESPONSE_LEN_FORMAT "%u"
663 #else
664 #define MSG_RESPONSE_BODY(a) ((a)->response_body->data)
665 #define MSG_RESPONSE_LEN(a) ((a)->response_body->length)
666 #define MSG_RESPONSE_LEN_FORMAT "%lld"
667 #endif
668
669 #if USE_LIBSOUP22
670 static void
671 osm_gps_map_tile_download_complete (SoupMessage *msg, gpointer user_data)
672 #else
673 static void
674 osm_gps_map_tile_download_complete (SoupSession *session, SoupMessage *msg, gpointer user_data)
675 #endif
676 {
677 FILE *file;
678 tile_download_t *dl = (tile_download_t *)user_data;
679 OsmGpsMap *map = OSM_GPS_MAP(dl->map);
680 OsmGpsMapPrivate *priv = map->priv;
681 gboolean file_saved = FALSE;
682
683 if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
684 {
685 /* save tile into cachedir if one has been specified */
686 if (priv->cache_dir)
687 {
688 if (g_mkdir_with_parents(dl->folder,0700) == 0)
689 {
690 file = g_fopen(dl->filename, "wb");
691 if (file != NULL)
692 {
693 fwrite (MSG_RESPONSE_BODY(msg), 1, MSG_RESPONSE_LEN(msg), file);
694 file_saved = TRUE;
695 g_debug("Wrote "MSG_RESPONSE_LEN_FORMAT" bytes to %s", MSG_RESPONSE_LEN(msg), dl->filename);
696 fclose (file);
697
698 }
699 }
700 else
701 {
702 g_warning("Error creating tile download directory: %s",
703 dl->folder);
704 perror("perror:");
705 }
706 }
707
708 if (dl->redraw)
709 {
710 GdkPixbuf *pixbuf = NULL;
711
712 /* if the file was actually stored on disk, we can simply */
713 /* load and decode it from that file */
714 if (priv->cache_dir)
715 {
716 if (file_saved)
717 {
718 pixbuf = gdk_pixbuf_new_from_file (dl->filename, NULL);
719 }
720 }
721 else
722 {
723 GdkPixbufLoader *loader;
724 char *extension = strrchr (dl->filename, '.');
725
726 /* parse file directly from memory */
727 if (extension)
728 {
729 loader = gdk_pixbuf_loader_new_with_type (extension+1, NULL);
730 if (!gdk_pixbuf_loader_write (loader, (unsigned char*)MSG_RESPONSE_BODY(msg), MSG_RESPONSE_LEN(msg), NULL))
731 {
732 g_warning("Error: Decoding of image failed");
733 }
734 gdk_pixbuf_loader_close(loader, NULL);
735
736 pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
737
738 /* give up loader but keep the pixbuf */
739 g_object_ref(pixbuf);
740 g_object_unref(loader);
741 }
742 else
743 {
744 g_warning("Error: Unable to determine image file format");
745 }
746 }
747
748 /* Store the tile into the cache */
749 if (G_LIKELY (pixbuf))
750 {
751 OsmCachedTile *tile = g_slice_new (OsmCachedTile);
752 tile->pixbuf = pixbuf;
753 tile->redraw_cycle = priv->redraw_cycle;
754 /* if the tile is already in the cache (it could be one
755 * rendered from another zoom level), it will be
756 * overwritten */
757 g_hash_table_insert (priv->tile_cache, dl->filename, tile);
758 /* NULL-ify dl->filename so that it won't be freed, as
759 * we are using it as a key in the hash table */
760 dl->filename = NULL;
761 }
762 osm_gps_map_map_redraw_idle (map);
763 }
764 g_hash_table_remove(priv->tile_queue, dl->uri);
765
766 g_free(dl->uri);
767 g_free(dl->folder);
768 g_free(dl->filename);
769 g_free(dl);
770 }
771 else
772 {
773 g_warning("Error downloading tile: %d - %s", msg->status_code, msg->reason_phrase);
774 if (msg->status_code == SOUP_STATUS_NOT_FOUND)
775 {
776 g_hash_table_insert(priv->missing_tiles, dl->uri, NULL);
777 g_hash_table_remove(priv->tile_queue, dl->uri);
778 }
779 else if (msg->status_code == SOUP_STATUS_CANCELLED)
780 {
781 ;//application exiting
782 }
783 else
784 {
785 #if USE_LIBSOUP22
786 soup_session_requeue_message(dl->session, msg);
787 #else
788 soup_session_requeue_message(session, msg);
789 #endif
790 return;
791 }
792 }
793
794
795 }
796
797 static void
798 osm_gps_map_download_tile (OsmGpsMap *map, int zoom, int x, int y, gboolean redraw)
799 {
800 SoupMessage *msg;
801 OsmGpsMapPrivate *priv = map->priv;
802 tile_download_t *dl = g_new0(tile_download_t,1);
803
804 //calculate the uri to download
805 dl->uri = replace_map_uri(map, priv->repo_uri, zoom, x, y);
806
807 #if USE_LIBSOUP22
808 dl->session = priv->soup_session;
809 #endif
810
811 //check the tile has not already been queued for download,
812 //or has been attempted, and its missing
813 if (g_hash_table_lookup_extended(priv->tile_queue, dl->uri, NULL, NULL) ||
814 g_hash_table_lookup_extended(priv->missing_tiles, dl->uri, NULL, NULL) )
815 {
816 g_debug("Tile already downloading (or missing)");
817 g_free(dl->uri);
818 g_free(dl);
819 } else {
820 dl->folder = g_strdup_printf("%s%c%d%c%d%c",
821 priv->cache_dir, G_DIR_SEPARATOR,
822 zoom, G_DIR_SEPARATOR,
823 x, G_DIR_SEPARATOR);
824 dl->filename = g_strdup_printf("%s%c%d%c%d%c%d.%s",
825 priv->cache_dir, G_DIR_SEPARATOR,
826 zoom, G_DIR_SEPARATOR,
827 x, G_DIR_SEPARATOR,
828 y,
829 priv->image_format);
830 dl->map = map;
831 dl->redraw = redraw;
832
833 g_debug("Download tile: %d,%d z:%d\n\t%s --> %s", x, y, zoom, dl->uri, dl->filename);
834
835 msg = soup_message_new (SOUP_METHOD_GET, dl->uri);
836 if (msg) {
837 if (priv->the_google) {
838 //Set maps.google.com as the referrer
839 g_debug("Setting Google Referrer");
840 soup_message_headers_append(msg->request_headers, "Referer", "http://maps.google.com/");
841 //For google satelite also set the appropriate cookie value
842 if (priv->uri_format & URI_HAS_Q) {
843 const char *cookie = g_getenv("GOOGLE_COOKIE");
844 if (cookie) {
845 g_debug("Adding Google Cookie");
846 soup_message_headers_append(msg->request_headers, "Cookie", cookie);
847 }
848 }
849 }
850
851 #if USE_LIBSOUP22
852 soup_message_headers_append(msg->request_headers,
853 "User-Agent", USER_AGENT);
854 #endif
855
856 g_hash_table_insert (priv->tile_queue, dl->uri, msg);
857 soup_session_queue_message (priv->soup_session, msg, osm_gps_map_tile_download_complete, dl);
858 } else {
859 g_warning("Could not create soup message");
860 g_free(dl->uri);
861 g_free(dl->folder);
862 g_free(dl->filename);
863 g_free(dl);
864 }
865 }
866 }
867
868 static GdkPixbuf *
869 osm_gps_map_load_cached_tile (OsmGpsMap *map, int zoom, int x, int y)
870 {
871 OsmGpsMapPrivate *priv = map->priv;
872 gchar *filename;
873 GdkPixbuf *pixbuf = NULL;
874 OsmCachedTile *tile;
875
876 filename = g_strdup_printf("%s%c%d%c%d%c%d.%s",
877 priv->cache_dir, G_DIR_SEPARATOR,
878 zoom, G_DIR_SEPARATOR,
879 x, G_DIR_SEPARATOR,
880 y,
881 priv->image_format);
882
883 tile = g_hash_table_lookup (priv->tile_cache, filename);
884 if (tile)
885 {
886 g_free (filename);
887 }
888 else
889 {
890 pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
891 if (pixbuf)
892 {
893 tile = g_slice_new (OsmCachedTile);
894 tile->pixbuf = pixbuf;
895 g_hash_table_insert (priv->tile_cache, filename, tile);
896 }
897 }
898
899 /* set/update the redraw_cycle timestamp on the tile */
900 if (tile)
901 {
902 tile->redraw_cycle = priv->redraw_cycle;
903 pixbuf = g_object_ref (tile->pixbuf);
904 }
905
906 return pixbuf;
907 }
908
909 static GdkPixbuf *
910 osm_gps_map_find_bigger_tile (OsmGpsMap *map, int zoom, int x, int y,
911 int *zoom_found)
912 {
913 GdkPixbuf *pixbuf;
914 int next_zoom, next_x, next_y;
915
916 if (zoom == 0) return NULL;
917 next_zoom = zoom - 1;
918 next_x = x / 2;
919 next_y = y / 2;
920 pixbuf = osm_gps_map_load_cached_tile (map, next_zoom, next_x, next_y);
921 if (pixbuf)
922 *zoom_found = next_zoom;
923 else
924 pixbuf = osm_gps_map_find_bigger_tile (map, next_zoom, next_x, next_y,
925 zoom_found);
926 return pixbuf;
927 }
928
929 static GdkPixbuf *
930 osm_gps_map_render_missing_tile_upscaled (OsmGpsMap *map, int zoom,
931 int x, int y)
932 {
933 GdkPixbuf *pixbuf, *big, *area;
934 int zoom_big, zoom_diff, area_size, area_x, area_y;
935 int modulo;
936
937 big = osm_gps_map_find_bigger_tile (map, zoom, x, y, &zoom_big);
938 if (!big) return NULL;
939
940 g_debug ("Found bigger tile (zoom = %d, wanted = %d)", zoom_big, zoom);
941
942 /* get a Pixbuf for the area to magnify */
943 zoom_diff = zoom - zoom_big;
944 area_size = TILESIZE >> zoom_diff;
945 modulo = 1 << zoom_diff;
946 area_x = (x % modulo) * area_size;
947 area_y = (y % modulo) * area_size;
948 area = gdk_pixbuf_new_subpixbuf (big, area_x, area_y,
949 area_size, area_size);
950 g_object_unref (big);
951 pixbuf = gdk_pixbuf_scale_simple (area, TILESIZE, TILESIZE,
952 GDK_INTERP_NEAREST);
953 g_object_unref (area);
954 return pixbuf;
955 }
956
957 static GdkPixbuf *
958 osm_gps_map_render_missing_tile (OsmGpsMap *map, int zoom, int x, int y)
959 {
960 /* maybe TODO: render from downscaled tiles, if the following fails */
961 return osm_gps_map_render_missing_tile_upscaled (map, zoom, x, y);
962 }
963
964 static void
965 osm_gps_map_load_tile (OsmGpsMap *map, int zoom, int x, int y, int offset_x, int offset_y)
966 {
967 OsmGpsMapPrivate *priv = map->priv;
968 gchar *filename;
969 GdkPixbuf *pixbuf;
970
971 g_debug("Load tile %d,%d (%d,%d) z:%d", x, y, offset_x, offset_y, zoom);
972
973 if (priv->map_source == OSM_GPS_MAP_SOURCE_NULL) {
974 osm_gps_map_blit_tile(map, priv->null_tile, offset_x,offset_y);
975 return;
976 }
977
978 filename = g_strdup_printf("%s%c%d%c%d%c%d.%s",
979 priv->cache_dir, G_DIR_SEPARATOR,
980 zoom, G_DIR_SEPARATOR,
981 x, G_DIR_SEPARATOR,
982 y,
983 priv->image_format);
984
985 /* try to get file from internal cache first */
986 if(!(pixbuf = osm_gps_map_load_cached_tile(map, zoom, x, y)))
987 pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
988
989 if(pixbuf)
990 {
991 g_debug("Found tile %s", filename);
992 osm_gps_map_blit_tile(map, pixbuf, offset_x,offset_y);
993 g_object_unref (pixbuf);
994 }
995 else
996 {
997 if (priv->map_auto_download)
998 osm_gps_map_download_tile(map, zoom, x, y, TRUE);
999
1000 /* try to render the tile by scaling cached tiles from other zoom
1001 * levels */
1002 pixbuf = osm_gps_map_render_missing_tile (map, zoom, x, y);
1003 if (pixbuf)
1004 {
1005 gdk_draw_pixbuf (priv->pixmap,
1006 priv->gc_map,
1007 pixbuf,
1008 0,0,
1009 offset_x,offset_y,
1010 TILESIZE,TILESIZE,
1011 GDK_RGB_DITHER_NONE, 0, 0);
1012 g_object_unref (pixbuf);
1013 }
1014 else
1015 {
1016 //prevent some artifacts when drawing not yet loaded areas.
1017 gdk_draw_rectangle (priv->pixmap,
1018 GTK_WIDGET(map)->style->white_gc,
1019 TRUE, offset_x, offset_y, TILESIZE, TILESIZE);
1020 }
1021 }
1022 g_free(filename);
1023 }
1024
1025 static void
1026 osm_gps_map_fill_tiles_pixel (OsmGpsMap *map)
1027 {
1028 OsmGpsMapPrivate *priv = map->priv;
1029 int i,j, width, height, tile_x0, tile_y0, tiles_nx, tiles_ny;
1030 int offset_xn = 0;
1031 int offset_yn = 0;
1032 int offset_x;
1033 int offset_y;
1034
1035 g_debug("Fill tiles: %d,%d z:%d", priv->map_x, priv->map_y, priv->map_zoom);
1036
1037 offset_x = - priv->map_x % TILESIZE;
1038 offset_y = - priv->map_y % TILESIZE;
1039 if (offset_x > 0) offset_x -= TILESIZE;
1040 if (offset_y > 0) offset_y -= TILESIZE;
1041
1042 offset_xn = offset_x + EXTRA_BORDER;
1043 offset_yn = offset_y + EXTRA_BORDER;
1044
1045 width = GTK_WIDGET(map)->allocation.width;
1046 height = GTK_WIDGET(map)->allocation.height;
1047
1048 tiles_nx = (width - offset_x) / TILESIZE + 1;
1049 tiles_ny = (height - offset_y) / TILESIZE + 1;
1050
1051 tile_x0 = floor((float)priv->map_x / (float)TILESIZE);
1052 tile_y0 = floor((float)priv->map_y / (float)TILESIZE);
1053
1054 //TODO: implement wrap around
1055 for (i=tile_x0; i<(tile_x0+tiles_nx);i++)
1056 {
1057 for (j=tile_y0; j<(tile_y0+tiles_ny); j++)
1058 {
1059 if( j<0 || i<0 || i>=exp(priv->map_zoom * M_LN2) || j>=exp(priv->map_zoom * M_LN2))
1060 {
1061 gdk_draw_rectangle (priv->pixmap,
1062 GTK_WIDGET(map)->style->white_gc,
1063 TRUE,
1064 offset_xn, offset_yn,
1065 TILESIZE,TILESIZE);
1066 }
1067 else
1068 {
1069 osm_gps_map_load_tile(map,
1070 priv->map_zoom,
1071 i,j,
1072 offset_xn,offset_yn);
1073 }
1074 offset_yn += TILESIZE;
1075 }
1076 offset_xn += TILESIZE;
1077 offset_yn = offset_y + EXTRA_BORDER;
1078 }
1079 }
1080
1081 static void
1082 osm_gps_map_print_track (OsmGpsMap *map, GSList *trackpoint_list)
1083 {
1084 OsmGpsMapPrivate *priv = map->priv;
1085
1086 GSList *list;
1087 int x,y;
1088 int min_x = 0,min_y = 0,max_x = 0,max_y = 0;
1089 int lw = priv->ui_gps_track_width;
1090 int map_x0, map_y0;
1091 cairo_t *cr;
1092
1093 cr = gdk_cairo_create(priv->pixmap);
1094 cairo_set_line_width (cr, lw);
1095 cairo_set_source_rgba (cr, 60000.0/65535.0, 0.0, 0.0, 0.6);
1096 cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
1097 cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
1098
1099 map_x0 = priv->map_x - EXTRA_BORDER;
1100 map_y0 = priv->map_y - EXTRA_BORDER;
1101 for(list = trackpoint_list; list != NULL; list = list->next)
1102 {
1103 coord_t *tp = list->data;
1104
1105 x = lon2pixel(priv->map_zoom, tp->rlon) - map_x0;
1106 y = lat2pixel(priv->map_zoom, tp->rlat) - map_y0;
1107
1108 // first time through loop
1109 if (list == trackpoint_list) {
1110 cairo_move_to(cr, x, y);
1111 }
1112
1113 cairo_line_to(cr, x, y);
1114
1115 max_x = MAX(x,max_x);
1116 min_x = MIN(x,min_x);
1117 max_y = MAX(y,max_y);
1118 min_y = MIN(y,min_y);
1119 }
1120
1121 gtk_widget_queue_draw_area (
1122 GTK_WIDGET(map),
1123 min_x - lw,
1124 min_y - lw,
1125 max_x + (lw * 2),
1126 max_y + (lw * 2));
1127
1128 cairo_stroke(cr);
1129 cairo_destroy(cr);
1130 }
1131
1132 /* Prints the gps trip history, and any other tracks */
1133 static void
1134 osm_gps_map_print_tracks (OsmGpsMap *map)
1135 {
1136 OsmGpsMapPrivate *priv = map->priv;
1137
1138 if (priv->show_trip_history)
1139 osm_gps_map_print_track (map, priv->trip_history);
1140
1141 if (priv->tracks)
1142 {
1143 GSList* tmp = priv->tracks;
1144 while (tmp != NULL)
1145 {
1146 osm_gps_map_print_track (map, tmp->data);
1147 tmp = g_slist_next(tmp);
1148 }
1149 }
1150 }
1151
1152 static gboolean
1153 osm_gps_map_purge_cache_check(gpointer key, gpointer value, gpointer user)
1154 {
1155 return (((OsmCachedTile*)value)->redraw_cycle != ((OsmGpsMapPrivate*)user)->redraw_cycle);
1156 }
1157
1158 static void
1159 osm_gps_map_purge_cache (OsmGpsMap *map)
1160 {
1161 OsmGpsMapPrivate *priv = map->priv;
1162
1163 if (g_hash_table_size (priv->tile_cache) < priv->max_tile_cache_size)
1164 return;
1165
1166 /* run through the cache, and remove the tiles which have not been used
1167 * during the last redraw operation */
1168 g_hash_table_foreach_remove(priv->tile_cache, osm_gps_map_purge_cache_check, priv);
1169 }
1170
1171 static gboolean
1172 osm_gps_map_map_redraw (OsmGpsMap *map)
1173 {
1174 OsmGpsMapPrivate *priv = map->priv;
1175
1176 priv->idle_map_redraw = 0;
1177
1178 /* don't redraw the entire map while the OSD is doing */
1179 /* some animation or the like. This is to keep the animation */
1180 /* fluid */
1181 if (priv->layers) {
1182 GSList *list;
1183 for(list = priv->layers; list != NULL; list = list->next) {
1184 OsmGpsMapLayer *layer = list->data;
1185 if (osm_gps_map_layer_busy(layer))
1186 return FALSE;
1187 }
1188 }
1189
1190 /* the motion_notify handler uses priv->pixmap to redraw the area; if we
1191 * change it while we are dragging, we will end up showing it in the wrong
1192 * place. This could be fixed by carefully recompute the coordinates, but
1193 * for now it's easier just to disable redrawing the map while dragging */
1194 if (priv->dragging)
1195 return FALSE;
1196
1197 /* undo all offsets that may have happened when dragging */
1198 priv->drag_mouse_dx = 0;
1199 priv->drag_mouse_dy = 0;
1200
1201 priv->redraw_cycle++;
1202
1203 /* draw white background to initialise pixmap */
1204 gdk_draw_rectangle (priv->pixmap,
1205 GTK_WIDGET(map)->style->white_gc,
1206 TRUE,
1207 0, 0,
1208 GTK_WIDGET(map)->allocation.width + EXTRA_BORDER * 2,
1209 GTK_WIDGET(map)->allocation.height + EXTRA_BORDER * 2);
1210
1211 osm_gps_map_fill_tiles_pixel(map);
1212
1213 osm_gps_map_print_tracks(map);
1214 osm_gps_map_draw_gps_point(map);
1215 osm_gps_map_print_images(map);
1216
1217 if (priv->layers) {
1218 GSList *list;
1219 for(list = priv->layers; list != NULL; list = list->next) {
1220 OsmGpsMapLayer *layer = list->data;
1221 osm_gps_map_layer_render (layer, map);
1222 }
1223 }
1224
1225 osm_gps_map_purge_cache(map);
1226 gtk_widget_queue_draw (GTK_WIDGET (map));
1227
1228 return FALSE;
1229 }
1230
1231 static void
1232 osm_gps_map_map_redraw_idle (OsmGpsMap *map)
1233 {
1234 OsmGpsMapPrivate *priv = map->priv;
1235
1236 if (priv->idle_map_redraw == 0)
1237 priv->idle_map_redraw = g_idle_add ((GSourceFunc)osm_gps_map_map_redraw, map);
1238 }
1239
1240 static void
1241 center_coord_update(OsmGpsMap *map) {
1242
1243 GtkWidget *widget = GTK_WIDGET(map);
1244 OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(map);
1245
1246 // pixel_x,y, offsets
1247 gint pixel_x = priv->map_x + widget->allocation.width/2;
1248 gint pixel_y = priv->map_y + widget->allocation.height/2;
1249
1250 priv->center_rlon = pixel2lon(priv->map_zoom, pixel_x);
1251 priv->center_rlat = pixel2lat(priv->map_zoom, pixel_y);
1252
1253 g_signal_emit_by_name(widget, "changed");
1254 }
1255
1256 static gboolean
1257 on_window_key_press(GtkWidget *widget, GdkEventKey *event, OsmGpsMapPrivate *priv)
1258 {
1259 int i;
1260 int step;
1261 gboolean handled;
1262 OsmGpsMap *map;
1263
1264 //if no keybindings are set, let the app handle them...
1265 if (!priv->keybindings_enabled)
1266 return FALSE;
1267
1268 handled = FALSE;
1269 map = OSM_GPS_MAP(widget);
1270 step = GTK_WIDGET(widget)->allocation.width/OSM_GPS_MAP_SCROLL_STEP;
1271
1272 //the map handles some keys on its own
1273 for (i = 0; i < OSM_GPS_MAP_KEY_MAX; i++) {
1274 //not the key we have a binding for
1275 if (map->priv->keybindings[i] != event->keyval)
1276 continue;
1277
1278 switch(i) {
1279 case OSM_GPS_MAP_KEY_FULLSCREEN: {
1280 GtkWidget *toplevel = gtk_widget_get_toplevel(GTK_WIDGET(widget));
1281 if(!priv->fullscreen)
1282 gtk_window_fullscreen(GTK_WINDOW(toplevel));
1283 else
1284 gtk_window_unfullscreen(GTK_WINDOW(toplevel));
1285
1286 priv->fullscreen = !priv->fullscreen;
1287 handled = TRUE;
1288 } break;
1289 case OSM_GPS_MAP_KEY_ZOOMIN:
1290 osm_gps_map_zoom_in(map);
1291 handled = TRUE;
1292 break;
1293 case OSM_GPS_MAP_KEY_ZOOMOUT:
1294 osm_gps_map_zoom_out(map);
1295 handled = TRUE;
1296 break;
1297 case OSM_GPS_MAP_KEY_UP:
1298 priv->map_y -= step;
1299 center_coord_update(map);
1300 osm_gps_map_map_redraw_idle(map);
1301 handled = TRUE;
1302 break;
1303 case OSM_GPS_MAP_KEY_DOWN:
1304 priv->map_y += step;
1305 center_coord_update(map);
1306 osm_gps_map_map_redraw_idle(map);
1307 handled = TRUE;
1308 break;
1309 case OSM_GPS_MAP_KEY_LEFT:
1310 priv->map_x -= step;
1311 center_coord_update(map);
1312 osm_gps_map_map_redraw_idle(map);
1313 handled = TRUE;
1314 break;
1315 case OSM_GPS_MAP_KEY_RIGHT:
1316 priv->map_x += step;
1317 center_coord_update(map);
1318 osm_gps_map_map_redraw_idle(OSM_GPS_MAP(widget));
1319 handled = TRUE;
1320 break;
1321 default:
1322 break;
1323 }
1324 }
1325
1326 return handled;
1327 }
1328
1329 static void
1330 osm_gps_map_init (OsmGpsMap *object)
1331 {
1332 int i;
1333 OsmGpsMapPrivate *priv;
1334
1335 priv = G_TYPE_INSTANCE_GET_PRIVATE (object, OSM_TYPE_GPS_MAP, OsmGpsMapPrivate);
1336 object->priv = priv;
1337
1338 priv->pixmap = NULL;
1339
1340 priv->trip_history = NULL;
1341 priv->gps = g_new0(coord_t, 1);
1342 priv->gps_valid = FALSE;
1343 priv->gps_heading = OSM_GPS_MAP_INVALID;
1344
1345 priv->tracks = NULL;
1346 priv->images = NULL;
1347 priv->layers = NULL;
1348
1349 priv->drag_counter = 0;
1350 priv->drag_mouse_dx = 0;
1351 priv->drag_mouse_dy = 0;
1352 priv->drag_start_mouse_x = 0;
1353 priv->drag_start_mouse_y = 0;
1354
1355 priv->uri_format = 0;
1356 priv->the_google = FALSE;
1357
1358 priv->map_source = -1;
1359
1360 priv->keybindings_enabled = FALSE;
1361 for (i = 0; i < OSM_GPS_MAP_KEY_MAX; i++)
1362 priv->keybindings[i] = 0;
1363
1364
1365 #if USE_LIBSOUP22
1366 /* libsoup-2.2 has no special way to set the user agent, so we */
1367 /* set it seperately as an extra header field for each reuest */
1368 priv->soup_session = soup_session_async_new();
1369 #else
1370 /* set the user agent */
1371 priv->soup_session =
1372 soup_session_async_new_with_options(SOUP_SESSION_USER_AGENT,
1373 USER_AGENT, NULL);
1374
1375 #endif
1376 //Hash table which maps tile d/l URIs to SoupMessage requests
1377 priv->tile_queue = g_hash_table_new (g_str_hash, g_str_equal);
1378
1379 //Some mapping providers (Google) have varying degrees of tiles at multiple
1380 //zoom levels
1381 priv->missing_tiles = g_hash_table_new (g_str_hash, g_str_equal);
1382
1383 /* memory cache for most recently used tiles */
1384 priv->tile_cache = g_hash_table_new_full (g_str_hash, g_str_equal,
1385 g_free, (GDestroyNotify)cached_tile_free);
1386 priv->max_tile_cache_size = 20;
1387
1388 gtk_widget_add_events (GTK_WIDGET (object),
1389 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
1390 GDK_POINTER_MOTION_MASK |
1391 GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
1392 GTK_WIDGET_SET_FLAGS (object, GTK_CAN_FOCUS);
1393
1394 g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MASK, my_log_handler, NULL);
1395
1396 //Setup signal handlers
1397 g_signal_connect(G_OBJECT(object), "key_press_event",
1398 G_CALLBACK(on_window_key_press), priv);
1399 }
1400
1401 static char*
1402 osm_gps_map_get_cache_dir(OsmGpsMapPrivate *priv)
1403 {
1404 if (priv->tile_base_dir)
1405 return g_strdup(priv->tile_base_dir);
1406 return osm_gps_map_get_default_cache_directory();
1407 }
1408
1409 /* strcmp0 was introduced with glib 2.16 */
1410 #if ! GLIB_CHECK_VERSION (2, 16, 0)
1411 int g_strcmp0(const char *str1, const char *str2)
1412 {
1413 if( str1 == NULL && str2 == NULL ) return 0;
1414 if( str1 == NULL ) return -1;
1415 if( str2 == NULL ) return 1;
1416 return strcmp(str1, str2);
1417 }
1418 #endif
1419
1420 static void
1421 osm_gps_map_setup(OsmGpsMapPrivate *priv)
1422 {
1423 const char *uri;
1424
1425 //user can specify a map source ID, or a repo URI as the map source
1426 uri = osm_gps_map_source_get_repo_uri(OSM_GPS_MAP_SOURCE_NULL);
1427 if ( (priv->map_source == 0) || (strcmp(priv->repo_uri, uri) == 0) ) {
1428 g_debug("Using null source");
1429 priv->map_source = OSM_GPS_MAP_SOURCE_NULL;
1430
1431 priv->null_tile = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, 256, 256);
1432 gdk_pixbuf_fill(priv->null_tile, 0xcccccc00);
1433 }
1434 else if (priv->map_source >= 0) {
1435 //check if the source given is valid
1436 uri = osm_gps_map_source_get_repo_uri(priv->map_source);
1437 if (uri) {
1438 g_debug("Setting map source from ID");
1439 g_free(priv->repo_uri);
1440
1441 priv->repo_uri = g_strdup(uri);
1442 priv->image_format = g_strdup(
1443 osm_gps_map_source_get_image_format(priv->map_source));
1444 priv->max_zoom = osm_gps_map_source_get_max_zoom(priv->map_source);
1445 priv->min_zoom = osm_gps_map_source_get_min_zoom(priv->map_source);
1446 }
1447 }
1448
1449 if (priv->tile_dir == NULL)
1450 priv->tile_dir = g_strdup(OSM_GPS_MAP_CACHE_DISABLED);
1451
1452 if ( g_strcmp0(priv->tile_dir, OSM_GPS_MAP_CACHE_DISABLED) == 0 ) {
1453 priv->cache_dir = NULL;
1454 } else if ( g_strcmp0(priv->tile_dir, OSM_GPS_MAP_CACHE_AUTO) == 0 ) {
1455 char *base = osm_gps_map_get_cache_dir(priv);
1456 #if GLIB_CHECK_VERSION (2, 16, 0)
1457 char *md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, priv->repo_uri, -1);
1458 #else
1459 char *md5 = g_strdup(osm_gps_map_source_get_friendly_name(priv->map_source));
1460 #endif
1461 priv->cache_dir = g_strdup_printf("%s%c%s", base, G_DIR_SEPARATOR, md5);
1462 g_free(base);
1463 g_free(md5);
1464 } else if ( g_strcmp0(priv->tile_dir, OSM_GPS_MAP_CACHE_FRIENDLY) == 0 ) {
1465 char *base = osm_gps_map_get_cache_dir(priv);
1466 const char *fname = osm_gps_map_source_get_friendly_name(priv->map_source);
1467 priv->cache_dir = g_strdup_printf("%s%c%s", base, G_DIR_SEPARATOR, fname);
1468 g_free(base);
1469 } else {
1470 priv->cache_dir = g_strdup(priv->tile_dir);
1471 }
1472 g_debug("Cache dir: %s", priv->cache_dir);
1473 }
1474
1475 static GObject *
1476 osm_gps_map_constructor (GType gtype, guint n_properties, GObjectConstructParam *properties)
1477 {
1478 //Always chain up to the parent constructor
1479 GObject *object =
1480 G_OBJECT_CLASS(osm_gps_map_parent_class)->constructor(gtype, n_properties, properties);
1481
1482 osm_gps_map_setup(OSM_GPS_MAP_PRIVATE(object));
1483
1484 inspect_map_uri(OSM_GPS_MAP(object));
1485
1486 return object;
1487 }
1488
1489 static void
1490 osm_gps_map_dispose (GObject *object)
1491 {
1492 OsmGpsMap *map = OSM_GPS_MAP(object);
1493 OsmGpsMapPrivate *priv = map->priv;
1494
1495 if (priv->is_disposed)
1496 return;
1497
1498 priv->is_disposed = TRUE;
1499
1500 soup_session_abort(priv->soup_session);
1501 g_object_unref(priv->soup_session);
1502
1503 g_hash_table_destroy(priv->tile_queue);
1504 g_hash_table_destroy(priv->missing_tiles);
1505 g_hash_table_destroy(priv->tile_cache);
1506
1507 /* images and layers contain GObjects which need unreffing, so free here */
1508 osm_gps_map_free_images(map);
1509 osm_gps_map_free_layers(map);
1510
1511 if(priv->pixmap)
1512 g_object_unref (priv->pixmap);
1513
1514 if (priv->null_tile)
1515 g_object_unref (priv->null_tile);
1516
1517 if(priv->gc_map)
1518 g_object_unref(priv->gc_map);
1519
1520 if (priv->idle_map_redraw != 0)
1521 g_source_remove (priv->idle_map_redraw);
1522
1523 if (priv->drag_expose != 0)
1524 g_source_remove (priv->drag_expose);
1525
1526 g_free(priv->gps);
1527
1528
1529 #ifdef OSD_DOUBLE_BUFFER
1530 if(priv->dbuf_pixmap)
1531 g_object_unref (priv->dbuf_pixmap);
1532 #endif
1533
1534 G_OBJECT_CLASS (osm_gps_map_parent_class)->dispose (object);
1535 }
1536
1537 static void
1538 osm_gps_map_finalize (GObject *object)
1539 {
1540 OsmGpsMap *map = OSM_GPS_MAP(object);
1541 OsmGpsMapPrivate *priv = map->priv;
1542
1543 if (priv->tile_dir)
1544 g_free(priv->tile_dir);
1545
1546 if (priv->cache_dir)
1547 g_free(priv->cache_dir);
1548
1549 g_free(priv->repo_uri);
1550 g_free(priv->image_format);
1551
1552 /* trip and tracks contain simple non GObject types, so free them here */
1553 osm_gps_map_free_trip(map);
1554 osm_gps_map_free_tracks(map);
1555
1556 G_OBJECT_CLASS (osm_gps_map_parent_class)->finalize (object);
1557 }
1558
1559 static void
1560 osm_gps_map_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
1561 {
1562 g_return_if_fail (OSM_IS_GPS_MAP (object));
1563 OsmGpsMap *map = OSM_GPS_MAP(object);
1564 OsmGpsMapPrivate *priv = map->priv;
1565
1566 switch (prop_id)
1567 {
1568 case PROP_AUTO_CENTER:
1569 priv->map_auto_center = g_value_get_boolean (value);
1570 break;
1571 case PROP_RECORD_TRIP_HISTORY:
1572 priv->record_trip_history = g_value_get_boolean (value);
1573 break;
1574 case PROP_SHOW_TRIP_HISTORY:
1575 priv->show_trip_history = g_value_get_boolean (value);
1576 break;
1577 case PROP_AUTO_DOWNLOAD:
1578 priv->map_auto_download = g_value_get_boolean (value);
1579 break;
1580 case PROP_REPO_URI:
1581 priv->repo_uri = g_value_dup_string (value);
1582 break;
1583 case PROP_PROXY_URI:
1584 if ( g_value_get_string(value) ) {
1585 priv->proxy_uri = g_value_dup_string (value);
1586 g_debug("Setting proxy server: %s", priv->proxy_uri);
1587
1588 #if USE_LIBSOUP22
1589 SoupUri* uri = soup_uri_new(priv->proxy_uri);
1590 g_object_set(G_OBJECT(priv->soup_session), SOUP_SESSION_PROXY_URI, uri, NULL);
1591 #else
1592 GValue val = {0};
1593 SoupURI* uri = soup_uri_new(priv->proxy_uri);
1594 g_value_init(&val, SOUP_TYPE_URI);
1595 g_value_take_boxed(&val, uri);
1596 g_object_set_property(G_OBJECT(priv->soup_session),SOUP_SESSION_PROXY_URI,&val);
1597 #endif
1598 } else
1599 priv->proxy_uri = NULL;
1600
1601 break;
1602 case PROP_TILE_CACHE_DIR:
1603 priv->tile_dir = g_value_dup_string (value);
1604 break;
1605 case PROP_TILE_CACHE_BASE_DIR:
1606 priv->tile_base_dir = g_value_dup_string (value);
1607 break;
1608 case PROP_TILE_CACHE_DIR_IS_FULL_PATH:
1609 g_warning("GObject property tile-cache-is-full-path depreciated");
1610 break;
1611 case PROP_ZOOM:
1612 priv->map_zoom = g_value_get_int (value);
1613 break;
1614 case PROP_MAX_ZOOM:
1615 priv->max_zoom = g_value_get_int (value);
1616 break;
1617 case PROP_MIN_ZOOM:
1618 priv->min_zoom = g_value_get_int (value);
1619 break;
1620 case PROP_MAP_X:
1621 priv->map_x = g_value_get_int (value);
1622 center_coord_update(map);
1623 break;
1624 case PROP_MAP_Y:
1625 priv->map_y = g_value_get_int (value);
1626 center_coord_update(map);
1627 break;
1628 case PROP_GPS_TRACK_WIDTH:
1629 priv->ui_gps_track_width = g_value_get_int (value);
1630 break;
1631 case PROP_GPS_POINT_R1:
1632 priv->ui_gps_point_inner_radius = g_value_get_int (value);
1633 break;
1634 case PROP_GPS_POINT_R2:
1635 priv->ui_gps_point_outer_radius = g_value_get_int (value);
1636 break;
1637 case PROP_MAP_SOURCE: {
1638 gint old = priv->map_source;
1639 priv->map_source = g_value_get_int (value);
1640 if(old >= OSM_GPS_MAP_SOURCE_NULL &&
1641 priv->map_source != old &&
1642 priv->map_source >= OSM_GPS_MAP_SOURCE_NULL &&
1643 priv->map_source <= OSM_GPS_MAP_SOURCE_LAST) {
1644
1645 /* we now have to switch the entire map */
1646
1647 /* flush the ram cache */
1648 g_hash_table_remove_all(priv->tile_cache);
1649
1650 osm_gps_map_setup(priv);
1651
1652 inspect_map_uri(map);
1653
1654 /* adjust zoom if necessary */
1655 if(priv->map_zoom > priv->max_zoom)
1656 osm_gps_map_set_zoom(map, priv->max_zoom);
1657
1658 if(priv->map_zoom < priv->min_zoom)
1659 osm_gps_map_set_zoom(map, priv->min_zoom);
1660
1661 } } break;
1662 case PROP_IMAGE_FORMAT:
1663 priv->image_format = g_value_dup_string (value);
1664 break;
1665 case PROP_DRAG_LIMIT:
1666 priv->drag_limit = g_value_get_int (value);
1667 break;
1668 default:
1669 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1670 break;
1671 }
1672 }
1673
1674 static void
1675 osm_gps_map_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
1676 {
1677 g_return_if_fail (OSM_IS_GPS_MAP (object));
1678 OsmGpsMap *map = OSM_GPS_MAP(object);
1679 OsmGpsMapPrivate *priv = map->priv;
1680
1681 switch (prop_id)
1682 {
1683 case PROP_AUTO_CENTER:
1684 g_value_set_boolean(value, priv->map_auto_center);
1685 break;
1686 case PROP_RECORD_TRIP_HISTORY:
1687 g_value_set_boolean(value, priv->record_trip_history);
1688 break;
1689 case PROP_SHOW_TRIP_HISTORY:
1690 g_value_set_boolean(value, priv->show_trip_history);
1691 break;
1692 case PROP_AUTO_DOWNLOAD:
1693 g_value_set_boolean(value, priv->map_auto_download);
1694 break;
1695 case PROP_REPO_URI:
1696 g_value_set_string(value, priv->repo_uri);
1697 break;
1698 case PROP_PROXY_URI:
1699 g_value_set_string(value, priv->proxy_uri);
1700 break;
1701 case PROP_TILE_CACHE_DIR:
1702 g_value_set_string(value, priv->cache_dir);
1703 break;
1704 case PROP_TILE_CACHE_BASE_DIR:
1705 g_value_set_string(value, priv->tile_base_dir);
1706 break;
1707 case PROP_TILE_CACHE_DIR_IS_FULL_PATH:
1708 g_value_set_boolean(value, FALSE);
1709 break;
1710 case PROP_ZOOM:
1711 g_value_set_int(value, priv->map_zoom);
1712 break;
1713 case PROP_MAX_ZOOM:
1714 g_value_set_int(value, priv->max_zoom);
1715 break;
1716 case PROP_MIN_ZOOM:
1717 g_value_set_int(value, priv->min_zoom);
1718 break;
1719 case PROP_LATITUDE:
1720 g_value_set_float(value, rad2deg(priv->center_rlat));
1721 break;
1722 case PROP_LONGITUDE:
1723 g_value_set_float(value, rad2deg(priv->center_rlon));
1724 break;
1725 case PROP_MAP_X:
1726 g_value_set_int(value, priv->map_x);
1727 break;
1728 case PROP_MAP_Y:
1729 g_value_set_int(value, priv->map_y);
1730 break;
1731 case PROP_TILES_QUEUED:
1732 g_value_set_int(value, g_hash_table_size(priv->tile_queue));
1733 break;
1734 case PROP_GPS_TRACK_WIDTH:
1735 g_value_set_int(value, priv->ui_gps_track_width);
1736 break;
1737 case PROP_GPS_POINT_R1:
1738 g_value_set_int(value, priv->ui_gps_point_inner_radius);
1739 break;
1740 case PROP_GPS_POINT_R2:
1741 g_value_set_int(value, priv->ui_gps_point_outer_radius);
1742 break;
1743 case PROP_MAP_SOURCE:
1744 g_value_set_int(value, priv->map_source);
1745 break;
1746 case PROP_IMAGE_FORMAT:
1747 g_value_set_string(value, priv->image_format);
1748 break;
1749 case PROP_DRAG_LIMIT:
1750 g_value_set_int(value, priv->drag_limit);
1751 break;
1752 default:
1753 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1754 break;
1755 }
1756 }
1757
1758 static gboolean
1759 osm_gps_map_scroll_event (GtkWidget *widget, GdkEventScroll *event)
1760 {
1761 OsmGpsMap *map = OSM_GPS_MAP(widget);
1762
1763 if (event->direction == GDK_SCROLL_UP)
1764 osm_gps_map_zoom_in(map);
1765 else if (event->direction == GDK_SCROLL_DOWN)
1766 osm_gps_map_zoom_out(map);
1767
1768 return FALSE;
1769 }
1770
1771 static gboolean
1772 osm_gps_map_button_press (GtkWidget *widget, GdkEventButton *event)
1773 {
1774 OsmGpsMap *map = OSM_GPS_MAP(widget);
1775 OsmGpsMapPrivate *priv = map->priv;
1776
1777 if (priv->layers) {
1778 GSList *list;
1779 for(list = priv->layers; list != NULL; list = list->next) {
1780 OsmGpsMapLayer *layer = list->data;
1781 if (osm_gps_map_layer_button_press(layer, map, event))
1782 return FALSE;
1783 }
1784 }
1785
1786 priv->button_down = TRUE;
1787 priv->drag_counter = 0;
1788 priv->drag_start_mouse_x = (int) event->x;
1789 priv->drag_start_mouse_y = (int) event->y;
1790 priv->drag_start_map_x = priv->map_x;
1791 priv->drag_start_map_y = priv->map_y;
1792
1793 return FALSE;
1794 }
1795
1796 static gboolean
1797 osm_gps_map_button_release (GtkWidget *widget, GdkEventButton *event)
1798 {
1799 OsmGpsMap *map = OSM_GPS_MAP(widget);
1800 OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);
1801
1802 if(!priv->button_down)
1803 return FALSE;
1804
1805 if (priv->dragging)
1806 {
1807 priv->dragging = FALSE;
1808
1809 priv->map_x = priv->drag_start_map_x;
1810 priv->map_y = priv->drag_start_map_y;
1811
1812 priv->map_x += (priv->drag_start_mouse_x - (int) event->x);
1813 priv->map_y += (priv->drag_start_mouse_y - (int) event->y);
1814
1815 center_coord_update(map);
1816
1817 osm_gps_map_map_redraw_idle(map);
1818 }
1819
1820 priv->drag_counter = -1;
1821 priv->button_down = 0;
1822
1823 return FALSE;
1824 }
1825
1826 static gboolean
1827 osm_gps_map_expose (GtkWidget *widget, GdkEventExpose *event);
1828
1829 static gboolean
1830 osm_gps_map_map_expose (GtkWidget *widget)
1831 {
1832 OsmGpsMapPrivate *priv = OSM_GPS_MAP(widget)->priv;
1833
1834 priv->drag_expose = 0;
1835 osm_gps_map_expose (widget, NULL);
1836 return FALSE;
1837 }
1838
1839 static gboolean
1840 osm_gps_map_motion_notify (GtkWidget *widget, GdkEventMotion *event)
1841 {
1842 int x, y;
1843 GdkModifierType state;
1844 OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);
1845
1846 if(!priv->button_down)
1847 return FALSE;
1848
1849 if (event->is_hint)
1850 gdk_window_get_pointer (event->window, &x, &y, &state);
1851 else
1852 {
1853 x = event->x;
1854 y = event->y;
1855 state = event->state;
1856 }
1857
1858 // are we being dragged
1859 if (!(state & GDK_BUTTON1_MASK))
1860 return FALSE;
1861
1862 if (priv->drag_counter < 0)
1863 return FALSE;
1864
1865 /* not yet dragged far enough? */
1866 if(!priv->drag_counter &&
1867 ( (x - priv->drag_start_mouse_x) * (x - priv->drag_start_mouse_x) +
1868 (y - priv->drag_start_mouse_y) * (y - priv->drag_start_mouse_y) <
1869 priv->drag_limit*priv->drag_limit))
1870 return FALSE;
1871
1872 priv->drag_counter++;
1873
1874 priv->dragging = TRUE;
1875
1876 if (priv->map_auto_center)
1877 g_object_set(G_OBJECT(widget), "auto-center", FALSE, NULL);
1878
1879 priv->drag_mouse_dx = x - priv->drag_start_mouse_x;
1880 priv->drag_mouse_dy = y - priv->drag_start_mouse_y;
1881
1882 /* instead of redrawing directly just add an idle function */
1883 if (!priv->drag_expose)
1884 priv->drag_expose =
1885 g_idle_add ((GSourceFunc)osm_gps_map_map_expose, widget);
1886
1887 return FALSE;
1888 }
1889
1890 static gboolean
1891 osm_gps_map_configure (GtkWidget *widget, GdkEventConfigure *event)
1892 {
1893 OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);
1894
1895 /* create pixmap */
1896 if (priv->pixmap)
1897 g_object_unref (priv->pixmap);
1898
1899 priv->pixmap = gdk_pixmap_new (
1900 widget->window,
1901 widget->allocation.width + EXTRA_BORDER * 2,
1902 widget->allocation.height + EXTRA_BORDER * 2,
1903 -1);
1904
1905 // pixel_x,y, offsets
1906 gint pixel_x = lon2pixel(priv->map_zoom, priv->center_rlon);
1907 gint pixel_y = lat2pixel(priv->map_zoom, priv->center_rlat);
1908
1909 priv->map_x = pixel_x - widget->allocation.width/2;
1910 priv->map_y = pixel_y - widget->allocation.height/2;
1911
1912 #ifdef OSD_DOUBLE_BUFFER
1913 if (priv->dbuf_pixmap)
1914 g_object_unref (priv->dbuf_pixmap);
1915
1916 priv->dbuf_pixmap = gdk_pixmap_new (
1917 widget->window,
1918 widget->allocation.width,
1919 widget->allocation.height,
1920 -1);
1921 #endif
1922
1923
1924 /* and gc, used for clipping (I think......) */
1925 if(priv->gc_map)
1926 g_object_unref(priv->gc_map);
1927
1928 priv->gc_map = gdk_gc_new(priv->pixmap);
1929
1930 osm_gps_map_map_redraw(OSM_GPS_MAP(widget));
1931
1932 g_signal_emit_by_name(widget, "changed");
1933
1934 return FALSE;
1935 }
1936
1937 static gboolean
1938 osm_gps_map_expose (GtkWidget *widget, GdkEventExpose *event)
1939 {
1940 OsmGpsMap *map = OSM_GPS_MAP(widget);
1941 OsmGpsMapPrivate *priv = map->priv;
1942
1943 #ifdef OSD_DOUBLE_BUFFER
1944 GdkDrawable *drawable = priv->dbuf_pixmap;
1945 #else
1946 GdkDrawable *drawable = widget->window;
1947 #endif
1948
1949 if (!priv->drag_mouse_dx && !priv->drag_mouse_dy && event)
1950 {
1951 gdk_draw_drawable (drawable,
1952 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
1953 priv->pixmap,
1954 event->area.x + EXTRA_BORDER, event->area.y + EXTRA_BORDER,
1955 event->area.x, event->area.y,
1956 event->area.width, event->area.height);
1957 }
1958 else
1959 {
1960 gdk_draw_drawable (drawable,
1961 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
1962 priv->pixmap,
1963 0,0,
1964 priv->drag_mouse_dx - EXTRA_BORDER,
1965 priv->drag_mouse_dy - EXTRA_BORDER,
1966 -1,-1);
1967
1968 //Paint white outside of the map if dragging. Its less
1969 //ugly than painting the corrupted map
1970 if(priv->drag_mouse_dx>EXTRA_BORDER) {
1971 gdk_draw_rectangle (drawable,
1972 widget->style->white_gc,
1973 TRUE,
1974 0, 0,
1975 priv->drag_mouse_dx - EXTRA_BORDER,
1976 widget->allocation.height);
1977 }
1978 else if (-priv->drag_mouse_dx > EXTRA_BORDER)
1979 {
1980 gdk_draw_rectangle (drawable,
1981 widget->style->white_gc,
1982 TRUE,
1983 priv->drag_mouse_dx + widget->allocation.width + EXTRA_BORDER, 0,
1984 -priv->drag_mouse_dx - EXTRA_BORDER,
1985 widget->allocation.height);
1986 }
1987
1988 if (priv->drag_mouse_dy>EXTRA_BORDER) {
1989 gdk_draw_rectangle (drawable,
1990 widget->style->white_gc,
1991 TRUE,
1992 0, 0,
1993 widget->allocation.width,
1994 priv->drag_mouse_dy - EXTRA_BORDER);
1995 }
1996 else if (-priv->drag_mouse_dy > EXTRA_BORDER)
1997 {
1998 gdk_draw_rectangle (drawable,
1999 widget->style->white_gc,
2000 TRUE,
2001 0, priv->drag_mouse_dy + widget->allocation.height + EXTRA_BORDER,
2002 widget->allocation.width,
2003 -priv->drag_mouse_dy - EXTRA_BORDER);
2004 }
2005 }
2006
2007 if (priv->layers) {
2008 GSList *list;
2009 for(list = priv->layers; list != NULL; list = list->next) {
2010 OsmGpsMapLayer *layer = list->data;
2011 osm_gps_map_layer_draw(layer, map, drawable);
2012 #ifdef OSD_DOUBLE_BUFFER
2013 gdk_draw_drawable (widget->window,
2014 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
2015 priv->dbuf_pixmap,
2016 0,0,0,0,-1,-1);
2017 #endif
2018 }
2019 }
2020
2021 return FALSE;
2022 }
2023
2024 static void
2025 osm_gps_map_class_init (OsmGpsMapClass *klass)
2026 {
2027 GObjectClass* object_class = G_OBJECT_CLASS (klass);
2028 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
2029
2030 g_type_class_add_private (klass, sizeof (OsmGpsMapPrivate));
2031
2032 object_class->dispose = osm_gps_map_dispose;
2033 object_class->finalize = osm_gps_map_finalize;
2034 object_class->constructor = osm_gps_map_constructor;
2035 object_class->set_property = osm_gps_map_set_property;
2036 object_class->get_property = osm_gps_map_get_property;
2037
2038 widget_class->expose_event = osm_gps_map_expose;
2039 widget_class->configure_event = osm_gps_map_configure;
2040 widget_class->button_press_event = osm_gps_map_button_press;
2041 widget_class->button_release_event = osm_gps_map_button_release;
2042 widget_class->motion_notify_event = osm_gps_map_motion_notify;
2043 widget_class->scroll_event = osm_gps_map_scroll_event;
2044
2045 g_object_class_install_property (object_class,
2046 PROP_AUTO_CENTER,
2047 g_param_spec_boolean ("auto-center",
2048 "auto center",
2049 "map auto center",
2050 TRUE,
2051 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
2052
2053 g_object_class_install_property (object_class,
2054 PROP_RECORD_TRIP_HISTORY,
2055 g_param_spec_boolean ("record-trip-history",
2056 "record trip history",
2057 "should all gps points be recorded in a trip history",
2058 TRUE,
2059 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
2060
2061 g_object_class_install_property (object_class,
2062 PROP_SHOW_TRIP_HISTORY,
2063 g_param_spec_boolean ("show-trip-history",
2064 "show trip history",
2065 "should the recorded trip history be shown on the map",
2066 TRUE,
2067 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
2068
2069 g_object_class_install_property (object_class,
2070 PROP_AUTO_DOWNLOAD,
2071 g_param_spec_boolean ("auto-download",
2072 "auto download",
2073 "map auto download",
2074 TRUE,
2075 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
2076
2077 g_object_class_install_property (object_class,
2078 PROP_REPO_URI,
2079 g_param_spec_string ("repo-uri",
2080 "repo uri",
2081 "map source tile repository uri",
2082 OSM_REPO_URI,
2083 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
2084
2085 g_object_class_install_property (object_class,
2086 PROP_PROXY_URI,
2087 g_param_spec_string ("proxy-uri",
2088 "proxy uri",
2089 "http proxy uri on NULL",
2090 NULL,
2091 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
2092
2093 g_object_class_install_property (object_class,
2094 PROP_TILE_CACHE_DIR,
2095 g_param_spec_string ("tile-cache",
2096 "tile cache",
2097 "osm local tile cache dir",
2098 OSM_GPS_MAP_CACHE_AUTO,
2099 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
2100
2101 g_object_class_install_property (object_class,
2102 PROP_TILE_CACHE_BASE_DIR,
2103 g_param_spec_string ("tile-cache-base",
2104 "tile cache-base",
2105 "base directory to which friendly and auto paths are appended",
2106 NULL,
2107 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
2108
2109 g_object_class_install_property (object_class,
2110 PROP_TILE_CACHE_DIR_IS_FULL_PATH,
2111 g_param_spec_boolean ("tile-cache-is-full-path",
2112 "tile cache is full path",
2113 "DEPRECIATED",
2114 FALSE,
2115 G_PARAM_READABLE | G_PARAM_WRITABLE));
2116
2117 g_object_class_install_property (object_class,
2118 PROP_ZOOM,
2119 g_param_spec_int ("zoom",
2120 "zoom",
2121 "initial zoom level",
2122 MIN_ZOOM, /* minimum property value */
2123 MAX_ZOOM, /* maximum property value */
2124 3,
2125 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
2126
2127 g_object_class_install_property (object_class,
2128 PROP_MAX_ZOOM,
2129 g_param_spec_int ("max-zoom",
2130 "max zoom",
2131 "maximum zoom level",
2132 MIN_ZOOM, /* minimum property value */
2133 MAX_ZOOM, /* maximum property value */
2134 OSM_MAX_ZOOM,
2135 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
2136
2137 g_object_class_install_property (object_class,
2138 PROP_MIN_ZOOM,
2139 g_param_spec_int ("min-zoom",
2140 "min zoom",
2141 "minimum zoom level",
2142 MIN_ZOOM, /* minimum property value */
2143 MAX_ZOOM, /* maximum property value */
2144 OSM_MIN_ZOOM,
2145 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
2146
2147 g_object_class_install_property (object_class,
2148 PROP_LATITUDE,
2149 g_param_spec_float ("latitude",
2150 "latitude",
2151 "latitude in degrees",
2152 -90.0, /* minimum property value */
2153 90.0, /* maximum property value */
2154 0,
2155 G_PARAM_READABLE));
2156
2157 g_object_class_install_property (object_class,
2158 PROP_LONGITUDE,
2159 g_param_spec_float ("longitude",
2160 "longitude",
2161 "longitude in degrees",
2162 -180.0, /* minimum property value */
2163 180.0, /* maximum property value */
2164 0,
2165 G_PARAM_READABLE));
2166
2167 g_object_class_install_property (object_class,
2168 PROP_MAP_X,
2169 g_param_spec_int ("map-x",
2170 "map-x",
2171 "initial map x location",
2172 G_MININT, /* minimum property value */
2173 G_MAXINT, /* maximum property value */
2174 890,
2175 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
2176
2177 g_object_class_install_property (object_class,
2178 PROP_MAP_Y,
2179 g_param_spec_int ("map-y",
2180 "map-y",
2181 "initial map y location",
2182 G_MININT, /* minimum property value */
2183 G_MAXINT, /* maximum property value */
2184 515,
2185 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
2186
2187 g_object_class_install_property (object_class,
2188 PROP_TILES_QUEUED,
2189 g_param_spec_int ("tiles-queued",
2190 "tiles-queued",
2191 "number of tiles currently waiting to download",
2192 G_MININT, /* minimum property value */
2193 G_MAXINT, /* maximum property value */
2194 0,
2195 G_PARAM_READABLE));
2196
2197 g_object_class_install_property (object_class,
2198 PROP_GPS_TRACK_WIDTH,
2199 g_param_spec_int ("gps-track-width",
2200 "gps-track-width",
2201 "width of the lines drawn for the gps track",
2202 1, /* minimum property value */
2203 G_MAXINT, /* maximum property value */
2204 4,
2205 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
2206
2207 g_object_class_install_property (object_class,
2208 PROP_GPS_POINT_R1,
2209 g_param_spec_int ("gps-track-point-radius",
2210 "gps-track-point-radius",
2211 "radius of the gps point inner circle",
2212 0, /* minimum property value */
2213 G_MAXINT, /* maximum property value */
2214 5,
2215 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
2216
2217 g_object_class_install_property (object_class,
2218 PROP_GPS_POINT_R2,
2219 g_param_spec_int ("gps-track-highlight-radius",
2220 "gps-track-highlight-radius",
2221 "radius of the gps point highlight circle",
2222 0, /* minimum property value */
2223 G_MAXINT, /* maximum property value */
2224 20,
2225 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
2226
2227 g_object_class_install_property (object_class,
2228 PROP_MAP_SOURCE,
2229 g_param_spec_int ("map-source",
2230 "map source",
2231 "map source ID",
2232 -1, /* minimum property value */
2233 G_MAXINT, /* maximum property value */
2234 -1,
2235 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
2236
2237 g_object_class_install_property (object_class,
2238 PROP_IMAGE_FORMAT,
2239 g_param_spec_string ("image-format",
2240 "image format",
2241 "map source tile repository image format (jpg, png)",
2242 OSM_IMAGE_FORMAT,
2243 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
2244
2245 g_object_class_install_property (object_class,
2246 PROP_DRAG_LIMIT,
2247 g_param_spec_int ("drag-limit",
2248 "drag limit",
2249 "the number of pixels the user has to move the pointer in order to start dragging",
2250 0, /* minimum property value */
2251 G_MAXINT, /* maximum property value */
2252 10,
2253 G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
2254
2255 g_signal_new ("changed", OSM_TYPE_GPS_MAP,
2256 G_SIGNAL_RUN_FIRST, 0, NULL, NULL,
2257 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
2258 }
2259
2260 const char*
2261 osm_gps_map_source_get_friendly_name(OsmGpsMapSource_t source)
2262 {
2263 switch(source)
2264 {
2265 case OSM_GPS_MAP_SOURCE_NULL:
2266 return "None";
2267 case OSM_GPS_MAP_SOURCE_OPENSTREETMAP:
2268 return "OpenStreetMap I";
2269 case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER:
2270 return "OpenStreetMap II";
2271 case OSM_GPS_MAP_SOURCE_OPENAERIALMAP:
2272 return "OpenAerialMap";
2273 case OSM_GPS_MAP_SOURCE_OPENCYCLEMAP:
2274 return "OpenCycleMap";
2275 case OSM_GPS_MAP_SOURCE_OSM_PUBLIC_TRANSPORT:
2276 return "Public Transport";
2277 case OSM_GPS_MAP_SOURCE_OSMC_TRAILS:
2278 return "OSMC Trails";
2279 case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE:
2280 return "Maps-For-Free";
2281 case OSM_GPS_MAP_SOURCE_GOOGLE_STREET:
2282 return "Google Maps";
2283 case OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE:
2284 return "Google Satellite";
2285 case OSM_GPS_MAP_SOURCE_GOOGLE_HYBRID:
2286 return "Google Hybrid";
2287 case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_STREET:
2288 return "Virtual Earth";
2289 case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_SATELLITE:
2290 return "Virtual Earth Satellite";
2291 case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_HYBRID:
2292 return "Virtual Earth Hybrid";
2293 case OSM_GPS_MAP_SOURCE_YAHOO_STREET:
2294 return "Yahoo Maps";
2295 case OSM_GPS_MAP_SOURCE_YAHOO_SATELLITE:
2296 return "Yahoo Satellite";
2297 case OSM_GPS_MAP_SOURCE_YAHOO_HYBRID:
2298 return "Yahoo Hybrid";
2299 case OSM_GPS_MAP_SOURCE_LAST:
2300 default:
2301 return NULL;
2302 }
2303 return NULL;
2304 }
2305
2306 //http://www.internettablettalk.com/forums/showthread.php?t=5209
2307 //https://garage.maemo.org/plugins/scmsvn/viewcvs.php/trunk/src/maps.c?root=maemo-mapper&view=markup
2308 //http://www.ponies.me.uk/maps/GoogleTileUtils.java
2309 //http://www.mgmaps.com/cache/MapTileCacher.perl
2310 const char*
2311 osm_gps_map_source_get_repo_uri(OsmGpsMapSource_t source)
2312 {
2313 switch(source)
2314 {
2315 case OSM_GPS_MAP_SOURCE_NULL:
2316 return "none://";
2317 case OSM_GPS_MAP_SOURCE_OPENSTREETMAP:
2318 return OSM_REPO_URI;
2319 case OSM_GPS_MAP_SOURCE_OPENAERIALMAP:
2320 /* OpenAerialMap is down, offline till furthur notice
2321 http://openaerialmap.org/pipermail/talk_openaerialmap.org/2008-December/000055.html */
2322 return NULL;
2323 case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER:
2324 return "http://tah.openstreetmap.org/Tiles/tile/#Z/#X/#Y.png";
2325 case OSM_GPS_MAP_SOURCE_OPENCYCLEMAP:
2326 return "http://c.andy.sandbox.cloudmade.com/tiles/cycle/#Z/#X/#Y.png";
2327 case OSM_GPS_MAP_SOURCE_OSM_PUBLIC_TRANSPORT:
2328 return "http://tile.xn--pnvkarte-m4a.de/tilegen/#Z/#X/#Y.png";
2329 case OSM_GPS_MAP_SOURCE_OSMC_TRAILS:
2330 return "http://topo.geofabrik.de/trails/#Z/#X/#Y.png";
2331 case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE:
2332 return "http://maps-for-free.com/layer/relief/z#Z/row#Y/#Z_#X-#Y.jpg";
2333 case OSM_GPS_MAP_SOURCE_GOOGLE_STREET:
2334 return "http://mt#R.google.com/vt/v=w2.97&x=#X&y=#Y&z=#Z";
2335 case OSM_GPS_MAP_SOURCE_GOOGLE_HYBRID:
2336 /* No longer working
2337 "http://mt#R.google.com/mt?n=404&v=w2t.99&x=#X&y=#Y&zoom=#S" */
2338 return NULL;
2339 case OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE:
2340 return "http://khm#R.google.com/kh/v=51&x=#X&y=#Y&z=#Z";
2341 case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_STREET:
2342 return "http://a#R.ortho.tiles.virtualearth.net/tiles/r#W.jpeg?g=50";
2343 case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_SATELLITE:
2344 return "http://a#R.ortho.tiles.virtualearth.net/tiles/a#W.jpeg?g=50";
2345 case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_HYBRID:
2346 return "http://a#R.ortho.tiles.virtualearth.net/tiles/h#W.jpeg?g=50";
2347 case OSM_GPS_MAP_SOURCE_YAHOO_STREET:
2348 case OSM_GPS_MAP_SOURCE_YAHOO_SATELLITE:
2349 case OSM_GPS_MAP_SOURCE_YAHOO_HYBRID:
2350 /* TODO: Implement signed Y, aka U
2351 * http://us.maps3.yimg.com/aerial.maps.yimg.com/ximg?v=1.7&t=a&s=256&x=%d&y=%-d&z=%d
2352 * x = tilex,
2353 * y = (1 << (MAX_ZOOM - zoom)) - tiley - 1,
2354 * z = zoom - (MAX_ZOOM - 17));
2355 */
2356 return NULL;
2357 case OSM_GPS_MAP_SOURCE_LAST:
2358 default:
2359 return NULL;
2360 }
2361 return NULL;
2362 }
2363
2364 const char *
2365 osm_gps_map_source_get_image_format(OsmGpsMapSource_t source)
2366 {
2367 switch(source) {
2368 case OSM_GPS_MAP_SOURCE_NULL:
2369 case OSM_GPS_MAP_SOURCE_OPENSTREETMAP:
2370 case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER:
2371 case OSM_GPS_MAP_SOURCE_OPENCYCLEMAP:
2372 case OSM_GPS_MAP_SOURCE_OSM_PUBLIC_TRANSPORT:
2373 case OSM_GPS_MAP_SOURCE_OSMC_TRAILS:
2374 return "png";
2375 case OSM_GPS_MAP_SOURCE_OPENAERIALMAP:
2376 case OSM_GPS_MAP_SOURCE_GOOGLE_STREET:
2377 case OSM_GPS_MAP_SOURCE_GOOGLE_HYBRID:
2378 case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_STREET:
2379 case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_SATELLITE:
2380 case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_HYBRID:
2381 case OSM_GPS_MAP_SOURCE_YAHOO_STREET:
2382 case OSM_GPS_MAP_SOURCE_YAHOO_SATELLITE:
2383 case OSM_GPS_MAP_SOURCE_YAHOO_HYBRID:
2384 case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE:
2385 case OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE:
2386 return "jpg";
2387 case OSM_GPS_MAP_SOURCE_LAST:
2388 default:
2389 return "bin";
2390 }
2391 return "bin";
2392 }
2393
2394
2395 int
2396 osm_gps_map_source_get_min_zoom(OsmGpsMapSource_t source)
2397 {
2398 return 1;
2399 }
2400
2401 int
2402 osm_gps_map_source_get_max_zoom(OsmGpsMapSource_t source)
2403 {
2404 switch(source) {
2405 case OSM_GPS_MAP_SOURCE_NULL:
2406 return 18;
2407 case OSM_GPS_MAP_SOURCE_OPENSTREETMAP:
2408 case OSM_GPS_MAP_SOURCE_OPENCYCLEMAP:
2409 case OSM_GPS_MAP_SOURCE_OSM_PUBLIC_TRANSPORT:
2410 return OSM_MAX_ZOOM;
2411 case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER:
2412 case OSM_GPS_MAP_SOURCE_OPENAERIALMAP:
2413 case OSM_GPS_MAP_SOURCE_GOOGLE_STREET:
2414 case OSM_GPS_MAP_SOURCE_GOOGLE_HYBRID:
2415 case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_STREET:
2416 case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_SATELLITE:
2417 case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_HYBRID:
2418 case OSM_GPS_MAP_SOURCE_YAHOO_STREET:
2419 case OSM_GPS_MAP_SOURCE_YAHOO_SATELLITE:
2420 case OSM_GPS_MAP_SOURCE_YAHOO_HYBRID:
2421 return 17;
2422 case OSM_GPS_MAP_SOURCE_OSMC_TRAILS:
2423 return 15;
2424 case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE:
2425 return 11;
2426 case OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE:
2427 return 18;
2428 case OSM_GPS_MAP_SOURCE_LAST:
2429 default:
2430 return 17;
2431 }
2432 return 17;
2433 }
2434
2435 gboolean
2436 osm_gps_map_source_is_valid(OsmGpsMapSource_t source)
2437 {
2438 return osm_gps_map_source_get_repo_uri(source) != NULL;
2439 }
2440
2441 void
2442 osm_gps_map_download_maps (OsmGpsMap *map, coord_t *pt1, coord_t *pt2, int zoom_start, int zoom_end)
2443 {
2444 int i,j,zoom,num_tiles;
2445 OsmGpsMapPrivate *priv = map->priv;
2446
2447 if (pt1 && pt2)
2448 {
2449 gchar *filename;
2450 num_tiles = 0;
2451 zoom_end = CLAMP(zoom_end, priv->min_zoom, priv->max_zoom);
2452 g_debug("Download maps: z:%d->%d",zoom_start, zoom_end);
2453
2454 for(zoom=zoom_start; zoom<=zoom_end; zoom++)
2455 {
2456 int x1,y1,x2,y2;
2457
2458 x1 = (int)floor((float)lon2pixel(zoom, pt1->rlon) / (float)TILESIZE);
2459 y1 = (int)floor((float)lat2pixel(zoom, pt1->rlat) / (float)TILESIZE);
2460
2461 x2 = (int)floor((float)lon2pixel(zoom, pt2->rlon) / (float)TILESIZE);
2462 y2 = (int)floor((float)lat2pixel(zoom, pt2->rlat) / (float)TILESIZE);
2463
2464 // loop x1-x2
2465 for(i=x1; i<=x2; i++)
2466 {
2467 // loop y1 - y2
2468 for(j=y1; j<=y2; j++)
2469 {
2470 // x = i, y = j
2471 filename = g_strdup_printf("%s%c%d%c%d%c%d.%s",
2472 priv->cache_dir, G_DIR_SEPARATOR,
2473 zoom, G_DIR_SEPARATOR,
2474 i, G_DIR_SEPARATOR,
2475 j,
2476 priv->image_format);
2477 if (!g_file_test(filename, G_FILE_TEST_EXISTS))
2478 {
2479 osm_gps_map_download_tile(map, zoom, i, j, FALSE);
2480 num_tiles++;
2481 }
2482 g_free(filename);
2483 }
2484 }
2485 g_debug("DL @Z:%d = %d tiles",zoom,num_tiles);
2486 }
2487 }
2488 }
2489
2490 void
2491 osm_gps_map_get_bbox (OsmGpsMap *map, coord_t *pt1, coord_t *pt2)
2492 {
2493 OsmGpsMapPrivate *priv = map->priv;
2494
2495 if (pt1 && pt2) {
2496 pt1->rlat = pixel2lat(priv->map_zoom, priv->map_y);
2497 pt1->rlon = pixel2lon(priv->map_zoom, priv->map_x);
2498 pt2->rlat = pixel2lat(priv->map_zoom, priv->map_y + GTK_WIDGET(map)->allocation.height);
2499 pt2->rlon = pixel2lon(priv->map_zoom, priv->map_x + GTK_WIDGET(map)->allocation.width);
2500
2501 g_debug("BBOX: %f %f %f %f", pt1->rlat, pt1->rlon, pt2->rlat, pt2->rlon);
2502 }
2503 }
2504
2505 void
2506 osm_gps_map_set_mapcenter (OsmGpsMap *map, float latitude, float longitude, int zoom)
2507 {
2508 osm_gps_map_set_center (map, latitude, longitude);
2509 osm_gps_map_set_zoom (map, zoom);
2510 }
2511
2512 void
2513 osm_gps_map_set_center (OsmGpsMap *map, float latitude, float longitude)
2514 {
2515 int pixel_x, pixel_y;
2516 OsmGpsMapPrivate *priv;
2517
2518 g_return_if_fail (OSM_IS_GPS_MAP (map));
2519 priv = map->priv;
2520
2521 g_object_set(G_OBJECT(map), "auto-center", FALSE, NULL);
2522
2523 priv->center_rlat = deg2rad(latitude);
2524 priv->center_rlon = deg2rad(longitude);
2525
2526 // pixel_x,y, offsets
2527 pixel_x = lon2pixel(priv->map_zoom, priv->center_rlon);
2528 pixel_y = lat2pixel(priv->map_zoom, priv->center_rlat);
2529
2530 priv->map_x = pixel_x - GTK_WIDGET(map)->allocation.width/2;
2531 priv->map_y = pixel_y - GTK_WIDGET(map)->allocation.height/2;
2532
2533 osm_gps_map_map_redraw_idle(map);
2534
2535 g_signal_emit_by_name(map, "changed");
2536 }
2537
2538 int
2539 osm_gps_map_set_zoom (OsmGpsMap *map, int zoom)
2540 {
2541 int zoom_old;
2542 double factor = 0.0;
2543 int width_center, height_center;
2544 OsmGpsMapPrivate *priv;
2545
2546 g_return_val_if_fail (OSM_IS_GPS_MAP (map), 0);
2547 priv = map->priv;
2548
2549 if (zoom != priv->map_zoom)
2550 {
2551 width_center = GTK_WIDGET(map)->allocation.width / 2;
2552 height_center = GTK_WIDGET(map)->allocation.height / 2;
2553
2554 zoom_old = priv->map_zoom;
2555 //constrain zoom min_zoom -> max_zoom
2556 priv->map_zoom = CLAMP(zoom, priv->min_zoom, priv->max_zoom);
2557
2558 priv->map_x = lon2pixel(priv->map_zoom, priv->center_rlon) - width_center;
2559 priv->map_y = lat2pixel(priv->map_zoom, priv->center_rlat) - height_center;
2560
2561 factor = pow(2, priv->map_zoom-zoom_old);
2562 g_debug("Zoom changed from %d to %d factor:%f x:%d",
2563 zoom_old, priv->map_zoom, factor, priv->map_x);
2564
2565 osm_gps_map_map_redraw_idle(map);
2566
2567 g_signal_emit_by_name(map, "changed");
2568 }
2569 return priv->map_zoom;
2570 }
2571
2572 int
2573 osm_gps_map_zoom_in (OsmGpsMap *map)
2574 {
2575 g_return_val_if_fail (OSM_IS_GPS_MAP (map), 0);
2576 return osm_gps_map_set_zoom(map, map->priv->map_zoom+1);
2577 }
2578
2579 int
2580 osm_gps_map_zoom_out (OsmGpsMap *map)
2581 {
2582 g_return_val_if_fail (OSM_IS_GPS_MAP (map), 0);
2583 return osm_gps_map_set_zoom(map, map->priv->map_zoom-1);
2584 }
2585
2586 void
2587 osm_gps_map_add_track (OsmGpsMap *map, GSList *track)
2588 {
2589 OsmGpsMapPrivate *priv;
2590
2591 g_return_if_fail (OSM_IS_GPS_MAP (map));
2592 priv = map->priv;
2593
2594 if (track) {
2595 priv->tracks = g_slist_append(priv->tracks, track);
2596 osm_gps_map_map_redraw_idle(map);
2597 }
2598 }
2599
2600 void
2601 osm_gps_map_replace_track (OsmGpsMap *map, GSList *old_track, GSList *new_track)
2602 {
2603 OsmGpsMapPrivate *priv;
2604
2605 if(!old_track) {
2606 osm_gps_map_add_track (map, new_track);
2607 return;
2608 }
2609
2610 g_return_if_fail (OSM_IS_GPS_MAP (map));
2611 priv = map->priv;
2612
2613 GSList *old = g_slist_find(priv->tracks, old_track);
2614 if(!old) {
2615 g_warning("track to be replaced not found");
2616 return;
2617 }
2618
2619 old->data = new_track;
2620 osm_gps_map_map_redraw_idle(map);
2621 }
2622
2623 void
2624 osm_gps_map_clear_tracks (OsmGpsMap *map)
2625 {
2626 g_return_if_fail (OSM_IS_GPS_MAP (map));
2627
2628 osm_gps_map_free_tracks(map);
2629 osm_gps_map_map_redraw_idle(map);
2630 }
2631
2632 void
2633 osm_gps_map_add_image_with_alignment (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image, float xalign, float yalign)
2634 {
2635 g_return_if_fail (OSM_IS_GPS_MAP (map));
2636
2637 if (image) {
2638 OsmGpsMapPrivate *priv = map->priv;
2639 image_t *im;
2640
2641 //cache w/h for speed, and add image to list
2642 im = g_new0(image_t,1);
2643 im->w = gdk_pixbuf_get_width(image);
2644 im->h = gdk_pixbuf_get_height(image);
2645 im->pt.rlat = deg2rad(latitude);
2646 im->pt.rlon = deg2rad(longitude);
2647
2648 //handle alignment
2649 im->xoffset = xalign * im->w;
2650 im->yoffset = yalign * im->h;
2651
2652 g_object_ref(image);
2653 im->image = image;
2654
2655 priv->images = g_slist_append(priv->images, im);
2656
2657 osm_gps_map_map_redraw_idle(map);
2658 }
2659 }
2660
2661 void
2662 osm_gps_map_add_image (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image)
2663 {
2664 osm_gps_map_add_image_with_alignment (map, latitude, longitude, image, 0.5, 0.5);
2665 }
2666
2667 gboolean
2668 osm_gps_map_remove_image (OsmGpsMap *map, GdkPixbuf *image)
2669 {
2670 OsmGpsMapPrivate *priv = map->priv;
2671 if (priv->images) {
2672 GSList *list;
2673 for(list = priv->images; list != NULL; list = list->next)
2674 {
2675 image_t *im = list->data;
2676 if (im->image == image)
2677 {
2678 priv->images = g_slist_remove_link(priv->images, list);
2679 g_object_unref(im->image);
2680 g_free(im);
2681 osm_gps_map_map_redraw_idle(map);
2682 return TRUE;
2683 }
2684 }
2685 }
2686 return FALSE;
2687 }
2688
2689 void
2690 osm_gps_map_clear_images (OsmGpsMap *map)
2691 {
2692 g_return_if_fail (OSM_IS_GPS_MAP (map));
2693
2694 osm_gps_map_free_images(map);
2695 osm_gps_map_map_redraw_idle(map);
2696 }
2697
2698 void
2699 osm_gps_map_draw_gps (OsmGpsMap *map, float latitude, float longitude, float heading)
2700 {
2701 int pixel_x, pixel_y;
2702 OsmGpsMapPrivate *priv;
2703
2704 g_return_if_fail (OSM_IS_GPS_MAP (map));
2705 priv = map->priv;
2706
2707 priv->gps->rlat = deg2rad(latitude);
2708 priv->gps->rlon = deg2rad(longitude);
2709 priv->gps_valid = TRUE;
2710 priv->gps_heading = deg2rad(heading);
2711
2712 // pixel_x,y, offsets
2713 pixel_x = lon2pixel(priv->map_zoom, priv->gps->rlon);
2714 pixel_y = lat2pixel(priv->map_zoom, priv->gps->rlat);
2715
2716 //If trip marker add to list of gps points.
2717 if (priv->record_trip_history) {
2718 coord_t *tp = g_new0(coord_t,1);
2719 tp->rlat = priv->gps->rlat;
2720 tp->rlon = priv->gps->rlon;
2721 priv->trip_history = g_slist_append(priv->trip_history, tp);
2722 }
2723
2724 // dont draw anything if we are dragging
2725 if (priv->dragging) {
2726 g_debug("Dragging");
2727 return;
2728 }
2729
2730 //Automatically center the map if the track approaches the edge
2731 if(priv->map_auto_center) {
2732 int x = pixel_x - priv->map_x;
2733 int y = pixel_y - priv->map_y;
2734 int width = GTK_WIDGET(map)->allocation.width;
2735 int height = GTK_WIDGET(map)->allocation.height;
2736 if( x < (width/2 - width/8) || x > (width/2 + width/8) ||
2737 y < (height/2 - height/8) || y > (height/2 + height/8)) {
2738
2739 priv->map_x = pixel_x - GTK_WIDGET(map)->allocation.width/2;
2740 priv->map_y = pixel_y - GTK_WIDGET(map)->allocation.height/2;
2741 center_coord_update(map);
2742 }
2743 }
2744
2745 // this redraws the map (including the gps track, and adjusts the
2746 // map center if it was changed
2747 osm_gps_map_map_redraw_idle(map);
2748 }
2749
2750 void
2751 osm_gps_map_clear_gps (OsmGpsMap *map)
2752 {
2753 osm_gps_map_free_trip(map);
2754 osm_gps_map_map_redraw_idle(map);
2755 }
2756
2757 coord_t
2758 osm_gps_map_get_co_ordinates (OsmGpsMap *map, int pixel_x, int pixel_y)
2759 {
2760 coord_t coord;
2761 OsmGpsMapPrivate *priv = map->priv;
2762
2763 coord.rlat = pixel2lat(priv->map_zoom, priv->map_y + pixel_y);
2764 coord.rlon = pixel2lon(priv->map_zoom, priv->map_x + pixel_x);
2765 return coord;
2766 }
2767
2768 GtkWidget *
2769 osm_gps_map_new (void)
2770 {
2771 return g_object_new (OSM_TYPE_GPS_MAP, NULL);
2772 }
2773
2774 void
2775 osm_gps_map_screen_to_geographic (OsmGpsMap *map, gint pixel_x, gint pixel_y,
2776 gfloat *latitude, gfloat *longitude)
2777 {
2778 OsmGpsMapPrivate *priv;
2779
2780 g_return_if_fail (OSM_IS_GPS_MAP (map));
2781 priv = map->priv;
2782
2783 if (latitude)
2784 *latitude = rad2deg(pixel2lat(priv->map_zoom, priv->map_y + pixel_y));
2785 if (longitude)
2786 *longitude = rad2deg(pixel2lon(priv->map_zoom, priv->map_x + pixel_x));
2787 }
2788
2789 void
2790 osm_gps_map_geographic_to_screen (OsmGpsMap *map,
2791 gfloat latitude, gfloat longitude,
2792 gint *pixel_x, gint *pixel_y)
2793 {
2794 OsmGpsMapPrivate *priv;
2795
2796 g_return_if_fail (OSM_IS_GPS_MAP (map));
2797 priv = map->priv;
2798
2799 if (pixel_x)
2800 *pixel_x = lon2pixel(priv->map_zoom, deg2rad(longitude)) -
2801 priv->map_x + priv->drag_mouse_dx;
2802 if (pixel_y)
2803 *pixel_y = lat2pixel(priv->map_zoom, deg2rad(latitude)) -
2804 priv->map_y + priv->drag_mouse_dy;
2805 }
2806
2807 void
2808 osm_gps_map_scroll (OsmGpsMap *map, gint dx, gint dy)
2809 {
2810 OsmGpsMapPrivate *priv;
2811
2812 g_return_if_fail (OSM_IS_GPS_MAP (map));
2813 priv = map->priv;
2814
2815 priv->map_x += dx;
2816 priv->map_y += dy;
2817 center_coord_update(map);
2818
2819 osm_gps_map_map_redraw_idle (map);
2820 }
2821
2822 float
2823 osm_gps_map_get_scale(OsmGpsMap *map)
2824 {
2825 OsmGpsMapPrivate *priv;
2826
2827 g_return_val_if_fail (OSM_IS_GPS_MAP (map), OSM_GPS_MAP_INVALID);
2828 priv = map->priv;
2829
2830 return osm_gps_map_get_scale_at_point(priv->map_zoom, priv->center_rlat, priv->center_rlon);
2831 }
2832
2833 char * osm_gps_map_get_default_cache_directory(void)
2834 {
2835 return g_build_filename(
2836 g_get_user_cache_dir(),
2837 "osmgpsmap",
2838 NULL);
2839 }
2840
2841 void osm_gps_map_set_keyboard_shortcut(OsmGpsMap *map, OsmGpsMapKey_t key, guint keyval)
2842 {
2843 g_return_if_fail (OSM_IS_GPS_MAP (map));
2844 g_return_if_fail(key < OSM_GPS_MAP_KEY_MAX);
2845
2846 map->priv->keybindings[key] = keyval;
2847 map->priv->keybindings_enabled = TRUE;
2848 }
2849
2850 void osm_gps_map_add_layer (OsmGpsMap *map, OsmGpsMapLayer *layer)
2851 {
2852 g_return_if_fail (OSM_IS_GPS_MAP (map));
2853 g_return_if_fail (OSM_GPS_MAP_IS_LAYER (layer));
2854
2855 g_object_ref(G_OBJECT(layer));
2856 map->priv->layers = g_slist_append(map->priv->layers, layer);
2857 }
2858
0 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */
1 /* vim:set et sw=4 ts=4 cino=t0,(0: */
2 /*
3 * osm-gps-map.h
4 * Copyright (C) Marcus Bauer 2008 <marcus.bauer@gmail.com>
5 * Copyright (C) John Stowers 2009 <john.stowers@gmail.com>
6 * Copyright (C) Till Harbaum 2009 <till@harbaum.org>
7 *
8 * Contributions by
9 * Everaldo Canuto 2009 <everaldo.canuto@gmail.com>
10 *
11 * This is free software: you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; version 2.
14 *
15 * This program 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.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 */
23
240 #ifndef _OSM_GPS_MAP_H_
251 #define _OSM_GPS_MAP_H_
262
27 #include <glib.h>
28 #include <glib-object.h>
29 #include <gtk/gtk.h>
30 #include <gdk-pixbuf/gdk-pixbuf.h>
31
32 G_BEGIN_DECLS
33
34 #define OSM_TYPE_GPS_MAP (osm_gps_map_get_type ())
35 #define OSM_GPS_MAP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), OSM_TYPE_GPS_MAP, OsmGpsMap))
36 #define OSM_GPS_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), OSM_TYPE_GPS_MAP, OsmGpsMapClass))
37 #define OSM_IS_GPS_MAP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OSM_TYPE_GPS_MAP))
38 #define OSM_IS_GPS_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OSM_TYPE_GPS_MAP))
39 #define OSM_GPS_MAP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OSM_TYPE_GPS_MAP, OsmGpsMapClass))
40
41 typedef struct _OsmGpsMapClass OsmGpsMapClass;
42 typedef struct _OsmGpsMap OsmGpsMap;
43 typedef struct _OsmGpsMapPrivate OsmGpsMapPrivate;
44
45 #include "osm-gps-map-layer.h"
46
47 struct _OsmGpsMapClass
48 {
49 GtkDrawingAreaClass parent_class;
50 };
51
52 struct _OsmGpsMap
53 {
54 GtkDrawingArea parent_instance;
55 OsmGpsMapPrivate *priv;
56 };
57
58 typedef struct {
59 float rlat;
60 float rlon;
61 } coord_t;
62
63 typedef enum {
64 OSM_GPS_MAP_SOURCE_NULL,
65 OSM_GPS_MAP_SOURCE_OPENSTREETMAP,
66 OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER,
67 OSM_GPS_MAP_SOURCE_OPENAERIALMAP,
68 OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE,
69 OSM_GPS_MAP_SOURCE_OPENCYCLEMAP,
70 OSM_GPS_MAP_SOURCE_OSM_PUBLIC_TRANSPORT,
71 OSM_GPS_MAP_SOURCE_GOOGLE_STREET,
72 OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE,
73 OSM_GPS_MAP_SOURCE_GOOGLE_HYBRID,
74 OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_STREET,
75 OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_SATELLITE,
76 OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_HYBRID,
77 OSM_GPS_MAP_SOURCE_YAHOO_STREET,
78 OSM_GPS_MAP_SOURCE_YAHOO_SATELLITE,
79 OSM_GPS_MAP_SOURCE_YAHOO_HYBRID,
80 OSM_GPS_MAP_SOURCE_OSMC_TRAILS,
81
82 OSM_GPS_MAP_SOURCE_LAST
83 } OsmGpsMapSource_t;
84
85 typedef enum {
86 OSM_GPS_MAP_KEY_FULLSCREEN,
87 OSM_GPS_MAP_KEY_ZOOMIN,
88 OSM_GPS_MAP_KEY_ZOOMOUT,
89 OSM_GPS_MAP_KEY_UP,
90 OSM_GPS_MAP_KEY_DOWN,
91 OSM_GPS_MAP_KEY_LEFT,
92 OSM_GPS_MAP_KEY_RIGHT,
93 OSM_GPS_MAP_KEY_MAX
94 } OsmGpsMapKey_t;
95
96 #define OSM_GPS_MAP_INVALID (0.0/0.0)
97 #define OSM_GPS_MAP_CACHE_DISABLED "none://"
98 #define OSM_GPS_MAP_CACHE_AUTO "auto://"
99 #define OSM_GPS_MAP_CACHE_FRIENDLY "friendly://"
100
101 GType osm_gps_map_get_type (void) G_GNUC_CONST;
102
103 GtkWidget* osm_gps_map_new (void);
104
105 char* osm_gps_map_get_default_cache_directory (void);
106
107 const char* osm_gps_map_source_get_friendly_name (OsmGpsMapSource_t source);
108 const char* osm_gps_map_source_get_repo_uri (OsmGpsMapSource_t source);
109 const char* osm_gps_map_source_get_image_format (OsmGpsMapSource_t source);
110 int osm_gps_map_source_get_min_zoom (OsmGpsMapSource_t source);
111 int osm_gps_map_source_get_max_zoom (OsmGpsMapSource_t source);
112 gboolean osm_gps_map_source_is_valid (OsmGpsMapSource_t source);
113
114 void osm_gps_map_download_maps (OsmGpsMap *map, coord_t *pt1, coord_t *pt2, int zoom_start, int zoom_end);
115 void osm_gps_map_get_bbox (OsmGpsMap *map, coord_t *pt1, coord_t *pt2);
116 void osm_gps_map_set_mapcenter (OsmGpsMap *map, float latitude, float longitude, int zoom);
117 void osm_gps_map_set_center (OsmGpsMap *map, float latitude, float longitude);
118 int osm_gps_map_set_zoom (OsmGpsMap *map, int zoom);
119 int osm_gps_map_zoom_in (OsmGpsMap *map);
120 int osm_gps_map_zoom_out (OsmGpsMap *map);
121 void osm_gps_map_add_track (OsmGpsMap *map, GSList *track);
122 void osm_gps_map_replace_track (OsmGpsMap *map, GSList *old_track, GSList *new_track);
123 void osm_gps_map_clear_tracks (OsmGpsMap *map);
124 void osm_gps_map_add_image (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image);
125 void osm_gps_map_add_image_with_alignment (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image, float xalign, float yalign);
126 gboolean osm_gps_map_remove_image (OsmGpsMap *map, GdkPixbuf *image);
127 void osm_gps_map_clear_images (OsmGpsMap *map);
128 void osm_gps_map_draw_gps (OsmGpsMap *map, float latitude, float longitude, float heading);
129 void osm_gps_map_clear_gps (OsmGpsMap *map);
130 coord_t osm_gps_map_get_co_ordinates (OsmGpsMap *map, int pixel_x, int pixel_y);
131 void osm_gps_map_screen_to_geographic (OsmGpsMap *map, gint pixel_x, gint pixel_y, gfloat *latitude, gfloat *longitude);
132 void osm_gps_map_geographic_to_screen (OsmGpsMap *map, gfloat latitude, gfloat longitude, gint *pixel_x, gint *pixel_y);
133 void osm_gps_map_scroll (OsmGpsMap *map, gint dx, gint dy);
134 float osm_gps_map_get_scale (OsmGpsMap *map);
135 void osm_gps_map_set_keyboard_shortcut (OsmGpsMap *map, OsmGpsMapKey_t key, guint keyval);
136 void osm_gps_map_add_layer (OsmGpsMap *map, OsmGpsMapLayer *layer);
137
138 G_END_DECLS
3 #include <osm-gps-map-osd.h>
4 #include <osm-gps-map-layer.h>
5 #include <osm-gps-map-track.h>
6 #include <osm-gps-map-point.h>
7 #include <osm-gps-map-image.h>
8 #include <osm-gps-map-source.h>
9 #include <osm-gps-map-widget.h>
10 #include <osm-gps-map-compat.h>
13911
14012 #endif /* _OSM_GPS_MAP_H_ */
13
src/poi.png less more
Binary diff not shown