]> git.street.me.uk Git - andy/viking.git/blame - src/vikcoordlayer.c
Fix layer defaults fix, which breaks setting the layer defaults.
[andy/viking.git] / src / vikcoordlayer.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 */
4c77d5e0
GB
21#ifdef HAVE_CONFIG_H
22#include "config.h"
23#endif
8c00358d
GB
24
25#ifdef HAVE_MATH_H
80e450c0 26#include <math.h>
8c00358d 27#endif
4c77d5e0 28#include <glib/gi18n.h>
50a14534
EB
29
30#include "viking.h"
5bfafde9 31#include "icons/icons.h"
50a14534 32
a7023a1b 33static VikCoordLayer *coord_layer_new ( );
0a6cab71
AF
34static void coord_layer_marshall( VikCoordLayer *vcl, guint8 **data, gint *len );
35static VikCoordLayer *coord_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp );
158b3642
RN
36static gboolean coord_layer_set_param ( VikCoordLayer *vcl, guint16 id, VikLayerParamData data, VikViewport *vp, gboolean is_file_operation );
37static VikLayerParamData coord_layer_get_param ( VikCoordLayer *vcl, guint16 id, gboolean is_file_operation );
07059501 38static void coord_layer_post_read ( VikLayer *vl, VikViewport *vp, gboolean from_file );
50a14534 39
ad0a8c2d 40static VikLayerParamScale param_scales[] = {
50a14534
EB
41 { 0.05, 60.0, 0.25, 10 },
42 { 1, 10, 1, 0 },
43};
44
a7023a1b
RN
45static VikLayerParamData color_default ( void ) {
46 VikLayerParamData data; gdk_color_parse ( "red", &data.c ); return data;
47 // or: return VIK_LPD_COLOR ( 0, 65535, 0, 0 );
48}
49static VikLayerParamData min_inc_default ( void ) { return VIK_LPD_DOUBLE ( 1.0 ); }
50static VikLayerParamData line_thickness_default ( void ) { return VIK_LPD_UINT ( 3 ); }
51
ad0a8c2d 52static VikLayerParam coord_layer_params[] = {
a7023a1b
RN
53 { VIK_LAYER_COORD, "color", VIK_LAYER_PARAM_COLOR, VIK_LAYER_GROUP_NONE, N_("Color:"), VIK_LAYER_WIDGET_COLOR, NULL, NULL, NULL, color_default },
54 { VIK_LAYER_COORD, "min_inc", VIK_LAYER_PARAM_DOUBLE, VIK_LAYER_GROUP_NONE, N_("Minutes Width:"), VIK_LAYER_WIDGET_SPINBUTTON, &param_scales[0], NULL, NULL, min_inc_default },
55 { VIK_LAYER_COORD, "line_thickness", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Line Thickness:"), VIK_LAYER_WIDGET_SPINBUTTON, &param_scales[1], NULL, NULL, line_thickness_default },
50a14534
EB
56};
57
50a14534
EB
58enum { PARAM_COLOR = 0, PARAM_MIN_INC, PARAM_LINE_THICKNESS, NUM_PARAMS };
59
60VikLayerInterface vik_coord_layer_interface = {
db386630 61 "Coord",
affcc0f2 62 N_("Coordinate"),
75078768 63 NULL,
5bfafde9 64 &vikcoordlayer_pixbuf,
50a14534
EB
65
66 NULL,
67 0,
68
69 coord_layer_params,
70 NUM_PARAMS,
71 NULL,
72 0,
73
5a4a28bf
QT
74 VIK_MENU_ITEM_ALL,
75
50a14534
EB
76 (VikLayerFuncCreate) vik_coord_layer_create,
77 (VikLayerFuncRealize) NULL,
b112cbf5 78 (VikLayerFuncPostRead) coord_layer_post_read,
50a14534
EB
79 (VikLayerFuncFree) vik_coord_layer_free,
80
81 (VikLayerFuncProperties) NULL,
82 (VikLayerFuncDraw) vik_coord_layer_draw,
83 (VikLayerFuncChangeCoordMode) NULL,
84
20c7a3a0
QT
85 (VikLayerFuncSetMenuItemsSelection) NULL,
86 (VikLayerFuncGetMenuItemsSelection) NULL,
87
50a14534
EB
88 (VikLayerFuncAddMenuItems) NULL,
89 (VikLayerFuncSublayerAddMenuItems) NULL,
90
91 (VikLayerFuncSublayerRenameRequest) NULL,
92 (VikLayerFuncSublayerToggleVisible) NULL,
9da7faf2 93 (VikLayerFuncSublayerTooltip) NULL,
1e8b7f57 94 (VikLayerFuncLayerTooltip) NULL,
a5dcfdb7 95 (VikLayerFuncLayerSelected) NULL,
50a14534 96
0a6cab71
AF
97 (VikLayerFuncMarshall) coord_layer_marshall,
98 (VikLayerFuncUnmarshall) coord_layer_unmarshall,
50a14534
EB
99
100 (VikLayerFuncSetParam) coord_layer_set_param,
101 (VikLayerFuncGetParam) coord_layer_get_param,
102
103 (VikLayerFuncReadFileData) NULL,
104 (VikLayerFuncWriteFileData) NULL,
105
33534cd8 106 (VikLayerFuncDeleteItem) NULL,
d5874ef9 107 (VikLayerFuncCutItem) NULL,
50a14534
EB
108 (VikLayerFuncCopyItem) NULL,
109 (VikLayerFuncPasteItem) NULL,
110 (VikLayerFuncFreeCopiedItem) NULL,
70a23263 111 (VikLayerFuncDragDropRequest) NULL,
77ad64fa
RN
112
113 (VikLayerFuncSelectClick) NULL,
08f14055
RN
114 (VikLayerFuncSelectMove) NULL,
115 (VikLayerFuncSelectRelease) NULL,
e46f259a 116 (VikLayerFuncSelectedViewportMenu) NULL,
50a14534
EB
117};
118
119struct _VikCoordLayer {
120 VikLayer vl;
121 GdkGC *gc;
122 gdouble deg_inc;
123 guint8 line_thickness;
280e71ab 124 GdkColor color;
50a14534
EB
125};
126
127GType vik_coord_layer_get_type ()
128{
129 static GType vcl_type = 0;
130
131 if (!vcl_type)
132 {
133 static const GTypeInfo vcl_info =
134 {
135 sizeof (VikCoordLayerClass),
136 NULL, /* base_init */
137 NULL, /* base_finalize */
138 NULL, /* class init */
139 NULL, /* class_finalize */
140 NULL, /* class_data */
141 sizeof (VikCoordLayer),
142 0,
143 NULL /* instance init */
144 };
145 vcl_type = g_type_register_static ( VIK_LAYER_TYPE, "VikCoordLayer", &vcl_info, 0 );
146 }
147
148 return vcl_type;
149}
150
0a6cab71
AF
151static void coord_layer_marshall( VikCoordLayer *vcl, guint8 **data, gint *len )
152{
153 vik_layer_marshall_params ( VIK_LAYER(vcl), data, len );
154}
155
156static VikCoordLayer *coord_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp )
157{
a7023a1b 158 VikCoordLayer *rv = coord_layer_new ();
0a6cab71
AF
159 vik_layer_unmarshall_params ( VIK_LAYER(rv), data, len, vvp );
160 return rv;
161}
162
280e71ab 163// NB VikViewport can be null as it's not used ATM
158b3642 164gboolean coord_layer_set_param ( VikCoordLayer *vcl, guint16 id, VikLayerParamData data, VikViewport *vp, gboolean is_file_operation )
50a14534
EB
165{
166 switch ( id )
167 {
280e71ab 168 case PARAM_COLOR: vcl->color = data.c; break;
50a14534
EB
169 case PARAM_MIN_INC: vcl->deg_inc = data.d / 60.0; break;
170 case PARAM_LINE_THICKNESS: if ( data.u >= 1 && data.u <= 15 ) vcl->line_thickness = data.u; break;
171 }
172 return TRUE;
173}
174
158b3642 175static VikLayerParamData coord_layer_get_param ( VikCoordLayer *vcl, guint16 id, gboolean is_file_operation )
50a14534
EB
176{
177 VikLayerParamData rv;
178 switch ( id )
179 {
280e71ab 180 case PARAM_COLOR: rv.c = vcl->color; break;
50a14534
EB
181 case PARAM_MIN_INC: rv.d = vcl->deg_inc * 60.0; break;
182 case PARAM_LINE_THICKNESS: rv.i = vcl->line_thickness; break;
183 }
184 return rv;
185}
186
07059501 187static void coord_layer_post_read ( VikLayer *vl, VikViewport *vp, gboolean from_file )
50a14534 188{
94933cb8 189 VikCoordLayer *vcl = VIK_COORD_LAYER(vl);
50a14534
EB
190 if ( vcl->gc )
191 g_object_unref ( G_OBJECT(vcl->gc) );
192
280e71ab 193 vcl->gc = vik_viewport_new_gc_from_color ( vp, &(vcl->color), vcl->line_thickness );
50a14534
EB
194}
195
a7023a1b 196static VikCoordLayer *coord_layer_new ( VikViewport *vvp )
50a14534
EB
197{
198 VikCoordLayer *vcl = VIK_COORD_LAYER ( g_object_new ( VIK_COORD_LAYER_TYPE, NULL ) );
a0c65899 199 vik_layer_set_type ( VIK_LAYER(vcl), VIK_LAYER_COORD );
50a14534 200
a7023a1b 201 vik_layer_set_defaults ( VIK_LAYER(vcl), vvp );
ac68cea3 202
50a14534 203 vcl->gc = NULL;
a7023a1b 204
50a14534
EB
205 return vcl;
206}
207
208void vik_coord_layer_draw ( VikCoordLayer *vcl, gpointer data )
209{
210 VikViewport *vp = (VikViewport *) data;
80e450c0
AF
211
212 if ( !vcl->gc ) {
50a14534 213 return;
80e450c0
AF
214 }
215
216 if ( vik_viewport_get_coord_mode(vp) != VIK_COORD_UTM )
217 {
218 VikCoord left, right, left2, right2;
219 gdouble l, r, i, j;
220 gint x1, y1, x2, y2, smod = 1, mmod = 1;
221 gboolean mins = FALSE, secs = FALSE;
280e71ab
RN
222 GdkGC *dgc = vik_viewport_new_gc_from_color(vp, &(vcl->color), vcl->line_thickness);
223 GdkGC *mgc = vik_viewport_new_gc_from_color(vp, &(vcl->color), MAX(vcl->line_thickness/2, 1));
224 GdkGC *sgc = vik_viewport_new_gc_from_color(vp, &(vcl->color), MAX(vcl->line_thickness/5, 1));
80e450c0
AF
225
226 vik_viewport_screen_to_coord ( vp, 0, 0, &left );
227 vik_viewport_screen_to_coord ( vp, vik_viewport_get_width(vp), 0, &right );
228 vik_viewport_screen_to_coord ( vp, 0, vik_viewport_get_height(vp), &left2 );
229 vik_viewport_screen_to_coord ( vp, vik_viewport_get_width(vp), vik_viewport_get_height(vp), &right2 );
230
231#define CLINE(gc, c1, c2) { \
232 vik_viewport_coord_to_screen(vp, (c1), &x1, &y1); \
233 vik_viewport_coord_to_screen(vp, (c2), &x2, &y2); \
234 vik_viewport_draw_line (vp, (gc), x1, y1, x2, y2); \
235 }
236
237 l = left.east_west;
238 r = right.east_west;
239 if (60*fabs(l-r) < 4) {
240 secs = TRUE;
241 smod = MIN(6, (int)ceil(3600*fabs(l-r)/30.0));
242 }
243 if (fabs(l-r) < 4) {
244 mins = TRUE;
245 mmod = MIN(6, (int)ceil(60*fabs(l-r)/30.0));
246 }
247 for (i=floor(l*60); i<ceil(r*60); i+=1.0) {
248 if (secs) {
249 for (j=i*60+1; j<(i+1)*60; j+=1.0) {
250 left.east_west = j/3600.0;
251 left2.east_west = j/3600.0;
252 if ((int)j % smod == 0) CLINE(sgc, &left, &left2);
253 }
254 }
255 if (mins) {
256 left.east_west = i/60.0;
257 left2.east_west = i/60.0;
258 if ((int)i % mmod == 0) CLINE(mgc, &left, &left2);
259 }
260 if ((int)i % 60 == 0) {
261 left.east_west = i/60.0;
262 left2.east_west = i/60.0;
263 CLINE(dgc, &left, &left2);
264 }
265 }
266
267 vik_viewport_screen_to_coord ( vp, 0, 0, &left );
268 l = left2.north_south;
269 r = left.north_south;
270 for (i=floor(l*60); i<ceil(r*60); i+=1.0) {
271 if (secs) {
272 for (j=i*60+1; j<(i+1)*60; j+=1.0) {
273 left.north_south = j/3600.0;
274 right.north_south = j/3600.0;
275 if ((int)j % smod == 0) CLINE(sgc, &left, &right);
276 }
277 }
278 if (mins) {
279 left.north_south = i/60.0;
280 right.north_south = i/60.0;
281 if ((int)i % mmod == 0) CLINE(mgc, &left, &right);
282 }
283 if ((int)i % 60 == 0) {
284 left.north_south = i/60.0;
285 right.north_south = i/60.0;
286 CLINE(dgc, &left, &right);
287 }
288 }
289#undef CLINE
290 g_object_unref(dgc);
291 g_object_unref(sgc);
292 g_object_unref(mgc);
293 return;
294 }
295
296 if ( vik_viewport_get_coord_mode(vp) == VIK_COORD_UTM )
50a14534
EB
297 {
298 const struct UTM *center = (const struct UTM *)vik_viewport_get_center ( vp );
299 gdouble xmpp = vik_viewport_get_xmpp ( vp ), ympp = vik_viewport_get_ympp ( vp );
300 guint16 width = vik_viewport_get_width ( vp ), height = vik_viewport_get_height ( vp );
301 struct LatLon ll, ll2, min, max;
302 double lon;
303 int x1, x2;
304 struct UTM utm;
305
306 utm = *center;
307 utm.northing = center->northing - ( ympp * height / 2 );
308
309 a_coords_utm_to_latlon ( &utm, &ll );
310
311 utm.northing = center->northing + ( ympp * height / 2 );
312
313 a_coords_utm_to_latlon ( &utm, &ll2 );
314
315 {
316 /* find corner coords in lat/lon.
317 start at whichever is less: top or bottom left lon. goto whichever more: top or bottom right lon
318 */
319 struct LatLon topleft, topright, bottomleft, bottomright;
320 struct UTM temp_utm;
321 temp_utm = *center;
322 temp_utm.easting -= (width/2)*xmpp;
323 temp_utm.northing += (height/2)*ympp;
324 a_coords_utm_to_latlon ( &temp_utm, &topleft );
325 temp_utm.easting += (width*xmpp);
326 a_coords_utm_to_latlon ( &temp_utm, &topright );
327 temp_utm.northing -= (height*ympp);
328 a_coords_utm_to_latlon ( &temp_utm, &bottomright );
329 temp_utm.easting -= (width*xmpp);
330 a_coords_utm_to_latlon ( &temp_utm, &bottomleft );
331 min.lon = (topleft.lon < bottomleft.lon) ? topleft.lon : bottomleft.lon;
332 max.lon = (topright.lon > bottomright.lon) ? topright.lon : bottomright.lon;
333 min.lat = (bottomleft.lat < bottomright.lat) ? bottomleft.lat : bottomright.lat;
334 max.lat = (topleft.lat > topright.lat) ? topleft.lat : topright.lat;
335 }
336
5b1d90a5
RN
337 /* Can zoom out more than whole world and so the above can give invalid positions */
338 /* Restrict values properly so drawing doesn't go into a near 'infinite' loop */
339 if ( min.lon < -180.0 )
340 min.lon = -180.0;
341 if ( max.lon > 180.0 )
342 max.lon = 180.0;
343 if ( min.lat < -90.0 )
344 min.lat = -90.0;
345 if ( max.lat > 90.0 )
346 max.lat = 90.0;
347
50a14534
EB
348 lon = ((double) ((long) ((min.lon)/ vcl->deg_inc))) * vcl->deg_inc;
349 ll.lon = ll2.lon = lon;
350
351 for (; ll.lon <= max.lon; ll.lon+=vcl->deg_inc, ll2.lon+=vcl->deg_inc )
352 {
353 a_coords_latlon_to_utm ( &ll, &utm );
354 x1 = ( (utm.easting - center->easting) / xmpp ) + (width / 2);
355 a_coords_latlon_to_utm ( &ll2, &utm );
356 x2 = ( (utm.easting - center->easting) / xmpp ) + (width / 2);
357 vik_viewport_draw_line (vp, vcl->gc, x1, height, x2, 0);
358 }
359
360 utm = *center;
361 utm.easting = center->easting - ( xmpp * width / 2 );
362
363 a_coords_utm_to_latlon ( &utm, &ll );
364
365 utm.easting = center->easting + ( xmpp * width / 2 );
366
367 a_coords_utm_to_latlon ( &utm, &ll2 );
368
369 /* really lat, just reusing a variable */
370 lon = ((double) ((long) ((min.lat)/ vcl->deg_inc))) * vcl->deg_inc;
371 ll.lat = ll2.lat = lon;
372
373 for (; ll.lat <= max.lat ; ll.lat+=vcl->deg_inc, ll2.lat+=vcl->deg_inc )
374 {
375 a_coords_latlon_to_utm ( &ll, &utm );
376 x1 = (height / 2) - ( (utm.northing - center->northing) / ympp );
377 a_coords_latlon_to_utm ( &ll2, &utm );
378 x2 = (height / 2) - ( (utm.northing - center->northing) / ympp );
379 vik_viewport_draw_line (vp, vcl->gc, width, x2, 0, x1);
380 }
381 }
382}
383
384void vik_coord_layer_free ( VikCoordLayer *vcl )
385{
386 if ( vcl->gc != NULL )
387 g_object_unref ( G_OBJECT(vcl->gc) );
50a14534
EB
388}
389
280e71ab 390static void coord_layer_update_gc ( VikCoordLayer *vcl, VikViewport *vp )
50a14534 391{
50a14534
EB
392 if ( vcl->gc )
393 g_object_unref ( G_OBJECT(vcl->gc) );
394
280e71ab 395 vcl->gc = vik_viewport_new_gc_from_color ( vp, &(vcl->color), vcl->line_thickness );
50a14534
EB
396}
397
398VikCoordLayer *vik_coord_layer_create ( VikViewport *vp )
399{
a7023a1b 400 VikCoordLayer *vcl = coord_layer_new ( vp );
8aff54f2 401 if ( vp )
a7023a1b 402 coord_layer_update_gc ( vcl, vp );
50a14534
EB
403 return vcl;
404}