[gnome-builder/wip/gtk4-port: 82/94] libide/sourceview: untested port of gutter renderer




commit df320c2d76de27013345495e0eb9bc28c9685641
Author: Christian Hergert <chergert redhat com>
Date:   Sat Mar 26 23:42:38 2022 -0700

    libide/sourceview: untested port of gutter renderer
    
    This is a minimal port of the simple gutter renderer to GTK 4 and
    GtkSourceView 5. It has not been tested (like most of the port so far).

 .../sourceview/ide-line-change-gutter-renderer.c   | 259 +++++----------------
 .../sourceview/ide-line-change-gutter-renderer.h   |   3 +-
 2 files changed, 65 insertions(+), 197 deletions(-)
---
diff --git a/src/libide/sourceview/ide-line-change-gutter-renderer.c 
b/src/libide/sourceview/ide-line-change-gutter-renderer.c
index 839bd0382..df25f55bc 100644
--- a/src/libide/sourceview/ide-line-change-gutter-renderer.c
+++ b/src/libide/sourceview/ide-line-change-gutter-renderer.c
@@ -36,15 +36,9 @@ struct _IdeLineChangeGutterRenderer
 {
   GtkSourceGutterRenderer parent_instance;
 
-  GtkTextView            *text_view;
-  gulong                  text_view_notify_buffer;
-
-  GtkTextBuffer          *buffer;
+  GtkSourceBuffer        *buffer;
   gulong                  buffer_notify_style_scheme;
 
-  GArray                 *lines;
-  guint                   begin_line;
-
   struct {
     GdkRGBA add;
     GdkRGBA remove;
@@ -79,6 +73,10 @@ enum {
   BACKGROUND,
 };
 
+static GQuark added_quark;
+static GQuark changed_quark;
+static GQuark deleted_quark;
+
 G_DEFINE_FINAL_TYPE (IdeLineChangeGutterRenderer, ide_line_change_gutter_renderer, 
GTK_SOURCE_TYPE_GUTTER_RENDERER)
 
 static gboolean
@@ -139,28 +137,15 @@ disconnect_buffer (IdeLineChangeGutterRenderer *self)
     }
 }
 
-static void
-disconnect_view (IdeLineChangeGutterRenderer *self)
-{
-  disconnect_buffer (self);
-
-  if (self->text_view && self->text_view_notify_buffer)
-    {
-      g_signal_handler_disconnect (self->text_view, self->text_view_notify_buffer);
-      self->text_view_notify_buffer = 0;
-      g_clear_weak_pointer (&self->text_view);
-    }
-}
-
 static void
 connect_style_scheme (IdeLineChangeGutterRenderer *self)
 {
   GtkSourceStyleScheme *scheme;
   GtkTextBuffer *buffer;
-  GtkTextView *view;
+  GtkSourceView *view;
 
   if (!(view = gtk_source_gutter_renderer_get_view (GTK_SOURCE_GUTTER_RENDERER (self))) ||
-      !(buffer = gtk_text_view_get_buffer (view)) ||
+      !(buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view))) ||
       !GTK_SOURCE_IS_BUFFER (buffer))
     return;
 
