Diff of /trunk/src/map-tool.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 66 by harbaum, Wed Aug 19 20:03:28 2009 UTC revision 144 by harbaum, Tue Oct 27 08:38:31 2009 UTC
# Line 17  Line 17 
17   * along with GPXView.  If not, see <http://www.gnu.org/licenses/>.   * along with GPXView.  If not, see <http://www.gnu.org/licenses/>.
18   */   */
19    
20    /*
21     * http://topo.geofabrik.de/relief/${z}/${x}/${y}.png  8-15
22     * http://topo.geofabrik.de/trail/${z}/${x}/${y}.png   8-15
23     */
24    
25  #include "gpxview.h"  #include "gpxview.h"
26  #include "converter.h"  #include "converter.h"
27  #include <math.h>    // for isnan  #include <math.h>    // for isnan
28    
29  #ifdef ENABLE_OSM_GPS_MAP  #ifdef ENABLE_OSM_GPS_MAP
30  #include "osm-gps-map.h"  #include "osm-gps-map.h"
31    #include "osm-gps-map-osd-classic.h"
32    #endif
33    
34    #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR == 5)
35    #include <gdk/gdkx.h>
36    #include <X11/Xatom.h>
37  #endif  #endif
38    
39  #define MAP_SOURCE  OSM_GPS_MAP_SOURCE_OPENSTREETMAP  /* default values */
40    #define MAP_SOURCE  OSM_GPS_MAP_SOURCE_OPENCYCLEMAP
41  #define GPS_DEFAULT_ZOOM 13  #define GPS_DEFAULT_ZOOM 13
42    
43  #define PROXY_KEY  "/system/http_proxy/"  #define PROXY_KEY  "/system/http_proxy/"
# Line 67  static const char *get_proxy_uri(appdata Line 79  static const char *get_proxy_uri(appdata
79  }  }
80    
81  static void  static void
82  cb_map_gps(map_context_t *context) {  cb_map_gps(osd_button_t but, map_context_t *context) {
83    pos_t *refpos = get_pos(context->appdata);  
84    if(refpos && !isnan(refpos->lat) && !isnan(refpos->lon)) {    if(but == OSD_GPS) {
85      osm_gps_map_set_mapcenter(OSM_GPS_MAP(context->widget),      pos_t *refpos = get_pos(context->appdata);
86                        refpos->lat, refpos->lon, GPS_DEFAULT_ZOOM);      if(refpos && !isnan(refpos->lat) && !isnan(refpos->lon)) {
87    } else {        gint zoom;
88      /* no coordinates given: display the entire world */        g_object_get(OSM_GPS_MAP(context->widget), "zoom", &zoom, NULL);
89      osm_gps_map_set_mapcenter(OSM_GPS_MAP(context->widget),        if(zoom < 10)
90                                0.0, 0.0, 1);          osm_gps_map_set_mapcenter(OSM_GPS_MAP(context->widget),
91                                      refpos->lat, refpos->lon, GPS_DEFAULT_ZOOM);
92          else
93            osm_gps_map_set_center(OSM_GPS_MAP(context->widget),
94                                   refpos->lat, refpos->lon);
95    
96          /* re-enable centering */
97          g_object_set(context->widget, "auto-center", TRUE, NULL);
98        } else {
99          /* no coordinates given: display the entire world */
100          osm_gps_map_set_mapcenter(OSM_GPS_MAP(context->widget),
101                                    0.0, 0.0, 1);
102        }
103    }    }
104  }  }
105    
# Line 92  static gboolean map_gps_update(gpointer Line 116  static gboolean map_gps_update(gpointer
116    
117    /* ... and enable "goto" button if it's valid */    /* ... and enable "goto" button if it's valid */
118    osm_gps_map_osd_enable_gps (OSM_GPS_MAP(context->widget),    osm_gps_map_osd_enable_gps (OSM_GPS_MAP(context->widget),
119                                OSM_GPS_MAP_OSD_GPS_CALLBACK(ok?cb_map_gps:NULL), context);                   OSM_GPS_MAP_OSD_CALLBACK(ok?cb_map_gps:NULL), context);
120    
121    if(ok) {    if(ok) {
122      float heading = NAN;      float heading = NAN;
# Line 116  static gboolean map_gps_update(gpointer Line 140  static gboolean map_gps_update(gpointer
140    return TRUE;    return TRUE;
141  }  }
142    
143  static gboolean on_map_configure(GtkWidget *widget,  static void map_draw_cache(GtkWidget *map, cache_t *cache) {
144                                   GdkEventConfigure *event,    GdkPixbuf *icon = icon_get(ICON_CACHE_TYPE, cache->type);
                                  map_context_t *context) {  
145    
146    /* set default values if they are invalid */    /* check if there's also an overwritten coordinate */
147    if(!context->appdata->map.zoom ||    if(cache->notes && cache->notes->override) {
148       isnan(context->appdata->map.pos.lat) ||      GdkPixbuf *over = icon_get(ICON_MISC, 1);
      isnan(context->appdata->map.pos.lon)) {  
     printf("no valid map position found\n");  
   
     pos_t *refpos = get_pos(context->appdata);  
     if(refpos && !isnan(refpos->lat) && !isnan(refpos->lon)) {  
       /* use gps position if present */  
       context->appdata->map.pos = *refpos;  
       context->appdata->map.zoom = GPS_DEFAULT_ZOOM;  
     } else {  
       /* use world map otherwise */  
       context->appdata->map.pos.lat = 0.0;  
       context->appdata->map.pos.lon = 0.0;  
       context->appdata->map.zoom = 1;  
     }  
   }  
149    
150    /* jump to initial position */      osm_gps_map_add_image(OSM_GPS_MAP(map),
151    osm_gps_map_set_mapcenter(OSM_GPS_MAP(context->widget),            cache->notes->pos.lat, cache->notes->pos.lon, icon);
152                              context->appdata->map.pos.lat,  
153                              context->appdata->map.pos.lon,      osm_gps_map_add_image(OSM_GPS_MAP(map),
154                              context->appdata->map.zoom);            cache->notes->pos.lat, cache->notes->pos.lon, over);
155      } else {
156    return FALSE;      if(!isnan(cache->pos.lat) && !isnan(cache->pos.lon))
157          osm_gps_map_add_image(OSM_GPS_MAP(map),
158                                cache->pos.lat, cache->pos.lon, icon);
159      }
160  }  }
161    
162  static void map_draw_cachelist(GtkWidget *map, cache_t *cache) {  static void map_draw_gpx(appdata_t *appdata, GtkWidget *map, gpx_t *gpx) {
163      if(!gpx->notes_loaded) {
164        notes_load_all(appdata, gpx);
165        gpx->notes_loaded = TRUE;
166      }
167    
168      cache_t *cache = gpx->cache;
169    while(cache) {    while(cache) {
170      GdkPixbuf *icon = icon_get(ICON_CACHE_TYPE, cache->type);      map_draw_cache(map, cache);
171        cache = cache->next;
172      }
173    }
174    
175    /* draw geocaches and set window title */
176    static void map_setup(map_context_t *context) {
177      char *name = NULL;
178    
179      if(!context->appdata->cur_gpx && !context->appdata->cur_cache) {
180        if(context->state != MAP_ALL) {
181          printf("map_setup(ALL)\n");
182    
183    #ifdef OSD_NAV
184          /* no navigation in this mode */
185          osm_gps_map_osd_clear_nav (OSM_GPS_MAP(context->widget));
186    #endif
187    
188          /* clear all existing ccahe images */
189          osm_gps_map_clear_images (OSM_GPS_MAP(context->widget));
190    
191          /* draw all geocaches */
192          gpx_t *gpx = context->appdata->gpx;
193          while(gpx) {
194            map_draw_gpx(context->appdata, context->widget, gpx);
195            gpx = gpx->next;
196          }
197          name = g_strdup(_("all"));
198          context->state = MAP_ALL;
199        }
200      } else if(!context->appdata->cur_cache) {
201        if(context->state != MAP_GPX) {
202          printf("map_setup(GPX)\n");
203    
204    #ifdef OSD_NAV
205          /* no navigation in this mode */
206          osm_gps_map_osd_clear_nav (OSM_GPS_MAP(context->widget));
207    #endif
208    
209          /* clear all existing ccahe images */
210          osm_gps_map_clear_images (OSM_GPS_MAP(context->widget));
211    
212          map_draw_gpx(context->appdata, context->widget,
213                       context->appdata->cur_gpx);
214          name = g_strdup(context->appdata->cur_gpx->name);
215          context->state = MAP_GPX;
216        }
217      } else {
218        cache_t *cache = context->appdata->cur_cache;
219    
220      osm_gps_map_add_image(OSM_GPS_MAP(map),      printf("map_setp(CACHE)\n");
221                            cache->pos.lat, cache->pos.lon, icon);  
222        /* no balloons in this mode */
223        context->balloon = NULL;
224        osm_gps_map_osd_clear_balloon (OSM_GPS_MAP(context->widget));
225    
226        /* clear all existing ccahe images */
227        osm_gps_map_clear_images (OSM_GPS_MAP(context->widget));
228    
229        map_draw_cache(context->widget, cache);
230        name = g_strdup(cache->name);
231        context->state = MAP_CACHE;
232    
233        /* navigation in this mode! */
234        pos_t cpos = gpx_cache_pos(cache);
235    
236      cache = cache->next;  #ifdef OSD_NAV
237        osm_gps_map_osd_draw_nav (OSM_GPS_MAP(context->widget),
238                                  context->appdata->imperial,
239                                  cpos.lat, cpos.lon, cache->name);
240    #else
241    #warning OSD_NAV not defined!
242    #endif
243    }    }
244    
245      if(name) {
246        char *title = g_strdup_printf(_("Map - %s"), name);
247        g_free(name);
248    
249        gtk_window_set_title(GTK_WINDOW(context->window), title);
250    
251        g_free(title);
252      } else
253        printf("map_setup(keep)\n");
254    }
255    
256    static gboolean on_map_configure(GtkWidget *widget,
257                                     GdkEventConfigure *event,
258                                     map_context_t *context) {
259    
260      /* for some reason there's a configure event with 1/1 */
261      /* on diablo. We just ignore this! */
262    
263      printf("on_map_configure %d %d\n",
264             widget->allocation.width,
265             widget->allocation.height);
266    
267      if(!context->map_complete &&
268         (widget->allocation.width > 100) &&
269         (widget->allocation.height > 100)) {
270    
271        /* setup cache state */
272        map_setup(context);
273    
274        /* set default values if they are invalid */
275        if(!context->appdata->map.zoom ||
276           isnan(context->appdata->map.pos.lat) ||
277           isnan(context->appdata->map.pos.lon)) {
278          printf("no valid map position found\n");
279    
280          pos_t *refpos = get_pos(context->appdata);
281          if(refpos && !isnan(refpos->lat) && !isnan(refpos->lon)) {
282            printf("use refpos\n");
283    
284            /* use gps position if present */
285            context->appdata->map.pos = *refpos;
286            context->appdata->map.zoom = GPS_DEFAULT_ZOOM;
287          } else {
288            printf("use zero pos\n");
289    
290            /* use world map otherwise */
291            context->appdata->map.pos.lat = 0.0;
292            context->appdata->map.pos.lon = 0.0;
293            context->appdata->map.zoom = 1;
294          }
295        }
296    
297        /* jump to initial position */
298        printf("osm_gps_map_set_mapcenter(%f,%f,%d)\n",
299               context->appdata->map.pos.lat,
300               context->appdata->map.pos.lon,
301               context->appdata->map.zoom);
302    
303        osm_gps_map_set_mapcenter(OSM_GPS_MAP(context->widget),
304                                  context->appdata->map.pos.lat,
305                                  context->appdata->map.pos.lon,
306                                  context->appdata->map.zoom);
307        context->map_complete = TRUE;
308      }
309    
310      return FALSE;
311  }  }
312    
313  static void  static void
314  map_cachelist_nearest(cache_t *cache, pos_t *pos,  map_cachelist_nearest(cache_t *cache, pos_t *pos,
315                        cache_t **result, float *distance) {                        cache_t **result, float *distance) {
316    
317    while(cache) {    while(cache) {
318        pos_t cpos = gpx_cache_pos(cache);
319    
320      float dist =      float dist =
321        pow(cache->pos.lat - pos->lat, 2) +        pow(cpos.lat - pos->lat, 2) +
322        pow(cache->pos.lon - pos->lon, 2);        pow(cpos.lon - pos->lon, 2);
323    
324      if(!(dist > *distance)) {      if(!(dist > *distance)) {
325        *result = cache;        *result = cache;
# Line 180  static cache_t *map_closest(map_context_ Line 334  static cache_t *map_closest(map_context_
334    cache_t *result = NULL;    cache_t *result = NULL;
335    float distance = NAN;    float distance = NAN;
336    
337  #ifdef USE_MAEMO    if(!context->appdata->cur_gpx && !context->appdata->cur_cache) {
   if(!context->appdata->cur_gpx) {  
 #endif  
338      /* search all geocaches */      /* search all geocaches */
339      gpx_t *gpx = context->appdata->gpx;      gpx_t *gpx = context->appdata->gpx;
340      while(gpx) {      while(gpx) {
341        map_cachelist_nearest(gpx->cache, pos, &result, &distance);        map_cachelist_nearest(gpx->cache, pos, &result, &distance);
342        gpx = gpx->next;        gpx = gpx->next;
343      }      }
344  #ifdef USE_MAEMO    } else if(context->appdata->cur_gpx) {
   } else {  
345      map_cachelist_nearest(context->appdata->cur_gpx->cache,      map_cachelist_nearest(context->appdata->cur_gpx->cache,
346                            pos, &result, &distance);                            pos, &result, &distance);
347    }    } else
348  #endif      result = context->appdata->cur_gpx->cache;
349    
350    return result;    return result;
351  }  }
# Line 212  pos_t coord2pos(coord_t coo) { Line 363  pos_t coord2pos(coord_t coo) {
363  static gboolean  static gboolean
364  on_map_button_press_event(GtkWidget *widget,  on_map_button_press_event(GtkWidget *widget,
365                              GdkEventButton *event, map_context_t *context) {                              GdkEventButton *event, map_context_t *context) {
366    
367    OsmGpsMap *map = OSM_GPS_MAP(context->widget);    OsmGpsMap *map = OSM_GPS_MAP(context->widget);
368    
369      /* check if we actually clicked parts of the OSD */
370      if(osm_gps_map_osd_check(map, event->x, event->y) != OSD_NONE)
371        return FALSE;
372    
373    /* got a press event without release event? eat it! */    /* got a press event without release event? eat it! */
374    if(context->press_on != NULL) {    if(context->press_on != NULL) {
375      printf("PRESS: already\n");      printf("PRESS: already\n");
376      return TRUE;      return FALSE;
377    }    }
378    
379    pos_t pos =    pos_t pos =
# Line 225  on_map_button_press_event(GtkWidget *wid Line 381  on_map_button_press_event(GtkWidget *wid
381    
382    cache_t *nearest = map_closest(context, &pos);    cache_t *nearest = map_closest(context, &pos);
383    if(nearest) {    if(nearest) {
384      float dist = gpx_pos_get_distance(pos, nearest->pos, FALSE);      pos_t cpos = gpx_cache_pos(nearest);
385      if(dist2pixel(context, dist, nearest->pos.lat) < CLICK_FUZZ)  
386        float dist = gpx_pos_get_distance(pos, cpos, FALSE);
387        if(dist2pixel(context, dist, cpos.lat) < CLICK_FUZZ)
388        context->press_on = nearest;        context->press_on = nearest;
389    }    }
390    
# Line 263  cairo_draw_pixbuf(cairo_t *cr, GdkPixbuf Line 421  cairo_draw_pixbuf(cairo_t *cr, GdkPixbuf
421  #endif  #endif
422    
423  static void  static void
424  balloon_draw_cb(cairo_t *cr, OsmGpsMapRect_t *rect, gpointer data) {  balloon_cb(osm_gps_map_balloon_event_t *event, gpointer data) {
425    cache_t *cache = (cache_t*)data;    printf("balloon event: ");
426    
427      map_context_t *context = (map_context_t*)data;
428      cache_t *cache = context->balloon;
429    
430    //  printf("draw cb for \"%s\"\n", cache->name);    if(event->type == OSM_GPS_MAP_BALLOON_EVENT_TYPE_DRAW) {
431        printf("draw\n");
432    
433  #if 0  #if 0
434    /* draw pink background to check clipping */      /* draw pink background to check clipping */
435    cairo_rectangle (cr, rect->x-20, rect->y-20, rect->w+40, rect->h+40);      cairo_rectangle (event->data.draw.cr,
436    cairo_set_source_rgba (cr, 1, 0, 0, 0.3);                       event->data.draw.rect->x-20, event->data.draw.rect->y-20,
437    cairo_fill_preserve (cr);                       event->data.draw.rect->w+40, event->data.draw.rect->h+40);
438    cairo_set_line_width (cr, 0);      cairo_set_source_rgba (event->data.draw.cr, 1, 0, 0, 0.3);
439    cairo_stroke (cr);      cairo_fill_preserve (event->data.draw.cr);
440        cairo_set_line_width (event->data.draw.cr, 0);
441        cairo_stroke (event->data.draw.cr);
442  #endif  #endif
443    
444    /* leave a little border top and left */      /* leave a little border top and left */
445    gint x = rect->x, y = rect->y;      gint x = event->data.draw.rect->x, y = event->data.draw.rect->y;
446    
447    /* draw the cache type icon ... */      /* draw the cache type icon ... */
448    GdkPixbuf *icon = icon_get(ICON_CACHE_TYPE, cache->type);      GdkPixbuf *icon = icon_get(ICON_CACHE_TYPE, cache->type);
449    cairo_draw_pixbuf(cr, icon, x, y);      cairo_draw_pixbuf(event->data.draw.cr, icon, x, y);
450    
451    /* ... and right of it the waypoint id */      if(cache->notes && cache->notes->override) {
452    cairo_text_extents_t extents;        GdkPixbuf *over = icon_get(ICON_MISC, 1);
453          cairo_draw_pixbuf(event->data.draw.cr, over, x, y);
454    if(cache->id) {      }
455      cairo_select_font_face (cr, "Sans",  
456                              CAIRO_FONT_SLANT_NORMAL,      /* ... and right of it the waypoint id */
457                              CAIRO_FONT_WEIGHT_BOLD);      cairo_text_extents_t extents;
458    
459        if(cache->id) {
460          cairo_select_font_face (event->data.draw.cr, "Sans",
461                                  CAIRO_FONT_SLANT_NORMAL,
462                                  CAIRO_FONT_WEIGHT_BOLD);
463    
464  #ifndef BIG_BALLOONS  #ifndef BIG_BALLOONS
465      cairo_set_font_size (cr, 20.0);        cairo_set_font_size (event->data.draw.cr, 20.0);
466  #else  #else
467      cairo_set_font_size (cr, 36.0);        cairo_set_font_size (event->data.draw.cr, 36.0);
468  #endif  #endif
469    
470      cairo_text_extents (cr, cache->id, &extents);        cairo_text_extents (event->data.draw.cr, cache->id, &extents);
471    
472      /* display id right of icon vertically centered */        /* display id right of icon vertically centered */
473      x += gdk_pixbuf_get_width(icon) + 5;        x += gdk_pixbuf_get_width(icon) + 5;
474      y += (gdk_pixbuf_get_height(icon) + extents.height)/2;        y += (gdk_pixbuf_get_height(icon) + extents.height)/2;
475      cairo_move_to (cr, x, y);        cairo_move_to (event->data.draw.cr, x, y);
476      cairo_set_source_rgba (cr, 0, 0, 0, 1);        cairo_set_source_rgba (event->data.draw.cr, 0, 0, 0, 1);
477      cairo_show_text (cr, cache->id);        cairo_show_text (event->data.draw.cr, cache->id);
478      cairo_stroke (cr);        cairo_stroke (event->data.draw.cr);
479    
480      y += (gdk_pixbuf_get_height(icon) - extents.height)/2 + LINE_SKIP;        y += (gdk_pixbuf_get_height(icon) - extents.height)/2 + LINE_SKIP;
481    } else      } else
482      y += gdk_pixbuf_get_height(icon);        y += gdk_pixbuf_get_height(icon);
483    
484    /* return to the left border and below icon/text */      /* return to the left border and below icon/text */
485    x = rect->x;      x = event->data.draw.rect->x;
486    
487    /* everything from here uses the same font */      /* everything from here uses the same font */
488    cairo_select_font_face (cr, "Sans", CAIRO_FONT_SLANT_NORMAL,      cairo_select_font_face (event->data.draw.cr, "Sans", CAIRO_FONT_SLANT_NORMAL,
489                            CAIRO_FONT_WEIGHT_NORMAL);                              CAIRO_FONT_WEIGHT_NORMAL);
490  #ifndef BIG_BALLOONS  #ifndef BIG_BALLOONS
491    cairo_set_font_size (cr, 14.0);      cairo_set_font_size (event->data.draw.cr, 14.0);
492  #else  #else
493    cairo_set_font_size (cr, 22.0);      cairo_set_font_size (event->data.draw.cr, 22.0);
494  #endif  #endif
495    
496    if(cache->name) {      if(cache->name) {
497      /* draw cache name */        /* draw cache name */
498      cairo_text_extents (cr, cache->name, &extents);        cairo_text_extents (event->data.draw.cr, cache->name, &extents);
499      y += extents.height;        y += extents.height;
500      cairo_move_to (cr, x, y);        cairo_move_to (event->data.draw.cr, x, y);
501      cairo_set_source_rgba (cr, 0, 0, 0, 1);        cairo_set_source_rgba (event->data.draw.cr, 0, 0, 0, 1);
502      cairo_show_text (cr, cache->name);        cairo_show_text (event->data.draw.cr, cache->name);
503      cairo_stroke (cr);        cairo_stroke (event->data.draw.cr);
504    
505      /* return to the left border and below text */        /* return to the left border and below text */
506      y += LINE_SKIP;        y += LINE_SKIP;
507      x = rect->x;        x = event->data.draw.rect->x;
508    }      }
509    
510    if(cache->terrain) {      if(cache->terrain) {
511      /* draw cache rating */        /* draw cache rating */
512      const char *terrain = "Terrain:";        const char *terrain = "Terrain:";
513      icon = icon_get(ICON_STARS, (int)(cache->terrain*2-2));        icon = icon_get(ICON_STARS, (int)(cache->terrain*2-2));
514      cairo_text_extents (cr, _(terrain), &extents);        cairo_text_extents (event->data.draw.cr, _(terrain), &extents);
515      y += (gdk_pixbuf_get_height(icon) + extents.height)/2;        y += (gdk_pixbuf_get_height(icon) + extents.height)/2;
516    
517      /* draw "Terrain:" string */        /* draw "Terrain:" string */
518      cairo_move_to (cr, x, y);        cairo_move_to (event->data.draw.cr, x, y);
519      cairo_set_source_rgba (cr, 0, 0, 0, 1);        cairo_set_source_rgba (event->data.draw.cr, 0, 0, 0, 1);
520      cairo_show_text (cr, _(terrain));        cairo_show_text (event->data.draw.cr, _(terrain));
521      cairo_stroke (cr);        cairo_stroke (event->data.draw.cr);
522      x += extents.width + 2;        x += extents.width + 2;
523    
524      /* draw terrain stars */        /* draw terrain stars */
525      cairo_draw_pixbuf(cr, icon, x, y -        cairo_draw_pixbuf(event->data.draw.cr, icon, x, y -
526                        (gdk_pixbuf_get_height(icon) + extents.height)/2);                          (gdk_pixbuf_get_height(icon) + extents.height)/2);
527    
528      x += gdk_pixbuf_get_width(icon) + LINE_SKIP;        x += gdk_pixbuf_get_width(icon) + LINE_SKIP;
529      y -= (gdk_pixbuf_get_height(icon) + extents.height)/2;      y -= (gdk_pixbuf_get_height(icon) + extents.height)/2;
530    }      }
   
   if(cache->difficulty) {  
     const char *difficulty = "Difficulty:";  
     cairo_text_extents (cr, _(difficulty), &extents);  
     y += (gdk_pixbuf_get_height(icon) + extents.height)/2;  
   
     /* draw "Difficulty:" string */  
     cairo_move_to (cr, x, y);  
     cairo_set_source_rgba (cr, 0, 0, 0, 1);  
     cairo_show_text (cr, _(difficulty));  
     cairo_stroke (cr);  
     x += extents.width + 2;  
531    
532      icon = icon_get(ICON_STARS, (int)(cache->difficulty*2-2));      if(cache->difficulty) {
533      cairo_draw_pixbuf(cr, icon, x, y -        const char *difficulty = "Difficulty:";
534          cairo_text_extents (event->data.draw.cr, _(difficulty), &extents);
535          y += (gdk_pixbuf_get_height(icon) + extents.height)/2;
536    
537          /* draw "Difficulty:" string */
538          cairo_move_to (event->data.draw.cr, x, y);
539          cairo_set_source_rgba (event->data.draw.cr, 0, 0, 0, 1);
540          cairo_show_text (event->data.draw.cr, _(difficulty));
541          cairo_stroke (event->data.draw.cr);
542          x += extents.width + 2;
543    
544          icon = icon_get(ICON_STARS, (int)(cache->difficulty*2-2));
545          cairo_draw_pixbuf(event->data.draw.cr, icon, x, y -
546                        (gdk_pixbuf_get_height(icon) + extents.height)/2);                        (gdk_pixbuf_get_height(icon) + extents.height)/2);
547        }
548      } else if(event->type == OSM_GPS_MAP_BALLOON_EVENT_TYPE_CLICK) {
549        printf("click %s event at %d %d\n",
550               event->data.click.down?"down":"up",
551               event->data.click.x, event->data.click.y);
552    
553        /* make the main screen jump to that cache */
554        if(!event->data.click.down) {
555          if(context->appdata->cur_cache) {
556            printf("ERROR: no current cache should be visible!\n");
557          } else {
558            gpx_t *is_in = NULL;
559    
560            if(!context->appdata->cur_gpx) {
561              printf("click while in \"all\" view\n");
562    
563              /* we first need to figure out which gpx file this cache */
564              /* is in so we can open it first */
565              gpx_t *gpx = context->appdata->gpx;
566              while(gpx && !is_in) {
567                cache_t *cur = gpx->cache;
568                while(cur && !is_in) {
569                  if(cur == cache)
570                    is_in = gpx;
571                  cur = cur->next;
572                }
573                gpx = gpx->next;
574              }
575    
576              if(is_in)
577                gpxlist_goto_cachelist(context->appdata, is_in);
578    
579            } else
580              /* the simple case: there already is an open gpx file and */
581              /* we just jump into the "cache" view */
582              is_in = context->appdata->cur_gpx;
583    
584            if(is_in) {
585              printf("selecting %s in %s\n",
586                     cache->id,
587                     context->appdata->cur_gpx->name);
588    
589              cachelist_goto_cache(context->appdata, cache);
590    
591              /* give focus to main screen (important for maemo) */
592              printf("raising main window\n");
593              gtk_window_present(GTK_WINDOW(context->appdata->window));
594            }
595          }
596        }
597      } else if(event->type == OSM_GPS_MAP_BALLOON_EVENT_TYPE_REMOVED) {
598        printf("removed\n");
599        context->balloon = NULL;
600    }    }
601  }  }
602    
# Line 383  on_map_button_release_event(GtkWidget *w Line 605  on_map_button_release_event(GtkWidget *w
605                              GdkEventButton *event, map_context_t *context) {                              GdkEventButton *event, map_context_t *context) {
606    OsmGpsMap *map = OSM_GPS_MAP(context->widget);    OsmGpsMap *map = OSM_GPS_MAP(context->widget);
607    
608    if(context->press_on) {    /* in "MAP_CACHE" state only one cache is visible */
609      /* and the map is in navigation mode. the balloon is */
610      /* pretty useless there */
611      if(context->press_on && (context->state != MAP_CACHE)) {
612    
613      coord_t coo;      coord_t coo;
614      coo = osm_gps_map_get_co_ordinates(map, event->x, event->y);      coo = osm_gps_map_get_co_ordinates(map, event->x, event->y);
615    
# Line 392  on_map_button_release_event(GtkWidget *w Line 618  on_map_button_release_event(GtkWidget *w
618    
619      cache_t *nearest = map_closest(context, &pos);      cache_t *nearest = map_closest(context, &pos);
620      if(nearest && nearest == context->press_on) {      if(nearest && nearest == context->press_on) {
621        float dist = gpx_pos_get_distance(pos, nearest->pos, FALSE);        pos_t cpos = gpx_cache_pos(nearest);
622        if(dist2pixel(context, dist, nearest->pos.lat) < CLICK_FUZZ) {  
623          float dist = gpx_pos_get_distance(pos, cpos, FALSE);
624          if(dist2pixel(context, dist, cpos.lat) < CLICK_FUZZ) {
625    
626          osm_gps_map_draw_balloon(map, nearest->pos.lat, nearest->pos.lon,          context->balloon = nearest;
627                                   balloon_draw_cb, nearest);          osm_gps_map_osd_draw_balloon(map, cpos.lat, cpos.lon,
628                                         balloon_cb, context);
629        }        }
630      }      }
631      context->press_on = NULL;      context->press_on = NULL;
# Line 414  on_map_button_release_event(GtkWidget *w Line 643  on_map_button_release_event(GtkWidget *w
643  static void on_window_destroy(GtkWidget *widget, map_context_t *context) {  static void on_window_destroy(GtkWidget *widget, map_context_t *context) {
644    appdata_t *appdata = context->appdata;    appdata_t *appdata = context->appdata;
645    
   printf("destroy map window\n");  
   
646    /* save map parameters */    /* save map parameters */
647    OsmGpsMap *map = OSM_GPS_MAP(context->widget);    OsmGpsMap *map = OSM_GPS_MAP(context->widget);
648    gint zoom;    gint zoom;
# Line 427  static void on_window_destroy(GtkWidget Line 654  static void on_window_destroy(GtkWidget
654    context->appdata->map.pos.lat = lat;    context->appdata->map.pos.lat = lat;
655    context->appdata->map.pos.lon = lon;    context->appdata->map.pos.lon = lon;
656    
657      gint source;
658      g_object_get(map, "map-source", &source, NULL);
659      context->appdata->map.source = source;
660    
661  #if MAEMO_VERSION_MAJOR == 5  #if MAEMO_VERSION_MAJOR == 5
662    /* restore cur_view */    /* restore cur_view */
663    context->appdata->cur_view = context->old_view;    context->appdata->cur_view = context->old_view;
# Line 438  static void on_window_destroy(GtkWidget Line 669  static void on_window_destroy(GtkWidget
669    appdata->map.context = NULL;    appdata->map.context = NULL;
670  }  }
671    
672    #if (MAEMO_VERSION_MAJOR == 5) && !defined(__i386__)
673    /* get access to zoom buttons */
674    static void
675    on_window_realize(GtkWidget *widget, gpointer data) {
676      if (widget->window) {
677        unsigned char value = 1;
678        Atom hildon_zoom_key_atom =
679          gdk_x11_get_xatom_by_name("_HILDON_ZOOM_KEY_ATOM"),
680          integer_atom = gdk_x11_get_xatom_by_name("INTEGER");
681        Display *dpy =
682          GDK_DISPLAY_XDISPLAY(gdk_drawable_get_display(widget->window));
683        Window w = GDK_WINDOW_XID(widget->window);
684    
685        XChangeProperty(dpy, w, hildon_zoom_key_atom,
686                        integer_atom, 8, PropModeReplace, &value, 1);
687      }
688    }
689    #endif
690    
691    /* on maemo a window is either on top or completely invisible. this */
692    /* means that we only need to update the map window if its raised.  */
693    /* on ordinary desktops this is different and we always update */
694    
695    static gboolean on_focus_in(GtkWidget *widget, GdkEventFocus *event,
696                             gpointer data) {
697      printf("map got focus\n");
698      map_setup((map_context_t*)data);
699      return FALSE;
700    }
701    
702    void map_update(appdata_t *appdata) {
703      printf("map_update\n");
704    #ifndef USE_MAEMO
705      if(appdata->map.context)
706        map_setup(appdata->map.context);
707    #endif
708    }
709    
710  void map(appdata_t *appdata) {  void map(appdata_t *appdata) {
711    map_context_t *context = NULL;    map_context_t *context = NULL;
712    
713    /* if the map window already exists, just raise it */    /* if the map window already exists, just raise it */
714    if(appdata->map.context) {    if(appdata->map.context) {
715        printf("using existing map!\n");
716      gtk_window_present(GTK_WINDOW(appdata->map.context->window));      gtk_window_present(GTK_WINDOW(appdata->map.context->window));
717        map_setup(appdata->map.context);
718      return;      return;
719    }    }
720    
721    context = appdata->map.context = g_new0(map_context_t, 1);    context = appdata->map.context = g_new0(map_context_t, 1);
722    context->appdata = appdata;    context->appdata = appdata;
723      context->map_complete = FALSE;
724      context->state = MAP_NONE;
725    
726      /* cleanup old (pre 0.8.7) path if it exists */
727      char *old_path = g_strdup_printf("%s/map/", appdata->image_path);
728      if(g_file_test(old_path, G_FILE_TEST_IS_DIR)) {
729        printf("old file path %s exists\n", old_path);
730        rmdir_recursive(old_path);
731      }
732    
733      /* It is recommanded that all applications share these same */
734      /* map path, so data is only cached once. The path should be: */
735      /* ~/.osm-gps-map on standard PC     (users home) */
736      /* /home/user/.osm-gps-map on Maemo5 (ext3 on internal card) */
737      /* /media/mmc2/osm-gps-map on Maemo4 (vfat on internal card) */
738    #if !defined(USE_MAEMO)
739      char *p = getenv("HOME");
740      if(!p) p = "/tmp";
741      char *path = g_strdup_printf("%s/.osm-gps-map", p);
742    #else
743    #if MAEMO_VERSION_MAJOR == 5
744      char *path = g_strdup("/home/user/.osm-gps-map");
745    #else
746      char *path = g_strdup("/media/mmc2/osm-gps-map");
747    #endif
748    #endif
749    
   char *path = g_strdup_printf("%s/map/", appdata->image_path);  
750    const char *proxy = get_proxy_uri(appdata);    const char *proxy = get_proxy_uri(appdata);
751    
752      gint source = context->appdata->map.source;
753      if(!source) source = MAP_SOURCE;
754    
755    context->widget = g_object_new(OSM_TYPE_GPS_MAP,    context->widget = g_object_new(OSM_TYPE_GPS_MAP,
756                   "map-source",               MAP_SOURCE,                   "map-source",               source,
757                   "tile-cache",               path,                   "tile-cache",               path,
758                   "auto-center",              FALSE,                   "auto-center",              FALSE,
759                   "record-trip-history",      FALSE,                   "record-trip-history",      FALSE,
# Line 464  void map(appdata_t *appdata) { Line 763  void map(appdata_t *appdata) {
763    
764    g_free(path);    g_free(path);
765    
766    char *name = NULL;    osm_gps_map_osd_classic_init(OSM_GPS_MAP(context->widget));
 #ifdef USE_MAEMO  
   if(!appdata->cur_gpx) {  
 #endif  
     /* draw all geocaches */  
     gpx_t *gpx = appdata->gpx;  
     while(gpx) {  
       map_draw_cachelist(context->widget, gpx->cache);  
       gpx = gpx->next;  
     }  
     name = g_strdup(_("all geocaches"));  
 #ifdef USE_MAEMO  
   } else {  
     map_draw_cachelist(context->widget, appdata->cur_gpx->cache);  
     name = g_strdup(appdata->cur_gpx->name);  
   }  
 #endif  
   
   char *title = g_strdup_printf(_("Map - %s"), name);  
   g_free(name);  
767    
768  #ifdef USE_MAEMO  #ifdef USE_MAEMO
769  #ifdef USE_STACKABLE_WINDOW    /* we don't use a stackable window here on fremantle, since */
770    context->window = hildon_stackable_window_new();    /* this leaves the main window independent from the map and */
771  #else    /* the user can e.g. still navigate the main menu */
772    context->window = hildon_window_new();    context->window = hildon_window_new();
773  #endif  
774    #if (MAEMO_VERSION_MAJOR == 5) && !defined(__i386__)
775      g_signal_connect(G_OBJECT(context->window), "realize",
776                       G_CALLBACK(on_window_realize), NULL);
777    #endif // MAEMO_VERSION
778  #else  #else
779    context->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);    context->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
780  #endif  #endif
781    
   gtk_window_set_title(GTK_WINDOW(context->window), title);  
   
782  #ifndef USE_MAEMO  #ifndef USE_MAEMO
783    gtk_window_set_default_size(GTK_WINDOW(context->window), 640, 480);    gtk_window_set_default_size(GTK_WINDOW(context->window), 640, 480);
784  #endif  #endif
785    
786    g_free(title);    g_signal_connect(G_OBJECT(context->widget), "focus-in-event",
787                       G_CALLBACK(on_focus_in), context);
788    
789    g_signal_connect(G_OBJECT(context->widget), "configure-event",    g_signal_connect(G_OBJECT(context->widget), "configure-event",
790                     G_CALLBACK(on_map_configure), context);                     G_CALLBACK(on_map_configure), context);

Legend:
Removed from v.66  
changed lines
  Added in v.144