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