[gnome-builder] snippets: use GtkTextTag instead of drawing chunk backgrounds



commit 248c59ae4660c30d38626a44766aed4f88998213
Author: Christian Hergert <chergert redhat com>
Date:   Wed Mar 2 21:44:07 2016 -0800

    snippets: use GtkTextTag instead of drawing chunk backgrounds
    
    This was always a sort of nasty part of the snippet system, so lets just
    use GtkTextTags instead. They aren't quite as fancy (we can't do rounded
    corners yet or anything), but they get the job done and look better with
    custom backgrounds drawn.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=762505

 libide/ide-buffer.c         |   70 ++++++++++++++++++++++--
 libide/ide-source-snippet.c |   74 ++++++++++++++++++++++++-
 libide/ide-source-view.c    |  127 +------------------------------------------
 3 files changed, 138 insertions(+), 133 deletions(-)
---
diff --git a/libide/ide-buffer.c b/libide/ide-buffer.c
index a64baea..53f17ef 100644
--- a/libide/ide-buffer.c
+++ b/libide/ide-buffer.c
@@ -40,6 +40,7 @@
 #include "ide-source-iter.h"
 #include "ide-source-location.h"
 #include "ide-source-range.h"
+#include "ide-source-style-scheme.h"
 #include "ide-symbol.h"
 #include "ide-symbol-resolver.h"
 #include "ide-unsaved-files.h"
@@ -50,10 +51,11 @@
 #define RECLAIMATION_TIMEOUT_SECS              1
 #define MODIFICATION_TIMEOUT_SECS              1
 
-#define TAG_ERROR      "diagnostician::error"
-#define TAG_WARNING    "diagnostician::warning"
-#define TAG_DEPRECATED "diagnostician::deprecated"
-#define TAG_NOTE       "diagnostician::note"
+#define TAG_ERROR            "diagnostician::error"
+#define TAG_WARNING          "diagnostician::warning"
+#define TAG_DEPRECATED       "diagnostician::deprecated"
+#define TAG_NOTE             "diagnostician::note"
+#define TAG_SNIPPET_TAB_STOP "snippet::tab-stop"
 
 typedef struct
 {
@@ -918,6 +920,53 @@ ide_buffer_notify_language (IdeBuffer  *self,
 }
 
 static void
+ide_buffer_notify_style_scheme (IdeBuffer  *self,
+                                GParamSpec *pspec,
+                                gpointer    unused)
+{
+  GtkSourceStyleScheme *style_scheme;
+  GtkTextTagTable *table;
+
+  g_assert (IDE_IS_BUFFER (self));
+  g_assert (pspec != NULL);
+
+  style_scheme = gtk_source_buffer_get_style_scheme (GTK_SOURCE_BUFFER (self));
+  table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (self));
+
+#define GET_TAG(name) (gtk_text_tag_table_lookup(table, name))
+
+  if (style_scheme != NULL)
+    {
+      ide_source_style_scheme_apply_style (style_scheme,
+                                           TAG_SNIPPET_TAB_STOP,
+                                           GET_TAG (TAG_SNIPPET_TAB_STOP));
+    }
+
+#undef GET_TAG
+}
+
+static void
+ide_buffer_on_tag_added (IdeBuffer       *self,
+                         GtkTextTag      *tag,
+                         GtkTextTagTable *table)
+{
+  GtkTextTag *chunk_tag;
+
+  g_assert (IDE_IS_BUFFER (self));
+  g_assert (GTK_IS_TEXT_TAG (tag));
+  g_assert (GTK_IS_TEXT_TAG_TABLE (table));
+
+  /*
+   * Adjust priority of our tab-stop tag.
+   */
+
+  chunk_tag = gtk_text_tag_table_lookup (table, "snippet::tab-stop");
+  if (chunk_tag != NULL)
+    gtk_text_tag_set_priority (chunk_tag,
+                               gtk_text_tag_table_get_size (table) - 1);
+}
+
+static void
 ide_buffer_constructed (GObject *object)
 {
   IdeBuffer *self = (IdeBuffer *)object;
@@ -960,6 +1009,14 @@ ide_buffer_constructed (GObject *object)
                               "underline", PANGO_UNDERLINE_ERROR,
                               "underline-rgba", &error_rgba,
                               NULL);
