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
29 #include <glib/gstdio.h>
30 #include <glib/gi18n.h>
35 #include "icons/icons.h"
37 static VikLayerParamData image_default ( void )
39 VikLayerParamData data;
40 data.s = g_strdup ("");
45 VikLayerParam georef_layer_params[] = {
46 { VIK_LAYER_GEOREF, "image", VIK_LAYER_PARAM_STRING, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL },
47 { VIK_LAYER_GEOREF, "corner_easting", VIK_LAYER_PARAM_DOUBLE, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL },
48 { VIK_LAYER_GEOREF, "corner_northing", VIK_LAYER_PARAM_DOUBLE, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL },
49 { VIK_LAYER_GEOREF, "mpp_easting", VIK_LAYER_PARAM_DOUBLE, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL },
50 { VIK_LAYER_GEOREF, "mpp_northing", VIK_LAYER_PARAM_DOUBLE, VIK_LAYER_NOT_IN_PROPERTIES, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL },
53 enum { PARAM_IMAGE = 0, PARAM_CE, PARAM_CN, PARAM_ME, PARAM_MN, NUM_PARAMS };
55 static const gchar* georef_layer_tooltip ( VikGeorefLayer *vgl );
56 static void georef_layer_marshall( VikGeorefLayer *vgl, guint8 **data, gint *len );
57 static VikGeorefLayer *georef_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp );
58 static gboolean georef_layer_set_param ( VikGeorefLayer *vgl, guint16 id, VikLayerParamData data, VikViewport *vp, gboolean is_file_operation );
59 static VikLayerParamData georef_layer_get_param ( VikGeorefLayer *vgl, guint16 id, gboolean is_file_operation );
60 static VikGeorefLayer *georef_layer_new ( VikViewport *vvp );
61 static VikGeorefLayer *georef_layer_create ( VikViewport *vp );
62 static void georef_layer_free ( VikGeorefLayer *vgl );
63 static gboolean georef_layer_properties ( VikGeorefLayer *vgl, gpointer vp );
64 static void georef_layer_draw ( VikGeorefLayer *vgl, VikViewport *vp );
65 static void georef_layer_add_menu_items ( VikGeorefLayer *vgl, GtkMenu *menu, gpointer vlp );
66 static void georef_layer_set_image ( VikGeorefLayer *vgl, const gchar *image );
67 static gboolean georef_layer_dialog ( VikGeorefLayer **vgl, gpointer vp, GtkWindow *w );
68 static void georef_layer_load_image ( VikGeorefLayer *vgl, VikViewport *vp, gboolean from_file );
71 static gpointer georef_layer_move_create ( VikWindow *vw, VikViewport *vvp);
72 static gboolean georef_layer_move_release ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp );
73 static gboolean georef_layer_move_press ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp );
74 static gpointer georef_layer_zoom_create ( VikWindow *vw, VikViewport *vvp);
75 static gboolean georef_layer_zoom_press ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp );
77 // See comment in viktrwlayer.c for advice on values used
78 static VikToolInterface georef_tools[] = {
79 { { "GeorefMoveMap", "vik-icon-Georef Move Map", N_("_Georef Move Map"), NULL, N_("Georef Move Map"), 0 },
80 (VikToolConstructorFunc) georef_layer_move_create, NULL, NULL, NULL,
81 (VikToolMouseFunc) georef_layer_move_press, NULL, (VikToolMouseFunc) georef_layer_move_release,
82 (VikToolKeyFunc) NULL,
84 GDK_CURSOR_IS_PIXMAP, &cursor_geomove_pixbuf },
86 { { "GeorefZoomTool", "vik-icon-Georef Zoom Tool", N_("Georef Z_oom Tool"), NULL, N_("Georef Zoom Tool"), 0 },
87 (VikToolConstructorFunc) georef_layer_zoom_create, NULL, NULL, NULL,
88 (VikToolMouseFunc) georef_layer_zoom_press, NULL, NULL,
89 (VikToolKeyFunc) NULL,
91 GDK_CURSOR_IS_PIXMAP, &cursor_geozoom_pixbuf },
94 VikLayerInterface vik_georef_layer_interface = {
98 &vikgeoreflayer_pixbuf, /*icon */
101 sizeof(georef_tools) / sizeof(VikToolInterface),
110 (VikLayerFuncCreate) georef_layer_create,
111 (VikLayerFuncRealize) NULL,
112 (VikLayerFuncPostRead) georef_layer_load_image,
113 (VikLayerFuncFree) georef_layer_free,
115 (VikLayerFuncProperties) georef_layer_properties,
116 (VikLayerFuncDraw) georef_layer_draw,
117 (VikLayerFuncChangeCoordMode) NULL,
119 (VikLayerFuncSetMenuItemsSelection) NULL,
120 (VikLayerFuncGetMenuItemsSelection) NULL,
122 (VikLayerFuncAddMenuItems) georef_layer_add_menu_items,
123 (VikLayerFuncSublayerAddMenuItems) NULL,
125 (VikLayerFuncSublayerRenameRequest) NULL,
126 (VikLayerFuncSublayerToggleVisible) NULL,
127 (VikLayerFuncSublayerTooltip) NULL,
128 (VikLayerFuncLayerTooltip) georef_layer_tooltip,
129 (VikLayerFuncLayerSelected) NULL,
131 (VikLayerFuncMarshall) georef_layer_marshall,
132 (VikLayerFuncUnmarshall) georef_layer_unmarshall,
134 (VikLayerFuncSetParam) georef_layer_set_param,
135 (VikLayerFuncGetParam) georef_layer_get_param,
136 (VikLayerFuncChangeParam) NULL,
138 (VikLayerFuncReadFileData) NULL,
139 (VikLayerFuncWriteFileData) NULL,
141 (VikLayerFuncDeleteItem) NULL,
142 (VikLayerFuncCutItem) NULL,
143 (VikLayerFuncCopyItem) NULL,
144 (VikLayerFuncPasteItem) NULL,
145 (VikLayerFuncFreeCopiedItem) NULL,
146 (VikLayerFuncDragDropRequest) NULL,
148 (VikLayerFuncSelectClick) NULL,
149 (VikLayerFuncSelectMove) NULL,
150 (VikLayerFuncSelectRelease) NULL,
151 (VikLayerFuncSelectedViewportMenu) NULL,
154 struct _VikGeorefLayer {
159 gdouble mpp_easting, mpp_northing;
163 guint32 scaled_width, scaled_height;
165 gint click_x, click_y;
170 GType vik_georef_layer_get_type ()
172 static GType vgl_type = 0;
176 static const GTypeInfo vgl_info =
178 sizeof (VikGeorefLayerClass),
179 NULL, /* base_init */
180 NULL, /* base_finalize */
181 NULL, /* class init */
182 NULL, /* class_finalize */
183 NULL, /* class_data */
184 sizeof (VikGeorefLayer),
186 NULL /* instance init */
188 vgl_type = g_type_register_static ( VIK_LAYER_TYPE, "VikGeorefLayer", &vgl_info, 0 );
194 static const gchar* georef_layer_tooltip ( VikGeorefLayer *vgl )
199 static void georef_layer_marshall( VikGeorefLayer *vgl, guint8 **data, gint *len )
201 vik_layer_marshall_params ( VIK_LAYER(vgl), data, len );
204 static VikGeorefLayer *georef_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp )
206 VikGeorefLayer *rv = georef_layer_new ( vvp );
207 vik_layer_unmarshall_params ( VIK_LAYER(rv), data, len, vvp );
209 georef_layer_load_image ( rv, vvp, TRUE );
214 static gboolean georef_layer_set_param ( VikGeorefLayer *vgl, guint16 id, VikLayerParamData data, VikViewport *vp, gboolean is_file_operation )
218 case PARAM_IMAGE: georef_layer_set_image ( vgl, data.s ); break;
219 case PARAM_CN: vgl->corner.northing = data.d; break;
220 case PARAM_CE: vgl->corner.easting = data.d; break;
221 case PARAM_MN: vgl->mpp_northing = data.d; break;
222 case PARAM_ME: vgl->mpp_easting = data.d; break;
227 static VikLayerParamData georef_layer_get_param ( VikGeorefLayer *vgl, guint16 id, gboolean is_file_operation )
229 VikLayerParamData rv;
233 gboolean set = FALSE;
234 if ( is_file_operation ) {
235 if ( a_vik_get_file_ref_format() == VIK_FILE_REF_FORMAT_RELATIVE ) {
236 gchar *cwd = g_get_current_dir();
238 rv.s = file_GetRelativeFilename ( cwd, vgl->image );
239 if ( !rv.s ) rv.s = "";
245 rv.s = vgl->image ? vgl->image : "";
248 case PARAM_CN: rv.d = vgl->corner.northing; break;
249 case PARAM_CE: rv.d = vgl->corner.easting; break;
250 case PARAM_MN: rv.d = vgl->mpp_northing; break;
251 case PARAM_ME: rv.d = vgl->mpp_easting; break;
256 static VikGeorefLayer *georef_layer_new ( VikViewport *vvp )
258 VikGeorefLayer *vgl = VIK_GEOREF_LAYER ( g_object_new ( VIK_GEOREF_LAYER_TYPE, NULL ) );
259 vik_layer_set_type ( VIK_LAYER(vgl), VIK_LAYER_GEOREF );
261 // Since GeoRef layer doesn't use uibuilder
262 // initializing this way won't do anything yet..
263 vik_layer_set_defaults ( VIK_LAYER(vgl), vvp );
265 // Make these defaults based on the current view
266 vgl->mpp_northing = vik_viewport_get_ympp ( vvp );
267 vgl->mpp_easting = vik_viewport_get_xmpp ( vvp );
268 vik_coord_to_utm ( vik_viewport_get_center ( vvp ), &(vgl->corner) );
275 vgl->scaled_width = 0;
276 vgl->scaled_height = 0;
280 static void georef_layer_draw ( VikGeorefLayer *vgl, VikViewport *vp )
282 if ( vik_viewport_get_drawmode(vp) != VIK_VIEWPORT_DRAWMODE_UTM )
287 struct UTM utm_middle;
288 gdouble xmpp = vik_viewport_get_xmpp(vp), ympp = vik_viewport_get_ympp(vp);
289 GdkPixbuf *pixbuf = vgl->pixbuf;
290 guint layer_width = vgl->width;
291 guint layer_height = vgl->height;
293 vik_coord_to_utm ( vik_viewport_get_center ( vp ), &utm_middle );
295 guint width = vik_viewport_get_width(vp), height = vik_viewport_get_height(vp);
297 vgl->corner.zone = utm_middle.zone;
298 vgl->corner.letter = utm_middle.letter;
299 VikCoord corner_coord;
300 vik_coord_load_from_utm ( &corner_coord, vik_viewport_get_coord_mode(vp), &(vgl->corner) );
301 vik_viewport_coord_to_screen ( vp, &corner_coord, &x, &y );
303 /* mark to scale the pixbuf if it doesn't match our dimensions */
304 gboolean scale = FALSE;
305 if ( xmpp != vgl->mpp_easting || ympp != vgl->mpp_northing )
308 layer_width = round(vgl->width * vgl->mpp_easting / xmpp);
309 layer_height = round(vgl->height * vgl->mpp_northing / ympp);
312 // If image not in viewport bounds - no need to draw it (or bother with any scaling)
313 if ( (x < 0 || x < width) && (y < 0 || y < height) && x+layer_width > 0 && y+layer_height > 0 ) {
317 /* rescale if necessary */
318 if (layer_width == vgl->scaled_width && layer_height == vgl->scaled_height && vgl->scaled != NULL)
319 pixbuf = vgl->scaled;
322 pixbuf = gdk_pixbuf_scale_simple(
329 if (vgl->scaled != NULL)
330 g_object_unref(vgl->scaled);
332 vgl->scaled = pixbuf;
333 vgl->scaled_width = layer_width;
334 vgl->scaled_height = layer_height;
337 vik_viewport_draw_pixbuf ( vp, pixbuf, 0, 0, x, y, layer_width, layer_height ); /* todo: draw only what we need to. */
342 static void georef_layer_free ( VikGeorefLayer *vgl )
344 if ( vgl->image != NULL )
345 g_free ( vgl->image );
346 if ( vgl->scaled != NULL )
347 g_object_unref ( vgl->scaled );
350 static VikGeorefLayer *georef_layer_create ( VikViewport *vp )
352 return georef_layer_new ( vp );
355 static gboolean georef_layer_properties ( VikGeorefLayer *vgl, gpointer vp )
357 return georef_layer_dialog ( &vgl, vp, VIK_GTK_WINDOW_FROM_WIDGET(vp) );
360 static void georef_layer_load_image ( VikGeorefLayer *vgl, VikViewport *vp, gboolean from_file )
363 if ( vgl->image == NULL )
367 g_object_unref ( G_OBJECT(vgl->pixbuf) );
370 g_object_unref ( G_OBJECT(vgl->scaled) );
374 vgl->pixbuf = gdk_pixbuf_new_from_file ( vgl->image, &gx );
379 a_dialog_error_msg_extra ( VIK_GTK_WINDOW_FROM_WIDGET(vp), _("Couldn't open image file: %s"), gx->message );
384 vgl->width = gdk_pixbuf_get_width ( vgl->pixbuf );
385 vgl->height = gdk_pixbuf_get_height ( vgl->pixbuf );
390 if ( vik_viewport_get_drawmode(vp) != VIK_VIEWPORT_DRAWMODE_UTM )
392 a_dialog_warning_msg ( VIK_GTK_WINDOW_FROM_WIDGET(vp),
393 _("GeoRef map cannot be displayed in the current drawmode.\nSelect \"UTM Mode\" from View menu to view it.") );
396 /* should find length and width here too */
399 static void georef_layer_set_image ( VikGeorefLayer *vgl, const gchar *image )
402 g_free ( vgl->image );
405 g_object_unref ( vgl->scaled );
411 if ( g_strcmp0 (image, "") != 0 )
412 vgl->image = vu_get_canonical_filename ( VIK_LAYER(vgl), image );
414 vgl->image = g_strdup (image);
417 static gboolean world_file_read_line ( gchar *buffer, gint size, FILE *f, GtkWidget *widget, gboolean use_value )
419 if (!fgets ( buffer, 1024, f ))
421 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_WIDGET(widget), _("Unexpected end of file reading World file.") );
429 gdouble val = g_strtod ( buffer, NULL );
430 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(widget), val > 0 ? val : -val );
435 static void georef_layer_dialog_load ( GtkWidget *pass_along[4] )
437 GtkWidget *file_selector = gtk_file_chooser_dialog_new (_("Choose World file"),
439 GTK_FILE_CHOOSER_ACTION_OPEN,
440 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
441 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
444 if ( gtk_dialog_run ( GTK_DIALOG ( file_selector ) ) == GTK_RESPONSE_ACCEPT )
446 FILE *f = g_fopen ( gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER(file_selector) ), "r" );
447 gtk_widget_destroy ( file_selector );
450 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_WIDGET(pass_along[0]), _("The World file you requested could not be opened for reading.") );
455 gchar *buffer = g_malloc ( 1024 * sizeof(gchar) );
456 if ( world_file_read_line ( buffer, 1024, f, pass_along[0], TRUE ) && world_file_read_line ( buffer, 1024, f, pass_along[0], FALSE)
457 && world_file_read_line ( buffer, 1024, f, pass_along[0], FALSE ) && world_file_read_line ( buffer, 1024, f, pass_along[1], TRUE)
458 && world_file_read_line ( buffer, 1024, f, pass_along[2], TRUE ) && world_file_read_line ( buffer, 1024, f, pass_along[3], TRUE ) )
467 gtk_widget_destroy ( file_selector );
470 file selection dialog
471 file opener for reading, if NULL, send error_msg ( VIK_GTK_WINDOW_FROM_WIDGET(pass_along[0]) )
472 does that catch directories too?
473 read lines -- if not enough lines, give error.
474 if anything outside, give error. define range with #define CONSTANTS
475 put 'em in thar widgets, and that's it.
479 static void georef_layer_export_params ( gpointer *pass_along[2] )
481 VikGeorefLayer *vgl = VIK_GEOREF_LAYER(pass_along[0]);
482 GtkWidget *file_selector = gtk_file_chooser_dialog_new (_("Choose World file"),
484 GTK_FILE_CHOOSER_ACTION_SAVE,
485 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
486 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
488 if ( gtk_dialog_run ( GTK_DIALOG ( file_selector ) ) == GTK_RESPONSE_ACCEPT )
490 FILE *f = g_fopen ( gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER(file_selector) ), "w" );
492 gtk_widget_destroy ( file_selector );
495 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_WIDGET(pass_along[0]), _("The file you requested could not be opened for writing.") );
500 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 );
506 gtk_widget_destroy ( file_selector );
509 /* returns TRUE if OK was pressed. */
510 static gboolean georef_layer_dialog ( VikGeorefLayer **vgl, gpointer vp, GtkWindow *w )
512 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Layer Properties"),
514 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
520 /* Default to reject as user really needs to specify map file first */
521 gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_REJECT );
522 GtkWidget *response_w = NULL;
523 #if GTK_CHECK_VERSION (2, 20, 0)
524 response_w = gtk_dialog_get_widget_for_response ( GTK_DIALOG(dialog), GTK_RESPONSE_REJECT );
526 GtkWidget *table, *wfp_hbox, *wfp_label, *wfp_button, *ce_label, *ce_spin, *cn_label, *cn_spin, *xlabel, *xspin, *ylabel, *yspin, *imagelabel, *imageentry;
528 GtkWidget *pass_along[4];
530 table = gtk_table_new ( 6, 2, FALSE );
531 gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), table, TRUE, TRUE, 0 );
533 wfp_hbox = gtk_hbox_new ( FALSE, 0 );
534 wfp_label = gtk_label_new ( _("World File Parameters:") );
535 wfp_button = gtk_button_new_with_label ( _("Load From File...") );
537 gtk_box_pack_start ( GTK_BOX(wfp_hbox), wfp_label, TRUE, TRUE, 0 );
538 gtk_box_pack_start ( GTK_BOX(wfp_hbox), wfp_button, FALSE, FALSE, 3 );
540 ce_label = gtk_label_new ( _("Corner pixel easting:") );
541 ce_spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, 0.0, 1500000.0, 1, 5, 0 ), 1, 4 );
542 gtk_widget_set_tooltip_text ( GTK_WIDGET(ce_spin), _("the UTM \"easting\" value of the upper-left corner pixel of the map") );
544 cn_label = gtk_label_new ( _("Corner pixel northing:") );
545 cn_spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, 0.0, 9000000.0, 1, 5, 0 ), 1, 4 );
546 gtk_widget_set_tooltip_text ( GTK_WIDGET(cn_spin), _("the UTM \"northing\" value of the upper-left corner pixel of the map") );
548 xlabel = gtk_label_new ( _("X (easting) scale (mpp): "));
549 ylabel = gtk_label_new ( _("Y (northing) scale (mpp): "));
551 xspin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, VIK_VIEWPORT_MIN_ZOOM, VIK_VIEWPORT_MAX_ZOOM, 1, 5, 0 ), 1, 8 );
552 gtk_widget_set_tooltip_text ( GTK_WIDGET(xspin), _("the scale of the map in the X direction (meters per pixel)") );
553 yspin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, VIK_VIEWPORT_MIN_ZOOM, VIK_VIEWPORT_MAX_ZOOM, 1, 5, 0 ), 1, 8 );
554 gtk_widget_set_tooltip_text ( GTK_WIDGET(yspin), _("the scale of the map in the Y direction (meters per pixel)") );
556 imagelabel = gtk_label_new ( _("Map Image:") );
557 imageentry = vik_file_entry_new (GTK_FILE_CHOOSER_ACTION_OPEN, VF_FILTER_IMAGE);
561 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(ce_spin), (*vgl)->corner.easting );
562 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(cn_spin), (*vgl)->corner.northing );
563 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(xspin), (*vgl)->mpp_easting );
564 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(yspin), (*vgl)->mpp_northing );
566 vik_file_entry_set_filename ( VIK_FILE_ENTRY(imageentry), (*vgl)->image );
570 VikCoord corner_coord;
572 vik_viewport_screen_to_coord ( VIK_VIEWPORT(vp), 0, 0, &corner_coord );
573 vik_coord_to_utm ( &corner_coord, &utm );
574 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(ce_spin), utm.easting );
575 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(cn_spin), utm.northing );
576 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(xspin), vik_viewport_get_xmpp ( VIK_VIEWPORT(vp) ) );
577 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(yspin), vik_viewport_get_ympp ( VIK_VIEWPORT(vp) ) );
580 gtk_table_attach_defaults ( GTK_TABLE(table), imagelabel, 0, 1, 0, 1 );
581 gtk_table_attach_defaults ( GTK_TABLE(table), imageentry, 1, 2, 0, 1 );
582 gtk_table_attach_defaults ( GTK_TABLE(table), wfp_hbox, 0, 2, 1, 2 );
583 gtk_table_attach_defaults ( GTK_TABLE(table), xlabel, 0, 1, 2, 3 );
584 gtk_table_attach_defaults ( GTK_TABLE(table), xspin, 1, 2, 2, 3 );
585 gtk_table_attach_defaults ( GTK_TABLE(table), ylabel, 0, 1, 3, 4 );
586 gtk_table_attach_defaults ( GTK_TABLE(table), yspin, 1, 2, 3, 4 );
587 gtk_table_attach_defaults ( GTK_TABLE(table), ce_label, 0, 1, 4, 5 );
588 gtk_table_attach_defaults ( GTK_TABLE(table), ce_spin, 1, 2, 4, 5 );
589 gtk_table_attach_defaults ( GTK_TABLE(table), cn_label, 0, 1, 5, 6 );
590 gtk_table_attach_defaults ( GTK_TABLE(table), cn_spin, 1, 2, 5, 6 );
592 pass_along[0] = xspin;
593 pass_along[1] = yspin;
594 pass_along[2] = ce_spin;
595 pass_along[3] = cn_spin;
596 g_signal_connect_swapped ( G_OBJECT(wfp_button), "clicked", G_CALLBACK(georef_layer_dialog_load), pass_along );
599 gtk_widget_grab_focus ( response_w );
601 gtk_widget_show_all ( table );
603 if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
607 *vgl = georef_layer_new ( VIK_VIEWPORT(vp) );
608 vik_layer_rename ( VIK_LAYER(*vgl), vik_georef_layer_interface.name );
610 (*vgl)->corner.easting = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(ce_spin) );
611 (*vgl)->corner.northing = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(cn_spin) );
612 (*vgl)->mpp_easting = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(xspin) );
613 (*vgl)->mpp_northing = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(yspin) );
614 if ( (!(*vgl)->image) || strcmp( (*vgl)->image, vik_file_entry_get_filename(VIK_FILE_ENTRY(imageentry)) ) != 0 )
616 georef_layer_set_image ( *vgl, vik_file_entry_get_filename(VIK_FILE_ENTRY(imageentry)) );
617 georef_layer_load_image ( *vgl, VIK_VIEWPORT(vp), FALSE );
620 gtk_widget_destroy ( GTK_WIDGET(dialog) );
623 gtk_widget_destroy ( GTK_WIDGET(dialog) );
627 static void georef_layer_zoom_to_fit ( gpointer vgl_vlp[2] )
629 vik_viewport_set_xmpp ( vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vgl_vlp[1])), VIK_GEOREF_LAYER(vgl_vlp[0])->mpp_easting );
630 vik_viewport_set_ympp ( vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vgl_vlp[1])), VIK_GEOREF_LAYER(vgl_vlp[0])->mpp_northing );
631 vik_layers_panel_emit_update ( VIK_LAYERS_PANEL(vgl_vlp[1]) );
634 static void georef_layer_goto_center ( gpointer vgl_vlp[2] )
636 VikGeorefLayer *vgl = VIK_GEOREF_LAYER ( vgl_vlp[0] );
637 VikViewport *vp = vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vgl_vlp[1]));
641 vik_coord_to_utm ( vik_viewport_get_center ( vp ), &utm );
643 utm.easting = vgl->corner.easting + (vgl->width * vgl->mpp_easting / 2); /* only an approximation */
644 utm.northing = vgl->corner.northing - (vgl->height * vgl->mpp_northing / 2);
646 vik_coord_load_from_utm ( &coord, vik_viewport_get_coord_mode ( vp ), &utm );
647 vik_viewport_set_center_coord ( vp, &coord, TRUE );
649 vik_layers_panel_emit_update ( VIK_LAYERS_PANEL(vgl_vlp[1]) );
652 static void georef_layer_add_menu_items ( VikGeorefLayer *vgl, GtkMenu *menu, gpointer vlp )
654 static gpointer pass_along[2];
659 item = gtk_menu_item_new();
660 gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
661 gtk_widget_show ( item );
664 item = gtk_image_menu_item_new_with_mnemonic ( _("_Zoom to Fit Map") );
665 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ZOOM_FIT, GTK_ICON_SIZE_MENU) );
666 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(georef_layer_zoom_to_fit), 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 ( _("_Goto Map Center") );
671 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_MENU) );
672 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(georef_layer_goto_center), pass_along );
673 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
674 gtk_widget_show ( item );
676 item = gtk_image_menu_item_new_with_mnemonic ( _("_Export to World File") );
677 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_HARDDISK, GTK_ICON_SIZE_MENU) );
678 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(georef_layer_export_params), pass_along );
679 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
680 gtk_widget_show ( item );
684 static gpointer georef_layer_move_create ( VikWindow *vw, VikViewport *vvp)
689 static gboolean georef_layer_move_release ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp )
691 if (!vgl || vgl->vl.type != VIK_LAYER_GEOREF)
694 if ( vgl->click_x != -1 )
696 vgl->corner.easting += (event->x - vgl->click_x) * vik_viewport_get_xmpp (vvp);
697 vgl->corner.northing -= (event->y - vgl->click_y) * vik_viewport_get_ympp (vvp);
698 vik_layer_emit_update ( VIK_LAYER(vgl) );
701 return FALSE; /* I didn't move anything on this layer! */
704 static gpointer georef_layer_zoom_create ( VikWindow *vw, VikViewport *vvp)
709 static gboolean georef_layer_zoom_press ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp )
711 if (!vgl || vgl->vl.type != VIK_LAYER_GEOREF)
713 if ( event->button == 1 )
715 if ( vgl->mpp_easting < (VIK_VIEWPORT_MAX_ZOOM / 1.05) && vgl->mpp_northing < (VIK_VIEWPORT_MAX_ZOOM / 1.05) )
717 vgl->mpp_easting *= 1.01;
718 vgl->mpp_northing *= 1.01;
723 if ( vgl->mpp_easting > (VIK_VIEWPORT_MIN_ZOOM * 1.05) && vgl->mpp_northing > (VIK_VIEWPORT_MIN_ZOOM * 1.05) )
725 vgl->mpp_easting /= 1.01;
726 vgl->mpp_northing /= 1.01;
729 vik_viewport_set_xmpp ( vvp, vgl->mpp_easting );
730 vik_viewport_set_ympp ( vvp, vgl->mpp_northing );
731 vik_layer_emit_update ( VIK_LAYER(vgl) );
735 static gboolean georef_layer_move_press ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp )
737 if (!vgl || vgl->vl.type != VIK_LAYER_GEOREF)
739 vgl->click_x = event->x;
740 vgl->click_y = event->y;