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