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