]> git.street.me.uk Git - andy/viking.git/blame - src/vikgeoreflayer.c
[QA] Update year values.
[andy/viking.git] / src / vikgeoreflayer.c
CommitLineData
50a14534
EB
1/*
2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
3 *
4 * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
4c77d5e0
GB
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
25
50a14534 26#include "viking.h"
a0008235 27#include <glib.h>
6af463da 28#include <glib/gstdio.h>
4c77d5e0 29#include <glib/gi18n.h>
7960e897 30#include <string.h>
be75ec20
MR
31#include <math.h>
32#include <stdlib.h>
50a14534 33
bce3a7b0 34#include "icons/icons.h"
a7023a1b 35/*
a7023a1b
RN
36static VikLayerParamData image_default ( void )
37{
38 VikLayerParamData data;
39 data.s = g_strdup ("");
40 return data;
41}
a7023a1b 42*/
bce3a7b0 43
50a14534 44VikLayerParam georef_layer_params[] = {
a87f8fa1
RN
45 { VIK_LAYER_GEOREF, "image", VIK_LAYER_PARAM_STRING, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL },
46 { VIK_LAYER_GEOREF, "corner_easting", VIK_LAYER_PARAM_DOUBLE, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL },
47 { VIK_LAYER_GEOREF, "corner_northing", VIK_LAYER_PARAM_DOUBLE, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL },
48 { VIK_LAYER_GEOREF, "mpp_easting", VIK_LAYER_PARAM_DOUBLE, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL },
49 { VIK_LAYER_GEOREF, "mpp_northing", VIK_LAYER_PARAM_DOUBLE, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL },
50a14534
EB
50};
51
52enum { PARAM_IMAGE = 0, PARAM_CE, PARAM_CN, PARAM_ME, PARAM_MN, NUM_PARAMS };
53
e6b64c5d 54static const gchar* georef_layer_tooltip ( VikGeorefLayer *vgl );
0a6cab71
AF
55static void georef_layer_marshall( VikGeorefLayer *vgl, guint8 **data, gint *len );
56static VikGeorefLayer *georef_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp );
158b3642
RN
57static gboolean georef_layer_set_param ( VikGeorefLayer *vgl, guint16 id, VikLayerParamData data, VikViewport *vp, gboolean is_file_operation );
58static VikLayerParamData georef_layer_get_param ( VikGeorefLayer *vgl, guint16 id, gboolean is_file_operation );
a7023a1b 59static VikGeorefLayer *georef_layer_new ( VikViewport *vvp );
a6b90ba4 60static VikGeorefLayer *georef_layer_create ( VikViewport *vp );
50a14534 61static void georef_layer_free ( VikGeorefLayer *vgl );
a6b90ba4 62static gboolean georef_layer_properties ( VikGeorefLayer *vgl, gpointer vp );
fd22ce3e 63static void georef_layer_draw ( VikGeorefLayer *vgl, VikViewport *vp );
50a14534
EB
64static void georef_layer_add_menu_items ( VikGeorefLayer *vgl, GtkMenu *menu, gpointer vlp );
65static void georef_layer_set_image ( VikGeorefLayer *vgl, const gchar *image );
66static gboolean georef_layer_dialog ( VikGeorefLayer **vgl, gpointer vp, GtkWindow *w );
fd22ce3e 67static void georef_layer_load_image ( VikGeorefLayer *vgl, VikViewport *vp, gboolean from_file );
941aa6e9
AF
68
69/* tools */
70static gpointer georef_layer_move_create ( VikWindow *vw, VikViewport *vvp);
50a14534
EB
71static gboolean georef_layer_move_release ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp );
72static gboolean georef_layer_move_press ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp );
941aa6e9 73static gpointer georef_layer_zoom_create ( VikWindow *vw, VikViewport *vvp);
50a14534
EB
74static gboolean georef_layer_zoom_press ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp );
75
79dce0cb 76// See comment in viktrwlayer.c for advice on values used
50a14534 77static VikToolInterface georef_tools[] = {
79dce0cb
RN
78 { { "GeorefMoveMap", "vik-icon-Georef Move Map", N_("_Georef Move Map"), NULL, N_("Georef Move Map"), 0 },
79 (VikToolConstructorFunc) georef_layer_move_create, NULL, NULL, NULL,
bce3a7b0 80 (VikToolMouseFunc) georef_layer_move_press, NULL, (VikToolMouseFunc) georef_layer_move_release,
ef5e8132
RN
81 (VikToolKeyFunc) NULL,
82 FALSE,
83 GDK_CURSOR_IS_PIXMAP, &cursor_geomove_pixbuf },
941aa6e9 84
79dce0cb
RN
85 { { "GeorefZoomTool", "vik-icon-Georef Zoom Tool", N_("Georef Z_oom Tool"), NULL, N_("Georef Zoom Tool"), 0 },
86 (VikToolConstructorFunc) georef_layer_zoom_create, NULL, NULL, NULL,
bce3a7b0 87 (VikToolMouseFunc) georef_layer_zoom_press, NULL, NULL,
ef5e8132
RN
88 (VikToolKeyFunc) NULL,
89 FALSE,
90 GDK_CURSOR_IS_PIXMAP, &cursor_geozoom_pixbuf },
50a14534
EB
91};
92
93VikLayerInterface vik_georef_layer_interface = {
db386630 94 "GeoRef Map",
affcc0f2 95 N_("GeoRef Map"),
75078768 96 NULL,
5bfafde9 97 &vikgeoreflayer_pixbuf, /*icon */
50a14534
EB
98
99 georef_tools,
100 sizeof(georef_tools) / sizeof(VikToolInterface),
101
102 georef_layer_params,
103 NUM_PARAMS,
104 NULL,
105 0,
106
5a4a28bf
QT
107 VIK_MENU_ITEM_ALL,
108
50a14534
EB
109 (VikLayerFuncCreate) georef_layer_create,
110 (VikLayerFuncRealize) NULL,
111 (VikLayerFuncPostRead) georef_layer_load_image,
112 (VikLayerFuncFree) georef_layer_free,
113
114 (VikLayerFuncProperties) georef_layer_properties,
115 (VikLayerFuncDraw) georef_layer_draw,
116 (VikLayerFuncChangeCoordMode) NULL,
117
20c7a3a0
QT
118 (VikLayerFuncSetMenuItemsSelection) NULL,
119 (VikLayerFuncGetMenuItemsSelection) NULL,
120
50a14534
EB
121 (VikLayerFuncAddMenuItems) georef_layer_add_menu_items,
122 (VikLayerFuncSublayerAddMenuItems) NULL,
123
124 (VikLayerFuncSublayerRenameRequest) NULL,
125 (VikLayerFuncSublayerToggleVisible) NULL,
9da7faf2 126 (VikLayerFuncSublayerTooltip) NULL,
e6b64c5d 127 (VikLayerFuncLayerTooltip) georef_layer_tooltip,
a5dcfdb7 128 (VikLayerFuncLayerSelected) NULL,
50a14534 129
0a6cab71
AF
130 (VikLayerFuncMarshall) georef_layer_marshall,
131 (VikLayerFuncUnmarshall) georef_layer_unmarshall,
50a14534
EB
132
133 (VikLayerFuncSetParam) georef_layer_set_param,
134 (VikLayerFuncGetParam) georef_layer_get_param,
135
136 (VikLayerFuncReadFileData) NULL,
137 (VikLayerFuncWriteFileData) NULL,
138
33534cd8 139 (VikLayerFuncDeleteItem) NULL,
d5874ef9 140 (VikLayerFuncCutItem) NULL,
50a14534
EB
141 (VikLayerFuncCopyItem) NULL,
142 (VikLayerFuncPasteItem) NULL,
143 (VikLayerFuncFreeCopiedItem) NULL,
70a23263 144 (VikLayerFuncDragDropRequest) NULL,
77ad64fa
RN
145
146 (VikLayerFuncSelectClick) NULL,
08f14055
RN
147 (VikLayerFuncSelectMove) NULL,
148 (VikLayerFuncSelectRelease) NULL,
e46f259a 149 (VikLayerFuncSelectedViewportMenu) NULL,
50a14534
EB
150};
151
152struct _VikGeorefLayer {
153 VikLayer vl;
154 gchar *image;
155 GdkPixbuf *pixbuf;
156 struct UTM corner;
157 gdouble mpp_easting, mpp_northing;
158 guint width, height;
159
f3505ea3
MR
160 GdkPixbuf *scaled;
161 guint32 scaled_width, scaled_height;
162
50a14534
EB
163 gint click_x, click_y;
164};
165
166
167
168GType vik_georef_layer_get_type ()
169{
170 static GType vgl_type = 0;
171
172 if (!vgl_type)
173 {
174 static const GTypeInfo vgl_info =
175 {
176 sizeof (VikGeorefLayerClass),
177 NULL, /* base_init */
178 NULL, /* base_finalize */
179 NULL, /* class init */
180 NULL, /* class_finalize */
181 NULL, /* class_data */
182 sizeof (VikGeorefLayer),
183 0,
184 NULL /* instance init */
185 };
186 vgl_type = g_type_register_static ( VIK_LAYER_TYPE, "VikGeorefLayer", &vgl_info, 0 );
187 }
188
189 return vgl_type;
190}
191
e6b64c5d
RN
192static const gchar* georef_layer_tooltip ( VikGeorefLayer *vgl )
193{
194 return vgl->image;
195}
196
0a6cab71
AF
197static void georef_layer_marshall( VikGeorefLayer *vgl, guint8 **data, gint *len )
198{
199 vik_layer_marshall_params ( VIK_LAYER(vgl), data, len );
200}
201
202static VikGeorefLayer *georef_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp )
203{
a7023a1b 204 VikGeorefLayer *rv = georef_layer_new ( vvp );
0a6cab71
AF
205 vik_layer_unmarshall_params ( VIK_LAYER(rv), data, len, vvp );
206 if (rv->image) {
fd22ce3e 207 georef_layer_load_image ( rv, vvp, TRUE );
0a6cab71
AF
208 }
209 return rv;
210}
211
158b3642 212static gboolean georef_layer_set_param ( VikGeorefLayer *vgl, guint16 id, VikLayerParamData data, VikViewport *vp, gboolean is_file_operation )
50a14534
EB
213{
214 switch ( id )
215 {
216 case PARAM_IMAGE: georef_layer_set_image ( vgl, data.s ); break;
217 case PARAM_CN: vgl->corner.northing = data.d; break;
218 case PARAM_CE: vgl->corner.easting = data.d; break;
219 case PARAM_MN: vgl->mpp_northing = data.d; break;
220 case PARAM_ME: vgl->mpp_easting = data.d; break;
221 }
222 return TRUE;
223}
224
158b3642 225static VikLayerParamData georef_layer_get_param ( VikGeorefLayer *vgl, guint16 id, gboolean is_file_operation )
50a14534
EB
226{
227 VikLayerParamData rv;
228 switch ( id )
229 {
88542aa9
RN
230 case PARAM_IMAGE: {
231 gboolean set = FALSE;
232 if ( is_file_operation ) {
233 if ( a_vik_get_file_ref_format() == VIK_FILE_REF_FORMAT_RELATIVE ) {
234 gchar *cwd = g_get_current_dir();
235 if ( cwd ) {
236 rv.s = file_GetRelativeFilename ( cwd, vgl->image );
237 if ( !rv.s ) rv.s = "";
238 set = TRUE;
239 }
240 }
241 }
242 if ( !set )
243 rv.s = vgl->image ? vgl->image : "";
244 break;
245 }
50a14534
EB
246 case PARAM_CN: rv.d = vgl->corner.northing; break;
247 case PARAM_CE: rv.d = vgl->corner.easting; break;
248 case PARAM_MN: rv.d = vgl->mpp_northing; break;
249 case PARAM_ME: rv.d = vgl->mpp_easting; break;
250 }
251 return rv;
252}
253
a7023a1b 254static VikGeorefLayer *georef_layer_new ( VikViewport *vvp )
50a14534
EB
255{
256 VikGeorefLayer *vgl = VIK_GEOREF_LAYER ( g_object_new ( VIK_GEOREF_LAYER_TYPE, NULL ) );
a0c65899 257 vik_layer_set_type ( VIK_LAYER(vgl), VIK_LAYER_GEOREF );
50a14534 258
a7023a1b
RN
259 // Since GeoRef layer doesn't use uibuilder
260 // initializing this way won't do anything yet..
261 vik_layer_set_defaults ( VIK_LAYER(vgl), vvp );
262
26342bd8
RN
263 // Make these defaults based on the current view
264 vgl->mpp_northing = vik_viewport_get_ympp ( vvp );
265 vgl->mpp_easting = vik_viewport_get_xmpp ( vvp );
266 vik_coord_to_utm ( vik_viewport_get_center ( vvp ), &(vgl->corner) );
267
50a14534
EB
268 vgl->image = NULL;
269 vgl->pixbuf = NULL;
270 vgl->click_x = -1;
271 vgl->click_y = -1;
f3505ea3
MR
272 vgl->scaled = NULL;
273 vgl->scaled_width = 0;
274 vgl->scaled_height = 0;
50a14534
EB
275 return vgl;
276}
277
fd22ce3e 278static void georef_layer_draw ( VikGeorefLayer *vgl, VikViewport *vp )
50a14534 279{
fd22ce3e
RN
280 if ( vik_viewport_get_drawmode(vp) != VIK_VIEWPORT_DRAWMODE_UTM )
281 return;
282
50a14534
EB
283 if ( vgl->pixbuf )
284 {
50a14534
EB
285 struct UTM utm_middle;
286 gdouble xmpp = vik_viewport_get_xmpp(vp), ympp = vik_viewport_get_ympp(vp);
be75ec20
MR
287 GdkPixbuf *pixbuf = vgl->pixbuf;
288 guint layer_width = vgl->width;
289 guint layer_height = vgl->height;
290
50a14534
EB
291 vik_coord_to_utm ( vik_viewport_get_center ( vp ), &utm_middle );
292
be75ec20
MR
293 guint width = vik_viewport_get_width(vp), height = vik_viewport_get_height(vp);
294 gint32 x, y;
295 vgl->corner.zone = utm_middle.zone;
296 vgl->corner.letter = utm_middle.letter;
297 VikCoord corner_coord;
298 vik_coord_load_from_utm ( &corner_coord, vik_viewport_get_coord_mode(vp), &(vgl->corner) );
299 vik_viewport_coord_to_screen ( vp, &corner_coord, &x, &y );
1b4b9e3b
RN
300
301 /* mark to scale the pixbuf if it doesn't match our dimensions */
302 gboolean scale = FALSE;
303 if ( xmpp != vgl->mpp_easting || ympp != vgl->mpp_northing )
304 {
305 scale = TRUE;
306 layer_width = round(vgl->width * vgl->mpp_easting / xmpp);
307 layer_height = round(vgl->height * vgl->mpp_northing / ympp);
308 }
309
310 // If image not in viewport bounds - no need to draw it (or bother with any scaling)
311 if ( (x < 0 || x < width) && (y < 0 || y < height) && x+layer_width > 0 && y+layer_height > 0 ) {
312
313 if ( scale )
314 {
315 /* rescale if necessary */
316 if (layer_width == vgl->scaled_width && layer_height == vgl->scaled_height && vgl->scaled != NULL)
317 pixbuf = vgl->scaled;
318 else
319 {
320 pixbuf = gdk_pixbuf_scale_simple(
321 vgl->pixbuf,
322 layer_width,
323 layer_height,
324 GDK_INTERP_BILINEAR
325 );
326
327 if (vgl->scaled != NULL)
328 g_object_unref(vgl->scaled);
329
330 vgl->scaled = pixbuf;
331 vgl->scaled_width = layer_width;
332 vgl->scaled_height = layer_height;
333 }
334 }
be75ec20 335 vik_viewport_draw_pixbuf ( vp, pixbuf, 0, 0, x, y, layer_width, layer_height ); /* todo: draw only what we need to. */
1b4b9e3b 336 }
50a14534
EB
337 }
338}
339
340static void georef_layer_free ( VikGeorefLayer *vgl )
341{
342 if ( vgl->image != NULL )
343 g_free ( vgl->image );
f3505ea3
MR
344 if ( vgl->scaled != NULL )
345 g_object_unref ( vgl->scaled );
50a14534
EB
346}
347
a6b90ba4 348static VikGeorefLayer *georef_layer_create ( VikViewport *vp )
50a14534 349{
a7023a1b 350 return georef_layer_new ( vp );
50a14534
EB
351}
352
a6b90ba4 353static gboolean georef_layer_properties ( VikGeorefLayer *vgl, gpointer vp )
50a14534
EB
354{
355 return georef_layer_dialog ( &vgl, vp, VIK_GTK_WINDOW_FROM_WIDGET(vp) );
356}
357
fd22ce3e 358static void georef_layer_load_image ( VikGeorefLayer *vgl, VikViewport *vp, gboolean from_file )
50a14534
EB
359{
360 GError *gx = NULL;
361 if ( vgl->image == NULL )
362 return;
363
364 if ( vgl->pixbuf )
365 g_object_unref ( G_OBJECT(vgl->pixbuf) );
f3505ea3
MR
366 if ( vgl->scaled )
367 {
368 g_object_unref ( G_OBJECT(vgl->scaled) );
369 vgl->scaled = NULL;
370 }
50a14534
EB
371
372 vgl->pixbuf = gdk_pixbuf_new_from_file ( vgl->image, &gx );
373
374 if (gx)
375 {
28424566
RN
376 if ( !from_file )
377 a_dialog_error_msg_extra ( VIK_GTK_WINDOW_FROM_WIDGET(vp), _("Couldn't open image file: %s"), gx->message );
50a14534
EB
378 g_error_free ( gx );
379 }
380 else
381 {
382 vgl->width = gdk_pixbuf_get_width ( vgl->pixbuf );
383 vgl->height = gdk_pixbuf_get_height ( vgl->pixbuf );
384 }
385
fd22ce3e
RN
386 if ( !from_file )
387 {
388 if ( vik_viewport_get_drawmode(vp) != VIK_VIEWPORT_DRAWMODE_UTM )
389 {
390 a_dialog_warning_msg ( VIK_GTK_WINDOW_FROM_WIDGET(vp),
391 _("GeoRef map cannot be displayed in the current drawmode.\nSelect \"UTM Mode\" from View menu to view it.") );
392 }
393 }
50a14534
EB
394 /* should find length and width here too */
395}
396
397static void georef_layer_set_image ( VikGeorefLayer *vgl, const gchar *image )
398{
399 if ( vgl->image )
400 g_free ( vgl->image );
f3505ea3
MR
401 if ( vgl->scaled )
402 {
403 g_object_unref ( vgl->scaled );
404 vgl->scaled = NULL;
405 }
50a14534
EB
406 if ( image == NULL )
407 vgl->image = NULL;
408 vgl->image = g_strdup ( image );
409}
410
411static gboolean world_file_read_line ( gchar *buffer, gint size, FILE *f, GtkWidget *widget, gboolean use_value )
412{
413 if (!fgets ( buffer, 1024, f ))
414 {
4c77d5e0 415 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_WIDGET(widget), _("Unexpected end of file reading World file.") );
50a14534
EB
416 g_free ( buffer );
417 fclose ( f );
8c060406 418 f = NULL;
50a14534
EB
419 return FALSE;
420 }
421 if ( use_value )
422 {
a0008235 423 gdouble val = g_strtod ( buffer, NULL );
50a14534
EB
424 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(widget), val > 0 ? val : -val );
425 }
426 return TRUE;
427}
428
429static void georef_layer_dialog_load ( GtkWidget *pass_along[4] )
430{
6e4a49aa
MA
431 GtkWidget *file_selector = gtk_file_chooser_dialog_new (_("Choose World file"),
432 NULL,
433 GTK_FILE_CHOOSER_ACTION_OPEN,
434 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
435 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
436 NULL);
437
438 if ( gtk_dialog_run ( GTK_DIALOG ( file_selector ) ) == GTK_RESPONSE_ACCEPT )
50a14534 439 {
8c060406 440 FILE *f = g_fopen ( gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER(file_selector) ), "r" );
50a14534
EB
441 gtk_widget_destroy ( file_selector );
442 if ( !f )
443 {
4c77d5e0 444 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_WIDGET(pass_along[0]), _("The World file you requested could not be opened for reading.") );
50a14534
EB
445 return;
446 }
447 else
448 {
449 gchar *buffer = g_malloc ( 1024 * sizeof(gchar) );
0b647b0b
MA
450 if ( world_file_read_line ( buffer, 1024, f, pass_along[0], TRUE ) && world_file_read_line ( buffer, 1024, f, pass_along[0], FALSE)
451 && world_file_read_line ( buffer, 1024, f, pass_along[0], FALSE ) && world_file_read_line ( buffer, 1024, f, pass_along[1], TRUE)
50a14534
EB
452 && world_file_read_line ( buffer, 1024, f, pass_along[2], TRUE ) && world_file_read_line ( buffer, 1024, f, pass_along[3], TRUE ) )
453 {
454 g_free ( buffer );
455 fclose ( f );
8c060406 456 f = NULL;
50a14534
EB
457 }
458 }
459 }
460 else
461 gtk_widget_destroy ( file_selector );
462/* do your jazz
463We need a
464 file selection dialog
465 file opener for reading, if NULL, send error_msg ( VIK_GTK_WINDOW_FROM_WIDGET(pass_along[0]) )
466 does that catch directories too?
467 read lines -- if not enough lines, give error.
468 if anything outside, give error. define range with #define CONSTANTS
469 put 'em in thar widgets, and that's it.
470*/
471}
472
473static void georef_layer_export_params ( gpointer *pass_along[2] )
474{
475 VikGeorefLayer *vgl = VIK_GEOREF_LAYER(pass_along[0]);
6e4a49aa
MA
476 GtkWidget *file_selector = gtk_file_chooser_dialog_new (_("Choose World file"),
477 NULL,
478 GTK_FILE_CHOOSER_ACTION_SAVE,
479 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
480 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
481 NULL);
482 if ( gtk_dialog_run ( GTK_DIALOG ( file_selector ) ) == GTK_RESPONSE_ACCEPT )
50a14534 483 {
8c060406 484 FILE *f = g_fopen ( gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER(file_selector) ), "w" );
6e4a49aa 485
50a14534
EB
486 gtk_widget_destroy ( file_selector );
487 if ( !f )
488 {
4c77d5e0 489 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_WIDGET(pass_along[0]), _("The file you requested could not be opened for writing.") );
50a14534
EB
490 return;
491 }
492 else
493 {
494 fprintf ( f, "%f\n%f\n%f\n%f\n%f\n%f\n", vgl->mpp_easting, vgl->mpp_northing, 0.0, 0.0, vgl->corner.easting, vgl->corner.northing );
495 fclose ( f );
8c060406 496 f = NULL;
50a14534
EB
497 }
498 }
499 else
500 gtk_widget_destroy ( file_selector );
501}
502
503/* returns TRUE if OK was pressed. */
504static gboolean georef_layer_dialog ( VikGeorefLayer **vgl, gpointer vp, GtkWindow *w )
505{
4c77d5e0 506 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Layer Properties"),
50a14534
EB
507 w,
508 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
509 GTK_STOCK_CANCEL,
510 GTK_RESPONSE_REJECT,
511 GTK_STOCK_OK,
512 GTK_RESPONSE_ACCEPT,
10888930 513 NULL );
535747e9
RN
514 /* Default to reject as user really needs to specify map file first */
515 gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_REJECT );
516 GtkWidget *response_w = NULL;
517#if GTK_CHECK_VERSION (2, 20, 0)
518 response_w = gtk_dialog_get_widget_for_response ( GTK_DIALOG(dialog), GTK_RESPONSE_REJECT );
519#endif
50a14534
EB
520 GtkWidget *table, *wfp_hbox, *wfp_label, *wfp_button, *ce_label, *ce_spin, *cn_label, *cn_spin, *xlabel, *xspin, *ylabel, *yspin, *imagelabel, *imageentry;
521
522 GtkWidget *pass_along[4];
523
524 table = gtk_table_new ( 6, 2, FALSE );
9b082b39 525 gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), table, TRUE, TRUE, 0 );
50a14534
EB
526
527 wfp_hbox = gtk_hbox_new ( FALSE, 0 );
4c77d5e0
GB
528 wfp_label = gtk_label_new ( _("World File Parameters:") );
529 wfp_button = gtk_button_new_with_label ( _("Load From File...") );
50a14534
EB
530
531 gtk_box_pack_start ( GTK_BOX(wfp_hbox), wfp_label, TRUE, TRUE, 0 );
532 gtk_box_pack_start ( GTK_BOX(wfp_hbox), wfp_button, FALSE, FALSE, 3 );
533
4c77d5e0 534 ce_label = gtk_label_new ( _("Corner pixel easting:") );
ac33062d 535 ce_spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, 0.0, 1500000.0, 1, 5, 0 ), 1, 4 );
09b2a3c9 536 gtk_widget_set_tooltip_text ( GTK_WIDGET(ce_spin), _("the UTM \"easting\" value of the upper-left corner pixel of the map") );
50a14534 537
4c77d5e0 538 cn_label = gtk_label_new ( _("Corner pixel northing:") );
ac33062d 539 cn_spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, 0.0, 9000000.0, 1, 5, 0 ), 1, 4 );
09b2a3c9 540 gtk_widget_set_tooltip_text ( GTK_WIDGET(cn_spin), _("the UTM \"northing\" value of the upper-left corner pixel of the map") );
50a14534 541
4c77d5e0
GB
542 xlabel = gtk_label_new ( _("X (easting) scale (mpp): "));
543 ylabel = gtk_label_new ( _("Y (northing) scale (mpp): "));
50a14534 544
ac33062d 545 xspin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, VIK_VIEWPORT_MIN_ZOOM, VIK_VIEWPORT_MAX_ZOOM, 1, 5, 0 ), 1, 8 );
79a9a44f 546 gtk_widget_set_tooltip_text ( GTK_WIDGET(xspin), _("the scale of the map in the X direction (meters per pixel)") );
ac33062d 547 yspin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, VIK_VIEWPORT_MIN_ZOOM, VIK_VIEWPORT_MAX_ZOOM, 1, 5, 0 ), 1, 8 );
79a9a44f 548 gtk_widget_set_tooltip_text ( GTK_WIDGET(yspin), _("the scale of the map in the Y direction (meters per pixel)") );
50a14534 549
4c77d5e0 550 imagelabel = gtk_label_new ( _("Map Image:") );
79672b85 551 imageentry = vik_file_entry_new (GTK_FILE_CHOOSER_ACTION_OPEN);
50a14534
EB
552
553 if (*vgl)
554 {
555 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(ce_spin), (*vgl)->corner.easting );
556 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(cn_spin), (*vgl)->corner.northing );
557 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(xspin), (*vgl)->mpp_easting );
558 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(yspin), (*vgl)->mpp_northing );
559 if ( (*vgl)->image )
560 vik_file_entry_set_filename ( VIK_FILE_ENTRY(imageentry), (*vgl)->image );
561 }
562 else
563 {
564 VikCoord corner_coord;
565 struct UTM utm;
566 vik_viewport_screen_to_coord ( VIK_VIEWPORT(vp), 0, 0, &corner_coord );
567 vik_coord_to_utm ( &corner_coord, &utm );
568 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(ce_spin), utm.easting );
569 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(cn_spin), utm.northing );
570 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(xspin), vik_viewport_get_xmpp ( VIK_VIEWPORT(vp) ) );
571 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(yspin), vik_viewport_get_ympp ( VIK_VIEWPORT(vp) ) );
572 }
573
574 gtk_table_attach_defaults ( GTK_TABLE(table), imagelabel, 0, 1, 0, 1 );
575 gtk_table_attach_defaults ( GTK_TABLE(table), imageentry, 1, 2, 0, 1 );
576 gtk_table_attach_defaults ( GTK_TABLE(table), wfp_hbox, 0, 2, 1, 2 );
577 gtk_table_attach_defaults ( GTK_TABLE(table), xlabel, 0, 1, 2, 3 );
578 gtk_table_attach_defaults ( GTK_TABLE(table), xspin, 1, 2, 2, 3 );
579 gtk_table_attach_defaults ( GTK_TABLE(table), ylabel, 0, 1, 3, 4 );
580 gtk_table_attach_defaults ( GTK_TABLE(table), yspin, 1, 2, 3, 4 );
581 gtk_table_attach_defaults ( GTK_TABLE(table), ce_label, 0, 1, 4, 5 );
582 gtk_table_attach_defaults ( GTK_TABLE(table), ce_spin, 1, 2, 4, 5 );
583 gtk_table_attach_defaults ( GTK_TABLE(table), cn_label, 0, 1, 5, 6 );
584 gtk_table_attach_defaults ( GTK_TABLE(table), cn_spin, 1, 2, 5, 6 );
585
586 pass_along[0] = xspin;
587 pass_along[1] = yspin;
588 pass_along[2] = ce_spin;
589 pass_along[3] = cn_spin;
590 g_signal_connect_swapped ( G_OBJECT(wfp_button), "clicked", G_CALLBACK(georef_layer_dialog_load), pass_along );
591
535747e9
RN
592 if ( response_w )
593 gtk_widget_grab_focus ( response_w );
594
50a14534
EB
595 gtk_widget_show_all ( table );
596
597 if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
598 {
599 if (! *vgl)
600 {
a7023a1b 601 *vgl = georef_layer_new ( VIK_VIEWPORT(vp) );
50a14534
EB
602 vik_layer_rename ( VIK_LAYER(*vgl), vik_georef_layer_interface.name );
603 }
604 (*vgl)->corner.easting = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(ce_spin) );
605 (*vgl)->corner.northing = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(cn_spin) );
606 (*vgl)->mpp_easting = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(xspin) );
607 (*vgl)->mpp_northing = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(yspin) );
608 if ( (!(*vgl)->image) || strcmp( (*vgl)->image, vik_file_entry_get_filename(VIK_FILE_ENTRY(imageentry)) ) != 0 )
609 {
610 georef_layer_set_image ( *vgl, vik_file_entry_get_filename(VIK_FILE_ENTRY(imageentry)) );
fd22ce3e 611 georef_layer_load_image ( *vgl, VIK_VIEWPORT(vp), FALSE );
50a14534
EB
612 }
613
614 gtk_widget_destroy ( GTK_WIDGET(dialog) );
615 return TRUE;
616 }
617 gtk_widget_destroy ( GTK_WIDGET(dialog) );
618 return FALSE;
619}
620
621static void georef_layer_zoom_to_fit ( gpointer vgl_vlp[2] )
622{
623 vik_viewport_set_xmpp ( vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vgl_vlp[1])), VIK_GEOREF_LAYER(vgl_vlp[0])->mpp_easting );
624 vik_viewport_set_ympp ( vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vgl_vlp[1])), VIK_GEOREF_LAYER(vgl_vlp[0])->mpp_northing );
625 vik_layers_panel_emit_update ( VIK_LAYERS_PANEL(vgl_vlp[1]) );
626}
627
628static void georef_layer_goto_center ( gpointer vgl_vlp[2] )
629{
630 VikGeorefLayer *vgl = VIK_GEOREF_LAYER ( vgl_vlp[0] );
631 VikViewport *vp = vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vgl_vlp[1]));
632 struct UTM utm;
633 VikCoord coord;
634
635 vik_coord_to_utm ( vik_viewport_get_center ( vp ), &utm );
636
637 utm.easting = vgl->corner.easting + (vgl->width * vgl->mpp_easting / 2); /* only an approximation */
638 utm.northing = vgl->corner.northing - (vgl->height * vgl->mpp_northing / 2);
639
640 vik_coord_load_from_utm ( &coord, vik_viewport_get_coord_mode ( vp ), &utm );
641 vik_viewport_set_center_coord ( vp, &coord );
642
643 vik_layers_panel_emit_update ( VIK_LAYERS_PANEL(vgl_vlp[1]) );
644}
645
646static void georef_layer_add_menu_items ( VikGeorefLayer *vgl, GtkMenu *menu, gpointer vlp )
647{
648 static gpointer pass_along[2];
649 GtkWidget *item;
650 pass_along[0] = vgl;
651 pass_along[1] = vlp;
652
653 item = gtk_menu_item_new();
654 gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
655 gtk_widget_show ( item );
656
d6de71f9
RN
657 /* Now with icons */
658 item = gtk_image_menu_item_new_with_mnemonic ( _("_Zoom to Fit Map") );
659 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ZOOM_FIT, GTK_ICON_SIZE_MENU) );
50a14534
EB
660 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(georef_layer_zoom_to_fit), pass_along );
661 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
662 gtk_widget_show ( item );
663
d6de71f9
RN
664 item = gtk_image_menu_item_new_with_mnemonic ( _("_Goto Map Center") );
665 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_MENU) );
50a14534
EB
666 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(georef_layer_goto_center), pass_along );
667 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
668 gtk_widget_show ( item );
669
d6de71f9
RN
670 item = gtk_image_menu_item_new_with_mnemonic ( _("_Export to World File") );
671 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_HARDDISK, GTK_ICON_SIZE_MENU) );
50a14534
EB
672 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(georef_layer_export_params), pass_along );
673 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
674 gtk_widget_show ( item );
675}
676
941aa6e9
AF
677
678static gpointer georef_layer_move_create ( VikWindow *vw, VikViewport *vvp)
679{
680 return vvp;
681}
682
50a14534
EB
683static gboolean georef_layer_move_release ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp )
684{
941aa6e9
AF
685 if (!vgl || vgl->vl.type != VIK_LAYER_GEOREF)
686 return FALSE;
687
50a14534
EB
688 if ( vgl->click_x != -1 )
689 {
690 vgl->corner.easting += (event->x - vgl->click_x) * vik_viewport_get_xmpp (vvp);
691 vgl->corner.northing -= (event->y - vgl->click_y) * vik_viewport_get_ympp (vvp);
da121f9b 692 vik_layer_emit_update ( VIK_LAYER(vgl) );
50a14534
EB
693 return TRUE;
694 }
695 return FALSE; /* I didn't move anything on this layer! */
696}
697
941aa6e9
AF
698static gpointer georef_layer_zoom_create ( VikWindow *vw, VikViewport *vvp)
699{
700 return vvp;
701}
702
50a14534
EB
703static gboolean georef_layer_zoom_press ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp )
704{
941aa6e9
AF
705 if (!vgl || vgl->vl.type != VIK_LAYER_GEOREF)
706 return FALSE;
50a14534
EB
707 if ( event->button == 1 )
708 {
709 if ( vgl->mpp_easting < (VIK_VIEWPORT_MAX_ZOOM / 1.05) && vgl->mpp_northing < (VIK_VIEWPORT_MAX_ZOOM / 1.05) )
710 {
711 vgl->mpp_easting *= 1.01;
712 vgl->mpp_northing *= 1.01;
713 }
714 }
715 else
716 {
717 if ( vgl->mpp_easting > (VIK_VIEWPORT_MIN_ZOOM * 1.05) && vgl->mpp_northing > (VIK_VIEWPORT_MIN_ZOOM * 1.05) )
718 {
719 vgl->mpp_easting /= 1.01;
720 vgl->mpp_northing /= 1.01;
721 }
722 }
723 vik_viewport_set_xmpp ( vvp, vgl->mpp_easting );
724 vik_viewport_set_ympp ( vvp, vgl->mpp_northing );
da121f9b 725 vik_layer_emit_update ( VIK_LAYER(vgl) );
50a14534
EB
726 return TRUE;
727}
728
729static gboolean georef_layer_move_press ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp )
730{
941aa6e9
AF
731 if (!vgl || vgl->vl.type != VIK_LAYER_GEOREF)
732 return FALSE;
50a14534
EB
733 vgl->click_x = event->x;
734 vgl->click_y = event->y;
735 return TRUE;
736}