]> git.street.me.uk Git - andy/viking.git/blob - src/vikmapslayer.c
Check current drawmode after creating a new MapsLayer
[andy/viking.git] / src / vikmapslayer.c
1 /*
2  * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
3  *
4  * Copyright (C) 2005, Evan Battaglia <viking@greentorch.org>
5  * UTM multi-zone stuff by Kit Transue <notlostyet@didactek.com>
6  * Dynamic map type by Guilhem Bonnefille <guilhem.bonnefille@gmail.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23
24 #define MAX_SHRINKFACTOR 8.0000001 /* zoom 1 viewing 8-tiles */
25 #define MIN_SHRINKFACTOR 0.0312499 /* zoom 32 viewing 1-tiles */
26
27 #include <gtk/gtk.h>
28 #include <gdk-pixbuf/gdk-pixdata.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <math.h>
32 #include "globals.h"
33 #include "coords.h"
34 #include "vikcoord.h"
35 #include "viktreeview.h"
36 #include "vikviewport.h"
37 #include "viklayer.h"
38 #include "vikmapslayer.h"
39 #include "vikmapslayer_pixmap.h"
40
41 #include <unistd.h>
42 #include <sys/stat.h>
43 #include <sys/types.h>
44
45 #include "mapcache.h"
46 /* only for dialog.h -- ugh */
47 #include "vikwaypoint.h"
48 #include "dialog.h"
49
50 #include "vikstatus.h"
51 #include "background.h"
52
53 #include "vikaggregatelayer.h"
54 #include "viklayerspanel.h"
55
56 #include "mapcoord.h"
57 #include "terraserver.h"
58
59 /****** MAP TYPES ******/
60
61 static GList *__map_types = NULL;
62
63 #define NUM_MAP_TYPES g_list_length(__map_types)
64
65 /* List of label for each map type */
66 static GList *params_maptypes = NULL;
67
68 /* Corresponding IDS. (Cf. field uniq_id in VikMapsLayer struct) */
69 static GList *params_maptypes_ids = NULL;
70
71 /******** MAPZOOMS *********/
72
73 static gchar *params_mapzooms[] = { "Use Viking Zoom Level", "0.25", "1", "2", "4", "8", "16", "32", "64", "128", "256", "512", "1024", "USGS 10k", "USGS 24k", "USGS 25k", "USGS 50k", "USGS 100k", "USGS 200k", "USGS 250k", NULL };
74 static gdouble __mapzooms_x[] = { 0.0, 0.25, 1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0, 512.0, 1024.0, 1.016, 2.4384, 2.54, 5.08, 10.16, 20.32, 25.4 };
75 static gdouble __mapzooms_y[] = { 0.0, 0.25, 1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0, 512.0, 1024.0, 1.016, 2.4384, 2.54, 5.08, 10.16, 20.32, 25.4 };
76
77 #define NUM_MAPZOOMS (sizeof(params_mapzooms)/sizeof(params_mapzooms[0]) - 1)
78
79 /**************************/
80
81
82 static VikMapsLayer *maps_layer_copy ( VikMapsLayer *vml, VikViewport *vvp );
83 static void maps_layer_post_read (VikMapsLayer *vml, gpointer vp);
84 static void maps_layer_marshall( VikMapsLayer *vml, guint8 **data, gint *len );
85 static VikMapsLayer *maps_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp );
86 static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerParamData data, VikViewport *vvp );
87 static VikLayerParamData maps_layer_get_param ( VikMapsLayer *vml, guint16 id );
88 static void maps_layer_draw ( VikMapsLayer *vml, VikViewport *vvp );
89 static VikMapsLayer *maps_layer_new ( VikViewport *vvp );
90 static void maps_layer_free ( VikMapsLayer *vml );
91 static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp );
92 static gboolean maps_layer_download_click ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp );
93 static gpointer maps_layer_download_create ( VikWindow *vw, VikViewport *vvp );
94 static void maps_layer_set_cache_dir ( VikMapsLayer *vml, const gchar *dir );
95 static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const VikCoord *ul, const VikCoord *br, gint redownload );
96 static void maps_layer_add_menu_items ( VikMapsLayer *vml, GtkMenu *menu, VikLayersPanel *vlp );
97
98
99 static VikLayerParamScale params_scales[] = {
100   /* min, max, step, digits (decimal places) */
101  { 0, 255, 3, 0 }, /* alpha */
102 };
103
104 VikLayerParam maps_layer_params[] = {
105   { "mode", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, "Map Type:", VIK_LAYER_WIDGET_RADIOGROUP, NULL, NULL },
106   { "directory", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, "Maps Directory (Optional):", VIK_LAYER_WIDGET_FILEENTRY },
107   { "alpha", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, "Alpha:", VIK_LAYER_WIDGET_HSCALE, params_scales },
108   { "autodownload", VIK_LAYER_PARAM_BOOLEAN, VIK_LAYER_GROUP_NONE, "Autodownload maps:", VIK_LAYER_WIDGET_CHECKBUTTON },
109   { "mapzoom", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, "Zoom Level:", VIK_LAYER_WIDGET_COMBOBOX, params_mapzooms },
110 };
111
112 enum { PARAM_MAPTYPE=0, PARAM_CACHE_DIR, PARAM_ALPHA, PARAM_AUTODOWNLOAD, PARAM_MAPZOOM, NUM_PARAMS };
113
114 static VikToolInterface maps_tools[] = {
115   { "Maps Download", (VikToolConstructorFunc) maps_layer_download_create, NULL, NULL, NULL,  
116     (VikToolMouseFunc) maps_layer_download_click, NULL,  (VikToolMouseFunc) maps_layer_download_release },
117 };
118
119 VikLayerInterface vik_maps_layer_interface = {
120   "Map",
121   &mapslayer_pixbuf,
122
123   maps_tools,
124   sizeof(maps_tools) / sizeof(maps_tools[0]),
125
126   maps_layer_params,
127   NUM_PARAMS,
128   NULL,
129   0,
130
131   VIK_MENU_ITEM_ALL,
132
133   (VikLayerFuncCreate)                  maps_layer_new,
134   (VikLayerFuncRealize)                 NULL,
135   (VikLayerFuncPostRead)                maps_layer_post_read,
136   (VikLayerFuncFree)                    maps_layer_free,
137
138   (VikLayerFuncProperties)              NULL,
139   (VikLayerFuncDraw)                    maps_layer_draw,
140   (VikLayerFuncChangeCoordMode)         NULL,
141
142   (VikLayerFuncSetMenuItemsSelection)   NULL,
143   (VikLayerFuncGetMenuItemsSelection)   NULL,
144
145   (VikLayerFuncAddMenuItems)            maps_layer_add_menu_items,
146   (VikLayerFuncSublayerAddMenuItems)    NULL,
147
148   (VikLayerFuncSublayerRenameRequest)   NULL,
149   (VikLayerFuncSublayerToggleVisible)   NULL,
150
151   (VikLayerFuncCopy)                    maps_layer_copy,
152   (VikLayerFuncMarshall)                maps_layer_marshall,
153   (VikLayerFuncUnmarshall)              maps_layer_unmarshall,
154
155   (VikLayerFuncSetParam)                maps_layer_set_param,
156   (VikLayerFuncGetParam)                maps_layer_get_param,
157
158   (VikLayerFuncReadFileData)            NULL,
159   (VikLayerFuncWriteFileData)           NULL,
160
161   (VikLayerFuncDeleteItem)              NULL,
162   (VikLayerFuncCopyItem)                NULL,
163   (VikLayerFuncPasteItem)               NULL,
164   (VikLayerFuncFreeCopiedItem)          NULL,
165   (VikLayerFuncDragDropRequest)         NULL,
166 };
167
168 struct _VikMapsLayer {
169   VikLayer vl;
170   guint maptype;
171   gchar *cache_dir;
172   guint8 alpha;
173   guint mapzoom_id;
174   gdouble xmapzoom, ymapzoom;
175
176   gboolean autodownload;
177   VikCoord *last_center;
178   gdouble last_xmpp;
179   gdouble last_ympp;
180
181   gint dl_tool_x, dl_tool_y;
182
183   GtkMenu *dl_right_click_menu;
184   VikCoord redownload_ul, redownload_br; /* right click menu only */
185   VikViewport *redownload_vvp;
186 };
187
188 enum { REDOWNLOAD_NONE = 0, REDOWNLOAD_BAD, REDOWNLOAD_ALL, DOWNLOAD_OR_REFRESH };
189
190
191 /****************************************/
192 /******** MAPS LAYER TYPES **************/
193 /****************************************/
194
195 void maps_layer_register_type ( const char *label, guint id, VikMapsLayer_MapType *map_type )
196 {
197   g_assert(label != NULL);
198   g_assert(map_type != NULL);
199   g_assert(id == map_type->uniq_id);
200
201   /* Add the label */
202   params_maptypes = g_list_append(params_maptypes, g_strdup(label));
203
204   /* Add the id */
205   params_maptypes_ids = g_list_append(params_maptypes_ids, (gpointer)id);
206
207   /* We have to clone */
208   VikMapsLayer_MapType *clone = g_memdup(map_type, sizeof(VikMapsLayer_MapType));
209   /* Register the clone in the list */
210   __map_types = g_list_append(__map_types, clone);
211
212   /* Hack
213      We have to ensure the mode LayerParam reference the up-to-date
214      GLists.
215   */
216   /*
217   memcpy(&maps_layer_params[0].widget_data, &params_maptypes, sizeof(gpointer));
218   memcpy(&maps_layer_params[0].extra_widget_data, &params_maptypes_ids, sizeof(gpointer));
219   */
220   maps_layer_params[0].widget_data = params_maptypes;
221   maps_layer_params[0].extra_widget_data = params_maptypes_ids;
222 }
223
224 #define MAPS_LAYER_NTH_LABEL(n) ((gchar*)g_list_nth_data(params_maptypes, (n)))
225 #define MAPS_LAYER_NTH_ID(n) ((guint)g_list_nth_data(params_maptypes_ids, (n)))
226 #define MAPS_LAYER_NTH_TYPE(n) ((VikMapsLayer_MapType*)g_list_nth_data(__map_types, (n)))
227
228 gint vik_maps_layer_get_map_type(VikMapsLayer *vml)
229 {
230   return(vml->maptype);
231 }
232
233 gchar *vik_maps_layer_get_map_label(VikMapsLayer *vml)
234 {
235   return(g_strdup(MAPS_LAYER_NTH_LABEL(vml->maptype)));
236 }
237
238 /****************************************/
239 /******** CACHE DIR STUFF ***************/
240 /****************************************/
241
242 #ifdef WINDOWS
243 #define MAPS_CACHE_DIR "C:\\VIKING-MAPS\\"
244 #define DIRSTRUCTURE "%st%ds%dz%d\\%d\\%d"
245 #else /* POSIX */
246
247 #include <stdlib.h>
248
249 #define MAPS_CACHE_DIR maps_layer_default_dir()
250 #define GLOBAL_MAPS_DIR "/var/cache/maps/"
251 #define DIRSTRUCTURE "%st%ds%dz%d/%d/%d"
252
253 static gchar *maps_layer_default_dir ()
254 {
255   static gchar defaultdir[512];
256   static gboolean already_run = 0;
257   if ( ! already_run )
258   {
259     /* Thanks to Mike Davison for the $VIKING_MAPS usage */
260     gchar *mapdir = getenv("VIKING_MAPS");
261     if ( mapdir && strlen(mapdir) < 497 ) {
262       strcpy ( defaultdir, mapdir );
263     } else if ( access ( GLOBAL_MAPS_DIR, W_OK ) == 0 ) {
264       strcpy ( defaultdir, GLOBAL_MAPS_DIR );
265     } else {
266       gchar *home = getenv("HOME");
267       if ( home && strlen(home) < 497 )
268       {
269         strcpy ( defaultdir, home );
270         strcat ( defaultdir, "/.viking-maps/" );
271       }
272       else
273       {
274         strcpy ( defaultdir, ".viking-maps/" );
275       }
276     }
277     already_run = 1;
278   }
279   return defaultdir;
280 }
281
282 #endif
283
284 static void maps_layer_mkdir_if_default_dir ( VikMapsLayer *vml )
285 {
286   if ( vml->cache_dir && strcmp ( vml->cache_dir, MAPS_CACHE_DIR ) == 0 && access ( vml->cache_dir, F_OK ) != 0 )
287   {
288 #ifdef WINDOWS
289     mkdir ( vml->cache_dir );
290 #else
291     mkdir ( vml->cache_dir, 0777 );
292 #endif
293   }
294 }
295
296 static void maps_layer_set_cache_dir ( VikMapsLayer *vml, const gchar *dir )
297 {
298   guint len;
299   g_assert ( vml != NULL);
300   g_free ( vml->cache_dir );
301   vml->cache_dir = NULL;
302
303   if ( dir == NULL || dir[0] == '\0' )
304     vml->cache_dir = g_strdup ( MAPS_CACHE_DIR );
305   else
306   {
307     len = strlen(dir);
308     if ( dir[len-1] != VIKING_FILE_SEP )
309     {
310       vml->cache_dir = g_malloc ( len+2 );
311       strncpy ( vml->cache_dir, dir, len );
312       vml->cache_dir[len] = VIKING_FILE_SEP;
313       vml->cache_dir[len+1] = '\0';
314     }
315     else
316       vml->cache_dir = g_strdup ( dir );
317   }
318   maps_layer_mkdir_if_default_dir ( vml );
319 }
320
321 /****************************************/
322 /******** GOBJECT STUFF *****************/
323 /****************************************/
324
325 GType vik_maps_layer_get_type ()
326 {
327   static GType vml_type = 0;
328
329   if (!vml_type)
330   {
331     static const GTypeInfo vml_info =
332     {
333       sizeof (VikMapsLayerClass),
334       NULL, /* base_init */
335       NULL, /* base_finalize */
336       NULL, /* class init */
337       NULL, /* class_finalize */
338       NULL, /* class_data */
339       sizeof (VikMapsLayer),
340       0,
341       NULL /* instance init */
342     };
343     vml_type = g_type_register_static ( VIK_LAYER_TYPE, "VikMapsLayer", &vml_info, 0 );
344   }
345
346   return vml_type;
347 }
348
349 /****************************************/
350 /************** PARAMETERS **************/
351 /****************************************/
352
353 static guint map_index_to_uniq_id (guint8 index)
354 {
355   g_assert ( index < NUM_MAP_TYPES );
356   return MAPS_LAYER_NTH_TYPE(index)->uniq_id;
357 }
358
359 static guint map_uniq_id_to_index ( guint uniq_id )
360 {
361   gint i;
362   for ( i = 0; i < NUM_MAP_TYPES; i++ )
363     if ( MAPS_LAYER_NTH_TYPE(i)->uniq_id == uniq_id )
364       return i;
365   return NUM_MAP_TYPES; /* no such thing */
366 }
367
368 static gboolean maps_layer_set_param ( VikMapsLayer *vml, guint16 id, VikLayerParamData data, VikViewport *vvp )
369 {
370   switch ( id )
371   {
372     case PARAM_CACHE_DIR: maps_layer_set_cache_dir ( vml, data.s ); break;
373     case PARAM_MAPTYPE: {
374       gint maptype = map_uniq_id_to_index(data.u);
375       if ( maptype == NUM_MAP_TYPES ) g_warning("Unknown map type");
376       else vml->maptype = maptype;
377       break;
378     }
379     case PARAM_ALPHA: if ( data.u <= 255 ) vml->alpha = data.u; break;
380     case PARAM_AUTODOWNLOAD: vml->autodownload = data.b; break;
381     case PARAM_MAPZOOM: if ( data.u < NUM_MAPZOOMS ) {
382                           vml->mapzoom_id = data.u;
383                           vml->xmapzoom = __mapzooms_x [data.u];
384                           vml->ymapzoom = __mapzooms_y [data.u];
385                         }else g_warning ("Unknown Map Zoom"); break;
386   }
387   return TRUE;
388 }
389
390 static VikLayerParamData maps_layer_get_param ( VikMapsLayer *vml, guint16 id )
391 {
392   VikLayerParamData rv;
393   switch ( id )
394   {
395     case PARAM_CACHE_DIR: rv.s = (vml->cache_dir && strcmp(vml->cache_dir, MAPS_CACHE_DIR) != 0) ? vml->cache_dir : ""; break;
396     case PARAM_MAPTYPE: rv.u = map_index_to_uniq_id ( vml->maptype ); break;
397     case PARAM_ALPHA: rv.u = vml->alpha; break;
398     case PARAM_AUTODOWNLOAD: rv.u = vml->autodownload; break;
399     case PARAM_MAPZOOM: rv.u = vml->mapzoom_id; break;
400   }
401   return rv;
402 }
403
404 /****************************************/
405 /****** CREATING, COPYING, FREEING ******/
406 /****************************************/
407
408 static VikMapsLayer *maps_layer_new ( VikViewport *vvp )
409 {
410   int idx;
411   VikMapsLayer *vml = VIK_MAPS_LAYER ( g_object_new ( VIK_MAPS_LAYER_TYPE, NULL ) );
412   vik_layer_init ( VIK_LAYER(vml), VIK_LAYER_MAPS );
413   idx = map_uniq_id_to_index(7); /* 7 is id for google maps */
414     vml->maptype = (idx < NUM_MAP_TYPES) ? idx : 0;
415   vml->alpha = 255;
416   vml->mapzoom_id = 0;
417   vml->dl_tool_x = vml->dl_tool_y = -1;
418   maps_layer_set_cache_dir ( vml, NULL );
419   vml->autodownload = FALSE;
420   vml->last_center = NULL;
421   vml->last_xmpp = 0.0;
422   vml->last_ympp = 0.0;
423
424   vml->dl_right_click_menu = NULL;
425
426   return vml;
427 }
428
429 static void maps_layer_free ( VikMapsLayer *vml )
430 {
431   g_free ( vml->cache_dir );
432   vml->cache_dir = NULL;
433   if ( vml->dl_right_click_menu )
434     gtk_object_sink ( GTK_OBJECT(vml->dl_right_click_menu) );
435   g_free(vml->last_center);
436   vml->last_center = NULL;
437 }
438
439 static void maps_layer_post_read (VikMapsLayer *vml, gpointer vp)
440 {
441   VikViewportDrawMode vp_drawmode;
442   VikMapsLayer_MapType *map_type = NULL;
443  
444   vp_drawmode = vik_viewport_get_drawmode ( VIK_VIEWPORT(vp) );
445   map_type = MAPS_LAYER_NTH_TYPE(vml->maptype);
446   if (map_type->drawmode != vp_drawmode) {
447     gchar *drawmode_name = vik_viewport_get_drawmode_name (VIK_VIEWPORT(vp), map_type->drawmode);
448     gchar *msg = g_strdup_printf("New map cannot be displayed in the current drawmode.\nSelect \"%s\" from View menu to view it.", drawmode_name);
449     a_dialog_warning_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), msg );
450     g_free(msg);
451   }
452 }
453
454 static VikMapsLayer *maps_layer_copy ( VikMapsLayer *vml, VikViewport *vvp )
455 {
456   VikMapsLayer *rv = maps_layer_new ( vvp );
457   *rv = *vml;
458   rv->cache_dir = g_strdup(rv->cache_dir);
459   VIK_LAYER(rv)->name = NULL;
460   return rv;
461 }
462
463 static void maps_layer_marshall( VikMapsLayer *vml, guint8 **data, gint *len )
464 {
465   vik_layer_marshall_params ( VIK_LAYER(vml), data, len );
466 }
467
468 static VikMapsLayer *maps_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp )
469 {
470   VikMapsLayer *rv = maps_layer_new ( vvp );
471   vik_layer_unmarshall_params ( VIK_LAYER(rv), data, len, vvp );
472   return rv;
473 }
474
475 /*********************/
476 /****** DRAWING ******/
477 /*********************/
478
479 static GdkPixbuf *pixbuf_set_alpha ( GdkPixbuf *pixbuf, guint8 alpha )
480 {
481   guchar *pixels;
482   gint width, height, iii, jjj;
483
484   if ( ! gdk_pixbuf_get_has_alpha ( pixbuf ) )
485   {
486     GdkPixbuf *tmp = gdk_pixbuf_add_alpha(pixbuf,FALSE,0,0,0);
487     g_object_unref(G_OBJECT(pixbuf));
488     pixbuf = tmp;
489   }
490
491   pixels = gdk_pixbuf_get_pixels(pixbuf);
492   width = gdk_pixbuf_get_width(pixbuf);
493   height = gdk_pixbuf_get_height(pixbuf);
494
495   /* r,g,b,a,r,g,b,a.... */
496   for (iii = 0; iii < width; iii++) for (jjj = 0; jjj < height; jjj++)
497   {
498     pixels += 3;
499     *pixels++ = alpha;
500   }
501   return pixbuf;
502 }
503
504 static GdkPixbuf *pixbuf_shrink ( GdkPixbuf *pixbuf, gdouble xshrinkfactor, gdouble yshrinkfactor )
505 {
506   GdkPixbuf *tmp;
507   guint16 width = gdk_pixbuf_get_width(pixbuf), height = gdk_pixbuf_get_height(pixbuf);
508   tmp = gdk_pixbuf_scale_simple(pixbuf, ceil(width * xshrinkfactor), ceil(height * yshrinkfactor), GDK_INTERP_BILINEAR);
509   g_object_unref ( G_OBJECT(pixbuf) );
510   return tmp;
511 }
512
513 static GdkPixbuf *get_pixbuf( VikMapsLayer *vml, gint mode, MapCoord *mapcoord, gchar *filename_buf, gint buf_len, gdouble xshrinkfactor, gdouble yshrinkfactor )
514 {
515   GdkPixbuf *pixbuf;
516
517   /* get the thing */
518   pixbuf = a_mapcache_get ( mapcoord->x, mapcoord->y, mapcoord->z,
519                             mode, mapcoord->scale, vml->alpha, xshrinkfactor, yshrinkfactor );
520
521   if ( ! pixbuf ) {
522     g_snprintf ( filename_buf, buf_len, DIRSTRUCTURE,
523                      vml->cache_dir, mode,
524                      mapcoord->scale, mapcoord->z, mapcoord->x, mapcoord->y );
525     if ( access ( filename_buf, R_OK ) == 0) {
526     {
527       GError *gx = NULL;
528       pixbuf = gdk_pixbuf_new_from_file ( filename_buf, &gx );
529
530       if (gx)
531       {
532         if ( gx->domain != GDK_PIXBUF_ERROR || gx->code != GDK_PIXBUF_ERROR_CORRUPT_IMAGE )
533           g_warning ( "Couldn't open image file: %s", gx->message );
534
535           g_error_free ( gx );
536           if ( pixbuf )
537             g_object_unref ( G_OBJECT(pixbuf) );
538           pixbuf = NULL;
539         } else {
540           if ( vml->alpha < 255 )
541             pixbuf = pixbuf_set_alpha ( pixbuf, vml->alpha );
542           if ( xshrinkfactor != 1.0 || yshrinkfactor != 1.0 )
543             pixbuf = pixbuf_shrink ( pixbuf, xshrinkfactor, yshrinkfactor );
544
545           a_mapcache_add ( pixbuf, mapcoord->x, mapcoord->y, 
546               mapcoord->z, MAPS_LAYER_NTH_TYPE(vml->maptype)->uniq_id, 
547               mapcoord->scale, vml->alpha, xshrinkfactor, yshrinkfactor );
548         }
549       }
550     }
551   }
552   return pixbuf;
553 }
554
555 gboolean should_start_autodownload(VikMapsLayer *vml, VikViewport *vvp)
556 {
557   const VikCoord *center = vik_viewport_get_center ( vvp );
558
559   if (vml->last_center == NULL) {
560     VikCoord *new_center = g_malloc(sizeof(VikCoord));
561     *new_center = *center;
562     vml->last_center = new_center;
563     vml->last_xmpp = vik_viewport_get_xmpp(vvp);
564     vml->last_ympp = vik_viewport_get_ympp(vvp);
565     return TRUE;
566   }
567
568   /* TODO: perhaps vik_coord_diff() */
569   if (vik_coord_equals(vml->last_center, center)
570       && (vml->last_xmpp == vik_viewport_get_xmpp(vvp))
571       && (vml->last_ympp == vik_viewport_get_ympp(vvp)))
572     return FALSE;
573
574   *(vml->last_center) = *center;
575     vml->last_xmpp = vik_viewport_get_xmpp(vvp);
576     vml->last_ympp = vik_viewport_get_ympp(vvp);
577   return TRUE;
578 }
579
580 static void maps_layer_draw_section ( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br )
581 {
582   MapCoord ulm, brm;
583   gdouble xzoom = vik_viewport_get_xmpp ( vvp );
584   gdouble yzoom = vik_viewport_get_ympp ( vvp );
585   gdouble xshrinkfactor = 1.0, yshrinkfactor = 1.0;
586
587   if ( vml->xmapzoom && (vml->xmapzoom != xzoom || vml->ymapzoom != yzoom) ) {
588     xshrinkfactor = vml->xmapzoom / xzoom;
589     yshrinkfactor = vml->ymapzoom / yzoom;
590     if ( xshrinkfactor > MIN_SHRINKFACTOR && xshrinkfactor < MAX_SHRINKFACTOR &&
591          yshrinkfactor > MIN_SHRINKFACTOR && yshrinkfactor < MAX_SHRINKFACTOR ) {
592       xzoom = vml->xmapzoom;
593       yzoom = vml->xmapzoom;
594     } else {
595       g_warning ( "Cowardly refusing to draw tiles at a shrinkfactor more than %.3f (zoomed out) or less than %.3f (zoomed in).", 1/MIN_SHRINKFACTOR, 1/MAX_SHRINKFACTOR );
596     }
597   }
598
599   /* coord -> ID */
600   VikMapsLayer_MapType *map_type = MAPS_LAYER_NTH_TYPE(vml->maptype);
601   if ( map_type->coord_to_mapcoord ( ul, xzoom, yzoom, &ulm ) &&
602        map_type->coord_to_mapcoord ( br, xzoom, yzoom, &brm ) ) {
603
604     /* loop & draw */
605     gint x, y;
606     gint xmin = MIN(ulm.x, brm.x), xmax = MAX(ulm.x, brm.x);
607     gint ymin = MIN(ulm.y, brm.y), ymax = MAX(ulm.y, brm.y);
608     gint mode = map_type->uniq_id;
609
610     VikCoord coord;
611     gint xx, yy, width, height;
612     GdkPixbuf *pixbuf;
613
614     guint max_path_len = strlen(vml->cache_dir) + 40;
615     gchar *path_buf = g_malloc ( max_path_len * sizeof(char) );
616
617     if ( vml->autodownload  && should_start_autodownload(vml, vvp)) {
618 #ifdef DEBUG
619       fputs(stderr, "DEBUG: Starting autodownload\n");
620 #endif
621       start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NONE );
622     }
623
624     if ( map_type->tilesize_x == 0 ) {
625       for ( x = xmin; x <= xmax; x++ ) {
626         for ( y = ymin; y <= ymax; y++ ) {
627           ulm.x = x;
628           ulm.y = y;
629           pixbuf = get_pixbuf ( vml, mode, &ulm, path_buf, max_path_len, xshrinkfactor, yshrinkfactor );
630           if ( pixbuf ) {
631             width = gdk_pixbuf_get_width ( pixbuf );
632             height = gdk_pixbuf_get_height ( pixbuf );
633
634             map_type->mapcoord_to_center_coord ( &ulm, &coord );
635             vik_viewport_coord_to_screen ( vvp, &coord, &xx, &yy );
636             xx -= (width/2);
637             yy -= (height/2);
638
639             vik_viewport_draw_pixbuf ( vvp, pixbuf, 0, 0, xx, yy, width, height );
640           }
641         }
642       }
643     } else { /* tilesize is known, don't have to keep converting coords */
644       gdouble tilesize_x = map_type->tilesize_x * xshrinkfactor;
645       gdouble tilesize_y = map_type->tilesize_y * yshrinkfactor;
646       /* ceiled so tiles will be maximum size in the case of funky shrinkfactor */
647       gint tilesize_x_ceil = ceil ( tilesize_x );
648       gint tilesize_y_ceil = ceil ( tilesize_y );
649       gint8 xinc = (ulm.x == xmin) ? 1 : -1;
650       gint8 yinc = (ulm.y == ymin) ? 1 : -1;
651       gdouble xx, yy; gint xx_tmp, yy_tmp;
652       gint base_yy, xend, yend;
653       xend = (xinc == 1) ? (xmax+1) : (xmin-1);
654       yend = (yinc == 1) ? (ymax+1) : (ymin-1);
655
656       map_type->mapcoord_to_center_coord ( &ulm, &coord );
657       vik_viewport_coord_to_screen ( vvp, &coord, &xx_tmp, &yy_tmp );
658       xx = xx_tmp; yy = yy_tmp;
659       /* above trick so xx,yy doubles. this is so shrinkfactors aren't rounded off
660        * eg if tile size 128, shrinkfactor 0.333 */
661       xx -= (tilesize_x/2);
662       base_yy = yy - (tilesize_y/2);
663
664       for ( x = ((xinc == 1) ? xmin : xmax); x != xend; x+=xinc ) {
665         yy = base_yy;
666         for ( y = ((yinc == 1) ? ymin : ymax); y != yend; y+=yinc ) {
667           ulm.x = x;
668           ulm.y = y;
669           pixbuf = get_pixbuf ( vml, mode, &ulm, path_buf, max_path_len, xshrinkfactor, yshrinkfactor );
670           if ( pixbuf )
671             vik_viewport_draw_pixbuf ( vvp, pixbuf, 0, 0, xx, yy, tilesize_x_ceil, tilesize_y_ceil );
672
673           yy += tilesize_y;
674         }
675         xx += tilesize_x;
676       }
677     }
678
679     g_free ( path_buf );
680   }
681 }
682
683 static void maps_layer_draw ( VikMapsLayer *vml, VikViewport *vvp )
684 {
685   if ( MAPS_LAYER_NTH_TYPE(vml->maptype)->drawmode == vik_viewport_get_drawmode ( vvp ) )
686   {
687     VikCoord ul, br;
688
689     /* get corner coords */
690     if ( vik_viewport_get_coord_mode ( vvp ) == VIK_COORD_UTM && ! vik_viewport_is_one_zone ( vvp ) ) {
691       /* UTM multi-zone stuff by Kit Transue */
692       gchar leftmost_zone, rightmost_zone, i;
693       leftmost_zone = vik_viewport_leftmost_zone( vvp );
694       rightmost_zone = vik_viewport_rightmost_zone( vvp );
695       for ( i = leftmost_zone; i <= rightmost_zone; ++i ) {
696         vik_viewport_corners_for_zonen ( vvp, i, &ul, &br );
697         maps_layer_draw_section ( vml, vvp, &ul, &br );
698       }
699     }
700     else {
701       vik_viewport_screen_to_coord ( vvp, 0, 0, &ul );
702       vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br );
703
704       maps_layer_draw_section ( vml, vvp, &ul, &br );
705     }
706   }
707 }
708
709 /*************************/
710 /****** DOWNLOADING ******/
711 /*************************/
712
713 /* pass along data to thread, exists even if layer is deleted. */
714 typedef struct {
715   gchar *cache_dir;
716   gchar *filename_buf;
717   gint x0, y0, xf, yf;
718   MapCoord mapcoord;
719   gint maptype;
720   gint maxlen;
721   gint mapstoget;
722   gint redownload;
723   gboolean refresh_display;
724   VikMapsLayer *vml;
725   VikViewport *vvp;
726   gboolean map_layer_alive;
727   GMutex *mutex;
728 } MapDownloadInfo;
729
730 static void mdi_free ( MapDownloadInfo *mdi )
731 {
732   g_mutex_free(mdi->mutex);
733   g_free ( mdi->cache_dir );
734   mdi->cache_dir = NULL;
735   g_free ( mdi->filename_buf );
736   mdi->filename_buf = NULL;
737   g_free ( mdi );
738 }
739
740 static void weak_ref_cb(gpointer ptr, GObject * dead_vml)
741 {
742   MapDownloadInfo *mdi = ptr;
743   g_mutex_lock(mdi->mutex);
744   mdi->map_layer_alive = FALSE;
745   g_mutex_unlock(mdi->mutex);
746 }
747
748 static void map_download_thread ( MapDownloadInfo *mdi, gpointer threaddata )
749 {
750   guint donemaps = 0;
751   gint x, y;
752   for ( x = mdi->x0; x <= mdi->xf; x++ )
753   {
754     for ( y = mdi->y0; y <= mdi->yf; y++ )
755     {
756       gboolean remove_mem_cache = FALSE;
757       gboolean need_download = FALSE;
758       g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
759                      mdi->cache_dir, MAPS_LAYER_NTH_TYPE(mdi->maptype)->uniq_id,
760                      mdi->mapcoord.scale, mdi->mapcoord.z, x, y );
761
762       donemaps++;
763       a_background_thread_progress ( threaddata, ((gdouble)donemaps) / mdi->mapstoget ); /* this also calls testcancel */
764
765       if ( mdi->redownload == REDOWNLOAD_ALL)
766         remove ( mdi->filename_buf );
767
768       else if ( (mdi->redownload == REDOWNLOAD_BAD) && (access ( mdi->filename_buf, F_OK ) == 0) )
769       {
770         /* see if this one is bad or what */
771         GError *gx = NULL;
772         GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file ( mdi->filename_buf, &gx );
773         if (gx || (!pixbuf))
774           remove ( mdi->filename_buf );
775         if ( pixbuf )
776           g_object_unref ( pixbuf );
777         if ( gx )
778           g_error_free ( gx );
779       }
780
781       if ( access ( mdi->filename_buf, F_OK ) != 0 )
782       {
783         need_download = TRUE;
784         if (( mdi->redownload != REDOWNLOAD_NONE ) &&
785             ( mdi->redownload != DOWNLOAD_OR_REFRESH ))
786           remove_mem_cache = TRUE;
787       } else if ( mdi->redownload == DOWNLOAD_OR_REFRESH ) {
788         remove_mem_cache = TRUE;
789       } else
790         continue;
791
792       mdi->mapcoord.x = x; mdi->mapcoord.y = y;
793
794       if (need_download) {
795         if ( MAPS_LAYER_NTH_TYPE(mdi->maptype)->download ( &(mdi->mapcoord), mdi->filename_buf ))
796           continue;
797       }
798
799       gdk_threads_enter();
800       g_mutex_lock(mdi->mutex);
801       if (remove_mem_cache)
802           a_mapcache_remove_all_shrinkfactors ( x, y, mdi->mapcoord.z, MAPS_LAYER_NTH_TYPE(mdi->maptype)->uniq_id, mdi->mapcoord.scale );
803       if (mdi->refresh_display && mdi->map_layer_alive) {
804         /* TODO: check if it's on visible area */
805         vik_layer_emit_update ( VIK_LAYER(mdi->vml) );
806       }
807       g_mutex_unlock(mdi->mutex);
808       gdk_threads_leave();
809       mdi->mapcoord.x = mdi->mapcoord.y = 0; /* we're temporarily between downloads */
810
811     }
812   }
813   g_mutex_lock(mdi->mutex);
814   if (mdi->map_layer_alive)
815     g_object_weak_unref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
816   g_mutex_unlock(mdi->mutex); 
817 }
818
819 static void mdi_cancel_cleanup ( MapDownloadInfo *mdi )
820 {
821   if ( mdi->mapcoord.x || mdi->mapcoord.y )
822   {
823     g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
824                      mdi->cache_dir, MAPS_LAYER_NTH_TYPE(mdi->maptype)->uniq_id,
825                      mdi->mapcoord.scale, mdi->mapcoord.z, mdi->mapcoord.x, mdi->mapcoord.y );
826     if ( access ( mdi->filename_buf, F_OK ) == 0)
827     {
828       remove ( mdi->filename_buf );
829     }
830   }
831 }
832
833 static void start_download_thread ( VikMapsLayer *vml, VikViewport *vvp, const VikCoord *ul, const VikCoord *br, gint redownload )
834 {
835   gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp );
836   gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp );
837   MapCoord ulm, brm;
838   VikMapsLayer_MapType *map_type = MAPS_LAYER_NTH_TYPE(vml->maptype);
839   if ( map_type->coord_to_mapcoord ( ul, xzoom, yzoom, &ulm ) 
840     && map_type->coord_to_mapcoord ( br, xzoom, yzoom, &brm ) )
841   {
842     MapDownloadInfo *mdi = g_malloc ( sizeof(MapDownloadInfo) );
843     gint a, b;
844
845     mdi->vml = vml;
846     mdi->vvp = vvp;
847     mdi->map_layer_alive = TRUE;
848     mdi->mutex = g_mutex_new();
849     mdi->refresh_display = TRUE;
850
851     /* cache_dir and buffer for dest filename */
852     mdi->cache_dir = g_strdup ( vml->cache_dir );
853     mdi->maxlen = strlen ( vml->cache_dir ) + 40;
854     mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) );
855     mdi->maptype = vml->maptype;
856
857     mdi->mapcoord = ulm;
858
859     mdi->redownload = redownload;
860
861     mdi->x0 = MIN(ulm.x, brm.x);
862     mdi->xf = MAX(ulm.x, brm.x);
863     mdi->y0 = MIN(ulm.y, brm.y);
864     mdi->yf = MAX(ulm.y, brm.y);
865
866     mdi->mapstoget = 0;
867
868     if ( mdi->redownload ) {
869       mdi->mapstoget = (mdi->xf - mdi->x0 + 1) * (mdi->yf - mdi->y0 + 1);
870     } else {
871       /* calculate how many we need */
872       for ( a = mdi->x0; a <= mdi->xf; a++ )
873       {
874         for ( b = mdi->y0; b <= mdi->yf; b++ )
875         {
876           g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
877                        vml->cache_dir, map_type->uniq_id, ulm.scale,
878                        ulm.z, a, b );
879           if ( access ( mdi->filename_buf, F_OK ) != 0)
880             mdi->mapstoget++;
881         }
882       }
883     }
884
885     mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */
886
887     if ( mdi->mapstoget )
888     {
889       gchar *tmp = g_strdup_printf ( "%s %s%d %s %s...", redownload ? "Redownloading" : "Downloading", redownload == REDOWNLOAD_BAD ? "up to " : "", mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype), (mdi->mapstoget == 1) ? "map" : "maps" );
890
891       g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
892       /* launch the thread */
893       a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */
894                             tmp,                                              /* description string */
895                             (vik_thr_func) map_download_thread,               /* function to call within thread */
896                             mdi,                                              /* pass along data */
897                             (vik_thr_free_func) mdi_free,                     /* function to free pass along data */
898                             (vik_thr_free_func) mdi_cancel_cleanup,
899                             mdi->mapstoget );
900       g_free ( tmp );
901     }
902     else
903       mdi_free ( mdi );
904   }
905 }
906
907 void maps_layer_download_section_without_redraw( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br, gdouble zoom)
908 {
909   MapCoord ulm, brm;
910   VikMapsLayer_MapType *map_type = MAPS_LAYER_NTH_TYPE(vml->maptype);
911
912   if (!map_type->coord_to_mapcoord(ul, zoom, zoom, &ulm) 
913     || !map_type->coord_to_mapcoord(br, zoom, zoom, &brm)) {
914     g_warning("%s() coord_to_mapcoord() failed\n", __PRETTY_FUNCTION__);
915     return;
916   }
917
918   MapDownloadInfo *mdi = g_malloc(sizeof(MapDownloadInfo));
919   gint i, j;
920
921   mdi->vml = vml;
922   mdi->vvp = vvp;
923   mdi->map_layer_alive = TRUE;
924   mdi->mutex = g_mutex_new();
925   mdi->refresh_display = FALSE;
926
927   mdi->cache_dir = g_strdup ( vml->cache_dir );
928   mdi->maxlen = strlen ( vml->cache_dir ) + 40;
929   mdi->filename_buf = g_malloc ( mdi->maxlen * sizeof(gchar) );
930   mdi->maptype = vml->maptype;
931
932   mdi->mapcoord = ulm;
933
934   mdi->redownload = REDOWNLOAD_NONE;
935
936   mdi->x0 = MIN(ulm.x, brm.x);
937   mdi->xf = MAX(ulm.x, brm.x);
938   mdi->y0 = MIN(ulm.y, brm.y);
939   mdi->yf = MAX(ulm.y, brm.y);
940
941   mdi->mapstoget = 0;
942
943   for (i = mdi->x0; i <= mdi->xf; i++) {
944     for (j = mdi->y0; j <= mdi->yf; j++) {
945       g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
946                    vml->cache_dir, map_type->uniq_id, ulm.scale,
947                    ulm.z, i, j );
948       if ( access ( mdi->filename_buf, F_OK ) != 0)
949             mdi->mapstoget++;
950     }
951   }
952
953   mdi->mapcoord.x = mdi->mapcoord.y = 0; /* for cleanup -- no current map */
954
955   if (mdi->mapstoget) {
956     gchar *tmp = g_strdup_printf ( "%s %d %s %s...", "Downloading", mdi->mapstoget, MAPS_LAYER_NTH_LABEL(vml->maptype), (mdi->mapstoget == 1) ? "map" : "maps" );
957
958     g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
959       /* launch the thread */
960     a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vml), /* parent window */
961       tmp,                                /* description string */
962       (vik_thr_func) map_download_thread, /* function to call within thread */
963       mdi,                                /* pass along data */
964       (vik_thr_free_func) mdi_free,       /* function to free pass along data */
965       (vik_thr_free_func) mdi_cancel_cleanup,
966       mdi->mapstoget );
967     g_free ( tmp );
968   }
969   else
970     mdi_free ( mdi );
971 }
972
973 static void maps_layer_redownload_bad ( VikMapsLayer *vml )
974 {
975   start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_BAD );
976 }
977 static void maps_layer_redownload_all ( VikMapsLayer *vml )
978 {
979   start_download_thread ( vml, vml->redownload_vvp, &(vml->redownload_ul), &(vml->redownload_br), REDOWNLOAD_ALL );
980 }
981
982 static gboolean maps_layer_download_release ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp )
983 {
984   if (!vml || vml->vl.type != VIK_LAYER_MAPS)
985     return FALSE;
986   if ( vml->dl_tool_x != -1 && vml->dl_tool_y != -1 )
987   {
988     if ( event->button == 1 )
989     {
990       VikCoord ul, br;
991       vik_viewport_screen_to_coord ( vvp, MAX(0, MIN(event->x, vml->dl_tool_x)), MAX(0, MIN(event->y, vml->dl_tool_y)), &ul );
992       vik_viewport_screen_to_coord ( vvp, MIN(vik_viewport_get_width(vvp), MAX(event->x, vml->dl_tool_x)), MIN(vik_viewport_get_height(vvp), MAX ( event->y, vml->dl_tool_y ) ), &br );
993       start_download_thread ( vml, vvp, &ul, &br, DOWNLOAD_OR_REFRESH );
994       vml->dl_tool_x = vml->dl_tool_y = -1;
995       return TRUE;
996     }
997     else
998     {
999       vik_viewport_screen_to_coord ( vvp, MAX(0, MIN(event->x, vml->dl_tool_x)), MAX(0, MIN(event->y, vml->dl_tool_y)), &(vml->redownload_ul) );
1000       vik_viewport_screen_to_coord ( vvp, MIN(vik_viewport_get_width(vvp), MAX(event->x, vml->dl_tool_x)), MIN(vik_viewport_get_height(vvp), MAX ( event->y, vml->dl_tool_y ) ), &(vml->redownload_br) );
1001
1002       vml->redownload_vvp = vvp;
1003
1004       vml->dl_tool_x = vml->dl_tool_y = -1;
1005
1006       if ( ! vml->dl_right_click_menu ) {
1007         GtkWidget *item;
1008         vml->dl_right_click_menu = GTK_MENU ( gtk_menu_new () );
1009
1010         item = gtk_menu_item_new_with_label ( "Redownload bad map(s)" );
1011         g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_bad), vml );
1012         gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1013
1014         item = gtk_menu_item_new_with_label ( "Redownload all map(s)" );
1015         g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all), vml );
1016         gtk_menu_shell_append ( GTK_MENU_SHELL(vml->dl_right_click_menu), item );
1017       }
1018
1019       gtk_menu_popup ( vml->dl_right_click_menu, NULL, NULL, NULL, NULL, event->button, event->time );
1020       gtk_widget_show_all ( GTK_WIDGET(vml->dl_right_click_menu) );
1021     }
1022   }
1023   return FALSE;
1024 }
1025
1026 static gpointer maps_layer_download_create ( VikWindow *vw, VikViewport *vvp)
1027 {
1028   return vvp;
1029 }
1030
1031 static gboolean maps_layer_download_click ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp )
1032 {
1033   MapCoord tmp;
1034   if (!vml || vml->vl.type != VIK_LAYER_MAPS)
1035     return FALSE;
1036   VikMapsLayer_MapType *map_type = MAPS_LAYER_NTH_TYPE(vml->maptype);
1037   if ( map_type->drawmode == vik_viewport_get_drawmode ( vvp ) &&
1038        map_type->coord_to_mapcoord ( vik_viewport_get_center ( vvp ),
1039            vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ),
1040            vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ),
1041            &tmp ) ) {
1042     vml->dl_tool_x = event->x, vml->dl_tool_y = event->y;
1043     return TRUE;
1044   }
1045   return FALSE;
1046
1047  
1048 #if 0
1049   if ( __map_types[vml->maptype].drawmode == vik_viewport_get_drawmode ( vvp ) )
1050   {
1051     VikCoord coord;
1052     MapCoord mapcoord;
1053     vik_viewport_screen_to_coord ( vvp, event->x, event->y, &coord );
1054     if ( __map_types[vml->maptype].coord_to_mapcoord ( &coord,
1055                 vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp ),
1056                 vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp ),
1057                 &mapcoord ) ) {
1058       gchar *filename_buf = g_strdup_printf ( DIRSTRUCTURE,
1059                      vml->cache_dir, __map_types[vml->maptype].uniq_id,
1060                      mapcoord.scale, mapcoord.z, mapcoord.x, mapcoord.y );
1061
1062       __map_types[vml->maptype].download ( &mapcoord, filename_buf );
1063       g_free ( filename_buf );
1064       vik_layer_emit_update ( VIK_LAYER(vml) );
1065       return TRUE;
1066     }
1067   }
1068   return FALSE;
1069 #endif
1070 }
1071
1072 static void download_onscreen_maps ( gpointer vml_vvp[2], gint redownload )
1073 {
1074   VikMapsLayer *vml = vml_vvp[0];
1075   VikViewport *vvp = vml_vvp[1];
1076   VikViewportDrawMode vp_drawmode = vik_viewport_get_drawmode ( vvp );
1077
1078   gdouble xzoom = vml->xmapzoom ? vml->xmapzoom : vik_viewport_get_xmpp ( vvp );
1079   gdouble yzoom = vml->ymapzoom ? vml->ymapzoom : vik_viewport_get_ympp ( vvp );
1080
1081   VikCoord ul, br;
1082   MapCoord ulm, brm;
1083
1084   vik_viewport_screen_to_coord ( vvp, 0, 0, &ul );
1085   vik_viewport_screen_to_coord ( vvp, vik_viewport_get_width(vvp), vik_viewport_get_height(vvp), &br );
1086
1087   VikMapsLayer_MapType *map_type = MAPS_LAYER_NTH_TYPE(vml->maptype);
1088   if ( map_type->drawmode == vp_drawmode &&
1089        map_type->coord_to_mapcoord ( &ul, xzoom, yzoom, &ulm ) &&
1090        map_type->coord_to_mapcoord ( &br, xzoom, yzoom, &brm ) )
1091     start_download_thread ( vml, vvp, &ul, &br, redownload );
1092   else if (map_type->drawmode != vp_drawmode) {
1093     gchar *drawmode_name = vik_viewport_get_drawmode_name (vvp, map_type->drawmode);
1094     gchar *err = g_strdup_printf("Wrong drawmode for this map.\nSelect \"%s\" from View menu and try again.", drawmode_name);
1095     a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), err );
1096     g_free(err);
1097   }
1098   else
1099     a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), "Wrong zoom level for this map." );
1100
1101 }
1102
1103 static void maps_layer_download_onscreen_maps ( gpointer vml_vvp[2] )
1104 {
1105   download_onscreen_maps( vml_vvp, REDOWNLOAD_NONE);
1106 }
1107
1108 static void maps_layer_redownload_all_onscreen_maps ( gpointer vml_vvp[2] )
1109 {
1110   download_onscreen_maps( vml_vvp, REDOWNLOAD_ALL);
1111 }
1112
1113 static void maps_layer_add_menu_items ( VikMapsLayer *vml, GtkMenu *menu, VikLayersPanel *vlp )
1114 {
1115   static gpointer pass_along[2];
1116   GtkWidget *item;
1117   pass_along[0] = vml;
1118   pass_along[1] = vik_layers_panel_get_viewport( VIK_LAYERS_PANEL(vlp) );
1119
1120   item = gtk_menu_item_new();
1121   gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
1122   gtk_widget_show ( item );
1123
1124   item = gtk_menu_item_new_with_label ( "Download Onscreen Maps" );
1125   g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_download_onscreen_maps), pass_along );
1126   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1127   gtk_widget_show ( item );
1128
1129   item = gtk_menu_item_new_with_label ( "Refresh Onscreen Tiles" );
1130   g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(maps_layer_redownload_all_onscreen_maps), pass_along );
1131   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1132   gtk_widget_show ( item );
1133 }