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