+  gtk_text_buffer_create_tag (GTK_TEXT_BUFFER (self), TAG_SNIPPET_TAB_STOP,
+                              NULL);
+
+  g_signal_connect_object (gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (self)),
+                           "tag-added",
+                           G_CALLBACK (ide_buffer_on_tag_added),
+                           self,
+                           G_CONNECT_SWAPPED);
 
   priv->highlight_engine = ide_highlight_engine_new (self);
 
@@ -979,6 +1036,11 @@ ide_buffer_constructed (GObject *object)
                     NULL);
 
   g_object_notify (G_OBJECT (self), "language");
+
+  g_signal_connect (self,
+                    "notify::style-scheme",
+                    G_CALLBACK (ide_buffer_notify_style_scheme),
+                    NULL);
 }
 
 static void
diff --git a/libide/ide-source-snippet.c b/libide/ide-source-snippet.c
index 2fcc894..33b0057 100644
--- a/libide/ide-source-snippet.c
+++ b/libide/ide-source-snippet.c
@@ -25,6 +25,8 @@
 #include "ide-source-snippet-chunk.h"
 #include "ide-source-snippet-context.h"
 
+#define TAG_SNIPPET_TAB_STOP "snippet::tab-stop"
+
 struct _IdeSourceSnippet
 {
   IdeObject                parent_instance;
@@ -484,16 +486,65 @@ ide_source_snippet_update_context (IdeSourceSnippet *self)
   ide_source_snippet_context_emit_changed (context);
 }
 
+static void
+ide_source_snippet_clear_tags (IdeSourceSnippet *self)
+{
+  g_assert (IDE_IS_SOURCE_SNIPPET (self));
+
+  if (self->mark_begin != NULL && self->mark_end != NULL)
+    {
+      GtkTextBuffer *buffer;
+      GtkTextIter begin;
+      GtkTextIter end;
+
+      buffer = gtk_text_mark_get_buffer (self->mark_begin);
+
+      gtk_text_buffer_get_iter_at_mark (buffer, &begin, self->mark_begin);
+      gtk_text_buffer_get_iter_at_mark (buffer, &end, self->mark_end);
+
+      gtk_text_buffer_remove_tag_by_name (buffer,
+                                          TAG_SNIPPET_TAB_STOP,
+                                          &begin, &end);
+    }
+}
+
+static void
+ide_source_snippet_update_tags (IdeSourceSnippet *self)
+{
+  GtkTextBuffer *buffer;
+  guint i;
+
+  g_assert (IDE_IS_SOURCE_SNIPPET (self));
+
+  ide_source_snippet_clear_tags (self);
+
+  buffer = gtk_text_mark_get_buffer (self->mark_begin);
+
+  for (i = 0; i < self->chunks->len; i++)
+    {
+      IdeSourceSnippetChunk *chunk = g_ptr_array_index (self->chunks, i);
+      gint tab_stop = ide_source_snippet_chunk_get_tab_stop (chunk);
+
+      if (tab_stop >= 0)
+        {
+          GtkTextIter begin;
+          GtkTextIter end;
+
+          ide_source_snippet_get_chunk_range (self, chunk, &begin, &end);
+          gtk_text_buffer_apply_tag_by_name (buffer,
+                                             TAG_SNIPPET_TAB_STOP,
+                                             &begin, &end);
+        }
+    }
+}
+
 gboolean
 ide_source_snippet_begin (IdeSourceSnippet *self,
                           GtkTextBuffer    *buffer,
                           GtkTextIter      *iter)
 {
   IdeSourceSnippetContext *context;
-  IdeSourceSnippetChunk *chunk;
-  const gchar *text;
   gboolean ret;
-  gint len;
   gint i;
 
   g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), FALSE);
