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