@@ -188,9 +173,7 @@ notify_style_scheme_cb (GtkTextBuffer               *buffer,
 static void
 connect_buffer (IdeLineChangeGutterRenderer *self)
 {
-  GtkTextBuffer *buffer;
-
-  buffer = gtk_text_view_get_buffer (self->text_view);
+  GtkSourceBuffer *buffer = gtk_source_gutter_renderer_get_buffer (GTK_SOURCE_GUTTER_RENDERER (self));
 
   if (buffer)
     {
@@ -204,37 +187,11 @@ connect_buffer (IdeLineChangeGutterRenderer *self)
 }
 
 static void
-notify_buffer_cb (GtkTextView                 *text_view,
-                  GParamSpec                  *pspec,
-                  IdeLineChangeGutterRenderer *self)
-{
-  disconnect_buffer (self);
-  connect_buffer (self);
-}
-
-static void
-connect_view (IdeLineChangeGutterRenderer *self)
-{
-  GtkTextView *view;
-
-  view = gtk_source_gutter_renderer_get_view (GTK_SOURCE_GUTTER_RENDERER (self));
-
-  if (view)
-    {
-      g_set_weak_pointer (&self->text_view, view);
-      self->text_view_notify_buffer = g_signal_connect (self->text_view,
-                                                        "notify::buffer",
-                                                        G_CALLBACK (notify_buffer_cb),
-                                                        self);
-      connect_buffer (self);
-    }
-}
-
-static void
-ide_line_change_gutter_renderer_notify_view (IdeLineChangeGutterRenderer *self)
+ide_line_change_gutter_renderer_change_buffer (GtkSourceGutterRenderer *renderer,
+                                               GtkSourceBuffer         *old_buffer)
 {
-  disconnect_view (self);
-  connect_view (self);
+  disconnect_buffer (IDE_LINE_CHANGE_GUTTER_RENDERER (renderer));
+  connect_buffer (IDE_LINE_CHANGE_GUTTER_RENDERER (renderer));
 }
 
 static void
@@ -242,171 +199,80 @@ populate_changes_cb (guint               line,
                      IdeBufferLineChange change,
                      gpointer            user_data)
 {
-  LineInfo *info;
-  struct {
-    GArray *lines;
-    guint   begin_line;
-    guint   end_line;
-  } *state = user_data;
-  guint pos;
+  GtkSourceGutterLines *lines = user_data;
 
-  g_assert (line >= state->begin_line);
-  g_assert (line <= state->end_line);
+  if (change & IDE_BUFFER_LINE_CHANGE_ADDED)
+    gtk_source_gutter_lines_add_qclass (lines, line, added_quark);
 
-  pos = line - state->begin_line;
+  if (change & IDE_BUFFER_LINE_CHANGE_CHANGED)
+    gtk_source_gutter_lines_add_qclass (lines, line, changed_quark);
 
-  info = &g_array_index (state->lines, LineInfo, pos);
-  info->is_add = !!(change & IDE_BUFFER_LINE_CHANGE_ADDED);
-  info->is_change = !!(change & IDE_BUFFER_LINE_CHANGE_CHANGED);
-  info->is_delete = !!(change & IDE_BUFFER_LINE_CHANGE_DELETED);
-
-  if (pos > 0)
-    {
-      LineInfo *last = &g_array_index (state->lines, LineInfo, pos - 1);
-
-      info->is_prev_delete = last->is_delete;
-      last->is_next_delete = info->is_delete;
-    }
+  if (change & IDE_BUFFER_LINE_CHANGE_DELETED)
+    gtk_source_gutter_lines_add_qclass (lines, line, deleted_quark);
 }
 
 static void
 ide_line_change_gutter_renderer_begin (GtkSourceGutterRenderer *renderer,
-                                       cairo_t                 *cr,
-                                       GdkRectangle            *bg_area,
-                                       GdkRectangle            *cell_area,
-                                       GtkTextIter             *begin,
-                                       GtkTextIter             *end)
+                                       GtkSourceGutterLines    *lines)
 {
   IdeLineChangeGutterRenderer *self = (IdeLineChangeGutterRenderer *)renderer;
   IdeBufferChangeMonitor *monitor;
-  GtkTextBuffer *buffer;
-  GtkTextView *view;
-  struct {
-    GArray *lines;
-    guint   begin_line;
-    guint   end_line;
-  } state;
+  int first;
+  int last;
 
   g_assert (IDE_IS_LINE_CHANGE_GUTTER_RENDERER (self));
-  g_assert (cr != NULL);
-  g_assert (bg_area != NULL);
-  g_assert (cell_area != NULL);
-  g_assert (begin != NULL);
-  g_assert (end != NULL);
-
-  if (!(view = gtk_source_gutter_renderer_get_view (renderer)) ||
-      !(buffer = gtk_text_view_get_buffer (view)) ||
-      !IDE_IS_BUFFER (buffer) ||
-      !(monitor = ide_buffer_get_change_monitor (IDE_BUFFER (buffer))))
-    return;
-
-  self->begin_line = state.begin_line = gtk_text_iter_get_line (begin);
-  state.end_line = gtk_text_iter_get_line (end);
-  state.lines = g_array_new (FALSE, TRUE, sizeof (LineInfo));
-  g_array_set_size (state.lines, state.end_line - state.begin_line + 1);
-
-  ide_buffer_change_monitor_foreach_change (monitor,
-                                            state.begin_line,
-                                            state.end_line,
-                                            populate_changes_cb,
-                                            &state);
+  g_assert (lines != NULL);
 
-  g_clear_pointer (&self->lines, g_array_unref);
-  self->lines = g_steal_pointer (&state.lines);
-}
-
-static void
-draw_line_change (IdeLineChangeGutterRenderer  *self,
-                  cairo_t                      *cr,
-                  GdkRectangle                 *area,
-                  LineInfo                     *info,
-                  GtkSourceGutterRendererState  state)
-{
-  g_assert (IDE_IS_LINE_CHANGE_GUTTER_RENDERER (self));
-  g_assert (cr != NULL);
-  g_assert (area != NULL);
-
-  /*
-   * Draw a simple line with the appropriate color from the style scheme
-   * based on the type of change we have.
-   */
-
-  if (info->is_add || info->is_change)
-    {
-      gdk_cairo_rectangle (cr, area);
-
-      if (info->is_add)
-        gdk_cairo_set_source_rgba (cr, &self->changes.add);
-      else
-        gdk_cairo_set_source_rgba (cr, &self->changes.change);
-
-      cairo_fill (cr);
-    }
+  if (!IDE_IS_BUFFER (self->buffer) ||
+      !(monitor = ide_buffer_get_change_monitor (IDE_BUFFER (self->buffer))))
+    return;
 
-  if (info->is_next_delete && !info->is_delete)
-    {
-      cairo_rectangle (cr,
-                       area->x,
-                       area->y + area->width / 2.0,
-                       area->width,
-                       area->height / 2.0);
-      gdk_cairo_set_source_rgba (cr, &self->changes.remove);
-      cairo_fill (cr);
-    }
+  first = MAX (0, (int)gtk_source_gutter_lines_get_first (lines) - 1);
+  last = gtk_source_gutter_lines_get_last (lines) + 1;
 
-  if (info->is_delete && !info->is_prev_delete)
-    {
-      cairo_rectangle (cr,
-                       area->x,
-                       area->y,
-                       area->width,
-                       area->height / 2.0);
-      gdk_cairo_set_source_rgba (cr, &self->changes.remove);
-      cairo_fill (cr);
-    }
+  ide_buffer_change_monitor_foreach_change (monitor, first, last, populate_changes_cb, lines);
 }
 
 static void
-ide_line_change_gutter_renderer_draw (GtkSourceGutterRenderer      *renderer,
-                                      cairo_t                      *cr,
-                                      GdkRectangle                 *bg_area,
-                                      GdkRectangle                 *cell_area,
-                                      GtkTextIter                  *begin,
-                                      GtkTextIter                  *end,
-                                      GtkSourceGutterRendererState  state)
+ide_line_change_gutter_renderer_snapshot_line (GtkSourceGutterRenderer *renderer,
+                                               GtkSnapshot             *snapshot,
+                                               GtkSourceGutterLines    *lines,
+                                               guint                    line)
 {
   IdeLineChangeGutterRenderer *self = (IdeLineChangeGutterRenderer *)renderer;
-  guint line;
-
-  g_assert (IDE_IS_LINE_CHANGE_GUTTER_RENDERER (self));
-  g_assert (cr != NULL);
-  g_assert (bg_area != NULL);
-  g_assert (cell_area != NULL);
-  g_assert (begin != NULL);
-  g_assert (end != NULL);
-
-  if (self->lines == NULL)
+  gboolean is_add = gtk_source_gutter_lines_has_qclass (lines, line, added_quark);
+  gboolean is_change = gtk_source_gutter_lines_has_qclass (lines, line, changed_quark);
+  gboolean is_delete = gtk_source_gutter_lines_has_qclass (lines, line, deleted_quark);
+  guint line_y;
+  guint line_height;
+  int width;
+
+  if (!is_add && !is_change && !is_delete)
     return;
 
-  line = gtk_text_iter_get_line (begin);
+  gtk_source_gutter_lines_get_yrange (lines, line, &line_y, &line_height);
+  width = gtk_widget_get_width (GTK_WIDGET (renderer));
 
-  if ((line - self->begin_line) < self->lines->len)
-    {
-      LineInfo *info = &g_array_index (self->lines, LineInfo, line - self->begin_line);
+  if (is_add || is_change)
+    gtk_snapshot_append_color (snapshot,
+                               is_add ? &self->changes.add : &self->changes.change,
+                               &GRAPHENE_RECT_INIT (0, line_y, width, line_height));
 
-      if (IS_LINE_CHANGE (info))
-        draw_line_change (self, cr, cell_area, info, state);
-    }
+  if (!is_delete && gtk_source_gutter_lines_has_qclass (lines, line+1, deleted_quark))
+    gtk_snapshot_append_color (snapshot,
+                               &self->changes.remove,
+                               &GRAPHENE_RECT_INIT (0, line_y+line_height/2., width, line_height/2.));
+
+  if (is_delete && line > 0 && gtk_source_gutter_lines_has_qclass (lines, line-1, deleted_quark))
+    gtk_snapshot_append_color (snapshot,
+                               &self->changes.remove,
+                               &GRAPHENE_RECT_INIT (0, line_y, width, line_height/2.));
 }
 
 static void
 ide_line_change_gutter_renderer_dispose (GObject *object)
 {
-  IdeLineChangeGutterRenderer *self = (IdeLineChangeGutterRenderer *)object;
-
-  disconnect_view (IDE_LINE_CHANGE_GUTTER_RENDERER (object));
-
-  g_clear_pointer (&self->lines, g_array_unref);
+  disconnect_buffer (IDE_LINE_CHANGE_GUTTER_RENDERER (object));
 
   G_OBJECT_CLASS (ide_line_change_gutter_renderer_parent_class)->dispose (object);
 }
@@ -420,14 +286,15 @@ ide_line_change_gutter_renderer_class_init (IdeLineChangeGutterRendererClass *kl
   object_class->dispose = ide_line_change_gutter_renderer_dispose;
 
   renderer_class->begin = ide_line_change_gutter_renderer_begin;
-  renderer_class->draw = ide_line_change_gutter_renderer_draw;
+  renderer_class->snapshot_line = ide_line_change_gutter_renderer_snapshot_line;
+  renderer_class->change_buffer = ide_line_change_gutter_renderer_change_buffer;
+
+  added_quark = g_quark_from_static_string ("added");
+  changed_quark = g_quark_from_static_string ("changed");
+  deleted_quark = g_quark_from_static_string ("deleted");
 }
 
 static void
 ide_line_change_gutter_renderer_init (IdeLineChangeGutterRenderer *self)
 {
-  g_signal_connect (self,
-                    "notify::view",
-                    G_CALLBACK (ide_line_change_gutter_renderer_notify_view),
-                    NULL);
 }
diff --git a/src/libide/sourceview/ide-line-change-gutter-renderer.h 
b/src/libide/sourceview/ide-line-change-gutter-renderer.h
index 244e6bb89..1d86ddf63 100644
--- a/src/libide/sourceview/ide-line-change-gutter-renderer.h
+++ b/src/libide/sourceview/ide-line-change-gutter-renderer.h
@@ -21,13 +21,14 @@
 #pragma once
 
 #include <gtksourceview/gtksource.h>
+
 #include <libide-core.h>
 
 G_BEGIN_DECLS
 
 #define IDE_TYPE_LINE_CHANGE_GUTTER_RENDERER (ide_line_change_gutter_renderer_get_type())
 
-IDE_AVAILABLE_IN_3_32
+IDE_AVAILABLE_IN_ALL
 G_DECLARE_FINAL_TYPE (IdeLineChangeGutterRenderer, ide_line_change_gutter_renderer, IDE, 
LINE_CHANGE_GUTTER_RENDERER, GtkSourceGutterRenderer)
 
 G_END_DECLS


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