[gtksourceview/wip/new-space-drawing-api] SpaceDrawer: new API with two enums (space types vs locations)



commit 5ebbc0d4bf36c3c3726c5448c6d3ee611b690a6f
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Sat Jul 23 17:37:25 2016 +0200

    SpaceDrawer: new API with two enums (space types vs locations)
    
    https://bugzilla.gnome.org/show_bug.cgi?id=683678

 docs/reference/gtksourceview-3.0-sections.txt |   10 +
 gtksourceview/gtksourcespacedrawer.c          |  391 +++++++++++++++++++++++++
 gtksourceview/gtksourcespacedrawer.h          |   64 ++++
 testsuite/Makefile.am                         |    3 +
 testsuite/test-space-drawer.c                 |  247 ++++++++++++++++
 5 files changed, 715 insertions(+), 0 deletions(-)
---
diff --git a/docs/reference/gtksourceview-3.0-sections.txt b/docs/reference/gtksourceview-3.0-sections.txt
index 3888e2a..5cca889 100644
--- a/docs/reference/gtksourceview-3.0-sections.txt
+++ b/docs/reference/gtksourceview-3.0-sections.txt
@@ -743,6 +743,12 @@ gtk_source_search_settings_get_type
 <FILE>spacedrawer</FILE>
 <TITLE>GtkSourceSpaceDrawer</TITLE>
 GtkSourceSpaceDrawer
+GtkSourceSpaceTypeFlags
+GtkSourceSpaceLocationFlags
+gtk_source_space_drawer_get_types_for_locations
+gtk_source_space_drawer_set_types_for_locations
+gtk_source_space_drawer_get_matrix
+gtk_source_space_drawer_set_matrix
 <SUBSECTION Standard>
 GTK_SOURCE_IS_SPACE_DRAWER
 GTK_SOURCE_IS_SPACE_DRAWER_CLASS
@@ -753,6 +759,10 @@ GTK_SOURCE_TYPE_SPACE_DRAWER
 GtkSourceSpaceDrawerClass
 GtkSourceSpaceDrawerPrivate
 gtk_source_space_drawer_get_type
+GTK_SOURCE_TYPE_SPACE_LOCATION_FLAGS
+GTK_SOURCE_TYPE_SPACE_TYPE_FLAGS
+gtk_source_space_location_flags_get_type
+gtk_source_space_type_flags_get_type
 </SECTION>
 
 <SECTION>
diff --git a/gtksourceview/gtksourcespacedrawer.c b/gtksourceview/gtksourcespacedrawer.c
index fc4416e..842a1c1 100644
--- a/gtksourceview/gtksourcespacedrawer.c
+++ b/gtksourceview/gtksourcespacedrawer.c
@@ -38,6 +38,10 @@
  * @See_also: #GtkSourceView
  */
 
+/* A drawer specially designed for the International Space Station. It comes by
+ * default with a DVD of Matrix, in case the astronauts are bored.
+ */
+
 /*
 #define ENABLE_PROFILE
 */
@@ -45,17 +49,151 @@
 
 struct _GtkSourceSpaceDrawerPrivate
 {
+       GtkSourceSpaceTypeFlags *matrix;
        GtkSourceDrawSpacesFlags flags;
        GdkRGBA *color;
 };
 
+enum
+{
+       PROP_0,
+       PROP_MATRIX,
+       N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES];
+
 G_DEFINE_TYPE_WITH_PRIVATE (GtkSourceSpaceDrawer, gtk_source_space_drawer, G_TYPE_OBJECT)
 
