]> git.street.me.uk Git - andy/viking.git/blame - src/viklayer.c
The "Selected Time" on track properties dialog is now correct.
[andy/viking.git] / src / viklayer.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
22#include "viking.h"
23#include "vikradiogroup.h"
ad0a8c2d 24#include "vikfilelist.h"
911400b5 25#include <string.h>
50a14534
EB
26
27/* functions common to all layers. */
28/* TODO longone: rename interface free -> finalize */
29
30extern VikLayerInterface vik_aggregate_layer_interface;
31extern VikLayerInterface vik_trw_layer_interface;
32extern VikLayerInterface vik_maps_layer_interface;
33extern VikLayerInterface vik_coord_layer_interface;
34extern VikLayerInterface vik_georef_layer_interface;
b364d6bc 35extern VikLayerInterface vik_gps_layer_interface;
ad0a8c2d 36extern VikLayerInterface vik_dem_layer_interface;
50a14534
EB
37
38enum {
39 VL_UPDATE_SIGNAL,
40 VL_LAST_SIGNAL
41};
42static guint layer_signals[VL_LAST_SIGNAL] = { 0 };
43
44static GObjectClass *parent_class;
45
46static void layer_class_init ( VikLayerClass *klass );
47static void layer_init ( VikLayer *vl );
48static void layer_finalize ( VikLayer *vl );
94933cb8 49static gboolean layer_properties_factory ( VikLayer *vl, VikViewport *vp );
50a14534
EB
50
51
52/* TODO longone: rename vik_layer_init -> set_type */
53
54GType vik_layer_get_type ()
55{
56 static GType vl_type = 0;
57
58 if (!vl_type)
59 {
60 static const GTypeInfo vl_info =
61 {
62 sizeof (VikLayerClass),
63 NULL, /* base_init */
64 NULL, /* base_finalize */
65 (GClassInitFunc) layer_class_init, /* class init */
66 NULL, /* class_finalize */
67 NULL, /* class_data */
68 sizeof (VikLayer),
69 0,
70 (GInstanceInitFunc) layer_init /* instance init */
71 };
72 vl_type = g_type_register_static ( G_TYPE_OBJECT, "VikLayer", &vl_info, 0 );
73 }
74
75 return vl_type;
76}
77
78static void layer_class_init (VikLayerClass *klass)
79{
80 GObjectClass *object_class;
81
82 object_class = G_OBJECT_CLASS (klass);
83
84 object_class->finalize = (GObjectFinalizeFunc) layer_finalize;
85
86 parent_class = g_type_class_peek_parent (klass);
87
88 layer_signals[VL_UPDATE_SIGNAL] = g_signal_new ( "update", G_TYPE_FROM_CLASS (klass),
89 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (VikLayerClass, update), NULL, NULL,
90 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
91}
92
93void vik_layer_emit_update ( VikLayer *vl )
0df66d57
EB
94{
95 if ( vl->visible ) {
c9177aae 96 vik_window_set_redraw_trigger(vl);
0df66d57
EB
97 g_signal_emit ( G_OBJECT(vl), layer_signals[VL_UPDATE_SIGNAL], 0 );
98 }
99}
100
101/* should only be done by VikLayersPanel -- need to redraw and record trigger
102 * when we make a layer invisible.
103 */
104void vik_layer_emit_update_although_invisible ( VikLayer *vl )
105{
c9177aae 106 vik_window_set_redraw_trigger(vl);
0df66d57
EB
107 g_signal_emit ( G_OBJECT(vl), layer_signals[VL_UPDATE_SIGNAL], 0 );
108}
109
0df66d57
EB
110/* doesn't set the trigger. should be done by aggregate layer when child emits update. */
111void vik_layer_emit_update_secondary ( VikLayer *vl )
50a14534
EB
112{
113 if ( vl->visible )
114 g_signal_emit ( G_OBJECT(vl), layer_signals[VL_UPDATE_SIGNAL], 0 );
115}
116
117static VikLayerInterface *vik_layer_interfaces[VIK_LAYER_NUM_TYPES] = {
118 &vik_aggregate_layer_interface,
119 &vik_trw_layer_interface,
120 &vik_coord_layer_interface,
121 &vik_georef_layer_interface,
b364d6bc 122 &vik_gps_layer_interface,
50a14534 123 &vik_maps_layer_interface,
ad0a8c2d 124 &vik_dem_layer_interface,
50a14534
EB
125};
126
127VikLayerInterface *vik_layer_get_interface ( gint type )
128{
129 g_assert ( type < VIK_LAYER_NUM_TYPES );
130 return vik_layer_interfaces[type];
131}
132
133static void layer_init ( VikLayer *vl )
134{
135 vl->visible = TRUE;
136 vl->name = NULL;
137 vl->realized = FALSE;
138}
139
140void vik_layer_init ( VikLayer *vl, gint type )
141{
142 vl->type = type;
143}
144
145/* frees old name */
146void vik_layer_rename ( VikLayer *l, const gchar *new_name )
147{
92558066
GB
148 g_assert ( l != NULL );
149 g_assert ( new_name != NULL );
150 g_free ( l->name );
50a14534
EB
151 l->name = g_strdup ( new_name );
152}
153
154void vik_layer_rename_no_copy ( VikLayer *l, gchar *new_name )
155{
92558066
GB
156 g_assert ( l != NULL );
157 g_assert ( new_name != NULL );
158 g_free ( l->name );
50a14534
EB
159 l->name = new_name;
160}
161
92558066
GB
162const gchar *vik_layer_get_name ( VikLayer *l )
163{
164 g_assert ( l != NULL);
165 return l->name;
166}
167
50a14534
EB
168VikLayer *vik_layer_create ( gint type, gpointer vp, GtkWindow *w, gboolean interactive )
169{
170 VikLayer *new_layer = NULL;
171 g_assert ( type < VIK_LAYER_NUM_TYPES );
172
173 new_layer = vik_layer_interfaces[type]->create ( vp );
174
175 g_assert ( new_layer != NULL );
176
177 if ( interactive )
178 {
179 if ( vik_layer_properties ( new_layer, vp ) )
180 vik_layer_rename ( VIK_LAYER(new_layer), vik_layer_interfaces[type]->name );
181 else
182 {
183 g_object_unref ( G_OBJECT(new_layer) ); /* cancel that */
184 new_layer = NULL;
185 }
186 }
187 return new_layer;
188}
189
190/* returns TRUE if OK was pressed */
191gboolean vik_layer_properties ( VikLayer *layer, gpointer vp )
192{
193 if ( vik_layer_interfaces[layer->type]->properties )
194 return vik_layer_interfaces[layer->type]->properties ( layer, vp );
195 return layer_properties_factory ( layer, vp );
196}
197
198void vik_layer_draw ( VikLayer *l, gpointer data )
199{
200 if ( l->visible )
201 if ( vik_layer_interfaces[l->type]->draw )
202 vik_layer_interfaces[l->type]->draw ( l, data );
203}
204
205void vik_layer_change_coord_mode ( VikLayer *l, VikCoordMode mode )
206{
207 if ( vik_layer_interfaces[l->type]->change_coord_mode )
208 vik_layer_interfaces[l->type]->change_coord_mode ( l, mode );
209}
210
911400b5
AF
211typedef struct {
212 gint layer_type;
213 gint len;
214 guint8 data[0];
215} header_t;
216
217void vik_layer_marshall ( VikLayer *vl, guint8 **data, gint *len )
218{
219 header_t *header;
220 if ( vl && vik_layer_interfaces[vl->type]->marshall ) {
221 vik_layer_interfaces[vl->type]->marshall ( vl, data, len );
222 if (*data) {
223 header = g_malloc(*len + sizeof(*header));
224 header->layer_type = vl->type;
225 header->len = *len;
226 memcpy(header->data, *data, *len);
227 g_free(*data);
228 *data = (guint8 *)header;
229 *len = *len + sizeof(*header);
230 }
231 } else {
232 *data = NULL;
233 }
234}
235
236void vik_layer_marshall_params ( VikLayer *vl, guint8 **data, gint *datalen )
237{
238 VikLayerParam *params = vik_layer_get_interface(vl->type)->params;
239 VikLayerFuncGetParam get_param = vik_layer_get_interface(vl->type)->get_param;
240 GByteArray* b = g_byte_array_new ();
241 gint len;
242
243#define vlm_append(obj, sz) \
244 len = (sz); \
245 g_byte_array_append ( b, (guint8 *)&len, sizeof(len) ); \
246 g_byte_array_append ( b, (guint8 *)(obj), len );
247
248 vlm_append(vl->name, strlen(vl->name));
249
250 if ( params && get_param )
251 {
252 VikLayerParamData d;
253 guint16 i, params_count = vik_layer_get_interface(vl->type)->params_count;
254 for ( i = 0; i < params_count; i++ )
255 {
256 d = get_param(vl, i);
257 switch ( params[i].type )
258 {
259 case VIK_LAYER_PARAM_STRING:
260 vlm_append(d.s, strlen(d.s));
261 break;
fa86f1c0
EB
262
263 /* print out the string list in the array */
264 case VIK_LAYER_PARAM_STRING_LIST: {
265 GList *list = d.sl;
266
267 /* write length of list (# of strings) */
268 gint listlen = g_list_length ( list );
269 g_byte_array_append ( b, (guint8 *)&listlen, sizeof(listlen) );
270
271 /* write each string */
272 while ( list ) {
273 gchar *s = (gchar *) list->data;
274 vlm_append(s, strlen(s));
275 list = list->next;
276 }
277
278 break;
279 }
911400b5
AF
280 default:
281 vlm_append(&d, sizeof(d));
282 break;
283 }
284 }
285 }
286
287 *data = b->data;
288 *datalen = b->len;
289 g_byte_array_free ( b, FALSE );
290
291#undef vlm_append
292}
293
294void vik_layer_unmarshall_params ( VikLayer *vl, guint8 *data, gint datalen, VikViewport *vvp )
295{
296 VikLayerParam *params = vik_layer_get_interface(vl->type)->params;
297 VikLayerFuncSetParam set_param = vik_layer_get_interface(vl->type)->set_param;
298 gchar *s;
299 guint8 *b = (guint8 *)data;
300
301#define vlm_size (*(gint *)b)
302#define vlm_read(obj) \
303 memcpy((obj), b+sizeof(gint), vlm_size); \
304 b += sizeof(gint) + vlm_size;
305
306 s = g_malloc(vlm_size + 1);
307 s[vlm_size]=0;
308 vlm_read(s);
309
310 vik_layer_rename(vl, s);
311
312 g_free(s);
313
314 if ( params && set_param )
315 {
316 VikLayerParamData d;
317 guint16 i, params_count = vik_layer_get_interface(vl->type)->params_count;
318 for ( i = 0; i < params_count; i++ )
319 {
320 switch ( params[i].type )
321 {
322 case VIK_LAYER_PARAM_STRING:
323 s = g_malloc(vlm_size + 1);
324 s[vlm_size]=0;
325 vlm_read(s);
326 d.s = s;
327 set_param(vl, i, d, vvp);
328 g_free(s);
329 break;
fa86f1c0
EB
330 case VIK_LAYER_PARAM_STRING_LIST: {
331 gint listlen = vlm_size, j;
332 GList *list = NULL;
333 b += sizeof(gint); /* skip listlen */;
334
335 for ( j = 0; j < listlen; j++ ) {
336 /* get a string */
337 s = g_malloc(vlm_size + 1);
338 s[vlm_size]=0;
339 vlm_read(s);
340 list = g_list_append ( list, s );
341 }
342 d.sl = list;
343 set_param ( vl, i, d, vvp );
344 /* don't free -- string list is responsibility of the layer */
345
346 break;
347 }
911400b5
AF
348 default:
349 vlm_read(&d);
350 set_param(vl, i, d, vvp);
351 break;
352 }
353 }
354 }
355}
356
357VikLayer *vik_layer_unmarshall ( guint8 *data, gint len, VikViewport *vvp )
358{
359 header_t *header;
360
361 header = (header_t *)data;
362
363 if ( vik_layer_interfaces[header->layer_type]->unmarshall ) {
364 return vik_layer_interfaces[header->layer_type]->unmarshall ( header->data, header->len, vvp );
365 } else {
366 return NULL;
367 }
368}
50a14534
EB
369
370static void layer_finalize ( VikLayer *vl )
371{
372 g_assert ( vl != NULL );
373 if ( vik_layer_interfaces[vl->type]->free )
374 vik_layer_interfaces[vl->type]->free ( vl );
375 if ( vl->name )
376 g_free ( vl->name );
377 G_OBJECT_CLASS(parent_class)->finalize(G_OBJECT(vl));
378}
379
380/* sublayer switching */
381gboolean vik_layer_sublayer_toggle_visible ( VikLayer *l, gint subtype, gpointer sublayer )
382{
383 if ( vik_layer_interfaces[l->type]->sublayer_toggle_visible )
384 return vik_layer_interfaces[l->type]->sublayer_toggle_visible ( l, subtype, sublayer );
385 return TRUE; /* if unknown, will always be visible */
386}
387
388void vik_layer_realize ( VikLayer *l, VikTreeview *vt, GtkTreeIter *layer_iter )
389{
390 l->vt = vt;
391 l->iter = *layer_iter;
392 l->realized = TRUE;
393 if ( vik_layer_interfaces[l->type]->realize )
394 vik_layer_interfaces[l->type]->realize ( l, vt, layer_iter );
395}
396
20c7a3a0
QT
397void vik_layer_set_menu_items_selection(VikLayer *l, guint16 selection)
398{
399 if ( vik_layer_interfaces[l->type]->set_menu_selection )
400 vik_layer_interfaces[l->type]->set_menu_selection ( l, selection );
401}
402
403guint16 vik_layer_get_menu_items_selection(VikLayer *l)
404{
405 if ( vik_layer_interfaces[l->type]->get_menu_selection )
406 return(vik_layer_interfaces[l->type]->get_menu_selection (l));
407 else
408 return(vik_layer_interfaces[l->type]->menu_items_selection);
409}
410
50a14534
EB
411void vik_layer_add_menu_items ( VikLayer *l, GtkMenu *menu, gpointer vlp )
412{
413 if ( vik_layer_interfaces[l->type]->add_menu_items )
414 vik_layer_interfaces[l->type]->add_menu_items ( l, menu, vlp );
415}
416
417gboolean vik_layer_sublayer_add_menu_items ( VikLayer *l, GtkMenu *menu, gpointer vlp, gint subtype, gpointer sublayer, GtkTreeIter *iter )
418{
419 if ( vik_layer_interfaces[l->type]->sublayer_add_menu_items )
420 return vik_layer_interfaces[l->type]->sublayer_add_menu_items ( l, menu, vlp, subtype, sublayer, iter );
421 return FALSE;
422}
423
424
425const gchar *vik_layer_sublayer_rename_request ( VikLayer *l, const gchar *newname, gpointer vlp, gint subtype, gpointer sublayer, GtkTreeIter *iter )
426{
427 if ( vik_layer_interfaces[l->type]->sublayer_rename_request )
428 return vik_layer_interfaces[l->type]->sublayer_rename_request ( l, newname, vlp, subtype, sublayer, iter );
429 return NULL;
430}
431
432GdkPixbuf *vik_layer_load_icon ( gint type )
433{
434 g_assert ( type < VIK_LAYER_NUM_TYPES );
435 if ( vik_layer_interfaces[type]->icon )
436 return gdk_pixbuf_from_pixdata ( vik_layer_interfaces[type]->icon, FALSE, NULL );
437 return NULL;
438}
439
440gboolean vik_layer_set_param ( VikLayer *layer, guint16 id, VikLayerParamData data, gpointer vp )
441{
442 if ( vik_layer_interfaces[layer->type]->set_param )
443 return vik_layer_interfaces[layer->type]->set_param ( layer, id, data, vp );
444 return FALSE;
445}
446
07059501 447void vik_layer_post_read ( VikLayer *layer, VikViewport *vp, gboolean from_file )
50a14534
EB
448{
449 if ( vik_layer_interfaces[layer->type]->post_read )
07059501 450 vik_layer_interfaces[layer->type]->post_read ( layer, vp, from_file );
50a14534
EB
451}
452
453static GtkWidget *properties_widget_new_widget ( VikLayerParam *param, VikLayerParamData data )
454{
cdcaf41c 455 GtkWidget *rv = NULL;
50a14534
EB
456 switch ( param->widget_type )
457 {
458 case VIK_LAYER_WIDGET_COLOR:
459 if ( param->type == VIK_LAYER_PARAM_COLOR )
460 rv = gtk_color_button_new_with_color ( &(data.c) );
461 break;
462 case VIK_LAYER_WIDGET_CHECKBUTTON:
463 if ( param->type == VIK_LAYER_PARAM_BOOLEAN )
464 {
465 //rv = gtk_check_button_new_with_label ( //param->title );
466 rv = gtk_check_button_new ();
467 if ( data.b )
468 gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON(rv), TRUE );
469 }
470 break;
471 case VIK_LAYER_WIDGET_COMBOBOX:
ad0a8c2d 472#ifndef GTK_2_2
50a14534
EB
473 if ( param->type == VIK_LAYER_PARAM_UINT && param->widget_data )
474 {
475 gchar **pstr = param->widget_data;
476 rv = gtk_combo_box_new_text ();
477 while ( *pstr )
478 gtk_combo_box_append_text ( GTK_COMBO_BOX ( rv ), *(pstr++) );
479 if ( param->extra_widget_data ) /* map of alternate uint values for options */
480 {
481 int i;
482 for ( i = 0; ((const char **)param->widget_data)[i]; i++ )
483 if ( ((guint *)param->extra_widget_data)[i] == data.u )
484 {
485 gtk_combo_box_set_active ( GTK_COMBO_BOX(rv), i );
486 break;
487 }
488 }
489 gtk_combo_box_set_active ( GTK_COMBO_BOX ( rv ), data.u );
490 }
491 break;
ad0a8c2d 492#endif
50a14534 493 case VIK_LAYER_WIDGET_RADIOGROUP:
cdcaf41c 494 /* widget_data and extra_widget_data are GList */
50a14534
EB
495 if ( param->type == VIK_LAYER_PARAM_UINT && param->widget_data )
496 {
cdcaf41c 497 rv = vik_radio_group_new ( param->widget_data );
50a14534
EB
498 if ( param->extra_widget_data ) /* map of alternate uint values for options */
499 {
500 int i;
cdcaf41c
QT
501 int nb_elem = g_list_length(param->widget_data);
502 for ( i = 0; i < nb_elem; i++ )
494eb388 503 if ( (guint32)g_list_nth_data(param->extra_widget_data, i) == data.u )
50a14534
EB
504 {
505 vik_radio_group_set_selected ( VIK_RADIO_GROUP(rv), i );
506 break;
507 }
508 }
509 else if ( data.u ) /* zero is already default */
510 vik_radio_group_set_selected ( VIK_RADIO_GROUP(rv), data.u );
511 }
512 break;
8c721f83
EB
513 case VIK_LAYER_WIDGET_RADIOGROUP_STATIC:
514 if ( param->type == VIK_LAYER_PARAM_UINT && param->widget_data )
515 {
516 rv = vik_radio_group_new_static ( (const gchar **) param->widget_data );
517 if ( param->extra_widget_data ) /* map of alternate uint values for options */
518 {
519 int i;
520 for ( i = 0; ((const char **)param->widget_data)[i]; i++ )
521 if ( ((guint *)param->extra_widget_data)[i] == data.u )
522 {
523 vik_radio_group_set_selected ( VIK_RADIO_GROUP(rv), i );
524 break;
525 }
526 }
527 else if ( data.u ) /* zero is already default */
528 vik_radio_group_set_selected ( VIK_RADIO_GROUP(rv), data.u );
529 }
530 break;
50a14534
EB
531 case VIK_LAYER_WIDGET_SPINBUTTON:
532 if ( (param->type == VIK_LAYER_PARAM_DOUBLE || param->type == VIK_LAYER_PARAM_UINT
533 || param->type == VIK_LAYER_PARAM_INT) && param->widget_data )
534 {
535 gdouble init_val = (param->type == VIK_LAYER_PARAM_DOUBLE) ? data.d : (param->type == VIK_LAYER_PARAM_UINT ? data.u : data.i);
536 VikLayerParamScale *scale = (VikLayerParamScale *) param->widget_data;
537 rv = gtk_spin_button_new ( GTK_ADJUSTMENT(gtk_adjustment_new( init_val, scale->min, scale->max, scale->step, scale->step, scale->step )), scale->step, scale->digits );
538 }
539 break;
540 case VIK_LAYER_WIDGET_ENTRY:
541 if ( param->type == VIK_LAYER_PARAM_STRING )
542 {
543 rv = gtk_entry_new ();
544 gtk_entry_set_text ( GTK_ENTRY(rv), data.s );
545 }
546 break;
547 case VIK_LAYER_WIDGET_FILEENTRY:
548 if ( param->type == VIK_LAYER_PARAM_STRING )
549 {
550 rv = vik_file_entry_new ();
551 vik_file_entry_set_filename ( VIK_FILE_ENTRY(rv), data.s );
552 }
553 break;
ad0a8c2d
EB
554 case VIK_LAYER_WIDGET_FILELIST:
555 if ( param->type == VIK_LAYER_PARAM_STRING_LIST )
556 {
557 rv = vik_file_list_new ( param->title );
558 vik_file_list_set_files ( VIK_FILE_LIST(rv), data.sl );
559 }
560 break;
50a14534
EB
561 case VIK_LAYER_WIDGET_HSCALE:
562 if ( (param->type == VIK_LAYER_PARAM_DOUBLE || param->type == VIK_LAYER_PARAM_UINT
563 || param->type == VIK_LAYER_PARAM_INT) && param->widget_data )
564 {
565 gdouble init_val = (param->type == VIK_LAYER_PARAM_DOUBLE) ? data.d : (param->type == VIK_LAYER_PARAM_UINT ? data.u : data.i);
566 VikLayerParamScale *scale = (VikLayerParamScale *) param->widget_data;
567 rv = gtk_hscale_new_with_range ( scale->min, scale->max, scale->step );
568 gtk_scale_set_digits ( GTK_SCALE(rv), scale->digits );
569 gtk_range_set_value ( GTK_RANGE(rv), init_val );
570 }
571 }
572 return rv;
573}
574
575static VikLayerParamData properties_widget_get_value ( GtkWidget *widget, VikLayerParam *param )
576{
577 VikLayerParamData rv;
578 switch ( param->widget_type )
579 {
580 case VIK_LAYER_WIDGET_COLOR:
581 gtk_color_button_get_color ( GTK_COLOR_BUTTON(widget), &(rv.c) );
582 break;
583 case VIK_LAYER_WIDGET_CHECKBUTTON:
584 rv.b = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
585 break;
586 case VIK_LAYER_WIDGET_COMBOBOX:
ad0a8c2d 587#ifndef GTK_2_2
50a14534
EB
588 rv.i = gtk_combo_box_get_active ( GTK_COMBO_BOX(widget) );
589 if ( rv.i == -1 ) rv.i = 0;
590 rv.u = rv.i;
591 if ( param->extra_widget_data )
592 rv.u = ((guint *)param->extra_widget_data)[rv.u];
593 break;
ad0a8c2d 594#endif
50a14534 595 case VIK_LAYER_WIDGET_RADIOGROUP:
8c721f83 596 case VIK_LAYER_WIDGET_RADIOGROUP_STATIC:
50a14534
EB
597 rv.u = vik_radio_group_get_selected(VIK_RADIO_GROUP(widget));
598 if ( param->extra_widget_data )
e0b0b9c1 599 rv.u = (guint32)g_list_nth_data(param->extra_widget_data, rv.u);
50a14534
EB
600 break;
601 case VIK_LAYER_WIDGET_SPINBUTTON:
602 if ( param->type == VIK_LAYER_PARAM_UINT )
603 rv.u = gtk_spin_button_get_value_as_int ( GTK_SPIN_BUTTON(widget) );
604 else if ( param->type == VIK_LAYER_PARAM_INT )
605 rv.i = gtk_spin_button_get_value_as_int ( GTK_SPIN_BUTTON(widget) );
606 else
607 rv.d = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(widget) );
608 break;
609 case VIK_LAYER_WIDGET_ENTRY:
610 rv.s = gtk_entry_get_text ( GTK_ENTRY(widget) );
611 break;
612 case VIK_LAYER_WIDGET_FILEENTRY:
613 rv.s = vik_file_entry_get_filename ( VIK_FILE_ENTRY(widget) );
614 break;
ad0a8c2d
EB
615 case VIK_LAYER_WIDGET_FILELIST:
616 rv.sl = vik_file_list_get_files ( VIK_FILE_LIST(widget) );
617 break;
50a14534
EB
618 case VIK_LAYER_WIDGET_HSCALE:
619 if ( param->type == VIK_LAYER_PARAM_UINT )
620 rv.u = (guint32) gtk_range_get_value ( GTK_RANGE(widget) );
621 else if ( param->type == VIK_LAYER_PARAM_INT )
622 rv.i = (gint32) gtk_range_get_value ( GTK_RANGE(widget) );
623 else
624 rv.d = gtk_range_get_value ( GTK_RANGE(widget) );
625 break;
626 }
627 return rv;
628}
629
630/* false if cancel, true if OK */
631/* some would claim this wasn't written to be human-readable. */
94933cb8 632static gboolean layer_properties_factory ( VikLayer *vl, VikViewport *vp )
50a14534
EB
633{
634 VikLayerParam *params = vik_layer_interfaces[vl->type]->params;
635 guint16 params_count = vik_layer_interfaces[vl->type]->params_count;
636 guint16 i, j, widget_count = 0;
637 gboolean must_redraw = FALSE;
638
639 if ( ! params )
640 return TRUE; /* no params == no options, so all is good */
641
642 for ( i = 0; i < params_count; i++ )
643 if ( params[i].group != VIK_LAYER_NOT_IN_PROPERTIES )
644 widget_count++;
645
646 if ( widget_count == 0)
647 return FALSE;
648 else
649 {
650 /* create widgets and titles; place in table */
651 GtkWidget *dialog = gtk_dialog_new_with_buttons ( "Layer Properties",
652 VIK_GTK_WINDOW_FROM_WIDGET(vp),
653 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
654 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
655 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL );
656 gint resp;
657
658 gchar **groups = vik_layer_interfaces[vl->type]->params_groups;
659 guint8 groups_count = vik_layer_interfaces[vl->type]->params_groups_count;
660
661 GtkWidget *table = NULL;
662 GtkWidget **tables = NULL; /* for more than one group */
663
664 GtkWidget *notebook = NULL;
665 GtkWidget **widgets = g_malloc ( sizeof(GtkWidget *) * widget_count );
666
667 if ( groups && groups_count )
668 {
669 guint8 current_group;
670 guint16 tab_widget_count;
671 notebook = gtk_notebook_new ();
672 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), notebook, FALSE, FALSE, 0);
673 tables = g_malloc ( sizeof(GtkWidget *) * groups_count );
674 for ( current_group = 0; current_group < groups_count; current_group++ )
675 {
676 tab_widget_count = 0;
677 for ( j = 0; j < params_count; j ++ )
678 if ( params[j].group == current_group )
679 tab_widget_count++;
680
681 if ( tab_widget_count )
682 {
683 tables[current_group] = gtk_table_new ( tab_widget_count, 1, FALSE );
684 gtk_notebook_append_page ( GTK_NOTEBOOK(notebook), tables[current_group], gtk_label_new(groups[current_group]) );
685 }
686 }
687 }
688 else
689 {
690 table = gtk_table_new( widget_count, 1, FALSE );
691 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), table, FALSE, FALSE, 0);
692 }
693
694 for ( i = 0, j = 0; i < params_count; i++ )
695 {
696 if ( params[i].group != VIK_LAYER_NOT_IN_PROPERTIES )
697 {
698 if ( tables )
699 table = tables[MAX(0, params[i].group)]; /* round up NOT_IN_GROUP, that's not reasonable here */
700
701 widgets[j] = properties_widget_new_widget ( &(params[i]),
702 vik_layer_interfaces[vl->type]->get_param ( vl, i ) );
703
704 g_assert ( widgets[j] != NULL );
705
706 gtk_table_attach ( GTK_TABLE(table), gtk_label_new(params[i].title), 0, 1, j, j+1, 0, 0, 0, 0 );
707 gtk_table_attach ( GTK_TABLE(table), widgets[j], 1, 2, j, j+1, GTK_EXPAND | GTK_FILL, 0, 2, 2 );
708 j++;
709 }
710 }
711
712 gtk_widget_show_all ( dialog );
713
714 resp = gtk_dialog_run (GTK_DIALOG (dialog));
715 if ( resp == GTK_RESPONSE_ACCEPT )
716 {
717 for ( i = 0, j = 0; i < params_count; i++ )
718 {
719 if ( params[i].group != VIK_LAYER_NOT_IN_PROPERTIES )
720 {
721 if ( vik_layer_interfaces[vl->type]->set_param ( vl, i,
722 properties_widget_get_value ( widgets[j], &(params[i]) ), vp ) )
723 must_redraw = TRUE;
724 j++;
725 }
726 }
07059501 727 vik_layer_post_read ( vl, vp, FALSE ); /* update any gc's */
50a14534
EB
728
729 gtk_widget_destroy ( dialog ); /* hide before redrawing. */
730 g_free ( widgets );
731
c2e97e57 732#ifdef XXXXXXXXXXXXXXXXXXXX
50a14534
EB
733 if ( must_redraw )
734 vik_layer_emit_update ( vl ); /* if this is a new layer, it won't redraw twice because no on'es listening to this signal. */
c2e97e57 735#endif /*XXXXXXXXXXXXXXXXXXXXX*/
50a14534
EB
736 return TRUE; /* user clicked OK */
737 }
738
739 if ( tables )
740 g_free ( tables );
741 gtk_widget_destroy ( dialog );
742 g_free ( widgets );
743 return FALSE;
744 }
745}