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