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;
231 gboolean set = FALSE;
232 if ( is_file_operation ) {
233 if ( a_vik_get_file_ref_format() == VIK_FILE_REF_FORMAT_RELATIVE ) {
234 gchar *cwd = g_get_current_dir();
236 rv.s = file_GetRelativeFilename ( cwd, vgl->image );
237 if ( !rv.s ) rv.s = "";
243 rv.s = vgl->image ? vgl->image : "";
246 case PARAM_CN: rv.d = vgl->corner.northing; break;
247 case PARAM_CE: rv.d = vgl->corner.easting; break;
248 case PARAM_MN: rv.d = vgl->mpp_northing; break;
249 case PARAM_ME: rv.d = vgl->mpp_easting; break;
254 static VikGeorefLayer *georef_layer_new ( VikViewport *vvp )
256 VikGeorefLayer *vgl = VIK_GEOREF_LAYER ( g_object_new ( VIK_GEOREF_LAYER_TYPE, NULL ) );
257 vik_layer_set_type ( VIK_LAYER(vgl), VIK_LAYER_GEOREF );
259 // Since GeoRef layer doesn't use uibuilder
260 // initializing this way won't do anything yet..
261 vik_layer_set_defaults ( VIK_LAYER(vgl), vvp );
263 // Make these defaults based on the current view
264 vgl->mpp_northing = vik_viewport_get_ympp ( vvp );
265 vgl->mpp_easting = vik_viewport_get_xmpp ( vvp );
266 vik_coord_to_utm ( vik_viewport_get_center ( vvp ), &(vgl->corner) );
273 vgl->scaled_width = 0;
274 vgl->scaled_height = 0;
278 static void georef_layer_draw ( VikGeorefLayer *vgl, VikViewport *vp )
280 if ( vik_viewport_get_drawmode(vp) != VIK_VIEWPORT_DRAWMODE_UTM )
285 struct UTM utm_middle;
286 gdouble xmpp = vik_viewport_get_xmpp(vp), ympp = vik_viewport_get_ympp(vp);
287 GdkPixbuf *pixbuf = vgl->pixbuf;
288 guint layer_width = vgl->width;
289 guint layer_height = vgl->height;
291 vik_coord_to_utm ( vik_viewport_get_center ( vp ), &utm_middle );
293 guint width = vik_viewport_get_width(vp), height = vik_viewport_get_height(vp);
295 vgl->corner.zone = utm_middle.zone;
296 vgl->corner.letter = utm_middle.letter;
297 VikCoord corner_coord;
298 vik_coord_load_from_utm ( &corner_coord, vik_viewport_get_coord_mode(vp), &(vgl->corner) );
299 vik_viewport_coord_to_screen ( vp, &corner_coord, &x, &y );
301 /* mark to scale the pixbuf if it doesn't match our dimensions */
302 gboolean scale = FALSE;
303 if ( xmpp != vgl->mpp_easting || ympp != vgl->mpp_northing )
306 layer_width = round(vgl->width * vgl->mpp_easting / xmpp);
307 layer_height = round(vgl->height * vgl->mpp_northing / ympp);
310 // If image not in viewport bounds - no need to draw it (or bother with any scaling)
311 if ( (x < 0 || x < width) && (y < 0 || y < height) && x+layer_width > 0 && y+layer_height > 0 ) {
315 /* rescale if necessary */
316 if (layer_width == vgl->scaled_width && layer_height == vgl->scaled_height && vgl->scaled != NULL)
317 pixbuf = vgl->scaled;
320 pixbuf = gdk_pixbuf_scale_simple(
327 if (vgl->scaled != NULL)
328 g_object_unref(vgl->scaled);
330 vgl->scaled = pixbuf;
331 vgl->scaled_width = layer_width;
332 vgl->scaled_height = layer_height;
335 vik_viewport_draw_pixbuf ( vp, pixbuf, 0, 0, x, y, layer_width, layer_height ); /* todo: draw only what we need to. */
340 static void georef_layer_free ( VikGeorefLayer *vgl )
342 if ( vgl->image != NULL )
343 g_free ( vgl->image );
344 if ( vgl->scaled != NULL )
345 g_object_unref ( vgl->scaled );
348 static VikGeorefLayer *georef_layer_create ( VikViewport *vp )
350 return georef_layer_new ( vp );
353 static gboolean georef_layer_properties ( VikGeorefLayer *vgl, gpointer vp )
355 return georef_layer_dialog ( &vgl, vp, VIK_GTK_WINDOW_FROM_WIDGET(vp) );
358 static void georef_layer_load_image ( VikGeorefLayer *vgl, VikViewport *vp, gboolean from_file )
361 if ( vgl->image == NULL )
365 g_object_unref ( G_OBJECT(vgl->pixbuf) );
368 g_object_unref ( G_OBJECT(vgl->scaled) );
372 vgl->pixbuf = gdk_pixbuf_new_from_file ( vgl->image, &gx );
377 a_dialog_error_msg_extra ( VIK_GTK_WINDOW_FROM_WIDGET(vp), _("Couldn't open image file: %s"), gx->message );
382 vgl->width = gdk_pixbuf_get_width ( vgl->pixbuf );
383 vgl->height = gdk_pixbuf_get_height ( vgl->pixbuf );
388 if ( vik_viewport_get_drawmode(vp) != VIK_VIEWPORT_DRAWMODE_UTM )
390 a_dialog_warning_msg ( VIK_GTK_WINDOW_FROM_WIDGET(vp),
391 _("GeoRef map cannot be displayed in the current drawmode.\nSelect \"UTM Mode\" from View menu to view it.") );
394 /* should find length and width here too */
397 static void georef_layer_set_image ( VikGeorefLayer *vgl, const gchar *image )
400 g_free ( vgl->image );
403 g_object_unref ( vgl->scaled );
408 vgl->image = g_strdup ( image );
411 static gboolean world_file_read_line ( gchar *buffer, gint size, FILE *f, GtkWidget *widget, gboolean use_value )
413 if (!fgets ( buffer, 1024, f ))
415 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_WIDGET(widget), _("Unexpected end of file reading World file.") );
423 gdouble val = g_strtod ( buffer, NULL );
424 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(widget), val > 0 ? val : -val );
429 static void georef_layer_dialog_load ( GtkWidget *pass_along[4] )
431 GtkWidget *file_selector = gtk_file_chooser_dialog_new (_("Choose World file"),
433 GTK_FILE_CHOOSER_ACTION_OPEN,
434 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
435 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
438 if ( gtk_dialog_run ( GTK_DIALOG ( file_selector ) ) == GTK_RESPONSE_ACCEPT )
440 FILE *f = g_fopen ( gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER(file_selector) ), "r" );
441 gtk_widget_destroy ( file_selector );
444 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_WIDGET(pass_along[0]), _("The World file you requested could not be opened for reading.") );
449 gchar *buffer = g_malloc ( 1024 * sizeof(gchar) );
450 if ( world_file_read_line ( buffer, 1024, f, pass_along[0], TRUE ) && world_file_read_line ( buffer, 1024, f, pass_along[0], FALSE)
451 && world_file_read_line ( buffer, 1024, f, pass_along[0], FALSE ) && world_file_read_line ( buffer, 1024, f, pass_along[1], TRUE)
452 && world_file_read_line ( buffer, 1024, f, pass_along[2], TRUE ) && world_file_read_line ( buffer, 1024, f, pass_along[3], TRUE ) )
461 gtk_widget_destroy ( file_selector );
464 file selection dialog
465 file opener for reading, if NULL, send error_msg ( VIK_GTK_WINDOW_FROM_WIDGET(pass_along[0]) )
466 does that catch directories too?
467 read lines -- if not enough lines, give error.
468 if anything outside, give error. define range with #define CONSTANTS
469 put 'em in thar widgets, and that's it.
473 static void georef_layer_export_params ( gpointer *pass_along[2] )
475 VikGeorefLayer *vgl = VIK_GEOREF_LAYER(pass_along[0]);
476 GtkWidget *file_selector = gtk_file_chooser_dialog_new (_("Choose World file"),
478 GTK_FILE_CHOOSER_ACTION_SAVE,
479 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
480 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
482 if ( gtk_dialog_run ( GTK_DIALOG ( file_selector ) ) == GTK_RESPONSE_ACCEPT )
484 FILE *f = g_fopen ( gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER(file_selector) ), "w" );
486 gtk_widget_destroy ( file_selector );
489 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_WIDGET(pass_along[0]), _("The file you requested could not be opened for writing.") );
494 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 );
500 gtk_widget_destroy ( file_selector );
503 /* returns TRUE if OK was pressed. */
504 static gboolean georef_layer_dialog ( VikGeorefLayer **vgl, gpointer vp, GtkWindow *w )
506 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Layer Properties"),
508 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
514 /* Default to reject as user really needs to specify map file first */
515 gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_REJECT );
516 GtkWidget *response_w = NULL;
517 #if GTK_CHECK_VERSION (2, 20, 0)
518 response_w = gtk_dialog_get_widget_for_response ( GTK_DIALOG(dialog), GTK_RESPONSE_REJECT );
520 GtkWidget *table, *wfp_hbox, *wfp_label, *wfp_button, *ce_label, *ce_spin, *cn_label, *cn_spin, *xlabel, *xspin, *ylabel, *yspin, *imagelabel, *imageentry;
522 GtkWidget *pass_along[4];
524 table = gtk_table_new ( 6, 2, FALSE );
525 gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), table, TRUE, TRUE, 0 );
527 wfp_hbox = gtk_hbox_new ( FALSE, 0 );
528 wfp_label = gtk_label_new ( _("World File Parameters:") );
529 wfp_button = gtk_button_new_with_label ( _("Load From File...") );
531 gtk_box_pack_start ( GTK_BOX(wfp_hbox), wfp_label, TRUE, TRUE, 0 );
532 gtk_box_pack_start ( GTK_BOX(wfp_hbox), wfp_button, FALSE, FALSE, 3 );
534 ce_label = gtk_label_new ( _("Corner pixel easting:") );
535 ce_spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, 0.0, 1500000.0, 1, 5, 0 ), 1, 4 );
536 gtk_widget_set_tooltip_text ( GTK_WIDGET(ce_spin), _("the UTM \"easting\" value of the upper-left corner pixel of the map") );
538 cn_label = gtk_label_new ( _("Corner pixel northing:") );
539 cn_spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, 0.0, 9000000.0, 1, 5, 0 ), 1, 4 );
540 gtk_widget_set_tooltip_text ( GTK_WIDGET(cn_spin), _("the UTM \"northing\" value of the upper-left corner pixel of the map") );
542 xlabel = gtk_label_new ( _("X (easting) scale (mpp): "));
543 ylabel = gtk_label_new ( _("Y (northing) scale (mpp): "));
545 xspin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, VIK_VIEWPORT_MIN_ZOOM, VIK_VIEWPORT_MAX_ZOOM, 1, 5, 0 ), 1, 8 );
546 gtk_widget_set_tooltip_text ( GTK_WIDGET(xspin), _("the scale of the map in the X direction (meters per pixel)") );
547 yspin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, VIK_VIEWPORT_MIN_ZOOM, VIK_VIEWPORT_MAX_ZOOM, 1, 5, 0 ), 1, 8 );
548 gtk_widget_set_tooltip_text ( GTK_WIDGET(yspin), _("the scale of the map in the Y direction (meters per pixel)") );
550 imagelabel = gtk_label_new ( _("Map Image:") );
551 imageentry = vik_file_entry_new (GTK_FILE_CHOOSER_ACTION_OPEN);
555 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(ce_spin), (*vgl)->corner.easting );
556 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(cn_spin), (*vgl)->corner.northing );
557 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(xspin), (*vgl)->mpp_easting );
558 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(yspin), (*vgl)->mpp_northing );
560 vik_file_entry_set_filename ( VIK_FILE_ENTRY(imageentry), (*vgl)->image );
564 VikCoord corner_coord;
566 vik_viewport_screen_to_coord ( VIK_VIEWPORT(vp), 0, 0, &corner_coord );
567 vik_coord_to_utm ( &corner_coord, &utm );
568 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(ce_spin), utm.easting );
569 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(cn_spin), utm.northing );
570 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(xspin), vik_viewport_get_xmpp ( VIK_VIEWPORT(vp) ) );
571 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(yspin), vik_viewport_get_ympp ( VIK_VIEWPORT(vp) ) );
574 gtk_table_attach_defaults ( GTK_TABLE(table), imagelabel, 0, 1, 0, 1 );
575 gtk_table_attach_defaults ( GTK_TABLE(table), imageentry, 1, 2, 0, 1 );
576 gtk_table_attach_defaults ( GTK_TABLE(table), wfp_hbox, 0, 2, 1, 2 );
577 gtk_table_attach_defaults ( GTK_TABLE(table), xlabel, 0, 1, 2, 3 );
578 gtk_table_attach_defaults ( GTK_TABLE(table), xspin, 1, 2, 2, 3 );
579 gtk_table_attach_defaults ( GTK_TABLE(table), ylabel, 0, 1, 3, 4 );
580 gtk_table_attach_defaults ( GTK_TABLE(table), yspin, 1, 2, 3, 4 );
581 gtk_table_attach_defaults ( GTK_TABLE(table), ce_label, 0, 1, 4, 5 );
582 gtk_table_attach_defaults ( GTK_TABLE(table), ce_spin, 1, 2, 4, 5 );
583 gtk_table_attach_defaults ( GTK_TABLE(table), cn_label, 0, 1, 5, 6 );
584 gtk_table_attach_defaults ( GTK_TABLE(table), cn_spin, 1, 2, 5, 6 );
586 pass_along[0] = xspin;
587 pass_along[1] = yspin;
588 pass_along[2] = ce_spin;
589 pass_along[3] = cn_spin;
590 g_signal_connect_swapped ( G_OBJECT(wfp_button), "clicked", G_CALLBACK(georef_layer_dialog_load), pass_along );
593 gtk_widget_grab_focus ( response_w );
595 gtk_widget_show_all ( table );
597 if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
601 *vgl = georef_layer_new ( VIK_VIEWPORT(vp) );
602 vik_layer_rename ( VIK_LAYER(*vgl), vik_georef_layer_interface.name );
604 (*vgl)->corner.easting = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(ce_spin) );
605 (*vgl)->corner.northing = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(cn_spin) );
606 (*vgl)->mpp_easting = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(xspin) );
607 (*vgl)->mpp_northing = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(yspin) );
608 if ( (!(*vgl)->image) || strcmp( (*vgl)->image, vik_file_entry_get_filename(VIK_FILE_ENTRY(imageentry)) ) != 0 )
610 georef_layer_set_image ( *vgl, vik_file_entry_get_filename(VIK_FILE_ENTRY(imageentry)) );
611 georef_layer_load_image ( *vgl, VIK_VIEWPORT(vp), FALSE );
614 gtk_widget_destroy ( GTK_WIDGET(dialog) );
617 gtk_widget_destroy ( GTK_WIDGET(dialog) );
621 static void georef_layer_zoom_to_fit ( gpointer vgl_vlp[2] )
623 vik_viewport_set_xmpp ( vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vgl_vlp[1])), VIK_GEOREF_LAYER(vgl_vlp[0])->mpp_easting );
624 vik_viewport_set_ympp ( vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vgl_vlp[1])), VIK_GEOREF_LAYER(vgl_vlp[0])->mpp_northing );
625 vik_layers_panel_emit_update ( VIK_LAYERS_PANEL(vgl_vlp[1]) );
628 static void georef_layer_goto_center ( gpointer vgl_vlp[2] )
630 VikGeorefLayer *vgl = VIK_GEOREF_LAYER ( vgl_vlp[0] );
631 VikViewport *vp = vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vgl_vlp[1]));
635 vik_coord_to_utm ( vik_viewport_get_center ( vp ), &utm );
637 utm.easting = vgl->corner.easting + (vgl->width * vgl->mpp_easting / 2); /* only an approximation */
638 utm.northing = vgl->corner.northing - (vgl->height * vgl->mpp_northing / 2);
640 vik_coord_load_from_utm ( &coord, vik_viewport_get_coord_mode ( vp ), &utm );
641 vik_viewport_set_center_coord ( vp, &coord );
643 vik_layers_panel_emit_update ( VIK_LAYERS_PANEL(vgl_vlp[1]) );
646 static void georef_layer_add_menu_items ( VikGeorefLayer *vgl, GtkMenu *menu, gpointer vlp )
648 static gpointer pass_along[2];
653 item = gtk_menu_item_new();
654 gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
655 gtk_widget_show ( item );
658 item = gtk_image_menu_item_new_with_mnemonic ( _("_Zoom to Fit Map") );
659 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ZOOM_FIT, GTK_ICON_SIZE_MENU) );
660 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(georef_layer_zoom_to_fit), pass_along );
661 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
662 gtk_widget_show ( item );
664 item = gtk_image_menu_item_new_with_mnemonic ( _("_Goto Map Center") );
665 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_MENU) );
666 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(georef_layer_goto_center), pass_along );
667 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
668 gtk_widget_show ( item );
670 item = gtk_image_menu_item_new_with_mnemonic ( _("_Export to World File") );
671 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_HARDDISK, GTK_ICON_SIZE_MENU) );
672 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(georef_layer_export_params), pass_along );
673 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
674 gtk_widget_show ( item );
678 static gpointer georef_layer_move_create ( VikWindow *vw, VikViewport *vvp)
683 static gboolean georef_layer_move_release ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp )
685 if (!vgl || vgl->vl.type != VIK_LAYER_GEOREF)
688 if ( vgl->click_x != -1 )
690 vgl->corner.easting += (event->x - vgl->click_x) * vik_viewport_get_xmpp (vvp);
691 vgl->corner.northing -= (event->y - vgl->click_y) * vik_viewport_get_ympp (vvp);
692 vik_layer_emit_update ( VIK_LAYER(vgl) );
695 return FALSE; /* I didn't move anything on this layer! */
698 static gpointer georef_layer_zoom_create ( VikWindow *vw, VikViewport *vvp)
703 static gboolean georef_layer_zoom_press ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp )
705 if (!vgl || vgl->vl.type != VIK_LAYER_GEOREF)
707 if ( event->button == 1 )
709 if ( vgl->mpp_easting < (VIK_VIEWPORT_MAX_ZOOM / 1.05) && vgl->mpp_northing < (VIK_VIEWPORT_MAX_ZOOM / 1.05) )
711 vgl->mpp_easting *= 1.01;
712 vgl->mpp_northing *= 1.01;
717 if ( vgl->mpp_easting > (VIK_VIEWPORT_MIN_ZOOM * 1.05) && vgl->mpp_northing > (VIK_VIEWPORT_MIN_ZOOM * 1.05) )
719 vgl->mpp_easting /= 1.01;
720 vgl->mpp_northing /= 1.01;
723 vik_viewport_set_xmpp ( vvp, vgl->mpp_easting );
724 vik_viewport_set_ympp ( vvp, vgl->mpp_northing );
725 vik_layer_emit_update ( VIK_LAYER(vgl) );
729 static gboolean georef_layer_move_press ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp )
731 if (!vgl || vgl->vl.type != VIK_LAYER_GEOREF)
733 vgl->click_x = event->x;
734 vgl->click_y = event->y;