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