]> git.street.me.uk Git - andy/viking.git/blobdiff - src/viklayer.c
Half-drawn hack
[andy/viking.git] / src / viklayer.c
index edd2eef48fdcdbaba72046e004f1a0d68b583483..0962577f3e6cb62e3ec69a7bcdab2e22f655addc 100644 (file)
 
 #include "viking.h"
 #include "vikradiogroup.h"
+#include "vikfilelist.h"
+#include <string.h>
+
+static VikLayer *trigger = NULL;
 
 /* functions common to all layers. */
 /* TODO longone: rename interface free -> finalize */
@@ -30,6 +34,8 @@ extern VikLayerInterface vik_trw_layer_interface;
 extern VikLayerInterface vik_maps_layer_interface;
 extern VikLayerInterface vik_coord_layer_interface;
 extern VikLayerInterface vik_georef_layer_interface;
+extern VikLayerInterface vik_gps_layer_interface;
+extern VikLayerInterface vik_dem_layer_interface;
 
 enum {
   VL_UPDATE_SIGNAL,
@@ -42,7 +48,7 @@ static GObjectClass *parent_class;
 static void layer_class_init ( VikLayerClass *klass );
 static void layer_init ( VikLayer *vl );
 static void layer_finalize ( VikLayer *vl );
-static gboolean layer_properties_factory ( VikLayer *vl, gpointer vp );
+static gboolean layer_properties_factory ( VikLayer *vl, VikViewport *vp );
 
 
 /* TODO longone: rename vik_layer_init -> set_type */
@@ -87,6 +93,31 @@ static void layer_class_init (VikLayerClass *klass)
 }
 
 void vik_layer_emit_update ( VikLayer *vl )
