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, NULL },
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, NULL },
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;
228 static VikLayerParamData georef_layer_get_param ( VikGeorefLayer *vgl, guint16 id, gboolean is_file_operation )
230 VikLayerParamData rv;
234 gboolean set = FALSE;
235 if ( is_file_operation ) {
236 if ( a_vik_get_file_ref_format() == VIK_FILE_REF_FORMAT_RELATIVE ) {
237 gchar *cwd = g_get_current_dir();
239 rv.s = file_GetRelativeFilename ( cwd, vgl->image );
240 if ( !rv.s ) rv.s = "";
246 rv.s = vgl->image ? vgl->image : "";
249 case PARAM_CN: rv.d = vgl->corner.northing; break;
250 case PARAM_CE: rv.d = vgl->corner.easting; break;
251 case PARAM_MN: rv.d = vgl->mpp_northing; break;
252 case PARAM_ME: rv.d = vgl->mpp_easting; break;
258 static VikGeorefLayer *georef_layer_new ( VikViewport *vvp )
260 VikGeorefLayer *vgl = VIK_GEOREF_LAYER ( g_object_new ( VIK_GEOREF_LAYER_TYPE, NULL ) );
261 vik_layer_set_type ( VIK_LAYER(vgl), VIK_LAYER_GEOREF );
263 // Since GeoRef layer doesn't use uibuilder
264 // initializing this way won't do anything yet..
265 vik_layer_set_defaults ( VIK_LAYER(vgl), vvp );
267 // Make these defaults based on the current view
268 vgl->mpp_northing = vik_viewport_get_ympp ( vvp );
269 vgl->mpp_easting = vik_viewport_get_xmpp ( vvp );
270 vik_coord_to_utm ( vik_viewport_get_center ( vvp ), &(vgl->corner) );
277 vgl->scaled_width = 0;
278 vgl->scaled_height = 0;
282 static void georef_layer_draw ( VikGeorefLayer *vgl, VikViewport *vp )
284 if ( vik_viewport_get_drawmode(vp) != VIK_VIEWPORT_DRAWMODE_UTM )
289 struct UTM utm_middle;
290 gdouble xmpp = vik_viewport_get_xmpp(vp), ympp = vik_viewport_get_ympp(vp);
291 GdkPixbuf *pixbuf = vgl->pixbuf;
292 guint layer_width = vgl->width;
293 guint layer_height = vgl->height;
295 vik_coord_to_utm ( vik_viewport_get_center ( vp ), &utm_middle );
297 guint width = vik_viewport_get_width(vp), height = vik_viewport_get_height(vp);
299 vgl->corner.zone = utm_middle.zone;
300 vgl->corner.letter = utm_middle.letter;
301 VikCoord corner_coord;
302 vik_coord_load_from_utm ( &corner_coord, vik_viewport_get_coord_mode(vp), &(vgl->corner) );
303 vik_viewport_coord_to_screen ( vp, &corner_coord, &x, &y );
305 /* mark to scale the pixbuf if it doesn't match our dimensions */
306 gboolean scale = FALSE;
307 if ( xmpp != vgl->mpp_easting || ympp != vgl->mpp_northing )
310 layer_width = round(vgl->width * vgl->mpp_easting / xmpp);
311 layer_height = round(vgl->height * vgl->mpp_northing / ympp);
314 // If image not in viewport bounds - no need to draw it (or bother with any scaling)
315 if ( (x < 0 || x < width) && (y < 0 || y < height) && x+layer_width > 0 && y+layer_height > 0 ) {
319 /* rescale if necessary */
320 if (layer_width == vgl->scaled_width && layer_height == vgl->scaled_height && vgl->scaled != NULL)
321 pixbuf = vgl->scaled;
324 pixbuf = gdk_pixbuf_scale_simple(
331 if (vgl->scaled != NULL)
332 g_object_unref(vgl->scaled);
334 vgl->scaled = pixbuf;
335 vgl->scaled_width = layer_width;
336 vgl->scaled_height = layer_height;
339 vik_viewport_draw_pixbuf ( vp, pixbuf, 0, 0, x, y, layer_width, layer_height ); /* todo: draw only what we need to. */
344 static void georef_layer_free ( VikGeorefLayer *vgl )
346 if ( vgl->image != NULL )
347 g_free ( vgl->image );
348 if ( vgl->scaled != NULL )
349 g_object_unref ( vgl->scaled );
352 static VikGeorefLayer *georef_layer_create ( VikViewport *vp )
354 return georef_layer_new ( vp );
357 static gboolean georef_layer_properties ( VikGeorefLayer *vgl, gpointer vp )
359 return georef_layer_dialog ( &vgl, vp, VIK_GTK_WINDOW_FROM_WIDGET(vp) );
362 static void georef_layer_load_image ( VikGeorefLayer *vgl, VikViewport *vp, gboolean from_file )
365 if ( vgl->image == NULL )
369 g_object_unref ( G_OBJECT(vgl->pixbuf) );
372 g_object_unref ( G_OBJECT(vgl->scaled) );
376 vgl->pixbuf = gdk_pixbuf_new_from_file ( vgl->image, &gx );
381 a_dialog_error_msg_extra ( VIK_GTK_WINDOW_FROM_WIDGET(vp), _("Couldn't open image file: %s"), gx->message );
386 vgl->width = gdk_pixbuf_get_width ( vgl->pixbuf );
387 vgl->height = gdk_pixbuf_get_height ( vgl->pixbuf );
392 if ( vik_viewport_get_drawmode(vp) != VIK_VIEWPORT_DRAWMODE_UTM )
394 a_dialog_warning_msg ( VIK_GTK_WINDOW_FROM_WIDGET(vp),
395 _("GeoRef map cannot be displayed in the current drawmode.\nSelect \"UTM Mode\" from View menu to view it.") );
398 /* should find length and width here too */
401 static void georef_layer_set_image ( VikGeorefLayer *vgl, const gchar *image )
404 g_free ( vgl->image );
407 g_object_unref ( vgl->scaled );
413 if ( g_strcmp0 (image, "") != 0 )
414 vgl->image = vu_get_canonical_filename ( VIK_LAYER(vgl), image );
416 vgl->image = g_strdup (image);
419 static gboolean world_file_read_line ( gchar *buffer, gint size, FILE *f, GtkWidget *widget, gboolean use_value )
421 if (!fgets ( buffer, 1024, f ))
423 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_WIDGET(widget), _("Unexpected end of file reading World file.") );
431 gdouble val = g_strtod ( buffer, NULL );
432 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(widget), val > 0 ? val : -val );
437 static void georef_layer_dialog_load ( GtkWidget *pass_along[4] )
439 GtkWidget *file_selector = gtk_file_chooser_dialog_new (_("Choose World file"),
441 GTK_FILE_CHOOSER_ACTION_OPEN,
442 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
443 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
446 if ( gtk_dialog_run ( GTK_DIALOG ( file_selector ) ) == GTK_RESPONSE_ACCEPT )
448 FILE *f = g_fopen ( gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER(file_selector) ), "r" );
449 gtk_widget_destroy ( file_selector );
452 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_WIDGET(pass_along[0]), _("The World file you requested could not be opened for reading.") );
457 gchar *buffer = g_malloc ( 1024 * sizeof(gchar) );
458 if ( world_file_read_line ( buffer, 1024, f, pass_along[0], TRUE ) && world_file_read_line ( buffer, 1024, f, pass_along[0], FALSE)
459 && world_file_read_line ( buffer, 1024, f, pass_along[0], FALSE ) && world_file_read_line ( buffer, 1024, f, pass_along[1], TRUE)
460 && world_file_read_line ( buffer, 1024, f, pass_along[2], TRUE ) && world_file_read_line ( buffer, 1024, f, pass_along[3], TRUE ) )
469 gtk_widget_destroy ( file_selector );
472 file selection dialog
473 file opener for reading, if NULL, send error_msg ( VIK_GTK_WINDOW_FROM_WIDGET(pass_along[0]) )
474 does that catch directories too?
475 read lines -- if not enough lines, give error.
476 if anything outside, give error. define range with #define CONSTANTS
477 put 'em in thar widgets, and that's it.
481 static void georef_layer_export_params ( gpointer *pass_along[2] )
483 VikGeorefLayer *vgl = VIK_GEOREF_LAYER(pass_along[0]);
484 GtkWidget *file_selector = gtk_file_chooser_dialog_new (_("Choose World file"),
486 GTK_FILE_CHOOSER_ACTION_SAVE,
487 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
488 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
490 if ( gtk_dialog_run ( GTK_DIALOG ( file_selector ) ) == GTK_RESPONSE_ACCEPT )
492 FILE *f = g_fopen ( gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER(file_selector) ), "w" );
494 gtk_widget_destroy ( file_selector );
497 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_WIDGET(pass_along[0]), _("The file you requested could not be opened for writing.") );
502 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 );
508 gtk_widget_destroy ( file_selector );
511 /* returns TRUE if OK was pressed. */
512 static gboolean georef_layer_dialog ( VikGeorefLayer **vgl, gpointer vp, GtkWindow *w )
514 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Layer Properties"),
516 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
522 /* Default to reject as user really needs to specify map file first */
523 gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_REJECT );
524 GtkWidget *response_w = NULL;
525 #if GTK_CHECK_VERSION (2, 20, 0)
526 response_w = gtk_dialog_get_widget_for_response ( GTK_DIALOG(dialog), GTK_RESPONSE_REJECT );
528 GtkWidget *table, *wfp_hbox, *wfp_label, *wfp_button, *ce_label, *ce_spin, *cn_label, *cn_spin, *xlabel, *xspin, *ylabel, *yspin, *imagelabel, *imageentry;
530 GtkWidget *pass_along[4];
532 table = gtk_table_new ( 6, 2, FALSE );
533 gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), table, TRUE, TRUE, 0 );
535 wfp_hbox = gtk_hbox_new ( FALSE, 0 );
536 wfp_label = gtk_label_new ( _("World File Parameters:") );
537 wfp_button = gtk_button_new_with_label ( _("Load From File...") );
539 gtk_box_pack_start ( GTK_BOX(wfp_hbox), wfp_label, TRUE, TRUE, 0 );
540 gtk_box_pack_start ( GTK_BOX(wfp_hbox), wfp_button, FALSE, FALSE, 3 );
542 ce_label = gtk_label_new ( _("Corner pixel easting:") );
543 ce_spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, 0.0, 1500000.0, 1, 5, 0 ), 1, 4 );
544 gtk_widget_set_tooltip_text ( GTK_WIDGET(ce_spin), _("the UTM \"easting\" value of the upper-left corner pixel of the map") );
546 cn_label = gtk_label_new ( _("Corner pixel northing:") );
547 cn_spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, 0.0, 9000000.0, 1, 5, 0 ), 1, 4 );
548 gtk_widget_set_tooltip_text ( GTK_WIDGET(cn_spin), _("the UTM \"northing\" value of the upper-left corner pixel of the map") );
550 xlabel = gtk_label_new ( _("X (easting) scale (mpp): "));
551 ylabel = gtk_label_new ( _("Y (northing) scale (mpp): "));
553 xspin = 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(xspin), _("the scale of the map in the X direction (meters per pixel)") );
555 yspin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, VIK_VIEWPORT_MIN_ZOOM, VIK_VIEWPORT_MAX_ZOOM, 1, 5, 0 ), 1, 8 );
556 gtk_widget_set_tooltip_text ( GTK_WIDGET(yspin), _("the scale of the map in the Y direction (meters per pixel)") );
558 imagelabel = gtk_label_new ( _("Map Image:") );
559 imageentry = vik_file_entry_new (GTK_FILE_CHOOSER_ACTION_OPEN, VF_FILTER_IMAGE);
563 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(ce_spin), (*vgl)->corner.easting );
564 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(cn_spin), (*vgl)->corner.northing );
565 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(xspin), (*vgl)->mpp_easting );
566 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(yspin), (*vgl)->mpp_northing );
568 vik_file_entry_set_filename ( VIK_FILE_ENTRY(imageentry), (*vgl)->image );
572 VikCoord corner_coord;
574 vik_viewport_screen_to_coord ( VIK_VIEWPORT(vp), 0, 0, &corner_coord );
575 vik_coord_to_utm ( &corner_coord, &utm );
576 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(ce_spin), utm.easting );
577 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(cn_spin), utm.northing );
578 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(xspin), vik_viewport_get_xmpp ( VIK_VIEWPORT(vp) ) );
579 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(yspin), vik_viewport_get_ympp ( VIK_VIEWPORT(vp) ) );
582 gtk_table_attach_defaults ( GTK_TABLE(table), imagelabel, 0, 1, 0, 1 );
583 gtk_table_attach_defaults ( GTK_TABLE(table), imageentry, 1, 2, 0, 1 );
584 gtk_table_attach_defaults ( GTK_TABLE(table), wfp_hbox, 0, 2, 1, 2 );
585 gtk_table_attach_defaults ( GTK_TABLE(table), xlabel, 0, 1, 2, 3 );
586 gtk_table_attach_defaults ( GTK_TABLE(table), xspin, 1, 2, 2, 3 );
587 gtk_table_attach_defaults ( GTK_TABLE(table), ylabel, 0, 1, 3, 4 );
588 gtk_table_attach_defaults ( GTK_TABLE(table), yspin, 1, 2, 3, 4 );
589 gtk_table_attach_defaults ( GTK_TABLE(table), ce_label, 0, 1, 4, 5 );
590 gtk_table_attach_defaults ( GTK_TABLE(table), ce_spin, 1, 2, 4, 5 );
591 gtk_table_attach_defaults ( GTK_TABLE(table), cn_label, 0, 1, 5, 6 );
592 gtk_table_attach_defaults ( GTK_TABLE(table), cn_spin, 1, 2, 5, 6 );
594 pass_along[0] = xspin;
595 pass_along[1] = yspin;
596 pass_along[2] = ce_spin;
597 pass_along[3] = cn_spin;
598 g_signal_connect_swapped ( G_OBJECT(wfp_button), "clicked", G_CALLBACK(georef_layer_dialog_load), pass_along );
601 gtk_widget_grab_focus ( response_w );
603 gtk_widget_show_all ( table );
605 if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
609 *vgl = georef_layer_new ( VIK_VIEWPORT(vp) );
610 vik_layer_rename ( VIK_LAYER(*vgl), vik_georef_layer_interface.name );
612 (*vgl)->corner.easting = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(ce_spin) );
613 (*vgl)->corner.northing = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(cn_spin) );
614 (*vgl)->mpp_easting = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(xspin) );
615 (*vgl)->mpp_northing = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(yspin) );
616 if ( (!(*vgl)->image) || strcmp( (*vgl)->image, vik_file_entry_get_filename(VIK_FILE_ENTRY(imageentry)) ) != 0 )
618 georef_layer_set_image ( *vgl, vik_file_entry_get_filename(VIK_FILE_ENTRY(imageentry)) );
619 georef_layer_load_image ( *vgl, VIK_VIEWPORT(vp), FALSE );
622 gtk_widget_destroy ( GTK_WIDGET(dialog) );
625 gtk_widget_destroy ( GTK_WIDGET(dialog) );
629 static void georef_layer_zoom_to_fit ( gpointer vgl_vlp[2] )
631 vik_viewport_set_xmpp ( vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vgl_vlp[1])), VIK_GEOREF_LAYER(vgl_vlp[0])->mpp_easting );
632 vik_viewport_set_ympp ( vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vgl_vlp[1])), VIK_GEOREF_LAYER(vgl_vlp[0])->mpp_northing );
633 vik_layers_panel_emit_update ( VIK_LAYERS_PANEL(vgl_vlp[1]) );
636 static void georef_layer_goto_center ( gpointer vgl_vlp[2] )
638 VikGeorefLayer *vgl = VIK_GEOREF_LAYER ( vgl_vlp[0] );
639 VikViewport *vp = vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vgl_vlp[1]));
643 vik_coord_to_utm ( vik_viewport_get_center ( vp ), &utm );
645 utm.easting = vgl->corner.easting + (vgl->width * vgl->mpp_easting / 2); /* only an approximation */
646 utm.northing = vgl->corner.northing - (vgl->height * vgl->mpp_northing / 2);
648 vik_coord_load_from_utm ( &coord, vik_viewport_get_coord_mode ( vp ), &utm );
649 vik_viewport_set_center_coord ( vp, &coord, TRUE );
651 vik_layers_panel_emit_update ( VIK_LAYERS_PANEL(vgl_vlp[1]) );
654 static void georef_layer_add_menu_items ( VikGeorefLayer *vgl, GtkMenu *menu, gpointer vlp )
656 static gpointer pass_along[2];
661 item = gtk_menu_item_new();
662 gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
663 gtk_widget_show ( item );
666 item = gtk_image_menu_item_new_with_mnemonic ( _("_Zoom to Fit Map") );
667 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ZOOM_FIT, GTK_ICON_SIZE_MENU) );
668 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(georef_layer_zoom_to_fit), pass_along );
669 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
670 gtk_widget_show ( item );
672 item = gtk_image_menu_item_new_with_mnemonic ( _("_Goto Map Center") );
673 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_MENU) );
674 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(georef_layer_goto_center), pass_along );
675 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
676 gtk_widget_show ( item );
678 item = gtk_image_menu_item_new_with_mnemonic ( _("_Export to World File") );
679 gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_HARDDISK, GTK_ICON_SIZE_MENU) );
680 g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(georef_layer_export_params), pass_along );
681 gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
682 gtk_widget_show ( item );
686 static gpointer georef_layer_move_create ( VikWindow *vw, VikViewport *vvp)
691 static gboolean georef_layer_move_release ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp )
693 if (!vgl || vgl->vl.type != VIK_LAYER_GEOREF)
696 if ( vgl->click_x != -1 )
698 vgl->corner.easting += (event->x - vgl->click_x) * vik_viewport_get_xmpp (vvp);
699 vgl->corner.northing -= (event->y - vgl->click_y) * vik_viewport_get_ympp (vvp);
700 vik_layer_emit_update ( VIK_LAYER(vgl) );
703 return FALSE; /* I didn't move anything on this layer! */
706 static gpointer georef_layer_zoom_create ( VikWindow *vw, VikViewport *vvp)
711 static gboolean georef_layer_zoom_press ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp )
713 if (!vgl || vgl->vl.type != VIK_LAYER_GEOREF)
715 if ( event->button == 1 )
717 if ( vgl->mpp_easting < (VIK_VIEWPORT_MAX_ZOOM / 1.05) && vgl->mpp_northing < (VIK_VIEWPORT_MAX_ZOOM / 1.05) )
719 vgl->mpp_easting *= 1.01;
720 vgl->mpp_northing *= 1.01;
725 if ( vgl->mpp_easting > (VIK_VIEWPORT_MIN_ZOOM * 1.05) && vgl->mpp_northing > (VIK_VIEWPORT_MIN_ZOOM * 1.05) )
727 vgl->mpp_easting /= 1.01;
728 vgl->mpp_northing /= 1.01;
731 vik_viewport_set_xmpp ( vvp, vgl->mpp_easting );
732 vik_viewport_set_ympp ( vvp, vgl->mpp_northing );
733 vik_layer_emit_update ( VIK_LAYER(vgl) );
737 static gboolean georef_layer_move_press ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp )
739 if (!vgl || vgl->vl.type != VIK_LAYER_GEOREF)
741 vgl->click_x = event->x;
742 vgl->click_y = event->y;