]> git.street.me.uk Git - andy/viking.git/blame - src/vikgeoreflayer.c
GeoRef Layer only works in UTM Projection Mode.
[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[] = {
a7023a1b
RN
45 { VIK_LAYER_GEOREF, "image", VIK_LAYER_PARAM_STRING, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, 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 },
47 { VIK_LAYER_GEOREF, "corner_northing", VIK_LAYER_PARAM_DOUBLE, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, 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 },
49 { VIK_LAYER_GEOREF, "mpp_northing", VIK_LAYER_PARAM_DOUBLE, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, 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 );
50a14534
EB
60VikGeorefLayer *georef_layer_create ( VikViewport *vp );
61static void georef_layer_free ( VikGeorefLayer *vgl );
62gboolean 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 {
230 case PARAM_IMAGE: rv.s = vgl->image ? vgl->image : ""; break;
231 case PARAM_CN: rv.d = vgl->corner.northing; break;
232 case PARAM_CE: rv.d = vgl->corner.easting; break;
233 case PARAM_MN: rv.d = vgl->mpp_northing; break;
234 case PARAM_ME: rv.d = vgl->mpp_easting; break;
235 }
236 return rv;
237}
238
a7023a1b 239static VikGeorefLayer *georef_layer_new ( VikViewport *vvp )
50a14534
EB
240{
241 VikGeorefLayer *vgl = VIK_GEOREF_LAYER ( g_object_new ( VIK_GEOREF_LAYER_TYPE, NULL ) );
a0c65899 242 vik_layer_set_type ( VIK_LAYER(vgl), VIK_LAYER_GEOREF );
50a14534 243
a7023a1b
RN
244 // Since GeoRef layer doesn't use uibuilder
245 // initializing this way won't do anything yet..
246 vik_layer_set_defaults ( VIK_LAYER(vgl), vvp );
247
26342bd8
RN
248 // Make these defaults based on the current view
249 vgl->mpp_northing = vik_viewport_get_ympp ( vvp );
250 vgl->mpp_easting = vik_viewport_get_xmpp ( vvp );
251 vik_coord_to_utm ( vik_viewport_get_center ( vvp ), &(vgl->corner) );
252
50a14534
EB
253 vgl->image = NULL;
254 vgl->pixbuf = NULL;
255 vgl->click_x = -1;
256 vgl->click_y = -1;
f3505ea3
MR
257 vgl->scaled = NULL;
258 vgl->scaled_width = 0;
259 vgl->scaled_height = 0;
50a14534
EB
260 return vgl;
261}
262
fd22ce3e 263static void georef_layer_draw ( VikGeorefLayer *vgl, VikViewport *vp )
50a14534 264{
fd22ce3e
RN
265 if ( vik_viewport_get_drawmode(vp) != VIK_VIEWPORT_DRAWMODE_UTM )
266 return;
267
50a14534
EB
268 if ( vgl->pixbuf )
269 {
50a14534
EB
270 struct UTM utm_middle;
271 gdouble xmpp = vik_viewport_get_xmpp(vp), ympp = vik_viewport_get_ympp(vp);
be75ec20
MR
272 GdkPixbuf *pixbuf = vgl->pixbuf;
273 guint layer_width = vgl->width;
274 guint layer_height = vgl->height;
275
50a14534
EB
276 vik_coord_to_utm ( vik_viewport_get_center ( vp ), &utm_middle );
277
be75ec20
MR
278 /* scale the pixbuf if it doesn't match our dimensions */
279 if ( xmpp != vgl->mpp_easting || ympp != vgl->mpp_northing )
50a14534 280 {
be75ec20
MR
281 layer_width = round(vgl->width * vgl->mpp_easting / xmpp);
282 layer_height = round(vgl->height * vgl->mpp_northing / ympp);
f3505ea3
MR
283
284 /* rescale if necessary */
285 if (layer_width == vgl->scaled_width && layer_height == vgl->scaled_height && vgl->scaled != NULL)
286 pixbuf = vgl->scaled;
287 else
288 {
289 pixbuf = gdk_pixbuf_scale_simple(
290 vgl->pixbuf,
291 layer_width,
292 layer_height,
293 GDK_INTERP_BILINEAR
294 );
295
296 if (vgl->scaled != NULL)
297 g_object_unref(vgl->scaled);
298
299 vgl->scaled = pixbuf;
300 vgl->scaled_width = layer_width;
301 vgl->scaled_height = layer_height;
302 }
50a14534 303 }
be75ec20
MR
304
305 guint width = vik_viewport_get_width(vp), height = vik_viewport_get_height(vp);
306 gint32 x, y;
307 vgl->corner.zone = utm_middle.zone;
308 vgl->corner.letter = utm_middle.letter;
309 VikCoord corner_coord;
310 vik_coord_load_from_utm ( &corner_coord, vik_viewport_get_coord_mode(vp), &(vgl->corner) );
311 vik_viewport_coord_to_screen ( vp, &corner_coord, &x, &y );
312 if ( (x < 0 || x < width) && (y < 0 || y < height) && x+layer_width > 0 && y+layer_height > 0 )
313 vik_viewport_draw_pixbuf ( vp, pixbuf, 0, 0, x, y, layer_width, layer_height ); /* todo: draw only what we need to. */
50a14534
EB
314 }
315}
316
317static void georef_layer_free ( VikGeorefLayer *vgl )
318{
319 if ( vgl->image != NULL )
320 g_free ( vgl->image );
f3505ea3
MR
321 if ( vgl->scaled != NULL )
322 g_object_unref ( vgl->scaled );
50a14534
EB
323}
324
325VikGeorefLayer *georef_layer_create ( VikViewport *vp )
326{
a7023a1b 327 return georef_layer_new ( vp );
50a14534
EB
328}
329
330gboolean georef_layer_properties ( VikGeorefLayer *vgl, gpointer vp )
331{
332 return georef_layer_dialog ( &vgl, vp, VIK_GTK_WINDOW_FROM_WIDGET(vp) );
333}
334
fd22ce3e 335static void georef_layer_load_image ( VikGeorefLayer *vgl, VikViewport *vp, gboolean from_file )
50a14534
EB
336{
337 GError *gx = NULL;
338 if ( vgl->image == NULL )
339 return;
340
341 if ( vgl->pixbuf )
342 g_object_unref ( G_OBJECT(vgl->pixbuf) );
f3505ea3
MR
343 if ( vgl->scaled )
344 {
345 g_object_unref ( G_OBJECT(vgl->scaled) );
346 vgl->scaled = NULL;
347 }
50a14534
EB
348
349 vgl->pixbuf = gdk_pixbuf_new_from_file ( vgl->image, &gx );
350
351 if (gx)
352 {
4c77d5e0 353 g_warning ( _("Couldn't open image file: %s"), gx->message );
50a14534
EB
354 g_error_free ( gx );
355 }
356 else
357 {
358 vgl->width = gdk_pixbuf_get_width ( vgl->pixbuf );
359 vgl->height = gdk_pixbuf_get_height ( vgl->pixbuf );
360 }
361
fd22ce3e
RN
362 if ( !from_file )
363 {
364 if ( vik_viewport_get_drawmode(vp) != VIK_VIEWPORT_DRAWMODE_UTM )
365 {
366 a_dialog_warning_msg ( VIK_GTK_WINDOW_FROM_WIDGET(vp),
367 _("GeoRef map cannot be displayed in the current drawmode.\nSelect \"UTM Mode\" from View menu to view it.") );
368 }
369 }
50a14534
EB
370 /* should find length and width here too */
371}
372
373static void georef_layer_set_image ( VikGeorefLayer *vgl, const gchar *image )
374{
375 if ( vgl->image )
376 g_free ( vgl->image );
f3505ea3
MR
377 if ( vgl->scaled )
378 {
379 g_object_unref ( vgl->scaled );
380 vgl->scaled = NULL;
381 }
50a14534
EB
382 if ( image == NULL )
383 vgl->image = NULL;
384 vgl->image = g_strdup ( image );
385}
386
387static gboolean world_file_read_line ( gchar *buffer, gint size, FILE *f, GtkWidget *widget, gboolean use_value )
388{
389 if (!fgets ( buffer, 1024, f ))
390 {
4c77d5e0 391 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_WIDGET(widget), _("Unexpected end of file reading World file.") );
50a14534
EB
392 g_free ( buffer );
393 fclose ( f );
8c060406 394 f = NULL;
50a14534
EB
395 return FALSE;
396 }
397 if ( use_value )
398 {
a0008235 399 gdouble val = g_strtod ( buffer, NULL );
50a14534
EB
400 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(widget), val > 0 ? val : -val );
401 }
402 return TRUE;
403}
404
405static void georef_layer_dialog_load ( GtkWidget *pass_along[4] )
406{
6e4a49aa
MA
407 GtkWidget *file_selector = gtk_file_chooser_dialog_new (_("Choose World file"),
408 NULL,
409 GTK_FILE_CHOOSER_ACTION_OPEN,
410 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
411 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
412 NULL);
413
414 if ( gtk_dialog_run ( GTK_DIALOG ( file_selector ) ) == GTK_RESPONSE_ACCEPT )
50a14534 415 {
8c060406 416 FILE *f = g_fopen ( gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER(file_selector) ), "r" );
50a14534
EB
417 gtk_widget_destroy ( file_selector );
418 if ( !f )
419 {
4c77d5e0 420 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
421 return;
422 }
423 else
424 {
425 gchar *buffer = g_malloc ( 1024 * sizeof(gchar) );
0b647b0b
MA
426 if ( world_file_read_line ( buffer, 1024, f, pass_along[0], TRUE ) && world_file_read_line ( buffer, 1024, f, pass_along[0], FALSE)
427 && world_file_read_line ( buffer, 1024, f, pass_along[0], FALSE ) && world_file_read_line ( buffer, 1024, f, pass_along[1], TRUE)
50a14534
EB
428 && world_file_read_line ( buffer, 1024, f, pass_along[2], TRUE ) && world_file_read_line ( buffer, 1024, f, pass_along[3], TRUE ) )
429 {
430 g_free ( buffer );
431 fclose ( f );
8c060406 432 f = NULL;
50a14534
EB
433 }
434 }
435 }
436 else
437 gtk_widget_destroy ( file_selector );
438/* do your jazz
439We need a
440 file selection dialog
441 file opener for reading, if NULL, send error_msg ( VIK_GTK_WINDOW_FROM_WIDGET(pass_along[0]) )
442 does that catch directories too?
443 read lines -- if not enough lines, give error.
444 if anything outside, give error. define range with #define CONSTANTS
445 put 'em in thar widgets, and that's it.
446*/
447}
448
449static void georef_layer_export_params ( gpointer *pass_along[2] )
450{
451 VikGeorefLayer *vgl = VIK_GEOREF_LAYER(pass_along[0]);
6e4a49aa
MA
452 GtkWidget *file_selector = gtk_file_chooser_dialog_new (_("Choose World file"),
453 NULL,
454 GTK_FILE_CHOOSER_ACTION_SAVE,
455 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
456 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
457 NULL);
458 if ( gtk_dialog_run ( GTK_DIALOG ( file_selector ) ) == GTK_RESPONSE_ACCEPT )
50a14534 459 {
8c060406 460 FILE *f = g_fopen ( gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER(file_selector) ), "w" );
6e4a49aa 461
50a14534
EB
462 gtk_widget_destroy ( file_selector );
463 if ( !f )
464 {
4c77d5e0 465 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_WIDGET(pass_along[0]), _("The file you requested could not be opened for writing.") );
50a14534
EB
466 return;
467 }
468 else
469 {
470 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 );
471 fclose ( f );
8c060406 472 f = NULL;
50a14534
EB
473 }
474 }
475 else
476 gtk_widget_destroy ( file_selector );
477}
478
479/* returns TRUE if OK was pressed. */
480static gboolean georef_layer_dialog ( VikGeorefLayer **vgl, gpointer vp, GtkWindow *w )
481{
4c77d5e0 482 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Layer Properties"),
50a14534
EB
483 w,
484 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
485 GTK_STOCK_CANCEL,
486 GTK_RESPONSE_REJECT,
487 GTK_STOCK_OK,
488 GTK_RESPONSE_ACCEPT,
10888930 489 NULL );
535747e9
RN
490 /* Default to reject as user really needs to specify map file first */
491 gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_REJECT );
492 GtkWidget *response_w = NULL;
493#if GTK_CHECK_VERSION (2, 20, 0)
494 response_w = gtk_dialog_get_widget_for_response ( GTK_DIALOG(dialog), GTK_RESPONSE_REJECT );
495#endif
50a14534
EB
496 GtkWidget *table, *wfp_hbox, *wfp_label, *wfp_button, *ce_label, *ce_spin, *cn_label, *cn_spin, *xlabel, *xspin, *ylabel, *yspin, *imagelabel, *imageentry;
497
498 GtkWidget *pass_along[4];
499
500 table = gtk_table_new ( 6, 2, FALSE );
501 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), table, TRUE, TRUE, 0 );
502
503 wfp_hbox = gtk_hbox_new ( FALSE, 0 );
4c77d5e0
GB
504 wfp_label = gtk_label_new ( _("World File Parameters:") );
505 wfp_button = gtk_button_new_with_label ( _("Load From File...") );
50a14534
EB
506
507 gtk_box_pack_start ( GTK_BOX(wfp_hbox), wfp_label, TRUE, TRUE, 0 );
508 gtk_box_pack_start ( GTK_BOX(wfp_hbox), wfp_button, FALSE, FALSE, 3 );
509
4c77d5e0 510 ce_label = gtk_label_new ( _("Corner pixel easting:") );
ac33062d 511 ce_spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, 0.0, 1500000.0, 1, 5, 0 ), 1, 4 );
09b2a3c9 512 gtk_widget_set_tooltip_text ( GTK_WIDGET(ce_spin), _("the UTM \"easting\" value of the upper-left corner pixel of the map") );
50a14534 513
4c77d5e0 514 cn_label = gtk_label_new ( _("Corner pixel northing:") );
ac33062d 515 cn_spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, 0.0, 9000000.0, 1, 5, 0 ), 1, 4 );
09b2a3c9 516 gtk_widget_set_tooltip_text ( GTK_WIDGET(cn_spin), _("the UTM \"northing\" value of the upper-left corner pixel of the map") );
50a14534 517
4c77d5e0
GB
518 xlabel = gtk_label_new ( _("X (easting) scale (mpp): "));
519 ylabel = gtk_label_new ( _("Y (northing) scale (mpp): "));
50a14534 520
ac33062d 521 xspin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, VIK_VIEWPORT_MIN_ZOOM, VIK_VIEWPORT_MAX_ZOOM, 1, 5, 0 ), 1, 8 );
79a9a44f 522 gtk_widget_set_tooltip_text ( GTK_WIDGET(xspin), _("the scale of the map in the X direction (meters per pixel)") );
ac33062d 523 yspin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, VIK_VIEWPORT_MIN_ZOOM, VIK_VIEWPORT_MAX_ZOOM, 1, 5, 0 ), 1, 8 );
79a9a44f 524 gtk_widget_set_tooltip_text ( GTK_WIDGET(yspin), _("the scale of the map in the Y direction (meters per pixel)") );
50a14534 525
4c77d5e0 526 imagelabel = gtk_label_new ( _("Map Image:") );
79672b85 527 imageentry = vik_file_entry_new (GTK_FILE_CHOOSER_ACTION_OPEN);
50a14534
EB
528
529 if (*vgl)
530 {
531 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(ce_spin), (*vgl)->corner.easting );
532 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(cn_spin), (*vgl)->corner.northing );
533 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(xspin), (*vgl)->mpp_easting );
534 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(yspin), (*vgl)->mpp_northing );
535 if ( (*vgl)->image )
536 vik_file_entry_set_filename ( VIK_FILE_ENTRY(imageentry), (*vgl)->image );
537 }
538 else
539 {
540 VikCoord corner_coord;
541 struct UTM utm;
542 vik_viewport_screen_to_coord ( VIK_VIEWPORT(vp), 0, 0, &corner_coord );
543 vik_coord_to_utm ( &corner_coord, &utm );
544 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(ce_spin), utm.easting );
545 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(cn_spin), utm.northing );
546 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(xspin), vik_viewport_get_xmpp ( VIK_VIEWPORT(vp) ) );
547 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(yspin), vik_viewport_get_ympp ( VIK_VIEWPORT(vp) ) );
548 }
549
550 gtk_table_attach_defaults ( GTK_TABLE(table), imagelabel, 0, 1, 0, 1 );
551 gtk_table_attach_defaults ( GTK_TABLE(table), imageentry, 1, 2, 0, 1 );
552 gtk_table_attach_defaults ( GTK_TABLE(table), wfp_hbox, 0, 2, 1, 2 );
553 gtk_table_attach_defaults ( GTK_TABLE(table), xlabel, 0, 1, 2, 3 );
554 gtk_table_attach_defaults ( GTK_TABLE(table), xspin, 1, 2, 2, 3 );
555 gtk_table_attach_defaults ( GTK_TABLE(table), ylabel, 0, 1, 3, 4 );
556 gtk_table_attach_defaults ( GTK_TABLE(table), yspin, 1, 2, 3, 4 );
557 gtk_table_attach_defaults ( GTK_TABLE(table), ce_label, 0, 1, 4, 5 );
558 gtk_table_attach_defaults ( GTK_TABLE(table), ce_spin, 1, 2, 4, 5 );
559 gtk_table_attach_defaults ( GTK_TABLE(table), cn_label, 0, 1, 5, 6 );
560 gtk_table_attach_defaults ( GTK_TABLE(table), cn_spin, 1, 2, 5, 6 );
561
562 pass_along[0] = xspin;
563 pass_along[1] = yspin;
564 pass_along[2] = ce_spin;
565 pass_along[3] = cn_spin;
566 g_signal_connect_swapped ( G_OBJECT(wfp_button), "clicked", G_CALLBACK(georef_layer_dialog_load), pass_along );
567
535747e9
RN
568 if ( response_w )
569 gtk_widget_grab_focus ( response_w );
570
50a14534
EB
571 gtk_widget_show_all ( table );
572
573 if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
574 {
575 if (! *vgl)
576 {
a7023a1b 577 *vgl = georef_layer_new ( VIK_VIEWPORT(vp) );
50a14534
EB
578 vik_layer_rename ( VIK_LAYER(*vgl), vik_georef_layer_interface.name );
579 }
580 (*vgl)->corner.easting = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(ce_spin) );
581 (*vgl)->corner.northing = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(cn_spin) );
582 (*vgl)->mpp_easting = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(xspin) );
583 (*vgl)->mpp_northing = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(yspin) );
584 if ( (!(*vgl)->image) || strcmp( (*vgl)->image, vik_file_entry_get_filename(VIK_FILE_ENTRY(imageentry)) ) != 0 )
585 {
586 georef_layer_set_image ( *vgl, vik_file_entry_get_filename(VIK_FILE_ENTRY(imageentry)) );
fd22ce3e 587 georef_layer_load_image ( *vgl, VIK_VIEWPORT(vp), FALSE );
50a14534
EB
588 }
589
590 gtk_widget_destroy ( GTK_WIDGET(dialog) );
591 return TRUE;
592 }
593 gtk_widget_destroy ( GTK_WIDGET(dialog) );
594 return FALSE;
595}
596
597static void georef_layer_zoom_to_fit ( gpointer vgl_vlp[2] )
598{
599 vik_viewport_set_xmpp ( vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vgl_vlp[1])), VIK_GEOREF_LAYER(vgl_vlp[0])->mpp_easting );
600 vik_viewport_set_ympp ( vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vgl_vlp[1])), VIK_GEOREF_LAYER(vgl_vlp[0])->mpp_northing );
601 vik_layers_panel_emit_update ( VIK_LAYERS_PANEL(vgl_vlp[1]) );
602}
603
604static void georef_layer_goto_center ( gpointer vgl_vlp[2] )
605{
606 VikGeorefLayer *vgl = VIK_GEOREF_LAYER ( vgl_vlp[0] );
607 VikViewport *vp = vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vgl_vlp[1]));
608 struct UTM utm;
609 VikCoord coord;
610
611 vik_coord_to_utm ( vik_viewport_get_center ( vp ), &utm );
612
613 utm.easting = vgl->corner.easting + (vgl->width * vgl->mpp_easting / 2); /* only an approximation */
614 utm.northing = vgl->corner.northing - (vgl->height * vgl->mpp_northing / 2);
615
616 vik_coord_load_from_utm ( &coord, vik_viewport_get_coord_mode ( vp ), &utm );
617 vik_viewport_set_center_coord ( vp, &coord );
618
619 vik_layers_panel_emit_update ( VIK_LAYERS_PANEL(vgl_vlp[1]) );
620}
621
622static void georef_layer_add_menu_items ( VikGeorefLayer *vgl, GtkMenu *menu, gpointer vlp )
623{
624 static gpointer pass_along[2];
625 GtkWidget *item;
626 pass_along[0] = vgl;
627 pass_along[1] = vlp;
628
629 item = gtk_menu_item_new();
630 gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
631 gtk_widget_show ( item );
632
d6de71f9
RN
633 /* Now with icons */
634 item = gtk_image_menu_item_new_with_mnemonic ( _("_Zoom to Fit Map") );
635 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ZOOM_FIT, GTK_ICON_SIZE_MENU) );
50a14534
EB
636 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(georef_layer_zoom_to_fit), pass_along );
637 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
638 gtk_widget_show ( item );
639
d6de71f9
RN
640 item = gtk_image_menu_item_new_with_mnemonic ( _("_Goto Map Center") );
641 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_MENU) );
50a14534
EB
642 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(georef_layer_goto_center), pass_along );
643 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
644 gtk_widget_show ( item );
645
d6de71f9
RN
646 item = gtk_image_menu_item_new_with_mnemonic ( _("_Export to World File") );
647 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_HARDDISK, GTK_ICON_SIZE_MENU) );
50a14534
EB
648 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(georef_layer_export_params), pass_along );
649 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
650 gtk_widget_show ( item );
651}
652
941aa6e9
AF
653
654static gpointer georef_layer_move_create ( VikWindow *vw, VikViewport *vvp)
655{
656 return vvp;
657}
658
50a14534
EB
659static gboolean georef_layer_move_release ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp )
660{
941aa6e9
AF
661 if (!vgl || vgl->vl.type != VIK_LAYER_GEOREF)
662 return FALSE;
663
50a14534
EB
664 if ( vgl->click_x != -1 )
665 {
666 vgl->corner.easting += (event->x - vgl->click_x) * vik_viewport_get_xmpp (vvp);
667 vgl->corner.northing -= (event->y - vgl->click_y) * vik_viewport_get_ympp (vvp);
da121f9b 668 vik_layer_emit_update ( VIK_LAYER(vgl) );
50a14534
EB
669 return TRUE;
670 }
671 return FALSE; /* I didn't move anything on this layer! */
672}
673
941aa6e9
AF
674static gpointer georef_layer_zoom_create ( VikWindow *vw, VikViewport *vvp)
675{
676 return vvp;
677}
678
50a14534
EB
679static gboolean georef_layer_zoom_press ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp )
680{
941aa6e9
AF
681 if (!vgl || vgl->vl.type != VIK_LAYER_GEOREF)
682 return FALSE;
50a14534
EB
683 if ( event->button == 1 )
684 {
685 if ( vgl->mpp_easting < (VIK_VIEWPORT_MAX_ZOOM / 1.05) && vgl->mpp_northing < (VIK_VIEWPORT_MAX_ZOOM / 1.05) )
686 {
687 vgl->mpp_easting *= 1.01;
688 vgl->mpp_northing *= 1.01;
689 }
690 }
691 else
692 {
693 if ( vgl->mpp_easting > (VIK_VIEWPORT_MIN_ZOOM * 1.05) && vgl->mpp_northing > (VIK_VIEWPORT_MIN_ZOOM * 1.05) )
694 {
695 vgl->mpp_easting /= 1.01;
696 vgl->mpp_northing /= 1.01;
697 }
698 }
699 vik_viewport_set_xmpp ( vvp, vgl->mpp_easting );
700 vik_viewport_set_ympp ( vvp, vgl->mpp_northing );
da121f9b 701 vik_layer_emit_update ( VIK_LAYER(vgl) );
50a14534
EB
702 return TRUE;
703}
704
705static gboolean georef_layer_move_press ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp )
706{
941aa6e9
AF
707 if (!vgl || vgl->vl.type != VIK_LAYER_GEOREF)
708 return FALSE;
50a14534
EB
709 vgl->click_x = event->x;
710 vgl->click_y = event->y;
711 return TRUE;
712}