@@ -520,9 +571,15 @@ ide_source_snippet_begin (IdeSourceSnippet *self,
 
   for (i = 0; i < self->chunks->len; i++)
     {
+      IdeSourceSnippetChunk *chunk;
+      const gchar *text;
+
       chunk = g_ptr_array_index (self->chunks, i);
+
       if ((text = ide_source_snippet_chunk_get_text (chunk)))
         {
+          gint len;
+
           len = g_utf8_strlen (text, -1);
           g_array_append_val (self->runs, len);
           gtk_text_buffer_insert (buffer, iter, text, -1);
@@ -538,6 +595,8 @@ ide_source_snippet_begin (IdeSourceSnippet *self,
 
   gtk_text_buffer_end_user_action (buffer);
 
+  ide_source_snippet_update_tags (self);
+
   ret = ide_source_snippet_move_next (self);
 
   return ret;
@@ -547,6 +606,11 @@ void
 ide_source_snippet_finish (IdeSourceSnippet *self)
 {
   g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self));
+
+  ide_source_snippet_clear_tags (self);
+
+  g_clear_object (&self->mark_begin);
+  g_clear_object (&self->mark_end);
 }
 
 void
@@ -703,6 +767,8 @@ ide_source_snippet_after_insert_text (IdeSourceSnippet *self,
   gtk_text_buffer_get_iter_at_mark (buffer, iter, here);
   gtk_text_buffer_delete_mark (buffer, here);
 
+  ide_source_snippet_update_tags (self);
+
 #if 0
   ide_source_snippet_context_dump (self->snippet_context);
 #endif
@@ -794,6 +860,8 @@ ide_source_snippet_after_delete_range (IdeSourceSnippet *self,
   gtk_text_buffer_get_iter_at_mark (buffer, end, here);
   gtk_text_buffer_delete_mark (buffer, here);
 
+  ide_source_snippet_update_tags (self);
+
 #if 0
   ide_source_snippet_context_dump (self->snippet_context);
 #endif
diff --git a/libide/ide-source-view.c b/libide/ide-source-view.c
index 525832f..2319538 100644
--- a/libide/ide-source-view.c
+++ b/libide/ide-source-view.c
@@ -4134,125 +4134,6 @@ ide_source_view_real_sort (IdeSourceView *self,
   gtk_text_buffer_end_user_action (buffer);
 }
 
-static cairo_region_t *
-region_create_bounds (GtkTextView       *text_view,
-                      const GtkTextIter *begin,
-                      const GtkTextIter *end)
-{
-  cairo_rectangle_int_t r;
-  cairo_region_t *region;
-  GtkAllocation alloc;
-  GdkRectangle rect;
-  GdkRectangle rect2;
-  gint x = 0;
-
-  gtk_widget_get_allocation (GTK_WIDGET (text_view), &alloc);
-
-  gtk_text_view_get_iter_location (text_view, begin, &rect);
-  gtk_text_view_buffer_to_window_coords (text_view, GTK_TEXT_WINDOW_TEXT,
-                                         rect.x, rect.y, &rect.x, &rect.y);
-
-  gtk_text_view_get_iter_location (text_view, end, &rect2);
-  gtk_text_view_buffer_to_window_coords (text_view, GTK_TEXT_WINDOW_TEXT,
-                                         rect2.x, rect2.y,
-                                         &rect2.x, &rect2.y);
-
-  gtk_text_view_buffer_to_window_coords (text_view, GTK_TEXT_WINDOW_TEXT,
-                                         0, 0, &x, NULL);
-
-  if (rect.y == rect2.y)
-    {
-      r.x = rect.x;
-      r.y = rect.y;
-      r.width = rect2.x - rect.x;
-      r.height = MAX (rect.height, rect2.height);
-      return cairo_region_create_rectangle (&r);
-    }
-
-  region = cairo_region_create ();
-
-  r.x = rect.x;
-  r.y = rect.y;
-  r.width = alloc.width;
-  r.height = rect.height;
-  /* ide_cairo_rounded_rectangle (cr, &r, 5, 5); */
-  cairo_region_union_rectangle (region, &r);
-
-  r.x = x;
-  r.y = rect.y + rect.height;
-  r.width = alloc.width;
-  r.height = rect2.y - rect.y - rect.height;
-  if (r.height > 0)
-    /* ide_cairo_rounded_rectangle (cr, &r, 5, 5); */
-    cairo_region_union_rectangle (region, &r);
-
-  r.x = 0;
-  r.y = rect2.y;
-  r.width = rect2.x + rect2.width;
-  r.height = rect2.height;
-  /* ide_cairo_rounded_rectangle (cr, &r, 5, 5); */
-  cairo_region_union_rectangle (region, &r);
-
-  return region;
-}
-
-static void
-ide_source_view_draw_snippet_chunks (IdeSourceView    *self,
-                                     IdeSourceSnippet *snippet,
-                                     cairo_t          *cr)
-{
-  static gboolean did_rgba;
-  static GdkRGBA rgba;
-  IdeSourceSnippetChunk *chunk;
-  GtkTextView *text_view = (GtkTextView *)self;
-  guint n_chunks;
-  guint i;
-  gint tab_stop;
-  gint current_stop;
-
-  g_assert (IDE_IS_SOURCE_VIEW (self));
-  g_assert (IDE_IS_SOURCE_SNIPPET (snippet));
-  g_assert (cr);
-
-  cairo_save (cr);
-
-  if (!did_rgba)
-    {
-      /* TODO: get this from style scheme? */
-      gdk_rgba_parse (&rgba, "#fcaf3e");
-      did_rgba = TRUE;
-    }
-
-  n_chunks = ide_source_snippet_get_n_chunks (snippet);
-  current_stop = ide_source_snippet_get_tab_stop (snippet);
-
-  for (i = 0; i < n_chunks; i++)
-    {
-      chunk = ide_source_snippet_get_nth_chunk (snippet, i);
-      tab_stop = ide_source_snippet_chunk_get_tab_stop (chunk);
-
-      if (tab_stop > 0)
-        {
-          GtkTextIter begin;
-          GtkTextIter end;
-          cairo_region_t *region;
-
-          rgba.alpha = (tab_stop == current_stop) ? 0.7 : 0.3;
-          gdk_cairo_set_source_rgba (cr, &rgba);
-
-          ide_source_snippet_get_chunk_range (snippet, chunk, &begin, &end);
-
-          region = region_create_bounds (text_view, &begin, &end);
-          gdk_cairo_region (cr, region);
-          cairo_region_destroy (region);
-
-          cairo_fill (cr);
-        }
-    }
-
-  cairo_restore (cr);
-}
-
 static void
 ide_source_view_draw_snippet_background (IdeSourceView    *self,
                                          cairo_t          *cr,
@@ -4541,13 +4422,7 @@ ide_source_view_real_draw_layer (GtkTextView      *text_view,
   if (layer == GTK_TEXT_VIEW_LAYER_BELOW)
     {
       if (priv->snippets->length)
-        {
-          IdeSourceSnippet *snippet;
-
-          ide_source_view_draw_snippets_background (self, cr);
-          snippet = g_queue_peek_head (priv->snippets);
-          ide_source_view_draw_snippet_chunks (self, snippet, cr);
-        }
+        ide_source_view_draw_snippets_background (self, cr);
     }
   else if (layer == GTK_TEXT_VIEW_LAYER_ABOVE)
     {


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