]> git.street.me.uk Git - andy/viking.git/blame - src/vikgeoreflayer.c
Rework combo boxes to work with GTK+2.24 or earlier.
[andy/viking.git] / src / vikgeoreflayer.c
CommitLineData
50a14534
EB
1/*
2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
3 *
4 * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
4c77d5e0
GB
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
25
50a14534 26#include "viking.h"
a0008235 27#include <glib.h>
6af463da 28#include <glib/gstdio.h>
4c77d5e0 29#include <glib/gi18n.h>
7960e897 30#include <string.h>
be75ec20
MR
31#include <math.h>
32#include <stdlib.h>
50a14534 33
bce3a7b0 34#include "icons/icons.h"
a7023a1b 35/*
a7023a1b
RN
36static VikLayerParamData image_default ( void )
37{
38 VikLayerParamData data;
39 data.s = g_strdup ("");
40 return data;
41}
a7023a1b 42*/
bce3a7b0 43
50a14534 44VikLayerParam georef_layer_params[] = {
a7023a1b
RN
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 },
50a14534
EB
50};
51
52enum { PARAM_IMAGE = 0, PARAM_CE, PARAM_CN, PARAM_ME, PARAM_MN, NUM_PARAMS };
53
e6b64c5d 54static const gchar* georef_layer_tooltip ( VikGeorefLayer *vgl );
0a6cab71
AF
55static void georef_layer_marshall( VikGeorefLayer *vgl, guint8 **data, gint *len );
56static VikGeorefLayer *georef_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp );
158b3642
RN
57static gboolean georef_layer_set_param ( VikGeorefLayer *vgl, guint16 id, VikLayerParamData data, VikViewport *vp, gboolean is_file_operation );
58static VikLayerParamData georef_layer_get_param ( VikGeorefLayer *vgl, guint16 id, gboolean is_file_operation );
a7023a1b 59static VikGeorefLayer *georef_layer_new ( VikViewport *vvp );
a6b90ba4 60static VikGeorefLayer *georef_layer_create ( VikViewport *vp );
50a14534 61static void georef_layer_free ( VikGeorefLayer *vgl );
a6b90ba4 62static gboolean georef_layer_properties ( VikGeorefLayer *vgl, gpointer vp );
fd22ce3e 63static void georef_layer_draw ( VikGeorefLayer *vgl, VikViewport *vp );
50a14534
EB
64static void georef_layer_add_menu_items ( VikGeorefLayer *vgl, GtkMenu *menu, gpointer vlp );
65static void georef_layer_set_image ( VikGeorefLayer *vgl, const gchar *image );
66static gboolean georef_layer_dialog ( VikGeorefLayer **vgl, gpointer vp, GtkWindow *w );
fd22ce3e 67static void georef_layer_load_image ( VikGeorefLayer *vgl, VikViewport *vp, gboolean from_file );
941aa6e9
AF
68
69/* tools */
70static gpointer georef_layer_move_create ( VikWindow *vw, VikViewport *vvp);
50a14534
EB
71static gboolean georef_layer_move_release ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp );
72static gboolean georef_layer_move_press ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp );
941aa6e9 73static gpointer georef_layer_zoom_create ( VikWindow *vw, VikViewport *vvp);
50a14534
EB
74static gboolean georef_layer_zoom_press ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp );
75
79dce0cb 76// See comment in viktrwlayer.c for advice on values used
50a14534 77static VikToolInterface georef_tools[] = {
79dce0cb
RN
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,
bce3a7b0 80 (VikToolMouseFunc) georef_layer_move_press, NULL, (VikToolMouseFunc) georef_layer_move_release,
ef5e8132
RN
81 (VikToolKeyFunc) NULL,
82 FALSE,
83 GDK_CURSOR_IS_PIXMAP, &cursor_geomove_pixbuf },
941aa6e9 84
79dce0cb
RN
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,
bce3a7b0 87 (VikToolMouseFunc) georef_layer_zoom_press, NULL, NULL,
ef5e8132
RN
88 (VikToolKeyFunc) NULL,
89 FALSE,
90 GDK_CURSOR_IS_PIXMAP, &cursor_geozoom_pixbuf },
50a14534
EB
91};
92
93VikLayerInterface vik_georef_layer_interface = {
db386630 94 "GeoRef Map",
affcc0f2 95 N_("GeoRef Map"),
75078768 96 NULL,
5bfafde9 97 &vikgeoreflayer_pixbuf, /*icon */
50a14534
EB
98
99 georef_tools,
100 sizeof(georef_tools) / sizeof(VikToolInterface),
101
102 georef_layer_params,
103 NUM_PARAMS,
104 NULL,
105 0,
106
5a4a28bf
QT
107 VIK_MENU_ITEM_ALL,
108
50a14534
EB
109 (VikLayerFuncCreate) georef_layer_create,
110 (VikLayerFuncRealize) NULL,
111 (VikLayerFuncPostRead) georef_layer_load_image,
112 (VikLayerFuncFree) georef_layer_free,
113
114 (VikLayerFuncProperties) georef_layer_properties,
115 (VikLayerFuncDraw) georef_layer_draw,
116 (VikLayerFuncChangeCoordMode) NULL,
117
20c7a3a0
QT
118 (VikLayerFuncSetMenuItemsSelection) NULL,
119 (VikLayerFuncGetMenuItemsSelection) NULL,
120
50a14534
EB
121 (VikLayerFuncAddMenuItems) georef_layer_add_menu_items,
122 (VikLayerFuncSublayerAddMenuItems) NULL,
123
124 (VikLayerFuncSublayerRenameRequest) NULL,
125 (VikLayerFuncSublayerToggleVisible) NULL,
9da7faf2 126 (VikLayerFuncSublayerTooltip) NULL,
e6b64c5d 127 (VikLayerFuncLayerTooltip) georef_layer_tooltip,
a5dcfdb7 128 (VikLayerFuncLayerSelected) NULL,
50a14534 129
0a6cab71
AF
130 (VikLayerFuncMarshall) georef_layer_marshall,
131 (VikLayerFuncUnmarshall) georef_layer_unmarshall,
50a14534
EB
132
133 (VikLayerFuncSetParam) georef_layer_set_param,
134 (VikLayerFuncGetParam) georef_layer_get_param,
135
136 (VikLayerFuncReadFileData) NULL,
137 (VikLayerFuncWriteFileData) NULL,
138
33534cd8 139 (VikLayerFuncDeleteItem) NULL,
d5874ef9 140 (VikLayerFuncCutItem) NULL,
50a14534
EB
141 (VikLayerFuncCopyItem) NULL,
142 (VikLayerFuncPasteItem) NULL,
143 (VikLayerFuncFreeCopiedItem) NULL,
70a23263 144 (VikLayerFuncDragDropRequest) NULL,
77ad64fa
RN
145
146 (VikLayerFuncSelectClick) NULL,
08f14055
RN
147 (VikLayerFuncSelectMove) NULL,
148 (VikLayerFuncSelectRelease) NULL,
e46f259a 149 (VikLayerFuncSelectedViewportMenu) NULL,
50a14534
EB
150};
151
152struct _VikGeorefLayer {
153 VikLayer vl;
154 gchar *image;
155 GdkPixbuf *pixbuf;
156 struct UTM corner;
157 gdouble mpp_easting, mpp_northing;
158 guint width, height;
159
f3505ea3
MR
160 GdkPixbuf *scaled;
161 guint32 scaled_width, scaled_height;
162
50a14534
EB
163 gint click_x, click_y;
164};
165
166
167
168GType vik_georef_layer_get_type ()
169{
170 static GType vgl_type = 0;
171
172 if (!vgl_type)
173 {
174 static const GTypeInfo vgl_info =
175 {
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),
183 0,
184 NULL /* instance init */
185 };
186 vgl_type = g_type_register_static ( VIK_LAYER_TYPE, "VikGeorefLayer", &vgl_info, 0 );
187 }
188
189 return vgl_type;
190}
191
e6b64c5d
RN
192static const gchar* georef_layer_tooltip ( VikGeorefLayer *vgl )
193{
194 return vgl->image;
195}
196
0a6cab71
AF
197static void georef_layer_marshall( VikGeorefLayer *vgl, guint8 **data, gint *len )
198{
199 vik_layer_marshall_params ( VIK_LAYER(vgl), data, len );
200}
201
202static VikGeorefLayer *georef_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp )
203{
a7023a1b 204 VikGeorefLayer *rv = georef_layer_new ( vvp );
0a6cab71
AF
205 vik_layer_unmarshall_params ( VIK_LAYER(rv), data, len, vvp );
206 if (rv->image) {
fd22ce3e 207 georef_layer_load_image ( rv, vvp, TRUE );
0a6cab71
AF
208 }
209 return rv;
210}
211
158b3642 212static gboolean georef_layer_set_param ( VikGeorefLayer *vgl, guint16 id, VikLayerParamData data, VikViewport *vp, gboolean is_file_operation )
50a14534
EB
213{
214 switch ( id )
215 {
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;
221 }
222 return TRUE;
223}
224
158b3642 225static VikLayerParamData georef_layer_get_param ( VikGeorefLayer *vgl, guint16 id, gboolean is_file_operation )
50a14534
EB
226{
227 VikLayerParamData rv;
228 switch ( id )
229 {
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;
235 }
236 return rv;
237}
238
a7023a1b 239static VikGeorefLayer *georef_layer_new ( VikViewport *vvp )
50a14534
EB
240{
241 VikGeorefLayer *vgl = VIK_GEOREF_LAYER ( g_object_new ( VIK_GEOREF_LAYER_TYPE, NULL ) );
a0c65899 242 vik_layer_set_type ( VIK_LAYER(vgl), VIK_LAYER_GEOREF );
50a14534 243
a7023a1b
RN
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 );
247
26342bd8
RN
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) );
252
50a14534
EB
253 vgl->image = NULL;
254 vgl->pixbuf = NULL;
255 vgl->click_x = -1;
256 vgl->click_y = -1;
f3505ea3
MR
257 vgl->scaled = NULL;
258 vgl->scaled_width = 0;
259 vgl->scaled_height = 0;
50a14534
EB
260 return vgl;
261}
262
fd22ce3e 263static void georef_layer_draw ( VikGeorefLayer *vgl, VikViewport *vp )
50a14534 264{
fd22ce3e
RN
265 if ( vik_viewport_get_drawmode(vp) != VIK_VIEWPORT_DRAWMODE_UTM )
266 return;
267
50a14534
EB
268 if ( vgl->pixbuf )
269 {
50a14534
EB
270 struct UTM utm_middle;
271 gdouble xmpp = vik_viewport_get_xmpp(vp), ympp = vik_viewport_get_ympp(vp);
be75ec20
MR
272 GdkPixbuf *pixbuf = vgl->pixbuf;
273 guint layer_width = vgl->width;
274 guint layer_height = vgl->height;
275
50a14534
EB
276 vik_coord_to_utm ( vik_viewport_get_center ( vp ), &utm_middle );
277
be75ec20
MR
278 guint width = vik_viewport_get_width(vp), height = vik_viewport_get_height(vp);
279 gint32 x, y;
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 );
1b4b9e3b
RN
285
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 )
289 {
290 scale = TRUE;
291 layer_width = round(vgl->width * vgl->mpp_easting / xmpp);
292 layer_height = round(vgl->height * vgl->mpp_northing / ympp);
293 }
294
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 ) {
297
298 if ( scale )
299 {
300 /* rescale if necessary */
301 if (layer_width == vgl->scaled_width && layer_height == vgl->scaled_height && vgl->scaled != NULL)
302 pixbuf = vgl->scaled;
303 else
304 {
305 pixbuf = gdk_pixbuf_scale_simple(
306 vgl->pixbuf,
307 layer_width,
308 layer_height,
309 GDK_INTERP_BILINEAR
310 );
311
312 if (vgl->scaled != NULL)
313 g_object_unref(vgl->scaled);
314
315 vgl->scaled = pixbuf;
316 vgl->scaled_width = layer_width;
317 vgl->scaled_height = layer_height;
318 }
319 }
be75ec20 320 vik_viewport_draw_pixbuf ( vp, pixbuf, 0, 0, x, y, layer_width, layer_height ); /* todo: draw only what we need to. */
1b4b9e3b 321 }
50a14534
EB
322 }
323}
324
325static void georef_layer_free ( VikGeorefLayer *vgl )
326{
327 if ( vgl->image != NULL )
328 g_free ( vgl->image );
f3505ea3
MR
329 if ( vgl->scaled != NULL )
330 g_object_unref ( vgl->scaled );
50a14534
EB
331}
332
a6b90ba4 333static VikGeorefLayer *georef_layer_create ( VikViewport *vp )
50a14534 334{
a7023a1b 335 return georef_layer_new ( vp );
50a14534
EB
336}
337
a6b90ba4 338static gboolean georef_layer_properties ( VikGeorefLayer *vgl, gpointer vp )
50a14534
EB
339{
340 return georef_layer_dialog ( &vgl, vp, VIK_GTK_WINDOW_FROM_WIDGET(vp) );
341}
342
fd22ce3e 343static void georef_layer_load_image ( VikGeorefLayer *vgl, VikViewport *vp, gboolean from_file )
50a14534
EB
344{
345 GError *gx = NULL;
346 if ( vgl->image == NULL )
347 return;
348
349 if ( vgl->pixbuf )
350 g_object_unref ( G_OBJECT(vgl->pixbuf) );
f3505ea3
MR
351 if ( vgl->scaled )
352 {
353 g_object_unref ( G_OBJECT(vgl->scaled) );
354 vgl->scaled = NULL;
355 }
50a14534
EB
356
357 vgl->pixbuf = gdk_pixbuf_new_from_file ( vgl->image, &gx );
358
359 if (gx)
360 {
28424566
RN
361 if ( !from_file )
362 a_dialog_error_msg_extra ( VIK_GTK_WINDOW_FROM_WIDGET(vp), _("Couldn't open image file: %s"), gx->message );
50a14534
EB
363 g_error_free ( gx );
364 }
365 else
366 {
367 vgl->width = gdk_pixbuf_get_width ( vgl->pixbuf );
368 vgl->height = gdk_pixbuf_get_height ( vgl->pixbuf );
369 }
370
fd22ce3e
RN
371 if ( !from_file )
372 {
373 if ( vik_viewport_get_drawmode(vp) != VIK_VIEWPORT_DRAWMODE_UTM )
374 {
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.") );
377 }
378 }
50a14534
EB
379 /* should find length and width here too */
380}
381
382static void georef_layer_set_image ( VikGeorefLayer *vgl, const gchar *image )
383{
384 if ( vgl->image )
385 g_free ( vgl->image );
f3505ea3
MR
386 if ( vgl->scaled )
387 {
388 g_object_unref ( vgl->scaled );
389 vgl->scaled = NULL;
390 }
50a14534
EB
391 if ( image == NULL )
392 vgl->image = NULL;
393 vgl->image = g_strdup ( image );
394}
395
396static gboolean world_file_read_line ( gchar *buffer, gint size, FILE *f, GtkWidget *widget, gboolean use_value )
397{
398 if (!fgets ( buffer, 1024, f ))
399 {
4c77d5e0 400 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_WIDGET(widget), _("Unexpected end of file reading World file.") );
50a14534
EB
401 g_free ( buffer );
402 fclose ( f );
8c060406 403 f = NULL;
50a14534
EB
404 return FALSE;
405 }
406 if ( use_value )
407 {
a0008235 408 gdouble val = g_strtod ( buffer, NULL );
50a14534
EB
409 gtk_spin_button_set_value ( GTK_SPIN_BUTTON(widget), val > 0 ? val : -val );
410 }
411 return TRUE;
412}
413
414static void georef_layer_dialog_load ( GtkWidget *pass_along[4] )
415{
6e4a49aa
MA
416 GtkWidget *file_selector = gtk_file_chooser_dialog_new (_("Choose World file"),
417 NULL,
418 GTK_FILE_CHOOSER_ACTION_OPEN,
419 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
420 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
421 NULL);
422
423 if ( gtk_dialog_run ( GTK_DIALOG ( file_selector ) ) == GTK_RESPONSE_ACCEPT )
50a14534 424 {
8c060406 425 FILE *f = g_fopen ( gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER(file_selector) ), "r" );
50a14534
EB
426 gtk_widget_destroy ( file_selector );
427 if ( !f )
428 {
4c77d5e0 429 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_WIDGET(pass_along[0]), _("The World file you requested could not be opened for reading.") );
50a14534
EB
430 return;
431 }
432 else
433 {
434 gchar *buffer = g_malloc ( 1024 * sizeof(gchar) );
0b647b0b
MA
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)
50a14534
EB
437 && world_file_read_line ( buffer, 1024, f, pass_along[2], TRUE ) && world_file_read_line ( buffer, 1024, f, pass_along[3], TRUE ) )
438 {
439 g_free ( buffer );
440 fclose ( f );
8c060406 441 f = NULL;
50a14534
EB
442 }
443 }
444 }
445 else
446 gtk_widget_destroy ( file_selector );
447/* do your jazz
448We need a
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.
455*/
456}
457
458static void georef_layer_export_params ( gpointer *pass_along[2] )
459{
460 VikGeorefLayer *vgl = VIK_GEOREF_LAYER(pass_along[0]);
6e4a49aa
MA
461 GtkWidget *file_selector = gtk_file_chooser_dialog_new (_("Choose World file"),
462 NULL,
463 GTK_FILE_CHOOSER_ACTION_SAVE,
464 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
465 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
466 NULL);
467 if ( gtk_dialog_run ( GTK_DIALOG ( file_selector ) ) == GTK_RESPONSE_ACCEPT )
50a14534 468 {
8c060406 469 FILE *f = g_fopen ( gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER(file_selector) ), "w" );
6e4a49aa 470
50a14534
EB
471 gtk_widget_destroy ( file_selector );
472 if ( !f )
473 {
4c77d5e0 474 a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_WIDGET(pass_along[0]), _("The file you requested could not be opened for writing.") );
50a14534
EB
475 return;
476 }
477 else
478 {
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 );
480 fclose ( f );
8c060406 481 f = NULL;
50a14534
EB
482 }
483 }
484 else
485 gtk_widget_destroy ( file_selector );
486}
487
488/* returns TRUE if OK was pressed. */
489static gboolean georef_layer_dialog ( VikGeorefLayer **vgl, gpointer vp, GtkWindow *w )
490{
4c77d5e0 491 GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Layer Properties"),
50a14534
EB
492 w,
493 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
494 GTK_STOCK_CANCEL,
495 GTK_RESPONSE_REJECT,
496 GTK_STOCK_OK,
497 GTK_RESPONSE_ACCEPT,
10888930 498 NULL );
535747e9
RN
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 );
504#endif
50a14534
EB
505 GtkWidget *table, *wfp_hbox, *wfp_label, *wfp_button, *ce_label, *ce_spin, *cn_label, *cn_spin, *xlabel, *xspin, *ylabel, *yspin, *imagelabel, *imageentry;
506
507 GtkWidget *pass_along[4];
508
509 table = gtk_table_new ( 6, 2, FALSE );
9b082b39 510 gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), table, TRUE, TRUE, 0 );
50a14534
EB
511
512 wfp_hbox = gtk_hbox_new ( FALSE, 0 );
4c77d5e0
GB
513 wfp_label = gtk_label_new ( _("World File Parameters:") );
514 wfp_button = gtk_button_new_with_label ( _("Load From File...") );
50a14534
EB
515
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 );
518
4c77d5e0 519 ce_label = gtk_label_new ( _("Corner pixel easting:") );
ac33062d 520 ce_spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, 0.0, 1500000.0, 1, 5, 0 ), 1, 4 );
09b2a3c9 521 gtk_widget_set_tooltip_text ( GTK_WIDGET(ce_spin), _("the UTM \"easting\" value of the upper-left corner pixel of the map") );
50a14534 522
4c77d5e0 523 cn_label = gtk_label_new ( _("Corner pixel northing:") );
ac33062d 524 cn_spin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, 0.0, 9000000.0, 1, 5, 0 ), 1, 4 );
09b2a3c9 525 gtk_widget_set_tooltip_text ( GTK_WIDGET(cn_spin), _("the UTM \"northing\" value of the upper-left corner pixel of the map") );
50a14534 526
4c77d5e0
GB
527 xlabel = gtk_label_new ( _("X (easting) scale (mpp): "));
528 ylabel = gtk_label_new ( _("Y (northing) scale (mpp): "));
50a14534 529
ac33062d 530 xspin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, VIK_VIEWPORT_MIN_ZOOM, VIK_VIEWPORT_MAX_ZOOM, 1, 5, 0 ), 1, 8 );
79a9a44f 531 gtk_widget_set_tooltip_text ( GTK_WIDGET(xspin), _("the scale of the map in the X direction (meters per pixel)") );
ac33062d 532 yspin = gtk_spin_button_new ( (GtkAdjustment *) gtk_adjustment_new ( 4, VIK_VIEWPORT_MIN_ZOOM, VIK_VIEWPORT_MAX_ZOOM, 1, 5, 0 ), 1, 8 );
79a9a44f 533 gtk_widget_set_tooltip_text ( GTK_WIDGET(yspin), _("the scale of the map in the Y direction (meters per pixel)") );
50a14534 534
4c77d5e0 535 imagelabel = gtk_label_new ( _("Map Image:") );
79672b85 536 imageentry = vik_file_entry_new (GTK_FILE_CHOOSER_ACTION_OPEN);
50a14534
EB
537
538 if (*vgl)
539 {
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 );
544 if ( (*vgl)->image )
545 vik_file_entry_set_filename ( VIK_FILE_ENTRY(imageentry), (*vgl)->image );
546 }
547 else
548 {
549 VikCoord corner_coord;
550 struct UTM utm;
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) ) );
557 }
558
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 );
570
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 );
576
535747e9
RN
577 if ( response_w )
578 gtk_widget_grab_focus ( response_w );
579
50a14534
EB
580 gtk_widget_show_all ( table );
581
582 if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
583 {
584 if (! *vgl)
585 {
a7023a1b 586 *vgl = georef_layer_new ( VIK_VIEWPORT(vp) );
50a14534
EB
587 vik_layer_rename ( VIK_LAYER(*vgl), vik_georef_layer_interface.name );
588 }
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 )
594 {
595 georef_layer_set_image ( *vgl, vik_file_entry_get_filename(VIK_FILE_ENTRY(imageentry)) );
fd22ce3e 596 georef_layer_load_image ( *vgl, VIK_VIEWPORT(vp), FALSE );
50a14534
EB
597 }
598
599 gtk_widget_destroy ( GTK_WIDGET(dialog) );
600 return TRUE;
601 }
602 gtk_widget_destroy ( GTK_WIDGET(dialog) );
603 return FALSE;
604}
605
606static void georef_layer_zoom_to_fit ( gpointer vgl_vlp[2] )
607{
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]) );
611}
612
613static void georef_layer_goto_center ( gpointer vgl_vlp[2] )
614{
615 VikGeorefLayer *vgl = VIK_GEOREF_LAYER ( vgl_vlp[0] );
616 VikViewport *vp = vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vgl_vlp[1]));
617 struct UTM utm;
618 VikCoord coord;
619
620 vik_coord_to_utm ( vik_viewport_get_center ( vp ), &utm );
621
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);
624
625 vik_coord_load_from_utm ( &coord, vik_viewport_get_coord_mode ( vp ), &utm );
626 vik_viewport_set_center_coord ( vp, &coord );
627
628 vik_layers_panel_emit_update ( VIK_LAYERS_PANEL(vgl_vlp[1]) );
629}
630
631static void georef_layer_add_menu_items ( VikGeorefLayer *vgl, GtkMenu *menu, gpointer vlp )
632{
633 static gpointer pass_along[2];
634 GtkWidget *item;
635 pass_along[0] = vgl;
636 pass_along[1] = vlp;
637
638 item = gtk_menu_item_new();
639 gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
640 gtk_widget_show ( item );
641
d6de71f9
RN
642 /* Now with icons */
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) );
50a14534
EB
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 );
648
d6de71f9
RN
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) );
50a14534
EB
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 );
654
d6de71f9
RN
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) );
50a14534
EB
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 );
660}
661
941aa6e9
AF
662
663static gpointer georef_layer_move_create ( VikWindow *vw, VikViewport *vvp)
664{
665 return vvp;
666}
667
50a14534
EB
668static gboolean georef_layer_move_release ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp )
669{
941aa6e9
AF
670 if (!vgl || vgl->vl.type != VIK_LAYER_GEOREF)
671 return FALSE;
672
50a14534
EB
673 if ( vgl->click_x != -1 )
674 {
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);
da121f9b 677 vik_layer_emit_update ( VIK_LAYER(vgl) );
50a14534
EB
678 return TRUE;
679 }
680 return FALSE; /* I didn't move anything on this layer! */
681}
682
941aa6e9
AF
683static gpointer georef_layer_zoom_create ( VikWindow *vw, VikViewport *vvp)
684{
685 return vvp;
686}
687
50a14534
EB
688static gboolean georef_layer_zoom_press ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp )
689{
941aa6e9
AF
690 if (!vgl || vgl->vl.type != VIK_LAYER_GEOREF)
691 return FALSE;
50a14534
EB
692 if ( event->button == 1 )
693 {
694 if ( vgl->mpp_easting < (VIK_VIEWPORT_MAX_ZOOM / 1.05) && vgl->mpp_northing < (VIK_VIEWPORT_MAX_ZOOM / 1.05) )
695 {
696 vgl->mpp_easting *= 1.01;
697 vgl->mpp_northing *= 1.01;
698 }
699 }
700 else
701 {
702 if ( vgl->mpp_easting > (VIK_VIEWPORT_MIN_ZOOM * 1.05) && vgl->mpp_northing > (VIK_VIEWPORT_MIN_ZOOM * 1.05) )
703 {
704 vgl->mpp_easting /= 1.01;
705 vgl->mpp_northing /= 1.01;
706 }
707 }
708 vik_viewport_set_xmpp ( vvp, vgl->mpp_easting );
709 vik_viewport_set_ympp ( vvp, vgl->mpp_northing );
da121f9b 710 vik_layer_emit_update ( VIK_LAYER(vgl) );
50a14534
EB
711 return TRUE;
712}
713
714static gboolean georef_layer_move_press ( VikGeorefLayer *vgl, GdkEventButton *event, VikViewport *vvp )
715{
941aa6e9
AF
716 if (!vgl || vgl->vl.type != VIK_LAYER_GEOREF)
717 return FALSE;
50a14534
EB
718 vgl->click_x = event->x;
719 vgl->click_y = event->y;
720 return TRUE;
721}