2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
4 * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include <glib/gi18n.h>
31 /* functions common to all layers. */
32 /* TODO longone: rename interface free -> finalize */
34 extern VikLayerInterface vik_aggregate_layer_interface
;
35 extern VikLayerInterface vik_trw_layer_interface
;
36 extern VikLayerInterface vik_maps_layer_interface
;
37 extern VikLayerInterface vik_coord_layer_interface
;
38 extern VikLayerInterface vik_georef_layer_interface
;
39 extern VikLayerInterface vik_gps_layer_interface
;
40 extern VikLayerInterface vik_dem_layer_interface
;
46 static guint layer_signals
[VL_LAST_SIGNAL
] = { 0 };
48 static GObjectClass
*parent_class
;
50 static void layer_class_init ( VikLayerClass
*klass
);
51 static void layer_init ( VikLayer
*vl
);
52 static void layer_finalize ( VikLayer
*vl
);
53 static gboolean
layer_properties_factory ( VikLayer
*vl
, VikViewport
*vp
);
56 /* TODO longone: rename vik_layer_init -> set_type */
58 GType
vik_layer_get_type ()
60 static GType vl_type
= 0;
64 static const GTypeInfo vl_info
=
66 sizeof (VikLayerClass
),
68 NULL
, /* base_finalize */
69 (GClassInitFunc
) layer_class_init
, /* class init */
70 NULL
, /* class_finalize */
71 NULL
, /* class_data */
74 (GInstanceInitFunc
) layer_init
/* instance init */
76 vl_type
= g_type_register_static ( G_TYPE_OBJECT
, "VikLayer", &vl_info
, 0 );
82 static void layer_class_init (VikLayerClass
*klass
)
84 GObjectClass
*object_class
;
86 object_class
= G_OBJECT_CLASS (klass
);
88 object_class
->finalize
= (GObjectFinalizeFunc
) layer_finalize
;
90 parent_class
= g_type_class_peek_parent (klass
);
92 layer_signals
[VL_UPDATE_SIGNAL
] = g_signal_new ( "update", G_TYPE_FROM_CLASS (klass
),
93 G_SIGNAL_RUN_FIRST
| G_SIGNAL_ACTION
, G_STRUCT_OFFSET (VikLayerClass
, update
), NULL
, NULL
,
94 g_cclosure_marshal_VOID__VOID
, G_TYPE_NONE
, 0);
97 void vik_layer_emit_update ( VikLayer
*vl
)
100 vik_window_set_redraw_trigger(vl
);
101 g_signal_emit ( G_OBJECT(vl
), layer_signals
[VL_UPDATE_SIGNAL
], 0 );
105 /* should only be done by VikLayersPanel -- need to redraw and record trigger
106 * when we make a layer invisible.
108 void vik_layer_emit_update_although_invisible ( VikLayer
*vl
)
110 vik_window_set_redraw_trigger(vl
);
111 g_signal_emit ( G_OBJECT(vl
), layer_signals
[VL_UPDATE_SIGNAL
], 0 );
114 /* doesn't set the trigger. should be done by aggregate layer when child emits update. */
115 void vik_layer_emit_update_secondary ( VikLayer
*vl
)
118 g_signal_emit ( G_OBJECT(vl
), layer_signals
[VL_UPDATE_SIGNAL
], 0 );
121 static VikLayerInterface
*vik_layer_interfaces
[VIK_LAYER_NUM_TYPES
] = {
122 &vik_aggregate_layer_interface
,
123 &vik_trw_layer_interface
,
124 &vik_coord_layer_interface
,
125 &vik_georef_layer_interface
,
126 &vik_gps_layer_interface
,
127 &vik_maps_layer_interface
,
128 &vik_dem_layer_interface
,
131 VikLayerInterface
*vik_layer_get_interface ( gint type
)
133 g_assert ( type
< VIK_LAYER_NUM_TYPES
);
134 return vik_layer_interfaces
[type
];
137 static void layer_init ( VikLayer
*vl
)
141 vl
->realized
= FALSE
;
144 void vik_layer_init ( VikLayer
*vl
, gint type
)
150 void vik_layer_rename ( VikLayer
*l
, const gchar
*new_name
)
152 g_assert ( l
!= NULL
);
153 g_assert ( new_name
!= NULL
);
155 l
->name
= g_strdup ( new_name
);
158 void vik_layer_rename_no_copy ( VikLayer
*l
, gchar
*new_name
)
160 g_assert ( l
!= NULL
);
161 g_assert ( new_name
!= NULL
);
166 const gchar
*vik_layer_get_name ( VikLayer
*l
)
168 g_assert ( l
!= NULL
);
172 VikLayer
*vik_layer_create ( gint type
, gpointer vp
, GtkWindow
*w
, gboolean interactive
)
174 VikLayer
*new_layer
= NULL
;
175 g_assert ( type
< VIK_LAYER_NUM_TYPES
);
177 new_layer
= vik_layer_interfaces
[type
]->create ( vp
);
179 g_assert ( new_layer
!= NULL
);
183 if ( vik_layer_properties ( new_layer
, vp
) )
184 /* We translate the name here */
185 /* in order to avoid translating name set by user */
186 vik_layer_rename ( VIK_LAYER(new_layer
), _(vik_layer_interfaces
[type
]->name
) );
189 g_object_unref ( G_OBJECT(new_layer
) ); /* cancel that */
196 /* returns TRUE if OK was pressed */
197 gboolean
vik_layer_properties ( VikLayer
*layer
, gpointer vp
)
199 if ( vik_layer_interfaces
[layer
->type
]->properties
)
200 return vik_layer_interfaces
[layer
->type
]->properties ( layer
, vp
);
201 return layer_properties_factory ( layer
, vp
);
204 void vik_layer_draw ( VikLayer
*l
, gpointer data
)
207 if ( vik_layer_interfaces
[l
->type
]->draw
)
208 vik_layer_interfaces
[l
->type
]->draw ( l
, data
);
211 void vik_layer_change_coord_mode ( VikLayer
*l
, VikCoordMode mode
)
213 if ( vik_layer_interfaces
[l
->type
]->change_coord_mode
)
214 vik_layer_interfaces
[l
->type
]->change_coord_mode ( l
, mode
);
223 void vik_layer_marshall ( VikLayer
*vl
, guint8
**data
, gint
*len
)
226 if ( vl
&& vik_layer_interfaces
[vl
->type
]->marshall
) {
227 vik_layer_interfaces
[vl
->type
]->marshall ( vl
, data
, len
);
229 header
= g_malloc(*len
+ sizeof(*header
));
230 header
->layer_type
= vl
->type
;
232 memcpy(header
->data
, *data
, *len
);
234 *data
= (guint8
*)header
;
235 *len
= *len
+ sizeof(*header
);
242 void vik_layer_marshall_params ( VikLayer
*vl
, guint8
**data
, gint
*datalen
)
244 VikLayerParam
*params
= vik_layer_get_interface(vl
->type
)->params
;
245 VikLayerFuncGetParam get_param
= vik_layer_get_interface(vl
->type
)->get_param
;
246 GByteArray
* b
= g_byte_array_new ();
249 #define vlm_append(obj, sz) \
251 g_byte_array_append ( b, (guint8 *)&len, sizeof(len) ); \
252 g_byte_array_append ( b, (guint8 *)(obj), len );
254 vlm_append(vl
->name
, strlen(vl
->name
));
256 if ( params
&& get_param
)
259 guint16 i
, params_count
= vik_layer_get_interface(vl
->type
)->params_count
;
260 for ( i
= 0; i
< params_count
; i
++ )
262 d
= get_param(vl
, i
);
263 switch ( params
[i
].type
)
265 case VIK_LAYER_PARAM_STRING
:
266 vlm_append(d
.s
, strlen(d
.s
));
269 /* print out the string list in the array */
270 case VIK_LAYER_PARAM_STRING_LIST
: {
273 /* write length of list (# of strings) */
274 gint listlen
= g_list_length ( list
);
275 g_byte_array_append ( b
, (guint8
*)&listlen
, sizeof(listlen
) );
277 /* write each string */
279 gchar
*s
= (gchar
*) list
->data
;
280 vlm_append(s
, strlen(s
));
287 vlm_append(&d
, sizeof(d
));
295 g_byte_array_free ( b
, FALSE
);
300 void vik_layer_unmarshall_params ( VikLayer
*vl
, guint8
*data
, gint datalen
, VikViewport
*vvp
)
302 VikLayerParam
*params
= vik_layer_get_interface(vl
->type
)->params
;
303 VikLayerFuncSetParam set_param
= vik_layer_get_interface(vl
->type
)->set_param
;
305 guint8
*b
= (guint8
*)data
;
307 #define vlm_size (*(gint *)b)
308 #define vlm_read(obj) \
309 memcpy((obj), b+sizeof(gint), vlm_size); \
310 b += sizeof(gint) + vlm_size;
312 s
= g_malloc(vlm_size
+ 1);
316 vik_layer_rename(vl
, s
);
320 if ( params
&& set_param
)
323 guint16 i
, params_count
= vik_layer_get_interface(vl
->type
)->params_count
;
324 for ( i
= 0; i
< params_count
; i
++ )
326 switch ( params
[i
].type
)
328 case VIK_LAYER_PARAM_STRING
:
329 s
= g_malloc(vlm_size
+ 1);
333 set_param(vl
, i
, d
, vvp
);
336 case VIK_LAYER_PARAM_STRING_LIST
: {
337 gint listlen
= vlm_size
, j
;
339 b
+= sizeof(gint
); /* skip listlen */;
341 for ( j
= 0; j
< listlen
; j
++ ) {
343 s
= g_malloc(vlm_size
+ 1);
346 list
= g_list_append ( list
, s
);
349 set_param ( vl
, i
, d
, vvp
);
350 /* don't free -- string list is responsibility of the layer */
356 set_param(vl
, i
, d
, vvp
);
363 VikLayer
*vik_layer_unmarshall ( guint8
*data
, gint len
, VikViewport
*vvp
)
367 header
= (header_t
*)data
;
369 if ( vik_layer_interfaces
[header
->layer_type
]->unmarshall
) {
370 return vik_layer_interfaces
[header
->layer_type
]->unmarshall ( header
->data
, header
->len
, vvp
);
376 static void layer_finalize ( VikLayer
*vl
)
378 g_assert ( vl
!= NULL
);
379 if ( vik_layer_interfaces
[vl
->type
]->free
)
380 vik_layer_interfaces
[vl
->type
]->free ( vl
);
383 G_OBJECT_CLASS(parent_class
)->finalize(G_OBJECT(vl
));
386 /* sublayer switching */
387 gboolean
vik_layer_sublayer_toggle_visible ( VikLayer
*l
, gint subtype
, gpointer sublayer
)
389 if ( vik_layer_interfaces
[l
->type
]->sublayer_toggle_visible
)
390 return vik_layer_interfaces
[l
->type
]->sublayer_toggle_visible ( l
, subtype
, sublayer
);
391 return TRUE
; /* if unknown, will always be visible */
394 void vik_layer_realize ( VikLayer
*l
, VikTreeview
*vt
, GtkTreeIter
*layer_iter
)
397 l
->iter
= *layer_iter
;
399 if ( vik_layer_interfaces
[l
->type
]->realize
)
400 vik_layer_interfaces
[l
->type
]->realize ( l
, vt
, layer_iter
);
403 void vik_layer_set_menu_items_selection(VikLayer
*l
, guint16 selection
)
405 if ( vik_layer_interfaces
[l
->type
]->set_menu_selection
)
406 vik_layer_interfaces
[l
->type
]->set_menu_selection ( l
, selection
);
409 guint16
vik_layer_get_menu_items_selection(VikLayer
*l
)
411 if ( vik_layer_interfaces
[l
->type
]->get_menu_selection
)
412 return(vik_layer_interfaces
[l
->type
]->get_menu_selection (l
));
414 return(vik_layer_interfaces
[l
->type
]->menu_items_selection
);
417 void vik_layer_add_menu_items ( VikLayer
*l
, GtkMenu
*menu
, gpointer vlp
)
419 if ( vik_layer_interfaces
[l
->type
]->add_menu_items
)
420 vik_layer_interfaces
[l
->type
]->add_menu_items ( l
, menu
, vlp
);
423 gboolean
vik_layer_sublayer_add_menu_items ( VikLayer
*l
, GtkMenu
*menu
, gpointer vlp
, gint subtype
, gpointer sublayer
, GtkTreeIter
*iter
)
425 if ( vik_layer_interfaces
[l
->type
]->sublayer_add_menu_items
)
426 return vik_layer_interfaces
[l
->type
]->sublayer_add_menu_items ( l
, menu
, vlp
, subtype
, sublayer
, iter
);
431 const gchar
*vik_layer_sublayer_rename_request ( VikLayer
*l
, const gchar
*newname
, gpointer vlp
, gint subtype
, gpointer sublayer
, GtkTreeIter
*iter
)
433 if ( vik_layer_interfaces
[l
->type
]->sublayer_rename_request
)
434 return vik_layer_interfaces
[l
->type
]->sublayer_rename_request ( l
, newname
, vlp
, subtype
, sublayer
, iter
);
438 GdkPixbuf
*vik_layer_load_icon ( gint type
)
440 g_assert ( type
< VIK_LAYER_NUM_TYPES
);
441 if ( vik_layer_interfaces
[type
]->icon
)
442 return gdk_pixbuf_from_pixdata ( vik_layer_interfaces
[type
]->icon
, FALSE
, NULL
);
446 gboolean
vik_layer_set_param ( VikLayer
*layer
, guint16 id
, VikLayerParamData data
, gpointer vp
)
448 if ( vik_layer_interfaces
[layer
->type
]->set_param
)
449 return vik_layer_interfaces
[layer
->type
]->set_param ( layer
, id
, data
, vp
);
453 void vik_layer_post_read ( VikLayer
*layer
, VikViewport
*vp
, gboolean from_file
)
455 if ( vik_layer_interfaces
[layer
->type
]->post_read
)
456 vik_layer_interfaces
[layer
->type
]->post_read ( layer
, vp
, from_file
);
459 static gboolean
layer_properties_factory ( VikLayer
*vl
, VikViewport
*vp
)
461 switch ( a_uibuilder_properties_factory ( VIK_GTK_WINDOW_FROM_WIDGET(vp
),
462 vik_layer_interfaces
[vl
->type
]->params
,
463 vik_layer_interfaces
[vl
->type
]->params_count
,
464 vik_layer_interfaces
[vl
->type
]->params_groups
,
465 vik_layer_interfaces
[vl
->type
]->params_groups_count
,
466 vik_layer_interfaces
[vl
->type
]->set_param
, vl
, vp
,
467 vik_layer_interfaces
[vl
->type
]->get_param
, vl
) ) {
473 vik_layer_post_read ( vl
, vp
, FALSE
); /* update any gc's */
479 static GdkCursor
***layers_cursors
;
481 GdkCursor
*vik_layer_get_tool_cursor ( gint layer_id
, gint tool_id
)
483 if ( layer_id
>= VIK_LAYER_NUM_TYPES
)
485 if ( tool_id
>= vik_layer_interfaces
[layer_id
]->tools_count
)
487 return layers_cursors
[layer_id
][tool_id
];
490 void vik_layer_cursors_init()
493 layers_cursors
= g_malloc ( sizeof(GdkCursor
**) * VIK_LAYER_NUM_TYPES
);
494 for ( i
= 0 ; i
< VIK_LAYER_NUM_TYPES
; i
++ ) {
495 if ( vik_layer_interfaces
[i
]->tools_count
) {
496 layers_cursors
[i
] = g_malloc ( sizeof(GdkCursor
*) * vik_layer_interfaces
[i
]->tools_count
);
497 for ( j
= 0; j
< vik_layer_interfaces
[i
]->tools_count
; j
++ ) {
498 if ( vik_layer_interfaces
[i
]->tools
[j
].cursor
) {
499 const GdkPixdata
*cursor_pixdata
= vik_layer_interfaces
[i
]->tools
[j
].cursor
;
500 GError
*cursor_load_err
= NULL
;
501 GdkPixbuf
*cursor_pixbuf
= gdk_pixbuf_from_pixdata (cursor_pixdata
, FALSE
, &cursor_load_err
);
502 /* TODO: settable offeset */
503 GdkCursor
*cursor
= gdk_cursor_new_from_pixbuf ( gdk_display_get_default(), cursor_pixbuf
, 3, 3 );
504 layers_cursors
[i
][j
] = cursor
;
506 g_object_unref ( G_OBJECT(cursor_pixbuf
) );
509 layers_cursors
[i
][j
] = NULL
;
512 layers_cursors
[i
] = NULL
;
516 void vik_layer_cursors_uninit()
519 for ( i
= 0 ; i
< VIK_LAYER_NUM_TYPES
; i
++ ) {
520 if ( vik_layer_interfaces
[i
]->tools_count
) {
521 for ( j
= 0; j
< vik_layer_interfaces
[i
]->tools_count
; j
++ ) {
522 if ( layers_cursors
[i
][j
] )
523 gdk_cursor_unref ( layers_cursors
[i
][j
] );
525 g_free ( layers_cursors
[i
] );
528 g_free ( layers_cursors
);