]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * viking -- GPS Data and Topo Analyzer, Explorer, and Manager | |
3 | * | |
4 | * Copyright (C) 2005, Alex Foobarian <foobarian@gmail.com> | |
5 | * Copyright (C) 2003-2007, Evan Battaglia <gtoevan@gmx.net> | |
6 | * Copyright (C) 2013, Rob Norris <rw_norris@hotmail.com> | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License as published by | |
10 | * the Free Software Foundation; either version 2 of the License, or | |
11 | * (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 | * | |
22 | */ | |
23 | ||
24 | #ifdef HAVE_CONFIG_H | |
25 | #include "config.h" | |
26 | #endif | |
27 | ||
28 | #include <glib/gi18n.h> | |
29 | ||
30 | #include "viking.h" | |
31 | #include <string.h> | |
32 | #include <stdlib.h> | |
33 | #include "viklayer_defaults.h" | |
34 | ||
35 | /* functions common to all layers. */ | |
36 | /* TODO longone: rename interface free -> finalize */ | |
37 | ||
38 | extern VikLayerInterface vik_aggregate_layer_interface; | |
39 | extern VikLayerInterface vik_trw_layer_interface; | |
40 | extern VikLayerInterface vik_maps_layer_interface; | |
41 | extern VikLayerInterface vik_coord_layer_interface; | |
42 | extern VikLayerInterface vik_georef_layer_interface; | |
43 | extern VikLayerInterface vik_gps_layer_interface; | |
44 | extern VikLayerInterface vik_dem_layer_interface; | |
45 | #ifdef HAVE_LIBMAPNIK | |
46 | extern VikLayerInterface vik_mapnik_layer_interface; | |
47 | #endif | |
48 | ||
49 | enum { | |
50 | VL_UPDATE_SIGNAL, | |
51 | VL_LAST_SIGNAL | |
52 | }; | |
53 | static guint layer_signals[VL_LAST_SIGNAL] = { 0 }; | |
54 | ||
55 | static GObjectClass *parent_class; | |
56 | ||
57 | static void vik_layer_finalize ( VikLayer *vl ); | |
58 | static gboolean vik_layer_properties_factory ( VikLayer *vl, VikViewport *vp ); | |
59 | static gboolean layer_defaults_register ( VikLayerTypeEnum type ); | |
60 | ||
61 | G_DEFINE_TYPE (VikLayer, vik_layer, G_TYPE_OBJECT) | |
62 | ||
63 | static void vik_layer_class_init (VikLayerClass *klass) | |
64 | { | |
65 | GObjectClass *object_class; | |
66 | ||
67 | object_class = G_OBJECT_CLASS (klass); | |
68 | ||
69 | object_class->finalize = (GObjectFinalizeFunc) vik_layer_finalize; | |
70 | ||
71 | parent_class = g_type_class_peek_parent (klass); | |
72 | ||
73 | layer_signals[VL_UPDATE_SIGNAL] = g_signal_new ( "update", G_TYPE_FROM_CLASS (klass), | |
74 | G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (VikLayerClass, update), NULL, NULL, | |
75 | g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); | |
76 | ||
77 | // Register all parameter defaults, early in the start up sequence | |
78 | VikLayerTypeEnum layer; | |
79 | for ( layer = 0; layer < VIK_LAYER_NUM_TYPES; layer++ ) | |
80 | // ATM ignore the returned value | |
81 | layer_defaults_register ( layer ); | |
82 | } | |
83 | ||
84 | /** | |
85 | * Invoke the actual drawing via signal method | |
86 | */ | |
87 | static gboolean idle_draw ( VikLayer *vl ) | |
88 | { | |
89 | g_signal_emit ( G_OBJECT(vl), layer_signals[VL_UPDATE_SIGNAL], 0 ); | |
90 | return FALSE; // Nothing else to do | |
91 | } | |
92 | ||
93 | /** | |
94 | * Draw specified layer | |
95 | */ | |
96 | void vik_layer_emit_update ( VikLayer *vl ) | |
97 | { | |
98 | if ( vl->visible && vl->realized ) { | |
99 | GThread *thread = vik_window_get_thread ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vl)) ); | |
100 | if ( !thread ) | |
101 | // Do nothing | |
102 | return; | |
103 | ||
104 | vik_window_set_redraw_trigger(vl); | |
105 | ||
106 | // Only ever draw when there is time to do so | |
107 | if ( g_thread_self() != thread ) | |
108 | // Drawing requested from another (background) thread, so handle via the gdk thread method | |
109 | gdk_threads_add_idle ( (GSourceFunc) idle_draw, vl ); | |
110 | else | |
111 | g_idle_add ( (GSourceFunc) idle_draw, vl ); | |
112 | } | |
113 | } | |
114 | ||
115 | /** | |
116 | * should only be done by VikLayersPanel (hence never used from the background) | |
117 | * need to redraw and record trigger when we make a layer invisible. | |
118 | */ | |
119 | void vik_layer_emit_update_although_invisible ( VikLayer *vl ) | |
120 | { | |
121 | vik_window_set_redraw_trigger(vl); | |
122 | g_idle_add ( (GSourceFunc) idle_draw, vl ); | |
123 | } | |
124 | ||
125 | /* doesn't set the trigger. should be done by aggregate layer when child emits update. */ | |
126 | void vik_layer_emit_update_secondary ( VikLayer *vl ) | |
127 | { | |
128 | if ( vl->visible ) | |
129 | // TODO: this can used from the background - eg in acquire | |
130 | // so will need to flow background update status through too | |
131 | g_idle_add ( (GSourceFunc) idle_draw, vl ); | |
132 | } | |
133 | ||
134 | static VikLayerInterface *vik_layer_interfaces[VIK_LAYER_NUM_TYPES] = { | |
135 | &vik_aggregate_layer_interface, | |
136 | &vik_trw_layer_interface, | |
137 | &vik_coord_layer_interface, | |
138 | &vik_georef_layer_interface, | |
139 | &vik_gps_layer_interface, | |
140 | &vik_maps_layer_interface, | |
141 | &vik_dem_layer_interface, | |
142 | #ifdef HAVE_LIBMAPNIK | |
143 | &vik_mapnik_layer_interface, | |
144 | #endif | |
145 | }; | |
146 | ||
147 | VikLayerInterface *vik_layer_get_interface ( VikLayerTypeEnum type ) | |
148 | { | |
149 | g_assert ( type < VIK_LAYER_NUM_TYPES ); | |
150 | return vik_layer_interfaces[type]; | |
151 | } | |
152 | ||
153 | /** | |
154 | * Store default values for this layer | |
155 | * | |
156 | * Returns whether any parameters where registered | |
157 | */ | |
158 | static gboolean layer_defaults_register ( VikLayerTypeEnum type ) | |
159 | { | |
160 | // See if any parameters | |
161 | VikLayerParam *params = vik_layer_interfaces[type]->params; | |
162 | if ( ! params ) | |
163 | return FALSE; | |
164 | ||
165 | gboolean answer = FALSE; // Incase all parameters are 'not in properties' | |
166 | guint16 params_count = vik_layer_interfaces[type]->params_count; | |
167 | guint16 i; | |
168 | // Process each parameter | |
169 | for ( i = 0; i < params_count; i++ ) { | |
170 | if ( params[i].group != VIK_LAYER_NOT_IN_PROPERTIES ) { | |
171 | if ( params[i].default_value ) { | |
172 | VikLayerParamData paramd = params[i].default_value(); | |
173 | a_layer_defaults_register ( ¶ms[i], paramd, vik_layer_interfaces[type]->fixed_layer_name ); | |
174 | answer = TRUE; | |
175 | } | |
176 | } | |
177 | } | |
178 | ||
179 | return answer; | |
180 | } | |
181 | ||
182 | static void vik_layer_init ( VikLayer *vl ) | |
183 | { | |
184 | vl->visible = TRUE; | |
185 | vl->name = NULL; | |
186 | vl->realized = FALSE; | |
187 | } | |
188 | ||
189 | void vik_layer_set_type ( VikLayer *vl, VikLayerTypeEnum type ) | |
190 | { | |
191 | vl->type = type; | |
192 | } | |
193 | ||
194 | /* frees old name */ | |
195 | void vik_layer_rename ( VikLayer *l, const gchar *new_name ) | |
196 | { | |
197 | g_assert ( l != NULL ); | |
198 | g_assert ( new_name != NULL ); | |
199 | g_free ( l->name ); | |
200 | l->name = g_strdup ( new_name ); | |
201 | } | |
202 | ||
203 | void vik_layer_rename_no_copy ( VikLayer *l, gchar *new_name ) | |
204 | { | |
205 | g_assert ( l != NULL ); | |
206 | g_assert ( new_name != NULL ); | |
207 | g_free ( l->name ); | |
208 | l->name = new_name; | |
209 | } | |
210 | ||
211 | const gchar *vik_layer_get_name ( VikLayer *l ) | |
212 | { | |
213 | g_assert ( l != NULL); | |
214 | return l->name; | |
215 | } | |
216 | ||
217 | time_t vik_layer_get_timestamp ( VikLayer *vl ) | |
218 | { | |
219 | if ( vik_layer_interfaces[vl->type]->get_timestamp ) | |
220 | return vik_layer_interfaces[vl->type]->get_timestamp ( vl ); | |
221 | return 0; | |
222 | } | |
223 | ||
224 | VikLayer *vik_layer_create ( VikLayerTypeEnum type, VikViewport *vp, gboolean interactive ) | |
225 | { | |
226 | VikLayer *new_layer = NULL; | |
227 | g_assert ( type < VIK_LAYER_NUM_TYPES ); | |
228 | ||
229 | new_layer = vik_layer_interfaces[type]->create ( vp ); | |
230 | ||
231 | g_assert ( new_layer != NULL ); | |
232 | ||
233 | if ( interactive ) | |
234 | { | |
235 | if ( vik_layer_properties ( new_layer, vp ) ) | |
236 | /* We translate the name here */ | |
237 | /* in order to avoid translating name set by user */ | |
238 | vik_layer_rename ( VIK_LAYER(new_layer), _(vik_layer_interfaces[type]->name) ); | |
239 | else | |
240 | { | |
241 | g_object_unref ( G_OBJECT(new_layer) ); /* cancel that */ | |
242 | new_layer = NULL; | |
243 | } | |
244 | } | |
245 | return new_layer; | |
246 | } | |
247 | ||
248 | /* returns TRUE if OK was pressed */ | |
249 | gboolean vik_layer_properties ( VikLayer *layer, VikViewport *vp ) | |
250 | { | |
251 | if ( vik_layer_interfaces[layer->type]->properties ) | |
252 | return vik_layer_interfaces[layer->type]->properties ( layer, vp ); | |
253 | return vik_layer_properties_factory ( layer, vp ); | |
254 | } | |
255 | ||
256 | void vik_layer_draw ( VikLayer *l, VikViewport *vp ) | |
257 | { | |
258 | if ( l->visible ) | |
259 | if ( vik_layer_interfaces[l->type]->draw ) | |
260 | vik_layer_interfaces[l->type]->draw ( l, vp ); | |
261 | } | |
262 | ||
263 | void vik_layer_change_coord_mode ( VikLayer *l, VikCoordMode mode ) | |
264 | { | |
265 | if ( vik_layer_interfaces[l->type]->change_coord_mode ) | |
266 | vik_layer_interfaces[l->type]->change_coord_mode ( l, mode ); | |
267 | } | |
268 | ||
269 | typedef struct { | |
270 | VikLayerTypeEnum layer_type; | |
271 | gint len; | |
272 | guint8 data[0]; | |
273 | } header_t; | |
274 | ||
275 | void vik_layer_marshall ( VikLayer *vl, guint8 **data, gint *len ) | |
276 | { | |
277 | header_t *header; | |
278 | if ( vl && vik_layer_interfaces[vl->type]->marshall ) { | |
279 | vik_layer_interfaces[vl->type]->marshall ( vl, data, len ); | |
280 | if (*data) { | |
281 | header = g_malloc(*len + sizeof(*header)); | |
282 | header->layer_type = vl->type; | |
283 | header->len = *len; | |
284 | memcpy(header->data, *data, *len); | |
285 | g_free(*data); | |
286 | *data = (guint8 *)header; | |
287 | *len = *len + sizeof(*header); | |
288 | } | |
289 | } else { | |
290 | *data = NULL; | |
291 | } | |
292 | } | |
293 | ||
294 | void vik_layer_marshall_params ( VikLayer *vl, guint8 **data, gint *datalen ) | |
295 | { | |
296 | VikLayerParam *params = vik_layer_get_interface(vl->type)->params; | |
297 | VikLayerFuncGetParam get_param = vik_layer_get_interface(vl->type)->get_param; | |
298 | GByteArray* b = g_byte_array_new (); | |
299 | gint len; | |
300 | ||
301 | #define vlm_append(obj, sz) \ | |
302 | len = (sz); \ | |
303 | g_byte_array_append ( b, (guint8 *)&len, sizeof(len) ); \ | |
304 | g_byte_array_append ( b, (guint8 *)(obj), len ); | |
305 | ||
306 | vlm_append(vl->name, strlen(vl->name)); | |
307 | ||
308 | if ( params && get_param ) | |
309 | { | |
310 | VikLayerParamData d; | |
311 | guint16 i, params_count = vik_layer_get_interface(vl->type)->params_count; | |
312 | for ( i = 0; i < params_count; i++ ) | |
313 | { | |
314 | g_debug("%s: %s", __FUNCTION__, params[i].name); | |
315 | d = get_param(vl, i, FALSE); | |
316 | switch ( params[i].type ) | |
317 | { | |
318 | case VIK_LAYER_PARAM_STRING: | |
319 | // Remember need braces as these are macro calls, not single statement functions! | |
320 | if ( d.s ) { | |
321 | vlm_append(d.s, strlen(d.s)); | |
322 | } | |
323 | else { | |
324 | // Need to insert empty string otherwise the unmarshall will get confused | |
325 | vlm_append("", 0); | |
326 | } | |
327 | break; | |
328 | /* print out the string list in the array */ | |
329 | case VIK_LAYER_PARAM_STRING_LIST: { | |
330 | GList *list = d.sl; | |
331 | ||
332 | /* write length of list (# of strings) */ | |
333 | gint listlen = g_list_length ( list ); | |
334 | g_byte_array_append ( b, (guint8 *)&listlen, sizeof(listlen) ); | |
335 | ||
336 | /* write each string */ | |
337 | while ( list ) { | |
338 | gchar *s = (gchar *) list->data; | |
339 | vlm_append(s, strlen(s)); | |
340 | list = list->next; | |
341 | } | |
342 | ||
343 | break; | |
344 | } | |
345 | default: | |
346 | vlm_append(&d, sizeof(d)); | |
347 | break; | |
348 | } | |
349 | } | |
350 | } | |
351 | ||
352 | *data = b->data; | |
353 | *datalen = b->len; | |
354 | g_byte_array_free ( b, FALSE ); | |
355 | ||
356 | #undef vlm_append | |
357 | } | |
358 | ||
359 | void vik_layer_unmarshall_params ( VikLayer *vl, guint8 *data, gint datalen, VikViewport *vvp ) | |
360 | { | |
361 | VikLayerParam *params = vik_layer_get_interface(vl->type)->params; | |
362 | VikLayerFuncSetParam set_param = vik_layer_get_interface(vl->type)->set_param; | |
363 | gchar *s; | |
364 | guint8 *b = (guint8 *)data; | |
365 | ||
366 | #define vlm_size (*(gint *)b) | |
367 | #define vlm_read(obj) \ | |
368 | memcpy((obj), b+sizeof(gint), vlm_size); \ | |
369 | b += sizeof(gint) + vlm_size; | |
370 | ||
371 | s = g_malloc(vlm_size + 1); | |
372 | s[vlm_size]=0; | |
373 | vlm_read(s); | |
374 | ||
375 | vik_layer_rename(vl, s); | |
376 | ||
377 | g_free(s); | |
378 | ||
379 | if ( params && set_param ) | |
380 | { | |
381 | VikLayerParamData d; | |
382 | guint16 i, params_count = vik_layer_get_interface(vl->type)->params_count; | |
383 | for ( i = 0; i < params_count; i++ ) | |
384 | { | |
385 | g_debug("%s: %s", __FUNCTION__, params[i].name); | |
386 | switch ( params[i].type ) | |
387 | { | |
388 | case VIK_LAYER_PARAM_STRING: | |
389 | s = g_malloc(vlm_size + 1); | |
390 | s[vlm_size]=0; | |
391 | vlm_read(s); | |
392 | d.s = s; | |
393 | set_param(vl, i, d, vvp, FALSE); | |
394 | g_free(s); | |
395 | break; | |
396 | case VIK_LAYER_PARAM_STRING_LIST: { | |
397 | gint listlen = vlm_size, j; | |
398 | GList *list = NULL; | |
399 | b += sizeof(gint); /* skip listlen */; | |
400 | ||
401 | for ( j = 0; j < listlen; j++ ) { | |
402 | /* get a string */ | |
403 | s = g_malloc(vlm_size + 1); | |
404 | s[vlm_size]=0; | |
405 | vlm_read(s); | |
406 | list = g_list_append ( list, s ); | |
407 | } | |
408 | d.sl = list; | |
409 | set_param(vl, i, d, vvp, FALSE); | |
410 | /* don't free -- string list is responsibility of the layer */ | |
411 | ||
412 | break; | |
413 | } | |
414 | default: | |
415 | vlm_read(&d); | |
416 | set_param(vl, i, d, vvp, FALSE); | |
417 | break; | |
418 | } | |
419 | } | |
420 | } | |
421 | } | |
422 | ||
423 | VikLayer *vik_layer_unmarshall ( guint8 *data, gint len, VikViewport *vvp ) | |
424 | { | |
425 | header_t *header; | |
426 | ||
427 | header = (header_t *)data; | |
428 | ||
429 | if ( vik_layer_interfaces[header->layer_type]->unmarshall ) { | |
430 | return vik_layer_interfaces[header->layer_type]->unmarshall ( header->data, header->len, vvp ); | |
431 | } else { | |
432 | return NULL; | |
433 | } | |
434 | } | |
435 | ||
436 | static void vik_layer_finalize ( VikLayer *vl ) | |
437 | { | |
438 | g_assert ( vl != NULL ); | |
439 | if ( vik_layer_interfaces[vl->type]->free ) | |
440 | vik_layer_interfaces[vl->type]->free ( vl ); | |
441 | if ( vl->name ) | |
442 | g_free ( vl->name ); | |
443 | G_OBJECT_CLASS(parent_class)->finalize(G_OBJECT(vl)); | |
444 | } | |
445 | ||
446 | /* sublayer switching */ | |
447 | gboolean vik_layer_sublayer_toggle_visible ( VikLayer *l, gint subtype, gpointer sublayer ) | |
448 | { | |
449 | if ( vik_layer_interfaces[l->type]->sublayer_toggle_visible ) | |
450 | return vik_layer_interfaces[l->type]->sublayer_toggle_visible ( l, subtype, sublayer ); | |
451 | return TRUE; /* if unknown, will always be visible */ | |
452 | } | |
453 | ||
454 | gboolean vik_layer_selected ( VikLayer *l, gint subtype, gpointer sublayer, gint type, gpointer vlp ) | |
455 | { | |
456 | if ( vik_layer_interfaces[l->type]->layer_selected ) | |
457 | return vik_layer_interfaces[l->type]->layer_selected ( l, subtype, sublayer, type, vlp ); | |
458 | /* Since no 'layer_selected' function explicitly turn off here */ | |
459 | return vik_window_clear_highlight ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l) ); | |
460 | } | |
461 | ||
462 | void vik_layer_realize ( VikLayer *l, VikTreeview *vt, GtkTreeIter *layer_iter ) | |
463 | { | |
464 | l->vt = vt; | |
465 | l->iter = *layer_iter; | |
466 | l->realized = TRUE; | |
467 | if ( vik_layer_interfaces[l->type]->realize ) | |
468 | vik_layer_interfaces[l->type]->realize ( l, vt, layer_iter ); | |
469 | } | |
470 | ||
471 | void vik_layer_set_menu_items_selection(VikLayer *l, guint16 selection) | |
472 | { | |
473 | if ( vik_layer_interfaces[l->type]->set_menu_selection ) | |
474 | vik_layer_interfaces[l->type]->set_menu_selection ( l, selection ); | |
475 | } | |
476 | ||
477 | guint16 vik_layer_get_menu_items_selection(VikLayer *l) | |
478 | { | |
479 | if ( vik_layer_interfaces[l->type]->get_menu_selection ) | |
480 | return(vik_layer_interfaces[l->type]->get_menu_selection (l)); | |
481 | else | |
482 | return(vik_layer_interfaces[l->type]->menu_items_selection); | |
483 | } | |
484 | ||
485 | void vik_layer_add_menu_items ( VikLayer *l, GtkMenu *menu, gpointer vlp ) | |
486 | { | |
487 | if ( vik_layer_interfaces[l->type]->add_menu_items ) | |
488 | vik_layer_interfaces[l->type]->add_menu_items ( l, menu, vlp ); | |
489 | } | |
490 | ||
491 | gboolean vik_layer_sublayer_add_menu_items ( VikLayer *l, GtkMenu *menu, gpointer vlp, gint subtype, gpointer sublayer, GtkTreeIter *iter, VikViewport *vvp ) | |
492 | { | |
493 | if ( vik_layer_interfaces[l->type]->sublayer_add_menu_items ) | |
494 | return vik_layer_interfaces[l->type]->sublayer_add_menu_items ( l, menu, vlp, subtype, sublayer, iter, vvp ); | |
495 | return FALSE; | |
496 | } | |
497 | ||
498 | ||
499 | const gchar *vik_layer_sublayer_rename_request ( VikLayer *l, const gchar *newname, gpointer vlp, gint subtype, gpointer sublayer, GtkTreeIter *iter ) | |
500 | { | |
501 | if ( vik_layer_interfaces[l->type]->sublayer_rename_request ) | |
502 | return vik_layer_interfaces[l->type]->sublayer_rename_request ( l, newname, vlp, subtype, sublayer, iter ); | |
503 | return NULL; | |
504 | } | |
505 | ||
506 | const gchar* vik_layer_sublayer_tooltip ( VikLayer *l, gint subtype, gpointer sublayer ) | |
507 | { | |
508 | if ( vik_layer_interfaces[l->type]->sublayer_tooltip ) | |
509 | return vik_layer_interfaces[l->type]->sublayer_tooltip ( l, subtype, sublayer ); | |
510 | return NULL; | |
511 | } | |
512 | ||
513 | const gchar* vik_layer_layer_tooltip ( VikLayer *l ) | |
514 | { | |
515 | if ( vik_layer_interfaces[l->type]->layer_tooltip ) | |
516 | return vik_layer_interfaces[l->type]->layer_tooltip ( l ); | |
517 | return NULL; | |
518 | } | |
519 | ||
520 | GdkPixbuf *vik_layer_load_icon ( VikLayerTypeEnum type ) | |
521 | { | |
522 | g_assert ( type < VIK_LAYER_NUM_TYPES ); | |
523 | if ( vik_layer_interfaces[type]->icon ) | |
524 | return gdk_pixbuf_from_pixdata ( vik_layer_interfaces[type]->icon, FALSE, NULL ); | |
525 | return NULL; | |
526 | } | |
527 | ||
528 | gboolean vik_layer_set_param ( VikLayer *layer, guint16 id, VikLayerParamData data, gpointer vp, gboolean is_file_operation ) | |
529 | { | |
530 | if ( vik_layer_interfaces[layer->type]->set_param ) | |
531 | return vik_layer_interfaces[layer->type]->set_param ( layer, id, data, vp, is_file_operation ); | |
532 | return FALSE; | |
533 | } | |
534 | ||
535 | void vik_layer_post_read ( VikLayer *layer, VikViewport *vp, gboolean from_file ) | |
536 | { | |
537 | if ( vik_layer_interfaces[layer->type]->post_read ) | |
538 | vik_layer_interfaces[layer->type]->post_read ( layer, vp, from_file ); | |
539 | } | |
540 | ||
541 | static gboolean vik_layer_properties_factory ( VikLayer *vl, VikViewport *vp ) | |
542 | { | |
543 | switch ( a_uibuilder_properties_factory ( _("Layer Properties"), | |
544 | VIK_GTK_WINDOW_FROM_WIDGET(vp), | |
545 | vik_layer_interfaces[vl->type]->params, | |
546 | vik_layer_interfaces[vl->type]->params_count, | |
547 | vik_layer_interfaces[vl->type]->params_groups, | |
548 | vik_layer_interfaces[vl->type]->params_groups_count, | |
549 | (gpointer) vik_layer_interfaces[vl->type]->set_param, | |
550 | vl, | |
551 | vp, | |
552 | (gpointer) vik_layer_interfaces[vl->type]->get_param, | |
553 | vl, | |
554 | (gpointer) vik_layer_interfaces[vl->type]->change_param ) ) { | |
555 | case 0: | |
556 | case 3: | |
557 | return FALSE; | |
558 | /* redraw (?) */ | |
559 | case 2: | |
560 | vik_layer_post_read ( vl, vp, FALSE ); /* update any gc's */ | |
561 | default: | |
562 | return TRUE; | |
563 | } | |
564 | } | |
565 | ||
566 | VikLayerTypeEnum vik_layer_type_from_string ( const gchar *str ) | |
567 | { | |
568 | VikLayerTypeEnum i; | |
569 | for ( i = 0; i < VIK_LAYER_NUM_TYPES; i++ ) | |
570 | if ( strcasecmp ( str, vik_layer_get_interface(i)->fixed_layer_name ) == 0 ) | |
571 | return i; | |
572 | return VIK_LAYER_NUM_TYPES; | |
573 | } | |
574 | ||
575 | void vik_layer_typed_param_data_free ( gpointer gp ) | |
576 | { | |
577 | VikLayerTypedParamData *val = (VikLayerTypedParamData *)gp; | |
578 | switch ( val->type ) { | |
579 | case VIK_LAYER_PARAM_STRING: | |
580 | if ( val->data.s ) | |
581 | g_free ( (gpointer)val->data.s ); | |
582 | break; | |
583 | /* TODO: APPLICABLE TO US? NOTE: string layer works auniquely: data.sl should NOT be free'd when | |
584 | * the internals call get_param -- i.e. it should be managed w/in the layer. | |
585 | * The value passed by the internals into set_param should also be managed | |
586 | * by the layer -- i.e. free'd by the layer. | |
587 | */ | |
588 | case VIK_LAYER_PARAM_STRING_LIST: | |
589 | g_warning ("Param strings not implemented"); //fake it | |
590 | break; | |
591 | default: | |
592 | break; | |
593 | } | |
594 | g_free ( val ); | |
595 | } | |
596 | ||
597 | VikLayerTypedParamData *vik_layer_typed_param_data_copy_from_data (VikLayerParamType type, VikLayerParamData val) { | |
598 | VikLayerTypedParamData *newval = g_new(VikLayerTypedParamData,1); | |
599 | newval->data = val; | |
600 | newval->type = type; | |
601 | switch ( newval->type ) { | |
602 | case VIK_LAYER_PARAM_STRING: { | |
603 | gchar *s = g_strdup(newval->data.s); | |
604 | newval->data.s = s; | |
605 | break; | |
606 | } | |
607 | /* TODO: APPLICABLE TO US? NOTE: string layer works auniquely: data.sl should NOT be free'd when | |
608 | * the internals call get_param -- i.e. it should be managed w/in the layer. | |
609 | * The value passed by the internals into set_param should also be managed | |
610 | * by the layer -- i.e. free'd by the layer. | |
611 | */ | |
612 | case VIK_LAYER_PARAM_STRING_LIST: | |
613 | g_critical ( "Param strings not implemented"); //fake it | |
614 | break; | |
615 | default: | |
616 | break; | |
617 | } | |
618 | return newval; | |
619 | } | |
620 | ||
621 | #define TEST_BOOLEAN(str) (! ((str)[0] == '\0' || (str)[0] == '0' || (str)[0] == 'n' || (str)[0] == 'N' || (str)[0] == 'f' || (str)[0] == 'F') ) | |
622 | ||
623 | VikLayerTypedParamData *vik_layer_data_typed_param_copy_from_string ( VikLayerParamType type, const gchar *str ) | |
624 | { | |
625 | VikLayerTypedParamData *rv = g_new(VikLayerTypedParamData,1); | |
626 | rv->type = type; | |
627 | switch ( type ) | |
628 | { | |
629 | case VIK_LAYER_PARAM_DOUBLE: rv->data.d = strtod(str, NULL); break; | |
630 | case VIK_LAYER_PARAM_UINT: rv->data.u = strtoul(str, NULL, 10); break; | |
631 | case VIK_LAYER_PARAM_INT: rv->data.i = strtol(str, NULL, 10); break; | |
632 | case VIK_LAYER_PARAM_BOOLEAN: rv->data.b = TEST_BOOLEAN(str); break; | |
633 | case VIK_LAYER_PARAM_COLOR: memset(&(rv->data.c), 0, sizeof(rv->data.c)); /* default: black */ | |
634 | gdk_color_parse ( str, &(rv->data.c) ); break; | |
635 | /* STRING or STRING_LIST -- if STRING_LIST, just set param to add a STRING */ | |
636 | default: { | |
637 | gchar *s = g_strdup(str); | |
638 | rv->data.s = s; | |
639 | } | |
640 | } | |
641 | return rv; | |
642 | } | |
643 | ||
644 | ||
645 | /** | |
646 | * vik_layer_set_defaults: | |
647 | * | |
648 | * Loop around all parameters for the specified layer to call the function to get the | |
649 | * default value for that parameter | |
650 | */ | |
651 | void vik_layer_set_defaults ( VikLayer *vl, VikViewport *vvp ) | |
652 | { | |
653 | // Sneaky initialize of the viewport value here | |
654 | vl->vvp = vvp; | |
655 | VikLayerInterface *vli = vik_layer_get_interface ( vl->type ); | |
656 | const gchar *layer_name = vli->fixed_layer_name; | |
657 | VikLayerParamData data; | |
658 | ||
659 | int i; | |
660 | for ( i = 0; i < vli->params_count; i++ ) { | |
661 | // Ensure parameter is for use | |
662 | if ( vli->params[i].group > VIK_LAYER_NOT_IN_PROPERTIES ) { | |
663 | // ATM can't handle string lists | |
664 | // only DEM files uses this currently | |
665 | if ( vli->params[i].type != VIK_LAYER_PARAM_STRING_LIST ) { | |
666 | data = a_layer_defaults_get ( layer_name, vli->params[i].name, vli->params[i].type ); | |
667 | vik_layer_set_param ( vl, i, data, vvp, TRUE ); // Possibly come from a file | |
668 | } | |
669 | } | |
670 | } | |
671 | } |