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