+{
+  if ( vl->visible ) {
+    trigger = vl;
+    g_signal_emit ( G_OBJECT(vl), layer_signals[VL_UPDATE_SIGNAL], 0 );
+  }
+}
+
+/* should only be done by VikLayersPanel -- need to redraw and record trigger
+ * when we make a layer invisible.
+ */
+void vik_layer_emit_update_although_invisible ( VikLayer *vl )
+{
+  trigger = vl;
+  g_signal_emit ( G_OBJECT(vl), layer_signals[VL_UPDATE_SIGNAL], 0 );
+}
+
+VikLayer *vik_layer_get_and_reset_trigger()
+{
+  VikLayer *rv = trigger;
+  trigger = NULL;
+  return rv;
+}
+
+/* doesn't set the trigger. should be done by aggregate layer when child emits update. */
+void vik_layer_emit_update_secondary ( VikLayer *vl )
 {
   if ( vl->visible )
     g_signal_emit ( G_OBJECT(vl), layer_signals[VL_UPDATE_SIGNAL], 0 );
@@ -97,7 +128,9 @@ static VikLayerInterface *vik_layer_interfaces[VIK_LAYER_NUM_TYPES] = {
   &vik_trw_layer_interface,
   &vik_coord_layer_interface,
   &vik_georef_layer_interface,
+  &vik_gps_layer_interface,
   &vik_maps_layer_interface,
+  &vik_dem_layer_interface,
 };
 
 VikLayerInterface *vik_layer_get_interface ( gint type )
@@ -121,20 +154,26 @@ void vik_layer_init ( VikLayer *vl, gint type )
 /* frees old name */
 void vik_layer_rename ( VikLayer *l, const gchar *new_name )
 {
-  g_assert ( l != NULL);
-  if ( l->name )
-    g_free ( l->name );
+  g_assert ( l != NULL );
+  g_assert ( new_name != NULL );
+  g_free ( l->name );
   l->name = g_strdup ( new_name );
 }
 
 void vik_layer_rename_no_copy ( VikLayer *l, gchar *new_name )
 {
-  g_assert ( l != NULL);
-  if ( l->name )
-    g_free ( l->name );
+  g_assert ( l != NULL );
+  g_assert ( new_name != NULL );
+  g_free ( l->name );
   l->name = new_name;
 }
 
+const gchar *vik_layer_get_name ( VikLayer *l )
+{
+  g_assert ( l != NULL);
+  return l->name;
+}
+
 VikLayer *vik_layer_create ( gint type, gpointer vp, GtkWindow *w, gboolean interactive )
 {
   VikLayer *new_layer = NULL;
@@ -178,22 +217,164 @@ void vik_layer_change_coord_mode ( VikLayer *l, VikCoordMode mode )
     vik_layer_interfaces[l->type]->change_coord_mode ( l, mode );
 }
 
-VikLayer *vik_layer_copy ( VikLayer *vl, gpointer vp )
+typedef struct {
+  gint layer_type;
+  gint len;
+  guint8 data[0];
+} header_t;
+
+void vik_layer_marshall ( VikLayer *vl, guint8 **data, gint *len )
+{
+  header_t *header;
+  if ( vl && vik_layer_interfaces[vl->type]->marshall ) {
+    vik_layer_interfaces[vl->type]->marshall ( vl, data, len );
+    if (*data) {
+      header = g_malloc(*len + sizeof(*header));
+      header->layer_type = vl->type;
+      header->len = *len;
+      memcpy(header->data, *data, *len);
+      g_free(*data);
+      *data = (guint8 *)header;
+      *len = *len + sizeof(*header);
+    }
+  } else {
+    *data = NULL;
+  }
+}
+
+void vik_layer_marshall_params ( VikLayer *vl, guint8 **data, gint *datalen )
 {
-  if ( vik_layer_interfaces[vl->type]->copy )
+  VikLayerParam *params = vik_layer_get_interface(vl->type)->params;
+  VikLayerFuncGetParam get_param = vik_layer_get_interface(vl->type)->get_param;
+  GByteArray* b = g_byte_array_new ();
+  gint len;
+
+#define vlm_append(obj, sz)    \
+  len = (sz);                  \
+  g_byte_array_append ( b, (guint8 *)&len, sizeof(len) );      \
+  g_byte_array_append ( b, (guint8 *)(obj), len );
+
+  vlm_append(vl->name, strlen(vl->name));
+
+  if ( params && get_param )
   {
-    VikLayer *rv = vik_layer_interfaces[vl->type]->copy ( vl, vp );
-    if ( rv )
+    VikLayerParamData d;
+    guint16 i, params_count = vik_layer_get_interface(vl->type)->params_count;
+    for ( i = 0; i < params_count; i++ )
     {
-      vik_layer_rename ( rv, vl->name );
-      rv->visible = vl->visible;
+      d = get_param(vl, i);
+      switch ( params[i].type )
+      {
+      case VIK_LAYER_PARAM_STRING: 
+       vlm_append(d.s, strlen(d.s));
+       break;
+
+      /* print out the string list in the array */
+      case VIK_LAYER_PARAM_STRING_LIST: {
+        GList *list = d.sl;
+        
+        /* write length of list (# of strings) */
+        gint listlen = g_list_length ( list );
+        g_byte_array_append ( b, (guint8 *)&listlen, sizeof(listlen) );
+
+        /* write each string */
+        while ( list ) {
+          gchar *s = (gchar *) list->data;
+          vlm_append(s, strlen(s));
+          list = list->next;
+        }
+
+       break;
+      }
+      default:
+       vlm_append(&d, sizeof(d));
+       break;
+      }
+    }
+  }
+  
+  *data = b->data;
+  *datalen = b->len;
+  g_byte_array_free ( b, FALSE );
+
+#undef vlm_append
+}
+
+void vik_layer_unmarshall_params ( VikLayer *vl, guint8 *data, gint datalen, VikViewport *vvp )
+{
+  VikLayerParam *params = vik_layer_get_interface(vl->type)->params;
+  VikLayerFuncSetParam set_param = vik_layer_get_interface(vl->type)->set_param;
+  gchar *s;
+  guint8 *b = (guint8 *)data;
+  
+#define vlm_size (*(gint *)b)
+#define vlm_read(obj)                          \
+  memcpy((obj), b+sizeof(gint), vlm_size);     \
+  b += sizeof(gint) + vlm_size;
+  
+  s = g_malloc(vlm_size + 1);
+  s[vlm_size]=0;
+  vlm_read(s);
+  
+  vik_layer_rename(vl, s);
+  
+  g_free(s);
+
+  if ( params && set_param )
+  {
+    VikLayerParamData d;
+    guint16 i, params_count = vik_layer_get_interface(vl->type)->params_count;
+    for ( i = 0; i < params_count; i++ )
+    {
+      switch ( params[i].type )
+      {
+      case VIK_LAYER_PARAM_STRING: 
+       s = g_malloc(vlm_size + 1);
+       s[vlm_size]=0;
+       vlm_read(s);
+       d.s = s;
+       set_param(vl, i, d, vvp);
+       g_free(s);
+       break;
+      case VIK_LAYER_PARAM_STRING_LIST:  {
+        gint listlen = vlm_size, j;
+        GList *list = NULL;
+        b += sizeof(gint); /* skip listlen */;
+
+        for ( j = 0; j < listlen; j++ ) {
+          /* get a string */
+          s = g_malloc(vlm_size + 1);
+         s[vlm_size]=0;
+         vlm_read(s);
+          list = g_list_append ( list, s );
+        }
+        d.sl = list;
+        set_param ( vl, i, d, vvp );
+        /* don't free -- string list is responsibility of the layer */
+
+        break;
+        }
+      default:
+       vlm_read(&d);
+       set_param(vl, i, d, vvp);
+       break;
+      }
     }
-    return rv;
   }
-  else
-    return NULL;
 }
 
+VikLayer *vik_layer_unmarshall ( guint8 *data, gint len, VikViewport *vvp )
+{
+  header_t *header;
+
+  header = (header_t *)data;
+  
+  if ( vik_layer_interfaces[header->layer_type]->unmarshall ) {
+    return vik_layer_interfaces[header->layer_type]->unmarshall ( header->data, header->len, vvp );
+  } else {
+    return NULL;
+  }
+}
 
 static void layer_finalize ( VikLayer *vl )
 {
@@ -222,6 +403,20 @@ void vik_layer_realize ( VikLayer *l, VikTreeview *vt, GtkTreeIter *layer_iter )
     vik_layer_interfaces[l->type]->realize ( l, vt, layer_iter );
 }
 
+void vik_layer_set_menu_items_selection(VikLayer *l, guint16 selection)
+{
+  if ( vik_layer_interfaces[l->type]->set_menu_selection )
+    vik_layer_interfaces[l->type]->set_menu_selection ( l, selection );
+}
+
+guint16 vik_layer_get_menu_items_selection(VikLayer *l)
+{
+  if ( vik_layer_interfaces[l->type]->get_menu_selection )
+    return(vik_layer_interfaces[l->type]->get_menu_selection (l));
+  else
+    return(vik_layer_interfaces[l->type]->menu_items_selection);
+}
+
 void vik_layer_add_menu_items ( VikLayer *l, GtkMenu *menu, gpointer vlp )
 {
   if ( vik_layer_interfaces[l->type]->add_menu_items )
@@ -258,15 +453,15 @@ gboolean vik_layer_set_param ( VikLayer *layer, guint16 id, VikLayerParamData da
   return FALSE;
 }
 
-void vik_layer_post_read ( VikLayer *layer, gpointer vp )
+void vik_layer_post_read ( VikLayer *layer, VikViewport *vp, gboolean from_file )
 {
   if ( vik_layer_interfaces[layer->type]->post_read )
-    vik_layer_interfaces[layer->type]->post_read ( layer, vp );
+    vik_layer_interfaces[layer->type]->post_read ( layer, vp, from_file );
 }
 
 static GtkWidget *properties_widget_new_widget ( VikLayerParam *param, VikLayerParamData data )
 {
-  GtkWidget *rv;
+  GtkWidget *rv = NULL;
   switch ( param->widget_type )
   {
     case VIK_LAYER_WIDGET_COLOR:
@@ -305,9 +500,29 @@ static GtkWidget *properties_widget_new_widget ( VikLayerParam *param, VikLayerP
       break;
 #endif
     case VIK_LAYER_WIDGET_RADIOGROUP:
+      /* widget_data and extra_widget_data are GList */
+      if ( param->type == VIK_LAYER_PARAM_UINT && param->widget_data )
+      {
+        rv = vik_radio_group_new ( param->widget_data );
+        if ( param->extra_widget_data ) /* map of alternate uint values for options */
+        {
+          int i;
+         int nb_elem = g_list_length(param->widget_data);
+          for ( i = 0; i < nb_elem; i++ )
+            if ( (guint32)g_list_nth_data(param->extra_widget_data, i) == data.u )
+            {
+              vik_radio_group_set_selected ( VIK_RADIO_GROUP(rv), i );
+              break;
+            }
+        }
+        else if ( data.u ) /* zero is already default */
+          vik_radio_group_set_selected ( VIK_RADIO_GROUP(rv), data.u );
+      }
+      break;
+    case VIK_LAYER_WIDGET_RADIOGROUP_STATIC:
       if ( param->type == VIK_LAYER_PARAM_UINT && param->widget_data )
       {
-        rv = vik_radio_group_new ( (const gchar **) param->widget_data );
+        rv = vik_radio_group_new_static ( (const gchar **) param->widget_data );
         if ( param->extra_widget_data ) /* map of alternate uint values for options */
         {
           int i;
@@ -345,6 +560,13 @@ static GtkWidget *properties_widget_new_widget ( VikLayerParam *param, VikLayerP
         vik_file_entry_set_filename ( VIK_FILE_ENTRY(rv), data.s );
       }
       break;
+    case VIK_LAYER_WIDGET_FILELIST:
+      if ( param->type == VIK_LAYER_PARAM_STRING_LIST )
+      {
+        rv = vik_file_list_new ( param->title );
+        vik_file_list_set_files ( VIK_FILE_LIST(rv), data.sl );
+      }
+      break;
     case VIK_LAYER_WIDGET_HSCALE:
       if ( (param->type == VIK_LAYER_PARAM_DOUBLE || param->type == VIK_LAYER_PARAM_UINT
            || param->type == VIK_LAYER_PARAM_INT)  && param->widget_data )
@@ -380,9 +602,10 @@ static VikLayerParamData properties_widget_get_value ( GtkWidget *widget, VikLay
       break;
 #endif
     case VIK_LAYER_WIDGET_RADIOGROUP:
+    case VIK_LAYER_WIDGET_RADIOGROUP_STATIC:
       rv.u = vik_radio_group_get_selected(VIK_RADIO_GROUP(widget));
       if ( param->extra_widget_data )
-        rv.u = ((guint *)param->extra_widget_data)[rv.u];
+        rv.u = (guint32)g_list_nth_data(param->extra_widget_data, rv.u);
       break;
     case VIK_LAYER_WIDGET_SPINBUTTON:
       if ( param->type == VIK_LAYER_PARAM_UINT )
@@ -398,6 +621,9 @@ static VikLayerParamData properties_widget_get_value ( GtkWidget *widget, VikLay
     case VIK_LAYER_WIDGET_FILEENTRY:
       rv.s = vik_file_entry_get_filename ( VIK_FILE_ENTRY(widget) );
       break;
+    case VIK_LAYER_WIDGET_FILELIST:
+      rv.sl = vik_file_list_get_files ( VIK_FILE_LIST(widget) );
+      break;
     case VIK_LAYER_WIDGET_HSCALE:
       if ( param->type == VIK_LAYER_PARAM_UINT )
         rv.u = (guint32) gtk_range_get_value ( GTK_RANGE(widget) );
@@ -412,7 +638,7 @@ static VikLayerParamData properties_widget_get_value ( GtkWidget *widget, VikLay
 
 /* false if cancel, true if OK */
 /* some would claim this wasn't written to be human-readable. */
-static gboolean layer_properties_factory ( VikLayer *vl, gpointer vp )
+static gboolean layer_properties_factory ( VikLayer *vl, VikViewport *vp )
 {
   VikLayerParam *params = vik_layer_interfaces[vl->type]->params;
   guint16 params_count = vik_layer_interfaces[vl->type]->params_count;
@@ -507,7 +733,7 @@ static gboolean layer_properties_factory ( VikLayer *vl, gpointer vp )
           j++;
         }
       }
-      vik_layer_post_read ( vl, vp ); /* update any gc's */
+      vik_layer_post_read ( vl, vp, FALSE ); /* update any gc's */
 
       gtk_widget_destroy ( dialog ); /* hide before redrawing. */
       g_free ( widgets );