+#if 0
+static gint
+get_flag_index (gint flag)
+{
+       gint index = 0;
+
+       if (flag <= 0)
+       {
+               return -1;
+       }
+
+       while ((flag & 1) == 0)
+       {
+               flag >>= 1;
+               index++;
+       }
+
+       return flag == 1 ? index : -1;
+}
+#endif
+
+static gint
+get_number_of_locations (void)
+{
+       gint num;
+       gint flags;
+
+       num = 0;
+       flags = GTK_SOURCE_SPACE_LOCATION_ALL;
+
+       while (flags != 0)
+       {
+               flags >>= 1;
+               num++;
+       }
+
+       return num;
+}
+
+static gboolean
+is_zero_matrix (GtkSourceSpaceDrawer *drawer)
+{
+       gint num_locations;
+       gint i;
+
+       num_locations = get_number_of_locations ();
+
+       for (i = 0; i < num_locations; i++)
+       {
+               if (drawer->priv->matrix[i] != 0)
+               {
+                       return FALSE;
+               }
+       }
+
+       return TRUE;
+}
+
+static void
+set_zero_matrix (GtkSourceSpaceDrawer *drawer)
+{
+       gint num_locations;
+       gint i;
+       gboolean changed = FALSE;
+
+       num_locations = get_number_of_locations ();
+
+       for (i = 0; i < num_locations; i++)
+       {
+               if (drawer->priv->matrix[i] != 0)
+               {
+                       drawer->priv->matrix[i] = 0;
+                       changed = TRUE;
+               }
+       }
+
+       if (changed)
+       {
+               g_object_notify_by_pspec (G_OBJECT (drawer), properties[PROP_MATRIX]);
+       }
+}
+
+static void
+gtk_source_space_drawer_get_property (GObject    *object,
+                                     guint       prop_id,
+                                     GValue     *value,
+                                     GParamSpec *pspec)
+{
+       GtkSourceSpaceDrawer *drawer = GTK_SOURCE_SPACE_DRAWER (object);
+
+       switch (prop_id)
+       {
+               case PROP_MATRIX:
+                       g_value_set_variant (value, gtk_source_space_drawer_get_matrix (drawer));
+                       break;
+
+               default:
+                       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                       break;
+       }
+}
+
+static void
+gtk_source_space_drawer_set_property (GObject      *object,
+                                     guint         prop_id,
+                                     const GValue *value,
+                                     GParamSpec   *pspec)
+{
+       GtkSourceSpaceDrawer *drawer = GTK_SOURCE_SPACE_DRAWER (object);
+
+       switch (prop_id)
+       {
+               case PROP_MATRIX:
+                       gtk_source_space_drawer_set_matrix (drawer, g_value_get_variant (value));
+                       break;
+
+               default:
+                       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                       break;
+       }
+}
+
 static void
 gtk_source_space_drawer_finalize (GObject *object)
 {
        GtkSourceSpaceDrawer *drawer = GTK_SOURCE_SPACE_DRAWER (object);
 
+       g_free (drawer->priv->matrix);
+
        if (drawer->priv->color != NULL)
        {
                gdk_rgba_free (drawer->priv->color);
@@ -69,13 +207,47 @@ gtk_source_space_drawer_class_init (GtkSourceSpaceDrawerClass *klass)
 {
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
+       object_class->get_property = gtk_source_space_drawer_get_property;
+       object_class->set_property = gtk_source_space_drawer_set_property;
        object_class->finalize = gtk_source_space_drawer_finalize;
+
+       /**
+        * GtkSourceSpaceDrawer:matrix:
+        *
+        * The :matrix property is a #GVariant property to specify where and
+        * what kind of whitespaces to draw.
+        *
+        * The #GVariant is of type `"au"`, an array of unsigned integers. Each
+        * integer is a combination of #GtkSourceSpaceTypeFlags. There is one
+        * integer for each #GtkSourceSpaceLocationFlags, in the same order as
+        * they are defined in the enum (%GTK_SOURCE_SPACE_LOCATION_NONE and
+        * %GTK_SOURCE_SPACE_LOCATION_ALL are not taken into account).
+        *
+        * If the array is shorter than the number of locations, then the value
+        * for the missing locations will be %GTK_SOURCE_SPACE_TYPE_NONE.
+        *
+        * The default value is the empty array `"[]"`.
+        *
+        * Since: 3.24
+        */
+       properties[PROP_MATRIX] =
+               g_param_spec_variant ("matrix",
+                                     "Matrix",
+                                     "",
+                                     G_VARIANT_TYPE ("au"),
+                                     g_variant_new ("au", NULL),
+                                     G_PARAM_READWRITE |
+                                     G_PARAM_STATIC_STRINGS);
+
+       g_object_class_install_properties (object_class, N_PROPERTIES, properties);
 }
 
 static void
 gtk_source_space_drawer_init (GtkSourceSpaceDrawer *drawer)
 {
        drawer->priv = gtk_source_space_drawer_get_instance_private (drawer);
+
+       drawer->priv->matrix = g_new0 (GtkSourceSpaceTypeFlags, get_number_of_locations ());
 }
 
 GtkSourceSpaceDrawer *
@@ -109,6 +281,225 @@ _gtk_source_space_drawer_set_flags (GtkSourceSpaceDrawer     *drawer,
        return changed;
 }
 
+/**
+ * gtk_source_space_drawer_get_types_for_locations:
+ * @drawer: a #GtkSourceSpaceDrawer.
+ * @locations: one or several #GtkSourceSpaceLocationFlags.
+ *
+ * If only one location is specified, this function returns what kind of
+ * whitespaces are drawn at that location. The value is retrieved from the
+ * #GtkSourceSpaceDrawer:matrix property.
+ *
+ * If several locations are specified, this function returns the logical AND for
+ * those locations. Which means that if a certain kind of whitespace is present
+ * in the return value, then that kind of whitespace is drawn at all the
+ * specified @locations.
+ *
+ * Returns: a combination of #GtkSourceSpaceTypeFlags.
+ * Since: 3.24
+ */
+GtkSourceSpaceTypeFlags
+gtk_source_space_drawer_get_types_for_locations (GtkSourceSpaceDrawer        *drawer,
+                                                GtkSourceSpaceLocationFlags  locations)
+{
+       GtkSourceSpaceTypeFlags ret = GTK_SOURCE_SPACE_TYPE_ALL;
+       gint index;
+       gint num_locations;
+       gboolean found;
+
+       g_return_val_if_fail (GTK_SOURCE_IS_SPACE_DRAWER (drawer), GTK_SOURCE_SPACE_TYPE_NONE);
+
+       index = 0;
+       num_locations = get_number_of_locations ();
+       found = FALSE;
+
+       while (locations != 0 && index < num_locations)
+       {
+               if ((locations & 1) == 1)
+               {
+                       ret &= drawer->priv->matrix[index];
+                       found = TRUE;
+               }
+
+               locations >>= 1;
+               index++;
+       }
+
+       return found ? ret : GTK_SOURCE_SPACE_TYPE_NONE;
+}
+
+/**
+ * gtk_source_space_drawer_set_types_for_locations:
+ * @drawer: a #GtkSourceSpaceDrawer.
+ * @locations: one or several #GtkSourceSpaceLocationFlags.
+ * @types: a combination of #GtkSourceSpaceTypeFlags.
+ *
+ * Modifies the #GtkSourceSpaceDrawer:matrix property at the specified
+ * @locations.
+ *
+ * Since: 3.24
+ */
+void
+gtk_source_space_drawer_set_types_for_locations (GtkSourceSpaceDrawer        *drawer,
+                                                GtkSourceSpaceLocationFlags  locations,
+                                                GtkSourceSpaceTypeFlags      types)
+{
+       gint index;
+       gint num_locations;
+       gboolean changed = FALSE;
+
+       g_return_if_fail (GTK_SOURCE_IS_SPACE_DRAWER (drawer));
+
+       index = 0;
+       num_locations = get_number_of_locations ();
+
+       while (locations != 0 && index < num_locations)
+       {
+               if ((locations & 1) == 1 &&
+                   drawer->priv->matrix[index] != types)
+               {
+                       drawer->priv->matrix[index] = types;
+                       changed = TRUE;
+               }
+
+               locations >>= 1;
+               index++;
+       }
+
+       if (changed)
+       {
+               g_object_notify_by_pspec (G_OBJECT (drawer), properties[PROP_MATRIX]);
+       }
+}
+
+/**
+ * gtk_source_space_drawer_get_matrix:
+ * @drawer: a #GtkSourceSpaceDrawer.
+ *
+ * Gets the value of the #GtkSourceSpaceDrawer:matrix property, as a #GVariant.
+ * An empty array can be returned in case the matrix is a zero matrix.
+ *
+ * The gtk_source_space_drawer_get_types_for_locations() function may be more
+ * convenient to use.
+ *
+ * Returns: the #GtkSourceSpaceDrawer:matrix value as a new floating #GVariant
+ *   instance.
+ * Since: 3.24
+ */
+GVariant *
+gtk_source_space_drawer_get_matrix (GtkSourceSpaceDrawer *drawer)
+{
+       GVariantBuilder builder;
+       gint num_locations;
+       gint i;
+
+       g_return_val_if_fail (GTK_SOURCE_IS_SPACE_DRAWER (drawer), NULL);
+
+       if (is_zero_matrix (drawer))
+       {
+               return g_variant_new ("au", NULL);
+       }
+
+       g_variant_builder_init (&builder, G_VARIANT_TYPE ("au"));
+
+       num_locations = get_number_of_locations ();
+
+       for (i = 0; i < num_locations; i++)
+       {
+               GVariant *space_types;
+
+               space_types = g_variant_new_uint32 (drawer->priv->matrix[i]);
+
+               g_variant_builder_add_value (&builder, space_types);
+       }
+
+       return g_variant_builder_end (&builder);
+}
+
+/**
+ * gtk_source_space_drawer_set_matrix:
+ * @drawer: a #GtkSourceSpaceDrawer.
+ * @matrix: (transfer floating) (nullable): the new matrix value, or %NULL.
+ *
+ * Sets a new value to the #GtkSourceSpaceDrawer:matrix property, as a
+ * #GVariant. If @matrix is %NULL, then an empty array is set.
+ *
+ * If @matrix is floating, it is consumed.
+ *
+ * The gtk_source_space_drawer_set_types_for_locations() function may be more
+ * convenient to use.
+ *
+ * Since: 3.24
+ */
+void
+gtk_source_space_drawer_set_matrix (GtkSourceSpaceDrawer *drawer,
+                                   GVariant             *matrix)
+{
+       gint num_locations;
+       gint index;
+       GVariantIter iter;
+       gboolean changed = FALSE;
+
+       g_return_if_fail (GTK_SOURCE_IS_SPACE_DRAWER (drawer));
+
+       if (matrix == NULL)
+       {
+               set_zero_matrix (drawer);
+               return;
+       }
+
+       g_return_if_fail (g_variant_is_of_type (matrix, G_VARIANT_TYPE ("au")));
+
+       g_variant_iter_init (&iter, matrix);
+
+       num_locations = get_number_of_locations ();
+       index = 0;
+       while (index < num_locations)
+       {
+               GVariant *child;
+               guint32 space_types;
+
+               child = g_variant_iter_next_value (&iter);
+               if (child == NULL)
+               {
+                       break;
+               }
+
+               space_types = g_variant_get_uint32 (child);
+
+               if (drawer->priv->matrix[index] != space_types)
+               {
+                       drawer->priv->matrix[index] = space_types;
+                       changed = TRUE;
+               }
+
+               g_variant_unref (child);
+               index++;
+       }
+
+       while (index < num_locations)
+       {
+               if (drawer->priv->matrix[index] != 0)
+               {
+                       drawer->priv->matrix[index] = 0;
+                       changed = TRUE;
+               }
+
+               index++;
+       }
+
+       if (changed)
+       {
+               g_object_notify_by_pspec (G_OBJECT (drawer), properties[PROP_MATRIX]);
+       }
+
+       if (g_variant_is_floating (matrix))
+       {
+               g_variant_ref_sink (matrix);
+               g_variant_unref (matrix);
+       }
+}
+
 void
 _gtk_source_space_drawer_update_color (GtkSourceSpaceDrawer *drawer,
                                       GtkSourceView        *view)
diff --git a/gtksourceview/gtksourcespacedrawer.h b/gtksourceview/gtksourcespacedrawer.h
index 624770d..e18f68f 100644
--- a/gtksourceview/gtksourcespacedrawer.h
+++ b/gtksourceview/gtksourcespacedrawer.h
@@ -59,9 +59,73 @@ struct _GtkSourceSpaceDrawerClass
        gpointer padding[20];
 };
 
+/**
+ * GtkSourceSpaceTypeFlags:
+ * @GTK_SOURCE_SPACE_TYPE_NONE: No flags.
+ * @GTK_SOURCE_SPACE_TYPE_SPACE: Space character.
+ * @GTK_SOURCE_SPACE_TYPE_TAB: Tab character.
+ * @GTK_SOURCE_SPACE_TYPE_NEWLINE: Line break character.
+ * @GTK_SOURCE_SPACE_TYPE_NBSP: Non-breaking space character.
+ * @GTK_SOURCE_SPACE_TYPE_ALL: All whitespaces.
+ *
+ * #GtkSourceSpaceTypeFlags contains flags for whitespace types.
+ *
+ * Since: 3.24
+ */
+typedef enum _GtkSourceSpaceTypeFlags
+{
+       GTK_SOURCE_SPACE_TYPE_NONE      = 0,
+       GTK_SOURCE_SPACE_TYPE_SPACE     = 1 << 0,
+       GTK_SOURCE_SPACE_TYPE_TAB       = 1 << 1,
+       GTK_SOURCE_SPACE_TYPE_NEWLINE   = 1 << 2,
+       GTK_SOURCE_SPACE_TYPE_NBSP      = 1 << 3,
+       GTK_SOURCE_SPACE_TYPE_ALL       = 0xf
+} GtkSourceSpaceTypeFlags;
+
+/**
+ * GtkSourceSpaceLocationFlags:
+ * @GTK_SOURCE_SPACE_LOCATION_NONE: No flags.
+ * @GTK_SOURCE_SPACE_LOCATION_LEADING: Leading whitespaces on a line, i.e. the
+ *   indentation.
+ * @GTK_SOURCE_SPACE_LOCATION_INSIDE_TEXT: Whitespaces inside a line of text.
+ * @GTK_SOURCE_SPACE_LOCATION_TRAILING: Trailing whitespaces on a line.
+ * @GTK_SOURCE_SPACE_LOCATION_ALL: Whitespaces anywhere.
+ *
+ * #GtkSourceSpaceLocationFlags contains flags for whitespace locations.
+ *
+ * If a line contains only whitespaces (no text), the whitespaces match both
+ * %GTK_SOURCE_SPACE_LOCATION_LEADING and %GTK_SOURCE_SPACE_LOCATION_TRAILING.
+ *
+ * Since: 3.24
+ */
+typedef enum _GtkSourceSpaceLocationFlags
+{
+       GTK_SOURCE_SPACE_LOCATION_NONE          = 0,
+       GTK_SOURCE_SPACE_LOCATION_LEADING       = 1 << 0,
+       GTK_SOURCE_SPACE_LOCATION_INSIDE_TEXT   = 1 << 1,
+       GTK_SOURCE_SPACE_LOCATION_TRAILING      = 1 << 2,
+       GTK_SOURCE_SPACE_LOCATION_ALL           = 0x7
+} GtkSourceSpaceLocationFlags;
+
 GTK_SOURCE_AVAILABLE_IN_3_24
 GType                  gtk_source_space_drawer_get_type                (void) G_GNUC_CONST;
 
+GTK_SOURCE_AVAILABLE_IN_3_24
+GtkSourceSpaceTypeFlags        gtk_source_space_drawer_get_types_for_locations (GtkSourceSpaceDrawer        
*drawer,
+                                                                        GtkSourceSpaceLocationFlags  
locations);
+
+GTK_SOURCE_AVAILABLE_IN_3_24
+void                   gtk_source_space_drawer_set_types_for_locations (GtkSourceSpaceDrawer        *drawer,
+                                                                        GtkSourceSpaceLocationFlags  
locations,
+                                                                        GtkSourceSpaceTypeFlags      types);
+
+GTK_SOURCE_AVAILABLE_IN_3_24
+GVariant *             gtk_source_space_drawer_get_matrix              (GtkSourceSpaceDrawer *drawer);
+
+GTK_SOURCE_AVAILABLE_IN_3_24
+void                   gtk_source_space_drawer_set_matrix              (GtkSourceSpaceDrawer *drawer,
+                                                                        GVariant             *matrix);
+
 G_END_DECLS
 
 #endif /* GTK_SOURCE_SPACE_DRAWER_H */
diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
index 31568fc..b918e3a 100644
--- a/testsuite/Makefile.am
+++ b/testsuite/Makefile.am
@@ -78,6 +78,9 @@ test_region_SOURCES = test-region.c
 UNIT_TEST_PROGS += test-search-context
 test_search_context_SOURCES = test-search-context.c
 
+UNIT_TEST_PROGS += test-space-drawer
+test_space_drawer_SOURCES = test-space-drawer.c
+
 UNIT_TEST_PROGS += test-stylescheme
 test_stylescheme_SOURCES = test-stylescheme.c
 
diff --git a/testsuite/test-space-drawer.c b/testsuite/test-space-drawer.c
new file mode 100644
index 0000000..8ef1c89
--- /dev/null
+++ b/testsuite/test-space-drawer.c
@@ -0,0 +1,247 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; coding: utf-8 -*- */
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright (C) 2016 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <gtksourceview/gtksource.h>
+
+#define NUM_LOCATIONS (3)
+#define LEADING_INDEX (0)
+#define INSIDE_TEXT_INDEX (1)
+#define TRAILING_INDEX (2)
+
+static gboolean
+is_zero_matrix (GtkSourceSpaceTypeFlags *matrix)
+{
+       gint i;
+
+       for (i = 0; i < NUM_LOCATIONS; i++)
+       {
+               if (matrix[i] != 0)
+               {
+                       return FALSE;
+               }
+       }
+
+       return TRUE;
+}
+
+static GVariant *
+create_variant_from_matrix (GtkSourceSpaceTypeFlags *matrix)
+{
+       GVariantBuilder builder;
+       gint i;
+
+       if (is_zero_matrix (matrix))
+       {
+               return g_variant_new ("au", NULL);
+       }
+
+       g_variant_builder_init (&builder, G_VARIANT_TYPE ("au"));
+
+       for (i = 0; i < NUM_LOCATIONS; i++)
+       {
+               GVariant *types;
+
+               types = g_variant_new_uint32 (matrix[i]);
+
+               g_variant_builder_add_value (&builder, types);
+       }
+
+       return g_variant_builder_end (&builder);
+}
+
+static void
+check_equal_matrix (GtkSourceSpaceDrawer    *drawer,
+                   GtkSourceSpaceTypeFlags *matrix)
+{
+       GtkSourceSpaceTypeFlags types;
+       GVariant *my_variant;
+       GVariant *drawer_variant;
+
+       types = gtk_source_space_drawer_get_types_for_locations (drawer, GTK_SOURCE_SPACE_LOCATION_LEADING);
+       g_assert_cmpint (types, ==, matrix[LEADING_INDEX]);
+
+       types = gtk_source_space_drawer_get_types_for_locations (drawer, 
GTK_SOURCE_SPACE_LOCATION_INSIDE_TEXT);
+       g_assert_cmpint (types, ==, matrix[INSIDE_TEXT_INDEX]);
+
+       types = gtk_source_space_drawer_get_types_for_locations (drawer, GTK_SOURCE_SPACE_LOCATION_TRAILING);
+       g_assert_cmpint (types, ==, matrix[TRAILING_INDEX]);
+
+       /* Check variants */
+       my_variant = create_variant_from_matrix (matrix);
+       drawer_variant = gtk_source_space_drawer_get_matrix (drawer);
+       g_assert (g_variant_equal (my_variant, drawer_variant));
+
+       gtk_source_space_drawer_set_types_for_locations (drawer,
+                                                        GTK_SOURCE_SPACE_LOCATION_ALL,
+                                                        GTK_SOURCE_SPACE_TYPE_NONE);
+       gtk_source_space_drawer_set_matrix (drawer, my_variant);
+       g_variant_ref_sink (drawer_variant);
+       g_variant_unref (drawer_variant);
+
+       my_variant = create_variant_from_matrix (matrix);
+       drawer_variant = gtk_source_space_drawer_get_matrix (drawer);
+       g_assert (g_variant_equal (my_variant, drawer_variant));
+       g_variant_ref_sink (my_variant);
+       g_variant_unref (my_variant);
+       g_variant_ref_sink (drawer_variant);
+       g_variant_unref (drawer_variant);
+
+       types = gtk_source_space_drawer_get_types_for_locations (drawer, GTK_SOURCE_SPACE_LOCATION_LEADING);
+       g_assert_cmpint (types, ==, matrix[LEADING_INDEX]);
+
+       types = gtk_source_space_drawer_get_types_for_locations (drawer, 
GTK_SOURCE_SPACE_LOCATION_INSIDE_TEXT);
+       g_assert_cmpint (types, ==, matrix[INSIDE_TEXT_INDEX]);
+
+       types = gtk_source_space_drawer_get_types_for_locations (drawer, GTK_SOURCE_SPACE_LOCATION_TRAILING);
+       g_assert_cmpint (types, ==, matrix[TRAILING_INDEX]);
+}
+
+static void
+set_matrix (GtkSourceSpaceDrawer    *drawer,
+           GtkSourceSpaceTypeFlags *matrix)
+{
+       GtkSourceSpaceTypeFlags types;
+
+       /* Leading */
+       gtk_source_space_drawer_set_types_for_locations (drawer,
+                                                        GTK_SOURCE_SPACE_LOCATION_LEADING,
+                                                        matrix[LEADING_INDEX]);
+
+       types = gtk_source_space_drawer_get_types_for_locations (drawer, GTK_SOURCE_SPACE_LOCATION_LEADING);
+       g_assert_cmpint (types, ==, matrix[LEADING_INDEX]);
+
+       /* Inside text */
+       gtk_source_space_drawer_set_types_for_locations (drawer,
+                                                        GTK_SOURCE_SPACE_LOCATION_INSIDE_TEXT,
+                                                        matrix[INSIDE_TEXT_INDEX]);
+
+       types = gtk_source_space_drawer_get_types_for_locations (drawer, 
GTK_SOURCE_SPACE_LOCATION_INSIDE_TEXT);
+       g_assert_cmpint (types, ==, matrix[INSIDE_TEXT_INDEX]);
+
+       /* Trailing */
+       gtk_source_space_drawer_set_types_for_locations (drawer,
+                                                        GTK_SOURCE_SPACE_LOCATION_TRAILING,
+                                                        matrix[TRAILING_INDEX]);
+
+       types = gtk_source_space_drawer_get_types_for_locations (drawer, GTK_SOURCE_SPACE_LOCATION_TRAILING);
+       g_assert_cmpint (types, ==, matrix[TRAILING_INDEX]);
+
+       /* Check all */
+       check_equal_matrix (drawer, matrix);
+}
+
+/* For a matrix, the getters and setters are less trivial so it's better to test
+ * them.
+ */
+static void
+test_matrix_getters_setters (void)
+{
+       GtkSourceView *view;
+       GtkSourceSpaceDrawer *drawer;
+       GtkSourceSpaceTypeFlags matrix[NUM_LOCATIONS];
+       GtkSourceSpaceTypeFlags types;
+
+       view = GTK_SOURCE_VIEW (gtk_source_view_new ());
+       g_object_ref_sink (view);
+
+       drawer = gtk_source_view_get_space_drawer (view);
+
+       /* Default value */
+       matrix[LEADING_INDEX] = 0;
+       matrix[INSIDE_TEXT_INDEX] = 0;
+       matrix[TRAILING_INDEX] = 0;
+       check_equal_matrix (drawer, matrix);
+
+       /* Set each location separately */
+       set_matrix (drawer, matrix);
+
+       matrix[INSIDE_TEXT_INDEX] = GTK_SOURCE_SPACE_TYPE_NBSP;
+       set_matrix (drawer, matrix);
+
+       matrix[TRAILING_INDEX] = GTK_SOURCE_SPACE_TYPE_ALL;
+       set_matrix (drawer, matrix);
+
+       /* Reset to 0 all at once */
+       gtk_source_space_drawer_set_types_for_locations (drawer,
+                                                        GTK_SOURCE_SPACE_LOCATION_ALL,
+                                                        GTK_SOURCE_SPACE_TYPE_NONE);
+
+       matrix[LEADING_INDEX] = 0;
+       matrix[INSIDE_TEXT_INDEX] = 0;
+       matrix[TRAILING_INDEX] = 0;
+       check_equal_matrix (drawer, matrix);
+
+       /* Set leading and trailing at once */
+       gtk_source_space_drawer_set_types_for_locations (drawer,
+                                                        GTK_SOURCE_SPACE_LOCATION_LEADING |
+                                                        GTK_SOURCE_SPACE_LOCATION_TRAILING,
+                                                        GTK_SOURCE_SPACE_TYPE_TAB);
+
+       matrix[LEADING_INDEX] = GTK_SOURCE_SPACE_TYPE_TAB;
+       matrix[TRAILING_INDEX] = GTK_SOURCE_SPACE_TYPE_TAB;
+       check_equal_matrix (drawer, matrix);
+
+       /* Enable all at once */
+       gtk_source_space_drawer_set_types_for_locations (drawer,
+                                                        GTK_SOURCE_SPACE_LOCATION_ALL,
+                                                        GTK_SOURCE_SPACE_TYPE_ALL);
+
+       matrix[LEADING_INDEX] = GTK_SOURCE_SPACE_TYPE_ALL;
+       matrix[INSIDE_TEXT_INDEX] = GTK_SOURCE_SPACE_TYPE_ALL;
+       matrix[TRAILING_INDEX] = GTK_SOURCE_SPACE_TYPE_ALL;
+       check_equal_matrix (drawer, matrix);
+
+       /* Get several locations at once */
+       matrix[LEADING_INDEX] = GTK_SOURCE_SPACE_TYPE_NBSP | GTK_SOURCE_SPACE_TYPE_TAB;
+       matrix[INSIDE_TEXT_INDEX] = GTK_SOURCE_SPACE_TYPE_NBSP;
+       matrix[TRAILING_INDEX] = GTK_SOURCE_SPACE_TYPE_ALL;
+       set_matrix (drawer, matrix);
+
+       types = gtk_source_space_drawer_get_types_for_locations (drawer, GTK_SOURCE_SPACE_LOCATION_ALL);
+       g_assert_cmpint (types, ==, GTK_SOURCE_SPACE_TYPE_NBSP);
+
+       types = gtk_source_space_drawer_get_types_for_locations (drawer,
+                                                                GTK_SOURCE_SPACE_LOCATION_LEADING |
+                                                                GTK_SOURCE_SPACE_LOCATION_TRAILING);
+       g_assert_cmpint (types, ==, GTK_SOURCE_SPACE_TYPE_NBSP | GTK_SOURCE_SPACE_TYPE_TAB);
+
+       /* Set at none locations */
+       gtk_source_space_drawer_set_types_for_locations (drawer,
+                                                        GTK_SOURCE_SPACE_LOCATION_NONE,
+                                                        GTK_SOURCE_SPACE_TYPE_ALL);
+       check_equal_matrix (drawer, matrix);
+
+       /* Get at none locations */
+       types = gtk_source_space_drawer_get_types_for_locations (drawer, GTK_SOURCE_SPACE_LOCATION_NONE);
+       g_assert_cmpint (types, ==, 0);
+
+       g_object_unref (view);
+}
+
+int
+main (int argc, char **argv)
+{
+       gtk_test_init (&argc, &argv);
+
+       g_test_add_func ("/SpaceDrawer/matrix-getters-setters", test_matrix_getters_setters);
+
+       return g_test_run();
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]