2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
4 * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
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.
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.
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
28 #include <glib/gstdio.h>
29 #include <glib/gi18n.h>
34 #include "icons/icons.h"
36 static VikLayerParamData image_default ( void )
38 VikLayerParamData data;
39 data.s = g_strdup ("");
44 VikLayerParam georef_layer_params[] = {
45 { VIK_LAYER_GEOREF, "image", VIK_LAYER_PARAM_STRING, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL, NULL, NULL },
46 { VIK_LAYER_GEOREF, "corner_easting", VIK_LAYER_PARAM_DOUBLE, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL, NULL, NULL },
47 { VIK_LAYER_GEOREF, "corner_northing", VIK_LAYER_PARAM_DOUBLE, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL, NULL, NULL },
48 { VIK_LAYER_GEOREF, "mpp_easting", VIK_LAYER_PARAM_DOUBLE, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL, NULL, NULL },
49 { VIK_LAYER_GEOREF, "mpp_northing", VIK_LAYER_PARAM_DOUBLE, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL, NULL, NULL },
52 enum { PARAM_IMAGE = 0, PARAM_CE, PARAM_CN, PARAM_ME, PARAM_MN, NUM_PARAMS };
54 static const gchar* georef_layer_tooltip ( VikGeorefLayer *vgl );
55 static void georef_layer_marshall( VikGeorefLayer *vgl, guint8 **data, gint *len );
56 static VikGeorefLayer *georef_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp );
57 static gboolean georef_layer_set_param ( VikGeorefLayer *vgl, guint16 id, VikLayerParamData data, VikViewport *vp, gboolean is_file_operation );
58 static VikLayerParamData georef_layer_get_param ( VikGeorefLayer *vgl, guint16 id, gboolean is_file_operation );
59 static VikGeorefLayer *georef_layer_new ( VikViewport *vvp );
60 static VikGeorefLayer *georef_layer_create ( VikViewport *vp );
61 static void georef_layer_free ( VikGeorefLayer *vgl );
62 static gboolean georef_layer_properties ( VikGeorefLayer *vgl, gpointer vp );
63 static void georef_layer_draw ( VikGeorefLayer *vgl, VikViewport *vp );
64 static void georef_layer_add_menu_items ( VikGeorefLayer *vgl, GtkMenu *menu, gpointer vlp );
65 static void georef_layer_set_image ( VikGeorefLayer *vgl, const gchar *image );
66 static gboolean georef_layer_dialog ( VikGeorefLayer **vgl, gpointer vp, GtkWindow *w );
67 static void georef_layer_load_image ( VikGeorefLayer *vgl, VikViewport *vp, gboolean from_file );
70 static gpointer georef_layer_move_create ( VikWindow *vw, VikViewport *vvp);
71 static gboolean georef_layer_move_release ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp );
72 static gboolean georef_layer_move_press ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp );
73 static gpointer georef_layer_zoom_create ( VikWindow *vw, VikViewport *vvp);
74 static gboolean georef_layer_zoom_press ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp );
76 // See comment in viktrwlayer.c for advice on values used
77 static VikToolInterface georef_tools[] = {
78 { { "GeorefMoveMap", "vik-icon-Georef Move Map", N_("_Georef Move Map"), NULL, N_("Georef Move Map"), 0 },
79 (VikToolConstructorFunc) georef_layer_move_create, NULL, NULL, NULL,
80 (VikToolMouseFunc) georef_layer_move_press, NULL, (VikToolMouseFunc) georef_layer_move_release,
81 (VikToolKeyFunc) NULL,
83 GDK_CURSOR_IS_PIXMAP, &cursor_geomove_pixbuf },
85 { { "GeorefZoomTool", "vik-icon-Georef Zoom Tool", N_("Georef Z_oom Tool"), NULL, N_("Georef Zoom Tool"), 0 },
86 (VikToolConstructorFunc) georef_layer_zoom_create, NULL, NULL, NULL,
87 (VikToolMouseFunc) georef_layer_zoom_press, NULL, NULL,
88 (VikToolKeyFunc) NULL,
90 GDK_CURSOR_IS_PIXMAP, &cursor_geozoom_pixbuf },
93 VikLayerInterface vik_georef_layer_interface = {
97 &vikgeoreflayer_pixbuf, /*icon */
100 sizeof(georef_tools) / sizeof(VikToolInterface),
109 (VikLayerFuncCreate) georef_layer_create,
110 (VikLayerFuncRealize) NULL,
111 (VikLayerFuncPostRead) georef_layer_load_image,
112 (VikLayerFuncFree) georef_layer_free,
114 (VikLayerFuncProperties) georef_layer_properties,
115 (VikLayerFuncDraw) georef_layer_draw,
116 (VikLayerFuncChangeCoordMode) NULL,
118 (VikLayerFuncSetMenuItemsSelection) NULL,
119 (VikLayerFuncGetMenuItemsSelection) NULL,
121 (VikLayerFuncAddMenuItems) georef_layer_add_menu_items,
122 (VikLayerFuncSublayerAddMenuItems) NULL,
124 (VikLayerFuncSublayerRenameRequest) NULL,
125 (VikLayerFuncSublayerToggleVisible) NULL,
126 (VikLayerFuncSublayerTooltip) NULL,
127 (VikLayerFuncLayerTooltip) georef_layer_tooltip,
128 (VikLayerFuncLayerSelected) NULL,
130 (VikLayerFuncMarshall) georef_layer_marshall,
131 (VikLayerFuncUnmarshall) georef_layer_unmarshall,
133 (VikLayerFuncSetParam) georef_layer_set_param,
134 (VikLayerFuncGetParam) georef_layer_get_param,
136 (VikLayerFuncReadFileData) NULL,
137 (VikLayerFuncWriteFileData) NULL,
139 (VikLayerFuncDeleteItem) NULL,
140 (VikLayerFuncCutItem) NULL,
141 (VikLayerFuncCopyItem) NULL,
142 (VikLayerFuncPasteItem) NULL,
143 (VikLayerFuncFreeCopiedItem) NULL,
144 (VikLayerFuncDragDropRequest) NULL,
146 (VikLayerFuncSelectClick) NULL,
147 (VikLayerFuncSelectMove) NULL,
148 (VikLayerFuncSelectRelease) NULL,
149 (VikLayerFuncSelectedViewportMenu) NULL,
152 struct _VikGeorefLayer {
157 gdouble mpp_easting, mpp_northing;
161 guint32 scaled_width, scaled_height;
163 gint click_x, click_y;
168 GType vik_georef_layer_get_type ()
170 static GType vgl_type = 0;
174 static const GTypeInfo vgl_info =
176 sizeof (VikGeorefLayerClass),
177 NULL, /* base_init */
178 NULL, /* base_finalize */
179 NULL, /* class init */
180 NULL, /* class_finalize */
181 NULL, /* class_data */
182 sizeof (VikGeorefLayer),
184 NULL /* instance init */
186 vgl_type = g_type_register_static ( VIK_LAYER_TYPE, "VikGeorefLayer", &vgl_info, 0 );
192 static const gchar* georef_layer_tooltip ( VikGeorefLayer *vgl )
197 static void georef_layer_marshall( VikGeorefLayer *vgl, guint8 **data, gint *len )
199 vik_layer_marshall_params ( VIK_LAYER(vgl), data, len );
202 static VikGeorefLayer *georef_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp )
204 VikGeorefLayer *rv = georef_layer_new ( vvp );
205 vik_layer_unmarshall_params ( VIK_LAYER(rv), data, len, vvp );
207 georef_layer_load_image ( rv, vvp, TRUE );
212 static gboolean georef_layer_set_param ( VikGeorefLayer *vgl, guint16 id, VikLayerParamData data, VikViewport *vp, gboolean is_file_operation )
216 case PARAM_IMAGE: georef_layer_set_image ( vgl, data.s ); break;
217 case PARAM_CN: vgl->corner.northing = data.d; break;
218 case PARAM_CE: vgl->corner.easting = data.d; break;
219 case PARAM_MN: vgl->mpp_northing = data.d; break;
220 case PARAM_ME: vgl->mpp_easting = data.d; break;
225 static VikLayerParamData georef_layer_get_param ( VikGeorefLayer *vgl, guint16 id, gboolean is_file_operation )
227 VikLayerParamData rv;
230 case PARAM_IMAGE: rv.s = vgl->image ? vgl->image : ""; break;
231 case PARAM_CN: rv.d = vgl->corner.northing; break;
232 case PARAM_CE: rv.d = vgl->corner.easting; break;
233 case PARAM_MN: rv.d = vgl->mpp_northing; break;
234 case PARAM_ME: rv.d = vgl->mpp_easting; break;
239 static VikGeorefLayer *georef_layer_new ( VikViewport *vvp )
241 VikGeorefLayer *vgl = VIK_GEOREF_LAYER ( g_object_new ( VIK_GEOREF_LAYER_TYPE, NULL ) );
242 vik_layer_set_type ( VIK_LAYER(vgl), VIK_LAYER_GEOREF );
244 // Since GeoRef layer doesn't use uibuilder
245 // initializing this way won't do anything yet..
246 vik_layer_set_defaults ( VIK_LAYER(vgl), vvp );
248 // Make these defaults based on the current view
249 vgl->mpp_northing = vik_viewport_get_ympp ( vvp );
250 vgl->mpp_easting = vik_viewport_get_xmpp ( vvp );
251 vik_coord_to_utm ( vik_viewport_get_center ( vvp ), &(vgl->corner) );
258 vgl->scaled_width = 0;
259 vgl->scaled_height = 0;
263 static void georef_layer_draw ( VikGeorefLayer *vgl, VikViewport *vp )
265 if ( vik_viewport_get_drawmode(vp) != VIK_VIEWPORT_DRAWMODE_UTM )
270 struct UTM utm_middle;
271 gdouble xmpp = vik_viewport_get_xmpp(vp), ympp = vik_viewport_get_ympp(vp);
272 GdkPixbuf *pixbuf = vgl->pixbuf;
273 guint layer_width = vgl->width;
274 guint layer_height = vgl->height;
276 vik_coord_to_utm ( vik_viewport_get_center ( vp ), &utm_middle );
278 guint width = vik_viewport_get_width(vp), height = vik_viewport_get_height(vp);
280 vgl->corner.zone = utm_middle.zone;
281 vgl->corner.letter = utm_middle.letter;
282 VikCoord corner_coord;
283 vik_coord_load_from_utm ( &corner_coord, vik_viewport_get_coord_mode(vp), &(vgl->corner) );
284 vik_viewport_coord_to_screen ( vp, &corner_coord, &x, &y );
286 /* mark to scale the pixbuf if it doesn't match our dimensions */
287 gboolean scale = FALSE;
288 if ( xmpp != vgl->mpp_easting || ympp != vgl->mpp_northing )
291 layer_width = round(vgl->width * vgl->mpp_easting / xmpp);
292 layer_height = round(vgl->height * vgl->mpp_northing / ympp);
295 // If image not in viewport bounds - no need to draw it (or bother with any scaling)
296 if ( (x < 0 || x < width) && (y < 0 || y < height) && x+layer_width > 0 && y+layer_height > 0 ) {
300 /* rescale if necessary */
301 if (layer_width == vgl->scaled_width && layer_height == vgl->scaled_height && vgl->scaled != NULL)
302 pixbuf = vgl->scaled;
305 pixbuf = gdk_pixbuf_scale_simple(
312 if (vgl->scaled != NULL)
313 g_object_unref(vgl->scaled);
315 vgl->scaled = pixbuf;
316 vgl->scaled_width = layer_width;
317 vgl->scaled_height = layer_height;
320 vik_viewport_draw_pixbuf ( vp, pixbuf, 0, 0, x, y, layer_width, layer_height ); /* todo: draw only what we need to. */
325 static void georef_layer_free ( VikGeorefLayer *vgl )
327 if ( vgl->image != NULL )
328 g_free ( vgl->image );
329 if ( vgl->scaled != NULL )
330 g_object_unref ( vgl->scaled );
333 static VikGeorefLayer *georef_layer_create ( VikViewport *vp )
335 return georef_layer_new ( vp );
338 static gboolean georef_layer_properties ( VikGeorefLayer *vgl, gpointer vp )
340 return georef_layer_dialog ( &vgl, vp, VIK_GTK_WINDOW_FROM_WIDGET(vp) );
343 static void georef_layer_load_image ( VikGeorefLayer *vgl, VikViewport *vp, gboolean from_file )
346 if ( vgl->image == NULL )
350 g_object_unref ( G_OBJECT(vgl->pixbuf) );
353 g_object_unref ( G_OBJECT(vgl->scaled) );
357 vgl->pixbuf = gdk_pixbuf_new_from_file ( vgl->image, &gx );
362 a_dialog_error_msg_extra ( VIK_GTK_WINDOW_FROM_WIDGET(vp), _("Couldn't open image file: %s"), gx->message );
367 vgl->width = gdk_pixbuf_get_width ( vgl->pixbuf );
368 vgl->height = gdk_pixbuf_get_height ( vgl->pixbuf );
373 if ( vik_viewport_get_drawmode(vp) != VIK_VIEWPORT_DRAWMODE_UTM )
375 a_dialog_warning_msg ( VIK_GTK_WINDOW_FROM_WIDGET(vp),
376 _("GeoRef map cannot be displayed in the current drawmode.\nSelect \"UTM Mode\" from View menu to view it.") );
379 /* should find length and width here too */
382 static void georef_layer_set_image ( VikGeorefLayer *vgl, const gchar *image )
385 g_free ( vgl->image );
388 g_object_unref ( vgl->scaled );
393 vgl->image = g_strdup ( image );
396 static gboolean world_file_read_line ( gchar *buffer, gint size, FILE *f, GtkWidget *widget, gboolean use_value )
398 if (!fgets ( buffer, 1024, f ))
400 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_WIDGET(widget), _("Unexpected end of file reading World file.") );
408 gdouble val = g_strtod ( buffer, NULL );
409 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(widget), val > 0 ? val : -val );
414 static void georef_layer_dialog_load ( GtkWidget *pass_along[4] )
416 GtkWidget *file_selector = gtk_file_chooser_dialog_new (_("Choose World file"),
418 GTK_FILE_CHOOSER_ACTION_OPEN,
419 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
420 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
423 if ( gtk_dialog_run ( GTK_DIALOG ( file_selector ) ) == GTK_RESPONSE_ACCEPT )
425 FILE *f = g_fopen ( gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER(file_selector) ), "r" );
426 gtk_widget_destroy ( file_selector );
429 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_WIDGET(pass_along[0]), _("The World file you requested could not be opened for reading.") );
434 gchar *buffer = g_malloc ( 1024 * sizeof(gchar) );
435 if ( world_file_read_line ( buffer, 1024, f, pass_along[0], TRUE ) && world_file_read_line ( buffer, 1024, f, pass_along[0], FALSE)
436 && world_file_read_line ( buffer, 1024, f, pass_along[0], FALSE ) && world_file_read_line ( buffer, 1024, f, pass_along[1], TRUE)
437 && world_file_read_line ( buffer, 1024, f, pass_along[2], TRUE ) && world_file_read_line ( buffer, 1024, f, pass_along[3], TRUE ) )
446 gtk_widget_destroy ( file_selector );
449 file selection dialog
450 file opener for reading, if NULL, send error_msg ( VIK_GTK_WINDOW_FROM_WIDGET(pass_along[0]) )
451 does that catch directories too?
452 read lines -- if not enough lines, give error.
453 if anything outside, give error. define range with #define CONSTANTS
454 put 'em in thar widgets, and that's it.
458 static void georef_layer_export_params ( gpointer *pass_along[2] )
460 VikGeorefLayer *vgl = VIK_GEOREF_LAYER(pass_along[0]);
461 GtkWidget *file_selector = gtk_file_chooser_dialog_new (_("Choose World file"),
463 GTK_FILE_CHOOSER_ACTION_SAVE,
464 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
465 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
467 if ( gtk_dialog_run ( GTK_DIALOG ( file_selector ) ) == GTK_RESPONSE_ACCEPT )
469 FILE *f = g_fopen ( gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER(file_selector) ), "w" );
471 gtk_widget_destroy ( file_selector );
474 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_WIDGET(pass_along[0]), _("The file you requested could not be opened for writing.") );
479 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 );
485 gtk_widget_destroy ( file_selector );
488 /* returns TRUE if OK was pressed. */
489 static gboolean georef_layer_dialog ( VikGeorefLayer **vgl, gpointer vp, GtkWindow *w )
491 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Layer Properties"),
493 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
499 /* Default to reject as user really needs to specify map file first */
500 gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_REJECT );
501 GtkWidget *response_w = NULL;
502 #if GTK_CHECK_VERSION (2, 20, 0)
503 response_w = gtk_dialog_get_widget_for_response ( GTK_DIALOG(dialog), GTK_RESPONSE_REJECT );
505 GtkWidget *table, *wfp_hbox, *wfp_label, *wfp_button, *ce_label, *ce_spin, *cn_label, *cn_spin, *xlabel, *xspin, *ylabel, *yspin, *imagelabel, *imageentry;
507 GtkWidget *pass_along[4];
509 table = gtk_table_new ( 6, 2, FALSE );
510 gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), table, TRUE, TRUE, 0 );
512 wfp_hbox = gtk_hbox_new ( FALSE, 0 );
513 wfp_label = gtk_label_new ( _("World File Parameters:") );
514 wfp_button = gtk_button_new_with_label ( _("Load From File...") );
516 gtk_box_pack_start ( GTK_BOX(wfp_hbox), wfp_label, TRUE, TRUE, 0 );
517 gtk_box_pack_start ( GTK_BOX(wfp_hbox), wfp_button, FALSE, FALSE, 3 );
519 ce_label = gtk_label_new ( _("Corner pixel easting:") );
520 ce_spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, 0.0, 1500000.0, 1, 5, 0 ), 1, 4 );
521 gtk_widget_set_tooltip_text ( GTK_WIDGET(ce_spin), _("the UTM \"easting\" value of the upper-left corner pixel of the map") );
523 cn_label = gtk_label_new ( _("Corner pixel northing:") );
524 cn_spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, 0.0, 9000000.0, 1, 5, 0 ), 1, 4 );
525 gtk_widget_set_tooltip_text ( GTK_WIDGET(cn_spin), _("the UTM \"northing\" value of the upper-left corner pixel of the map") );
527 xlabel = gtk_label_new ( _("X (easting) scale (mpp): "));
528 ylabel = gtk_label_new ( _("Y (northing) scale (mpp): "));
530 xspin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, VIK_VIEWPORT_MIN_ZOOM, VIK_VIEWPORT_MAX_ZOOM, 1, 5, 0 ), 1, 8 );
531 gtk_widget_set_tooltip_text ( GTK_WIDGET(xspin), _("the scale of the map in the X direction (meters per pixel)") );
532 yspin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, VIK_VIEWPORT_MIN_ZOOM, VIK_VIEWPORT_MAX_ZOOM, 1, 5, 0 ), 1, 8 );
533 gtk_widget_set_tooltip_text ( GTK_WIDGET(yspin), _("the scale of the map in the Y direction (meters per pixel)") );
535 imagelabel = gtk_label_new ( _("Map Image:") );
536 imageentry = vik_file_entry_new (GTK_FILE_CHOOSER_ACTION_OPEN);
540 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(ce_spin), (*vgl)->corner.easting );
541 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(cn_spin), (*vgl)->corner.northing );
542 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(xspin), (*vgl)->mpp_easting );
543 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(yspin), (*vgl)->mpp_northing );
545 vik_file_entry_set_filename ( VIK_FILE_ENTRY(imageentry), (*vgl)->image );
549 VikCoord corner_coord;
551 vik_viewport_screen_to_coord ( VIK_VIEWPORT(vp), 0, 0, &corner_coord );
552 vik_coord_to_utm ( &corner_coord, &utm );
553 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(ce_spin), utm.easting );
554 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(cn_spin), utm.northing );
555 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(xspin), vik_viewport_get_xmpp ( VIK_VIEWPORT(vp) ) );
556 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(yspin), vik_viewport_get_ympp ( VIK_VIEWPORT(vp) ) );
559 gtk_table_attach_defaults ( GTK_TABLE(table), imagelabel, 0, 1, 0, 1 );
560 gtk_table_attach_defaults ( GTK_TABLE(table), imageentry, 1, 2, 0, 1 );
561 gtk_table_attach_defaults ( GTK_TABLE(table), wfp_hbox, 0, 2, 1, 2 );
562 gtk_table_attach_defaults ( GTK_TABLE(table), xlabel, 0, 1, 2, 3 );
563 gtk_table_attach_defaults ( GTK_TABLE(table), xspin, 1, 2, 2, 3 );
564 gtk_table_attach_defaults ( GTK_TABLE(table), ylabel, 0, 1, 3, 4 );
565 gtk_table_attach_defaults ( GTK_TABLE(table), yspin, 1, 2, 3, 4 );
566 gtk_table_attach_defaults ( GTK_TABLE(table), ce_label, 0, 1, 4, 5 );
567 gtk_table_attach_defaults ( GTK_TABLE(table), ce_spin, 1, 2, 4, 5 );
568 gtk_table_attach_defaults ( GTK_TABLE(table), cn_label, 0, 1, 5, 6 );
569 gtk_table_attach_defaults ( GTK_TABLE(table), cn_spin, 1, 2, 5, 6 );
571 pass_along[0] = xspin;
572 pass_along[1] = yspin;
573 pass_along[2] = ce_spin;
574 pass_along[3] = cn_spin;
575 g_signal_connect_swapped ( G_OBJECT(wfp_button), "clicked", G_CALLBACK(georef_layer_dialog_load), pass_along );
578 gtk_widget_grab_focus ( response_w );
580 gtk_widget_show_all ( table );
582 if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
586 *vgl = georef_layer_new ( VIK_VIEWPORT(vp) );
587 vik_layer_rename ( VIK_LAYER(*vgl), vik_georef_layer_interface.name );
589 (*vgl)->corner.easting = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(ce_spin) );
590 (*vgl)->corner.northing = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(cn_spin) );
591 (*vgl)->mpp_easting = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(xspin) );
592 (*vgl)->mpp_northing = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(yspin) );
593 if ( (!(*vgl)->image) || strcmp( (*vgl)->image, vik_file_entry_get_filename(VIK_FILE_ENTRY(imageentry)) ) != 0 )
595 georef_layer_set_image ( *vgl, vik_file_entry_get_filename(VIK_FILE_ENTRY(imageentry)) );
596 georef_layer_load_image ( *vgl, VIK_VIEWPORT(vp), FALSE );
599 gtk_widget_destroy ( GTK_WIDGET(dialog) );
602 gtk_widget_destroy ( GTK_WIDGET(dialog) );
606 static void georef_layer_zoom_to_fit ( gpointer vgl_vlp[2] )
608 vik_viewport_set_xmpp ( vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vgl_vlp[1])), VIK_GEOREF_LAYER(vgl_vlp[0])->mpp_easting );
609 vik_viewport_set_ympp ( vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vgl_vlp[1])), VIK_GEOREF_LAYER(vgl_vlp[0])->mpp_northing );
610 vik_layers_panel_emit_update ( VIK_LAYERS_PANEL(vgl_vlp[1]) );
613 static void georef_layer_goto_center ( gpointer vgl_vlp[2] )
615 VikGeorefLayer *vgl = VIK_GEOREF_LAYER ( vgl_vlp[0] );
616 VikViewport *vp = vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vgl_vlp[1]));
620 vik_coord_to_utm ( vik_viewport_get_center ( vp ), &utm );
622 utm.easting = vgl->corner.easting + (vgl->width * vgl->mpp_easting / 2); /* only an approximation */
623 utm.northing = vgl->corner.northing - (vgl->height * vgl->mpp_northing / 2);
625 vik_coord_load_from_utm ( &coord, vik_viewport_get_coord_mode ( vp ), &utm );
626 vik_viewport_set_center_coord ( vp, &coord );
628 vik_layers_panel_emit_update ( VIK_LAYERS_PANEL(vgl_vlp[1]) );
631 static void georef_layer_add_menu_items ( VikGeorefLayer *vgl, GtkMenu *menu, gpointer vlp )
633 static gpointer pass_along[2];
638 item = gtk_menu_item_new();
639 gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
640 gtk_widget_show ( item );
643 item = gtk_image_menu_item_new_with_mnemonic ( _("_Zoom to Fit Map") );
644 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ZOOM_FIT, GTK_ICON_SIZE_MENU) );
645 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(georef_layer_zoom_to_fit), pass_along );
646 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
647 gtk_widget_show ( item );
649 item = gtk_image_menu_item_new_with_mnemonic ( _("_Goto Map Center") );
650 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_MENU) );
651 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(georef_layer_goto_center), pass_along );
652 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
653 gtk_widget_show ( item );
655 item = gtk_image_menu_item_new_with_mnemonic ( _("_Export to World File") );
656 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_HARDDISK, GTK_ICON_SIZE_MENU) );
657 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(georef_layer_export_params), pass_along );
658 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
659 gtk_widget_show ( item );
663 static gpointer georef_layer_move_create ( VikWindow *vw, VikViewport *vvp)
668 static gboolean georef_layer_move_release ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp )
670 if (!vgl || vgl->vl.type != VIK_LAYER_GEOREF)
673 if ( vgl->click_x != -1 )
675 vgl->corner.easting += (event->x - vgl->click_x) * vik_viewport_get_xmpp (vvp);
676 vgl->corner.northing -= (event->y - vgl->click_y) * vik_viewport_get_ympp (vvp);
677 vik_layer_emit_update ( VIK_LAYER(vgl) );
680 return FALSE; /* I didn't move anything on this layer! */
683 static gpointer georef_layer_zoom_create ( VikWindow *vw, VikViewport *vvp)
688 static gboolean georef_layer_zoom_press ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp )
690 if (!vgl || vgl->vl.type != VIK_LAYER_GEOREF)
692 if ( event->button == 1 )
694 if ( vgl->mpp_easting < (VIK_VIEWPORT_MAX_ZOOM / 1.05) && vgl->mpp_northing < (VIK_VIEWPORT_MAX_ZOOM / 1.05) )
696 vgl->mpp_easting *= 1.01;
697 vgl->mpp_northing *= 1.01;
702 if ( vgl->mpp_easting > (VIK_VIEWPORT_MIN_ZOOM * 1.05) && vgl->mpp_northing > (VIK_VIEWPORT_MIN_ZOOM * 1.05) )
704 vgl->mpp_easting /= 1.01;
705 vgl->mpp_northing /= 1.01;
708 vik_viewport_set_xmpp ( vvp, vgl->mpp_easting );
709 vik_viewport_set_ympp ( vvp, vgl->mpp_northing );
710 vik_layer_emit_update ( VIK_LAYER(vgl) );
714 static gboolean georef_layer_move_press ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp )
716 if (!vgl || vgl->vl.type != VIK_LAYER_GEOREF)
718 vgl->click_x = event->x;
719 vgl->click_y = event->y;