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