]> git.street.me.uk Git - andy/viking.git/blame - src/vikmapslayer.c
Make elev graph show better graph for low altitude tracks.
[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
732d1e25
EB
27#define REAL_MIN_SHRINKFACTOR 0.0039062499 /* if shrinkfactor is between MAX and REAL_MAX, will only check for existence */
28
50a14534
EB
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"
50a14534 60
bce3a7b0
EB
61#include "icons/icons.h"
62
50a14534
EB
63/****** MAP TYPES ******/
64
cdcaf41c
QT
65static GList *__map_types = NULL;
66
67#define NUM_MAP_TYPES g_list_length(__map_types)
50a14534 68
cdcaf41c
QT
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;
50a14534
EB
74
75/******** MAPZOOMS *********/
76
d756fb5c 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 };
50a14534
EB
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
d756fb5c 81#define NUM_MAPZOOMS (sizeof(params_mapzooms)/sizeof(params_mapzooms[0]) - 1)
50a14534
EB
82
83/**************************/
84
85
07059501 86static void maps_layer_post_read (VikLayer *vl, VikViewport *vp, gboolean from_file);
911400b5
AF
87static void maps_layer_marshall( VikMapsLayer *vml, guint8 **data, gint *len );
88static VikMapsLayer *maps_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp );
50a14534
EB
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 );
941aa6e9 96static gpointer maps_layer_download_create ( VikWindow *vw, VikViewport *vvp );
50a14534
EB
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[] = {
cdcaf41c 108 { "mode", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, "Map Type:", VIK_LAYER_WIDGET_RADIOGROUP, NULL, NULL },
50a14534
EB
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[] = {
941aa6e9 118 { "Maps Download", (VikToolConstructorFunc) maps_layer_download_create, NULL, NULL, NULL,
bce3a7b0 119 (VikToolMouseFunc) maps_layer_download_click, NULL, (VikToolMouseFunc) maps_layer_download_release,
777e2d4d 120 (VikToolKeyFunc) NULL, &cursor_mapdl },
50a14534
EB
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
5a4a28bf
QT
135 VIK_MENU_ITEM_ALL,
136
50a14534
EB
137 (VikLayerFuncCreate) maps_layer_new,
138 (VikLayerFuncRealize) NULL,
94933cb8 139 maps_layer_post_read,
50a14534
EB
140 (VikLayerFuncFree) maps_layer_free,
141
142 (VikLayerFuncProperties) NULL,
143 (VikLayerFuncDraw) maps_layer_draw,
144 (VikLayerFuncChangeCoordMode) NULL,
145
20c7a3a0
QT
146 (VikLayerFuncSetMenuItemsSelection) NULL,
147 (VikLayerFuncGetMenuItemsSelection) NULL,
148
50a14534
EB
149 (VikLayerFuncAddMenuItems) maps_layer_add_menu_items,
150 (VikLayerFuncSublayerAddMenuItems) NULL,
151
152 (VikLayerFuncSublayerRenameRequest) NULL,
153 (VikLayerFuncSublayerToggleVisible) NULL,
154
911400b5
AF
155 (VikLayerFuncMarshall) maps_layer_marshall,
156 (VikLayerFuncUnmarshall) maps_layer_unmarshall,
50a14534
EB
157
158 (VikLayerFuncSetParam) maps_layer_set_param,
159 (VikLayerFuncGetParam) maps_layer_get_param,
160
161 (VikLayerFuncReadFileData) NULL,
162 (VikLayerFuncWriteFileData) NULL,
163
33534cd8 164 (VikLayerFuncDeleteItem) NULL,
50a14534
EB
165 (VikLayerFuncCopyItem) NULL,
166 (VikLayerFuncPasteItem) NULL,
167 (VikLayerFuncFreeCopiedItem) NULL,
70a23263 168 (VikLayerFuncDragDropRequest) NULL,
50a14534
EB
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;
10ca2bfe
QT
180 VikCoord *last_center;
181 gdouble last_xmpp;
182 gdouble last_ympp;
50a14534
EB
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
a0b59f2f 191enum { REDOWNLOAD_NONE = 0, REDOWNLOAD_BAD, REDOWNLOAD_ALL, DOWNLOAD_OR_REFRESH };
50a14534
EB
192
193
cdcaf41c
QT
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
7114e879
QT
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
50a14534
EB
241/****************************************/
242/******** CACHE DIR STUFF ***************/
243/****************************************/
244
3d9454e6 245#define DIRSTRUCTURE "%st%ds%dz%d" G_DIR_SEPARATOR_S "%d" G_DIR_SEPARATOR_S "%d"
50a14534
EB
246#ifdef WINDOWS
247#define MAPS_CACHE_DIR "C:\\VIKING-MAPS\\"
50a14534
EB
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/"
50a14534 254
0c1044e9 255gchar *maps_layer_default_dir ()
50a14534 256{
3d9454e6
GB
257 static gchar *defaultdir = NULL;
258 if ( ! defaultdir )
50a14534
EB
259 {
260 /* Thanks to Mike Davison for the $VIKING_MAPS usage */
3d9454e6
GB
261 const gchar *mapdir = g_getenv("VIKING_MAPS");
262 if ( mapdir ) {
263 defaultdir = g_strdup ( mapdir );
50a14534 264 } else if ( access ( GLOBAL_MAPS_DIR, W_OK ) == 0 ) {
3d9454e6 265 defaultdir = g_strdup ( GLOBAL_MAPS_DIR );
50a14534 266 } else {
3d9454e6
GB
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 );
50a14534 272 else
3d9454e6 273 defaultdir = g_strdup ( ".viking-maps" );
50a14534 274 }
3d9454e6
GB
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);
50a14534
EB
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);
e65028db
GB
305 g_free ( vml->cache_dir );
306 vml->cache_dir = NULL;
50a14534
EB
307
308 if ( dir == NULL || dir[0] == '\0' )
309 vml->cache_dir = g_strdup ( MAPS_CACHE_DIR );
310 else
311 {
312 len = strlen(dir);
3d9454e6 313 if ( dir[len-1] != G_DIR_SEPARATOR )
50a14534
EB
314 {
315 vml->cache_dir = g_malloc ( len+2 );
316 strncpy ( vml->cache_dir, dir, len );
3d9454e6 317 vml->cache_dir[len] = G_DIR_SEPARATOR;
50a14534
EB
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 );
cdcaf41c 361 return MAPS_LAYER_NTH_TYPE(index)->uniq_id;
50a14534
EB
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++ )
cdcaf41c 368 if ( MAPS_LAYER_NTH_TYPE(i)->uniq_id == uniq_id )
50a14534
EB
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{
36c78d6d 415 int idx;
50a14534
EB
416 VikMapsLayer *vml = VIK_MAPS_LAYER ( g_object_new ( VIK_MAPS_LAYER_TYPE, NULL ) );
417 vik_layer_init ( VIK_LAYER(vml), VIK_LAYER_MAPS );
36c78d6d
QT
418 idx = map_uniq_id_to_index(7); /* 7 is id for google maps */
419 vml->maptype = (idx < NUM_MAP_TYPES) ? idx : 0;
50a14534
EB
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;
10ca2bfe
QT
425 vml->last_center = NULL;
426 vml->last_xmpp = 0.0;
427 vml->last_ympp = 0.0;
50a14534
EB
428
429 vml->dl_right_click_menu = NULL;
430
431 return vml;
432}
433
434static void maps_layer_free ( VikMapsLayer *vml )
435{
e65028db
GB
436 g_free ( vml->cache_dir );
437 vml->cache_dir = NULL;
50a14534
EB
438 if ( vml->dl_right_click_menu )
439 gtk_object_sink ( GTK_OBJECT(vml->dl_right_click_menu) );
e65028db
GB
440 g_free(vml->last_center);
441 vml->last_center = NULL;
50a14534
EB
442}
443
07059501 444static void maps_layer_post_read (VikLayer *vl, VikViewport *vp, gboolean from_file)
dc5758d3 445{
07059501
GB
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;
dc5758d3 454
07059501
GB
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 }
dc5758d3
GB
463 }
464}
465
911400b5
AF
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
50a14534
EB
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,
cdcaf41c 549 mapcoord->z, MAPS_LAYER_NTH_TYPE(vml->maptype)->uniq_id,
50a14534
EB
550 mapcoord->scale, vml->alpha, xshrinkfactor, yshrinkfactor );
551 }
552 }
553 }
554 }
555 return pixbuf;
556}
557
10ca2bfe
QT
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
50a14534
EB
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;
732d1e25 589 gdouble existence_only = FALSE;
50a14534
EB
590
591 if ( vml->xmapzoom && (vml->xmapzoom != xzoom || vml->ymapzoom != yzoom) ) {
592 xshrinkfactor = vml->xmapzoom / xzoom;
593 yshrinkfactor = vml->ymapzoom / yzoom;
732d1e25
EB
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 }
50a14534
EB
604 }
605 }
606
607 /* coord -> ID */
cdcaf41c
QT
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 ) ) {
50a14534
EB
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);
cdcaf41c 616 gint mode = map_type->uniq_id;
50a14534
EB
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
732d1e25 625 if ( (!existence_only) && vml->autodownload && should_start_autodownload(vml, vvp)) {
214f9ac2
QT
626#ifdef DEBUG
627 fputs(stderr, "DEBUG: Starting autodownload\n");
628#endif
50a14534 629 start_download_thread ( vml, vvp, ul, br, REDOWNLOAD_NONE );
10ca2bfe 630 }
50a14534 631
732d1e25 632 if ( map_type->tilesize_x == 0 && !existence_only ) {
50a14534
EB
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
cdcaf41c 642 map_type->mapcoord_to_center_coord ( &ulm, &coord );
50a14534
EB
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 */
cdcaf41c
QT
652 gdouble tilesize_x = map_type->tilesize_x * xshrinkfactor;
653 gdouble tilesize_y = map_type->tilesize_y * yshrinkfactor;
50a14534
EB
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;
732d1e25
EB
661
662 GdkGC *black_gc = GTK_WIDGET(vvp)->style->black_gc;
663
50a14534
EB
664 xend = (xinc == 1) ? (xmax+1) : (xmin-1);
665 yend = (yinc == 1) ? (ymax+1) : (ymin-1);
666
cdcaf41c 667 map_type->mapcoord_to_center_coord ( &ulm, &coord );
50a14534
EB
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;
732d1e25
EB
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 }
50a14534
EB
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{
cdcaf41c 706 if ( MAPS_LAYER_NTH_TYPE(vml->maptype)->drawmode == vik_viewport_get_drawmode ( vvp ) )
50a14534
EB
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;
7114e879 744 gboolean refresh_display;
550fd035
QT
745 VikMapsLayer *vml;
746 VikViewport *vvp;
747 gboolean map_layer_alive;
748 GMutex *mutex;
50a14534
EB
749} MapDownloadInfo;
750
751static void mdi_free ( MapDownloadInfo *mdi )
752{
550fd035 753 g_mutex_free(mdi->mutex);
50a14534 754 g_free ( mdi->cache_dir );
e65028db 755 mdi->cache_dir = NULL;
50a14534 756 g_free ( mdi->filename_buf );
e65028db 757 mdi->filename_buf = NULL;
50a14534
EB
758 g_free ( mdi );
759}
760
7bb60307 761static void weak_ref_cb(gpointer ptr, GObject * dead_vml)
550fd035 762{
7bb60307 763 MapDownloadInfo *mdi = ptr;
550fd035
QT
764 g_mutex_lock(mdi->mutex);
765 mdi->map_layer_alive = FALSE;
766 g_mutex_unlock(mdi->mutex);
767}
768
50a14534
EB
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 {
94493114 777 gboolean remove_mem_cache = FALSE;
84628352 778 gboolean need_download = FALSE;
50a14534 779 g_snprintf ( mdi->filename_buf, mdi->maxlen, DIRSTRUCTURE,
cdcaf41c 780 mdi->cache_dir, MAPS_LAYER_NTH_TYPE(mdi->maptype)->uniq_id,
50a14534
EB
781 mdi->mapcoord.scale, mdi->mapcoord.z, x, y );
782
84628352
QT
783 donemaps++;
784 a_background_thread_progress ( threaddata, ((gdouble)donemaps) / mdi->mapstoget ); /* this also calls testcancel */
785
50a14534
EB
786 if ( mdi->redownload == REDOWNLOAD_ALL)
787 remove ( mdi->filename_buf );
093c5c71 788
84628352 789 else if ( (mdi->redownload == REDOWNLOAD_BAD) && (access ( mdi->filename_buf, F_OK ) == 0) )
50a14534
EB
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 {
84628352
QT
804 need_download = TRUE;
805 if (( mdi->redownload != REDOWNLOAD_NONE ) &&
a0b59f2f 806 ( mdi->redownload != DOWNLOAD_OR_REFRESH ))
94493114
QT
807 remove_mem_cache = TRUE;
808 } else if ( mdi->redownload == DOWNLOAD_OR_REFRESH ) {
809 remove_mem_cache = TRUE;
810 } else
811 continue;
812
94493114 813 mdi->mapcoord.x = x; mdi->mapcoord.y = y;
84628352
QT
814
815 if (need_download) {
816 if ( MAPS_LAYER_NTH_TYPE(mdi->maptype)->download ( &(mdi->mapcoord), mdi->filename_buf ))
94493114 817 continue;
84628352 818 }
94493114
QT
819
820 gdk_threads_enter();
821 g_mutex_lock(mdi->mutex);
822 if (remove_mem_cache)
50bb3d25 823 a_mapcache_remove_all_shrinkfactors ( x, y, mdi->mapcoord.z, MAPS_LAYER_NTH_TYPE(mdi->maptype)->uniq_id, mdi->mapcoord.scale );
7114e879 824 if (mdi->refresh_display && mdi->map_layer_alive) {
94493114
QT
825 /* TODO: check if it's on visible area */
826 vik_layer_emit_update ( VIK_LAYER(mdi->vml) );
a0b59f2f 827 }
94493114
QT
828 g_mutex_unlock(mdi->mutex);
829 gdk_threads_leave();
830 mdi->mapcoord.x = mdi->mapcoord.y = 0; /* we're temporarily between downloads */
831
50a14534
EB
832 }
833 }
04e54492
QT
834 g_mutex_lock(mdi->mutex);
835 if (mdi->map_layer_alive)
7bb60307 836 g_object_weak_unref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
04e54492 837 g_mutex_unlock(mdi->mutex);
50a14534
EB
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,
cdcaf41c 845 mdi->cache_dir, MAPS_LAYER_NTH_TYPE(mdi->maptype)->uniq_id,
50a14534
EB
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;
cdcaf41c
QT
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 ) )
50a14534
EB
862 {
863 MapDownloadInfo *mdi = g_malloc ( sizeof(MapDownloadInfo) );
864 gint a, b;
865
550fd035
QT
866 mdi->vml = vml;
867 mdi->vvp = vvp;
868 mdi->map_layer_alive = TRUE;
869 mdi->mutex = g_mutex_new();
7114e879 870 mdi->refresh_display = TRUE;
550fd035 871
50a14534
EB
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,
cdcaf41c 898 vml->cache_dir, map_type->uniq_id, ulm.scale,
50a14534
EB
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 {
cdcaf41c 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" );
50a14534 911
7bb60307 912 g_object_weak_ref(G_OBJECT(mdi->vml), weak_ref_cb, mdi);
50a14534
EB
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
7114e879
QT
928void maps_layer_download_section_without_redraw( VikMapsLayer *vml, VikViewport *vvp, VikCoord *ul, VikCoord *br, gdouble zoom)
929{
7114e879
QT
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)) {
7742da66 935 g_warning("%s() coord_to_mapcoord() failed\n", __PRETTY_FUNCTION__);
7114e879
QT
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
50a14534
EB
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{
941aa6e9
AF
1005 if (!vml || vml->vl.type != VIK_LAYER_MAPS)
1006 return FALSE;
50a14534
EB
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 );
a0b59f2f 1014 start_download_thread ( vml, vvp, &ul, &br, DOWNLOAD_OR_REFRESH );
50a14534
EB
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
941aa6e9
AF
1047static gpointer maps_layer_download_create ( VikWindow *vw, VikViewport *vvp)
1048{
1049 return vvp;
1050}
1051
50a14534
EB
1052static gboolean maps_layer_download_click ( VikMapsLayer *vml, GdkEventButton *event, VikViewport *vvp )
1053{
1054 MapCoord tmp;
941aa6e9
AF
1055 if (!vml || vml->vl.type != VIK_LAYER_MAPS)
1056 return FALSE;
cdcaf41c
QT
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 ),
50a14534
EB
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
50817314 1093static void download_onscreen_maps ( gpointer vml_vvp[2], gint redownload )
50a14534
EB
1094{
1095 VikMapsLayer *vml = vml_vvp[0];
1096 VikViewport *vvp = vml_vvp[1];
314c1ccc 1097 VikViewportDrawMode vp_drawmode = vik_viewport_get_drawmode ( vvp );
50a14534
EB
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
cdcaf41c 1108 VikMapsLayer_MapType *map_type = MAPS_LAYER_NTH_TYPE(vml->maptype);
314c1ccc 1109 if ( map_type->drawmode == vp_drawmode &&
cdcaf41c
QT
1110 map_type->coord_to_mapcoord ( &ul, xzoom, yzoom, &ulm ) &&
1111 map_type->coord_to_mapcoord ( &br, xzoom, yzoom, &brm ) )
50817314 1112 start_download_thread ( vml, vvp, &ul, &br, redownload );
314c1ccc 1113 else if (map_type->drawmode != vp_drawmode) {
94933cb8 1114 const gchar *drawmode_name = vik_viewport_get_drawmode_name (vvp, map_type->drawmode);
7bc965c0 1115 gchar *err = g_strdup_printf("Wrong drawmode for this map.\nSelect \"%s\" from View menu and try again.", drawmode_name);
314c1ccc
QT
1116 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), err );
1117 g_free(err);
1118 }
50a14534 1119 else
314c1ccc 1120 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vml), "Wrong zoom level for this map." );
50a14534
EB
1121
1122}
1123
50817314
GB
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
50a14534
EB
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 );
50817314
GB
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 );
50a14534 1154}