[gnome-builder/wip/chergert/gutter] wip



commit 2d943890a695c71202c0aceaf63a6578c0ae306f
Author: Christian Hergert <chergert redhat com>
Date:   Sun Sep 17 03:39:02 2017 -0700

    wip

 libide/debugger/ide-debugger-editor-view-addin.c   |  135 ----
 libide/debugger/ide-debugger-plugin.c              |    4 -
 libide/meson.build                                 |    4 +-
 libide/sourceview/ide-omni-gutter-renderer.c       |  751 ++++++++++++++++++++
 .../ide-omni-gutter-renderer.h}                    |   15 +-
 libide/sourceview/ide-source-view.c                |   60 +--
 6 files changed, 782 insertions(+), 187 deletions(-)
---
diff --git a/libide/debugger/ide-debugger-plugin.c b/libide/debugger/ide-debugger-plugin.c
index 6ecb5a6..5feb415 100644
--- a/libide/debugger/ide-debugger-plugin.c
+++ b/libide/debugger/ide-debugger-plugin.c
@@ -19,7 +19,6 @@
 #include <libpeas/peas.h>
 
 #include "debugger/ide-debugger-editor-addin.h"
-#include "debugger/ide-debugger-editor-view-addin.h"
 #include "editor/ide-editor-addin.h"
 #include "editor/ide-editor-view-addin.h"
 
@@ -29,7 +28,4 @@ ide_debugger_register_types (PeasObjectModule *module)
   peas_object_module_register_extension_type (module,
                                               IDE_TYPE_EDITOR_ADDIN,
                                               IDE_TYPE_DEBUGGER_EDITOR_ADDIN);
-  peas_object_module_register_extension_type (module,
-                                              IDE_TYPE_EDITOR_VIEW_ADDIN,
-                                              IDE_TYPE_DEBUGGER_EDITOR_VIEW_ADDIN);
 }
diff --git a/libide/meson.build b/libide/meson.build
index acec572..ff0d242 100644
--- a/libide/meson.build
+++ b/libide/meson.build
@@ -517,8 +517,6 @@ libide_sources = libide_generated_headers + libide_public_sources + [
   'debugger/ide-debugger-disassembly-view.h',
   'debugger/ide-debugger-editor-addin.c',
   'debugger/ide-debugger-editor-addin.h',
-  'debugger/ide-debugger-editor-view-addin.c',
-  'debugger/ide-debugger-editor-view-addin.h',
   'debugger/ide-debugger-fallbacks.c',
   'debugger/ide-debugger-gutter-renderer.c',
   'debugger/ide-debugger-gutter-renderer.h',
@@ -595,6 +593,8 @@ libide_sources = libide_generated_headers + libide_public_sources + [
   'snippets/ide-source-snippet-parser.c',
   'snippets/ide-source-snippet-parser.h',
   'snippets/ide-source-snippet-private.h',
+  'sourceview/ide-omni-gutter-renderer.c',
+  'sourceview/ide-omni-gutter-renderer.h',
   'sourceview/ide-line-change-gutter-renderer.c',
   'sourceview/ide-line-change-gutter-renderer.h',
   'sourceview/ide-line-diagnostics-gutter-renderer.c',
diff --git a/libide/sourceview/ide-omni-gutter-renderer.c b/libide/sourceview/ide-omni-gutter-renderer.c
new file mode 100644
index 0000000..1be054f
--- /dev/null
+++ b/libide/sourceview/ide-omni-gutter-renderer.c
@@ -0,0 +1,751 @@
+/* ide-omni-gutter-renderer.c
+ *
+ * Copyright (C) 2017 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define G_LOG_DOMAIN "ide-omni-gutter-renderer"
+
+#include <dazzle.h>
+#include <string.h>
+
+#include "ide-context.h"
+#include "ide-debug.h"
+
+#include "buffers/ide-buffer.h"
+#include "debugger/ide-debug-manager.h"
+#include "debugger/ide-debugger-breakpoint.h"
+#include "debugger/ide-debugger-breakpoints.h"
+#include "debugger/ide-debugger-private.h"
+#include "files/ide-file.h"
+#include "sourceview/ide-omni-gutter-renderer.h"
+#include "sourceview/ide-source-view.h"
+
+#define DIAGNOSTICS_SIZE 16
+#define ARROW_WIDTH      7
+#define CHANGE_WIDTH     2
+
+struct _IdeOmniGutterRenderer
+{
+  GtkSourceGutterRenderer parent_instance;
+
+  IdeDebuggerBreakpoints *breakpoints;
+
+  GArray *lines;
+  guint begin_line;
+
+  DzlSignalGroup *view_signals;
+  DzlSignalGroup *buffer_signals;
+
+  PangoLayout *layout;
+
+  guint n_chars;
+
+  guint resize_source;
+
+  int  number_width;
+};
+
+typedef struct
+{
+  guint is_breakpoint : 1;
+  guint is_countpoint : 1;
+  guint is_watchpoint : 1;
+  guint is_add : 1;
+  guint is_change : 1;
+  guint is_delete : 1;
+  guint is_warning : 1;
+  guint is_note : 1;
+  guint is_error : 1;
+} LineInfo;
+
+G_DEFINE_TYPE (IdeOmniGutterRenderer, ide_omni_gutter_renderer, GTK_SOURCE_TYPE_GUTTER_RENDERER)
+
+static GdkRGBA rgbaAdded;
+static GdkRGBA rgbaChanged;
+static GdkRGBA rgbaRemoved;
+
+static void
+collect_breakpoint_info (IdeDebuggerBreakpoint *breakpoint,
+                         gpointer               user_data)
+{
+  struct {
+    GArray *lines;
+    guint begin;
+    guint end;
+  } *bkpt_info = user_data;
+  guint line;
+
+  if (!(line = ide_debugger_breakpoint_get_line (breakpoint)))
+    return;
+
+  line--;
+
+  if (line >= bkpt_info->begin && line <= bkpt_info->end)
+    {
+      IdeDebuggerBreakMode mode = ide_debugger_breakpoint_get_mode (breakpoint);
+      LineInfo *info = &g_array_index (bkpt_info->lines, LineInfo, line - bkpt_info->begin);
+
+      info->is_watchpoint = !!(mode & IDE_DEBUGGER_BREAK_WATCHPOINT);
+      info->is_countpoint = !!(mode & IDE_DEBUGGER_BREAK_COUNTPOINT);
+      info->is_breakpoint = !!(mode & IDE_DEBUGGER_BREAK_BREAKPOINT);
+    }
+}
+
+static void
+ide_omni_gutter_renderer_load_breakpoints (IdeOmniGutterRenderer *self,
+                                           GtkTextIter           *begin,
+                                           GtkTextIter           *end,
+                                           GArray                *lines)
+{
+  struct {
+    GArray *lines;
+    guint begin;
+    guint end;
+  } bkpt_info;
+
+  g_assert (IDE_IS_OMNI_GUTTER_RENDERER (self));
+  g_assert (begin != NULL);
+  g_assert (lines != NULL);
+  g_assert (lines->len > 0);
+
+  bkpt_info.lines = lines;
+  bkpt_info.begin = gtk_text_iter_get_line (begin);
+  bkpt_info.end = gtk_text_iter_get_line (end);
+
+  if (self->breakpoints != NULL)
+    ide_debugger_breakpoints_foreach (self->breakpoints,
+                                      (GFunc)collect_breakpoint_info,
+                                      &bkpt_info);
+}
+
+static void
+ide_omni_gutter_renderer_load_basic (IdeOmniGutterRenderer *self,
+                                     GtkTextIter           *begin,
+                                     GArray                *lines)
+{
+  IdeBuffer *buffer;
+  guint line;
+
+  g_assert (IDE_IS_OMNI_GUTTER_RENDERER (self));
+  g_assert (begin != NULL);
+  g_assert (lines != NULL);
+  g_assert (lines->len > 0);
+
+  buffer = (IdeBuffer *)gtk_text_iter_get_buffer (begin);
+
+  if (!IDE_IS_BUFFER (buffer))
+    return;
+
+  line = gtk_text_iter_get_line (begin);
+
+  if (buffer != NULL)
+    {
+      for (guint i = 0; i < lines->len; i++)
+        {
+          LineInfo *info = &g_array_index (lines, LineInfo, i);
+          IdeBufferLineFlags flags = ide_buffer_get_line_flags (buffer, line + i);
+
+          info->is_add = !!(flags & IDE_BUFFER_LINE_FLAGS_ADDED);
+          info->is_change = !!(flags & IDE_BUFFER_LINE_FLAGS_CHANGED);
+          info->is_delete = !!(flags & IDE_BUFFER_LINE_FLAGS_DELETED);
+          info->is_warning = !!(flags & IDE_BUFFER_LINE_FLAGS_WARNING);
+          info->is_note = !!(flags & IDE_BUFFER_LINE_FLAGS_NOTE);
+          info->is_error = !!(flags & IDE_BUFFER_LINE_FLAGS_ERROR);
+        }
+    }
+}
+
+static inline gint
+count_num_digits (gint num_lines)
+{
+  if (num_lines < 100)
+    return 2;
+  else if (num_lines < 1000)
+    return 3;
+  else if (num_lines < 10000)
+    return 4;
+  else if (num_lines < 100000)
+    return 5;
+  else if (num_lines < 1000000)
+    return 6;
+  else
+    return 10;
+}
+
+static void
+ide_omni_gutter_renderer_recalculate_size (IdeOmniGutterRenderer *self,
+                                           IdeSourceView         *view)
+{
+  const PangoFontDescription *font_desc;
+  g_autofree gchar *numbers = NULL;
+  GtkTextBuffer *buffer;
+  PangoLayout *layout;
+  GtkTextIter end;
+  guint line;
+  int height;
+
+  g_assert (IDE_IS_OMNI_GUTTER_RENDERER (self));
+  g_assert (IDE_IS_SOURCE_VIEW (view));
+
+  /*
+   * First, we need to get the size of the text for the last line of the
+   * buffer, which will be the longest. We size the font with '9' since it
+   * will generally be the widest of the numbers. Although, we only support
+   * monospace anyway, so it shouldn't matter.
+   */
+
+  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+  gtk_text_buffer_get_end_iter (buffer, &end);
+  line = gtk_text_iter_get_line (&end) + 1;
+
+  self->n_chars = count_num_digits (line);
+  numbers = g_strnfill (self->n_chars, '9');
+
+  font_desc = ide_source_view_get_font_desc (view);
+  layout = gtk_widget_create_pango_layout (GTK_WIDGET (view), numbers);
+  pango_layout_set_font_description (layout, font_desc);
+  pango_layout_get_pixel_size (layout, &self->number_width, &height);
+  g_clear_object (&layout);
+
+  /*
+   * The spacing for the different items in the gutter looks like:
+   *
+   * Spacing (2px) Diagnostics (16px) Numbers(N) Changes(2) Spacing(2px)
+   */
+
+  gtk_source_gutter_renderer_set_size (GTK_SOURCE_GUTTER_RENDERER (self),
+                                       (2 +
+                                        DIAGNOSTICS_SIZE +
+                                        2 +
+                                        self->number_width +
+                                        2 +
+                                        CHANGE_WIDTH +
+                                        2));
+
+  gtk_source_gutter_renderer_queue_draw (GTK_SOURCE_GUTTER_RENDERER (self));
+}
+
+static void
+ide_omni_gutter_renderer_notify_font_desc (IdeOmniGutterRenderer *self,
+                                           GParamSpec            *pspec,
+                                           IdeSourceView         *view)
+{
+  g_assert (IDE_IS_OMNI_GUTTER_RENDERER (self));
+  g_assert (IDE_IS_SOURCE_VIEW (view));
+
+  ide_omni_gutter_renderer_recalculate_size (self, view);
+}
+
+static void
+ide_omni_gutter_renderer_end (GtkSourceGutterRenderer *renderer)
+{
+  IdeOmniGutterRenderer *self = (IdeOmniGutterRenderer *)renderer;
+
+  g_assert (IDE_IS_OMNI_GUTTER_RENDERER (self));
+
+  g_clear_object (&self->layout);
+}
+
+static void
+ide_omni_gutter_renderer_begin (GtkSourceGutterRenderer *renderer,
+                                cairo_t                 *cr,
+                                GdkRectangle            *bg_area,
+                                GdkRectangle            *cell_area,
+                                GtkTextIter             *begin,
+                                GtkTextIter             *end)
+{
+  IdeOmniGutterRenderer *self = (IdeOmniGutterRenderer *)renderer;
+  IdeSourceView *view;
+  guint end_line;
+
+  g_assert (IDE_IS_OMNI_GUTTER_RENDERER (renderer));
+  g_assert (cr != NULL);
+  g_assert (bg_area != NULL);
+  g_assert (cell_area != NULL);
+  g_assert (begin != NULL);
+  g_assert (end != NULL);
+
+  /*
+   * This function is called before we render any of the lines in
+   * the gutter. To reduce our overhead, we want to collect information
+   * for all of the line numbers upfront.
+   */
+
+  view = IDE_SOURCE_VIEW (gtk_source_gutter_renderer_get_view (renderer));
+
+  self->begin_line = gtk_text_iter_get_line (begin);
+  end_line = gtk_text_iter_get_line (end);
+
+  g_array_set_size (self->lines, end_line - self->begin_line + 1);
+  memset (self->lines->data, 0, self->lines->len * sizeof (LineInfo));
+
+  ide_omni_gutter_renderer_load_basic (self, begin, self->lines);
+  ide_omni_gutter_renderer_load_breakpoints (self, begin, end, self->lines);
+
+  self->layout = gtk_widget_create_pango_layout (GTK_WIDGET (view), "");
+  pango_layout_set_alignment (self->layout, PANGO_ALIGN_RIGHT);
+  pango_layout_set_width (self->layout, (cell_area->width - ARROW_WIDTH - 4) * PANGO_SCALE);
+  pango_layout_set_font_description (self->layout,
+                                     ide_source_view_get_font_desc (view));
+}
+
+static gboolean
+ide_omni_gutter_renderer_query_activatable (GtkSourceGutterRenderer *renderer,
+                                            GtkTextIter             *begin,
+                                            GdkRectangle            *area,
+                                            GdkEvent                *event)
+{
+  IdeOmniGutterRenderer *self = (IdeOmniGutterRenderer *)renderer;
+
+  g_assert (IDE_IS_OMNI_GUTTER_RENDERER (self));
+  g_assert (begin != NULL);
+  g_assert (area != NULL);
+  g_assert (event != NULL);
+
+  return (self->breakpoints != NULL);
+}
+
+static void
+ide_omni_gutter_renderer_activate (GtkSourceGutterRenderer *renderer,
+                                   GtkTextIter             *iter,
+                                   GdkRectangle            *area,
+                                   GdkEvent                *event)
+{
+  IdeOmniGutterRenderer *self = (IdeOmniGutterRenderer *)renderer;
+  IdeDebuggerBreakpoint *breakpoint;
+  IdeDebuggerBreakMode break_type = IDE_DEBUGGER_BREAK_NONE;
+  g_autofree gchar *path = NULL;
+  IdeDebugManager *debug_manager;
+  GtkTextBuffer *buffer;
+  IdeContext *context;
+  GFile *file;
+  guint line;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_OMNI_GUTTER_RENDERER (self));
+  g_assert (iter != NULL);
+  g_assert (area != NULL);
+  g_assert (event != NULL);
+  g_assert (self->breakpoints != NULL);
+
+  buffer = gtk_text_iter_get_buffer (iter);
+  context = ide_buffer_get_context (IDE_BUFFER (buffer));
+  debug_manager = ide_context_get_debug_manager (context);
+
+  line = gtk_text_iter_get_line (iter) + 1;
+  file = ide_debugger_breakpoints_get_file (self->breakpoints);
+  path = g_file_get_path (file);
+
+  /* TODO: Should we show a Popover here to select the type? */
+  IDE_TRACE_MSG ("Toggle breakpoint on line %u [breakpoints=%p]",
+                 line, self->breakpoints);
+
+  breakpoint = ide_debugger_breakpoints_get_line (self->breakpoints, line);
+  if (breakpoint != NULL)
+    break_type = ide_debugger_breakpoint_get_mode (breakpoint);
+
+  switch (break_type)
+    {
+    case IDE_DEBUGGER_BREAK_NONE:
+      {
+        g_autoptr(IdeDebuggerBreakpoint) to_insert = NULL;
+
+        to_insert = ide_debugger_breakpoint_new (NULL);
+
+        ide_debugger_breakpoint_set_line (to_insert, line);
+        ide_debugger_breakpoint_set_file (to_insert, path);
+        ide_debugger_breakpoint_set_mode (to_insert, IDE_DEBUGGER_BREAK_BREAKPOINT);
+        ide_debugger_breakpoint_set_enabled (to_insert, TRUE);
+
+        _ide_debug_manager_add_breakpoint (debug_manager, to_insert);
+      }
+      break;
+
+    case IDE_DEBUGGER_BREAK_BREAKPOINT:
+    case IDE_DEBUGGER_BREAK_COUNTPOINT:
+    case IDE_DEBUGGER_BREAK_WATCHPOINT:
+      if (breakpoint != NULL)
+        _ide_debug_manager_remove_breakpoint (debug_manager, breakpoint);
+      break;
+
+    default:
+      g_return_if_reached ();
+    }
+
+  /*
+   * We will wait for changes to be applied to the #IdeDebuggerBreakpoints
+   * by the #IdeDebugManager. That will cause the gutter to be invalidated
+   * and redrawn.
+   */
+
+  IDE_EXIT;
+}
+
+static void
+draw_breakpoint_bg (IdeOmniGutterRenderer        *self,
+                    cairo_t                      *cr,
+                    GdkRectangle                 *bg_area,
+                    GtkSourceGutterRendererState  state)
+{
+  GdkRectangle area;
+
+  g_assert (GTK_SOURCE_IS_GUTTER_RENDERER (self));
+  g_assert (cr != NULL);
+  g_assert (bg_area != NULL);
+
+  area.x = bg_area->x;
+  area.y = bg_area->y + 1;
+  area.height = bg_area->height - 2;
+  area.width = bg_area->width;
+
+  cairo_move_to (cr, area.x, area.y);
+  cairo_line_to (cr,
+                 dzl_cairo_rectangle_x2 (bg_area) - ARROW_WIDTH,
+                 area.y);
+  cairo_line_to (cr,
+                 dzl_cairo_rectangle_x2 (bg_area),
+                 dzl_cairo_rectangle_middle (bg_area));
+  cairo_line_to (cr,
+                 dzl_cairo_rectangle_x2 (bg_area) - ARROW_WIDTH,
+                 dzl_cairo_rectangle_y2 (bg_area));
+  cairo_line_to (cr, area.x, dzl_cairo_rectangle_y2 (bg_area));
+  cairo_close_path (cr);
+
+  if (state & GTK_SOURCE_GUTTER_RENDERER_STATE_PRELIT)
+    cairo_set_source_rgba (cr, 0x4a / 255., 0x90 / 255., 0xd9 / 255., 0.3);
+  else
+    cairo_set_source_rgb (cr, 0x4a / 255., 0x90 / 255., 0xd9 / 255.);
+
+  cairo_fill (cr);
+}
+
+static void
+draw_add_change (IdeOmniGutterRenderer        *self,
+                 cairo_t                      *cr,
+                 GdkRectangle                 *area,
+                 LineInfo                     *info,
+                 GtkSourceGutterRendererState  state)
+{
+  g_assert (IDE_IS_OMNI_GUTTER_RENDERER (self));
+  g_assert (cr != NULL);
+  g_assert (area != NULL);
+
+  cairo_rectangle (cr,
+                   area->x + area->width - ARROW_WIDTH + 1,
+                   area->y,
+                   CHANGE_WIDTH,
+                   area->y + area->height);
+
+  if (info->is_add)
+    gdk_cairo_set_source_rgba (cr, &rgbaAdded);
+  else
+    gdk_cairo_set_source_rgba (cr, &rgbaChanged);
+
+  cairo_fill (cr);
+}
+
+static void
+draw_diagnostic (IdeOmniGutterRenderer        *self,
+                 cairo_t                      *cr,
+                 GdkRectangle                 *area,
+                 LineInfo                     *info,
+                 GtkSourceGutterRendererState  state)
+{
+  g_assert (IDE_IS_OMNI_GUTTER_RENDERER (self));
+  g_assert (cr != NULL);
+  g_assert (area != NULL);
+
+  cairo_rectangle (cr, area->x + 1, area->y, DIAGNOSTICS_SIZE, area->y + area->height);
+  gdk_cairo_set_source_rgba (cr, &rgbaRemoved);
+  cairo_fill (cr);
+}
+
+static void
+ide_omni_gutter_renderer_draw (GtkSourceGutterRenderer      *renderer,
+                               cairo_t                      *cr,
+                               GdkRectangle                 *bg_area,
+                               GdkRectangle                 *cell_area,
+                               GtkTextIter                  *begin,
+                               GtkTextIter                  *end,
+                               GtkSourceGutterRendererState  state)
+{
+  IdeOmniGutterRenderer *self = (IdeOmniGutterRenderer *)renderer;
+  guint line;
+
+  g_assert (IDE_IS_OMNI_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);
+
+  line = gtk_text_iter_get_line (begin);
+
+  if ((line - self->begin_line) < self->lines->len)
+    {
+      LineInfo *info = &g_array_index (self->lines, LineInfo, line - self->begin_line);
+      gboolean has_breakpoint = FALSE;
+      gchar linestr[16];
+      gint len;
+
+      if (info->is_add || info->is_change)
+        draw_add_change (self, cr, cell_area, info, state);
+
+      if (self->breakpoints != NULL)
+        {
+          has_breakpoint = info->is_breakpoint | info->is_countpoint | info->is_watchpoint;
+          if (has_breakpoint || (state & GTK_SOURCE_GUTTER_RENDERER_STATE_PRELIT) != 0)
+            draw_breakpoint_bg (self, cr, cell_area, state);
+        }
+
+      if (info->is_warning || info->is_error || info->is_note)
+        draw_diagnostic (self, cr, cell_area, info, state);
+
+      len = g_snprintf (linestr, sizeof linestr, "%u", line + 1);
+      pango_layout_set_text (self->layout, linestr, len);
+
+      cairo_move_to (cr, cell_area->x, cell_area->y);
+      if (has_breakpoint)
+        cairo_set_source_rgb (cr, 1, 1, 1);
+      else
+        cairo_set_source_rgba (cr, 0, 0, 0, 0.4);
+      pango_cairo_show_layout (cr, self->layout);
+    }
+}
+
+static void
+ide_omni_gutter_renderer_reload (IdeOmniGutterRenderer *self)
+{
+  g_autoptr(IdeDebuggerBreakpoints) breakpoints = NULL;
+  GtkSourceLanguage *language;
+  GtkTextBuffer *buffer;
+  GtkTextView *view;
+  const gchar *id = NULL;
+
+  g_assert (IDE_IS_OMNI_GUTTER_RENDERER (self));
+
+  view = gtk_source_gutter_renderer_get_view (GTK_SOURCE_GUTTER_RENDERER (self));
+  buffer = gtk_text_view_get_buffer (view);
+
+  if (NULL != (language = gtk_source_buffer_get_language (GTK_SOURCE_BUFFER (buffer))))
+    id = gtk_source_language_get_id (language);
+
+  if (IDE_IS_BUFFER (buffer))
+    {
+      IdeContext *context = ide_buffer_get_context (IDE_BUFFER (buffer));
+      IdeDebugManager *debug_manager = ide_context_get_debug_manager (context);
+
+      if (ide_debug_manager_supports_language (debug_manager, id))
+        {
+          IdeFile *file = ide_buffer_get_file (IDE_BUFFER (buffer));
+          GFile *gfile = ide_file_get_file (file);
+
+          breakpoints = ide_debug_manager_get_breakpoints_for_file (debug_manager, gfile);
+        }
+    }
+
+  g_set_object (&self->breakpoints, breakpoints);
+
+  ide_omni_gutter_renderer_recalculate_size (self, IDE_SOURCE_VIEW (view));
+}
+
+static void
+ide_omni_gutter_renderer_bind (IdeOmniGutterRenderer *self,
+                               IdeSourceView         *view,
+                               DzlSignalGroup        *view_signals)
+{
+  g_assert (IDE_IS_OMNI_GUTTER_RENDERER (self));
+  g_assert (IDE_IS_SOURCE_VIEW (view));
+  g_assert (DZL_IS_SIGNAL_GROUP (view_signals));
+
+  if (self->buffer_signals != NULL)
+    {
+      GtkTextBuffer *buffer;
+
+      buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+      if (IDE_IS_BUFFER (buffer))
+        dzl_signal_group_set_target (self->buffer_signals, buffer);
+
+      ide_omni_gutter_renderer_reload (self);
+    }
+}
+
+static void
+ide_omni_gutter_renderer_notify_buffer (IdeOmniGutterRenderer *self,
+                                        GParamSpec            *pspec,
+                                        IdeSourceView         *view)
+{
+  GtkTextBuffer *buffer;
+
+  g_assert (IDE_IS_OMNI_GUTTER_RENDERER (self));
+  g_assert (pspec != NULL);
+  g_assert (IDE_IS_SOURCE_VIEW (view));
+
+  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+  if (IDE_IS_BUFFER (buffer))
+    dzl_signal_group_set_target (self->buffer_signals, buffer);
+
+  ide_omni_gutter_renderer_reload (self);
+}
+
+static void
+ide_omni_gutter_renderer_notify_file (IdeOmniGutterRenderer *self,
+                                      GParamSpec            *pspec,
+                                      IdeBuffer             *buffer)
+{
+  g_assert (IDE_IS_OMNI_GUTTER_RENDERER (self));
+  g_assert (pspec != NULL);
+  g_assert (IDE_IS_BUFFER (buffer));
+
+  ide_omni_gutter_renderer_reload (self);
+}
+
+static void
+ide_omni_gutter_renderer_notify_view (IdeOmniGutterRenderer *self)
+{
+  GtkTextView *view;
+
+  g_assert (IDE_IS_OMNI_GUTTER_RENDERER (self));
+
+  view = gtk_source_gutter_renderer_get_view (GTK_SOURCE_GUTTER_RENDERER (self));
+  dzl_signal_group_set_target (self->view_signals, view);
+}
+
+static gboolean
+ide_omni_gutter_renderer_do_recalc (gpointer data)
+{
+  IdeOmniGutterRenderer *self = data;
+  GtkTextView *view;
+
+  g_assert (IDE_IS_OMNI_GUTTER_RENDERER (self));
+
+  self->resize_source = 0;
+
+  view = gtk_source_gutter_renderer_get_view (GTK_SOURCE_GUTTER_RENDERER (self));
+  if (IDE_IS_SOURCE_VIEW (view))
+    ide_omni_gutter_renderer_recalculate_size (self, IDE_SOURCE_VIEW (view));
+
+  return G_SOURCE_REMOVE;
+}
+
+static void
+ide_omni_gutter_renderer_buffer_changed (IdeOmniGutterRenderer *self,
+                                         IdeBuffer             *buffer)
+{
+  g_assert (IDE_IS_OMNI_GUTTER_RENDERER (self));
+  g_assert (IDE_IS_BUFFER (buffer));
+
+  if (self->resize_source == 0)
+    self->resize_source = gdk_threads_add_idle_full (G_PRIORITY_HIGH,
+                                                     ide_omni_gutter_renderer_do_recalc,
+                                                     g_object_ref (self),
+                                                     g_object_unref);
+}
+
+static void
+ide_omni_gutter_renderer_constructed (GObject *object)
+{
+  IdeOmniGutterRenderer *self = (IdeOmniGutterRenderer *)object;
+  GtkTextView *view;
+
+  g_assert (IDE_IS_OMNI_GUTTER_RENDERER (self));
+
+  G_OBJECT_CLASS (ide_omni_gutter_renderer_parent_class)->constructed (object);
+
+  view = gtk_source_gutter_renderer_get_view (GTK_SOURCE_GUTTER_RENDERER (self));
+  dzl_signal_group_set_target (self->view_signals, view);
+}
+
+static void
+ide_omni_gutter_renderer_dispose (GObject *object)
+{
+  IdeOmniGutterRenderer *self = (IdeOmniGutterRenderer *)object;
+
+  ide_clear_source (&self->resize_source);
+  g_clear_pointer (&self->lines, g_array_unref);
+  g_clear_object (&self->breakpoints);
+  g_clear_object (&self->buffer_signals);
+  g_clear_object (&self->view_signals);
+
+  G_OBJECT_CLASS (ide_omni_gutter_renderer_parent_class)->dispose (object);
+}
+
+static void
+ide_omni_gutter_renderer_class_init (IdeOmniGutterRendererClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkSourceGutterRendererClass *renderer_class = GTK_SOURCE_GUTTER_RENDERER_CLASS (klass);
+
+  object_class->constructed = ide_omni_gutter_renderer_constructed;
+  object_class->dispose = ide_omni_gutter_renderer_dispose;
+
+  renderer_class->draw = ide_omni_gutter_renderer_draw;
+  renderer_class->begin = ide_omni_gutter_renderer_begin;
+  renderer_class->end = ide_omni_gutter_renderer_end;
+  renderer_class->query_activatable = ide_omni_gutter_renderer_query_activatable;
+  renderer_class->activate = ide_omni_gutter_renderer_activate;
+
+  gdk_rgba_parse (&rgbaAdded, "#8ae234");
+  gdk_rgba_parse (&rgbaChanged, "#fcaf3e");
+  gdk_rgba_parse (&rgbaRemoved, "#ff0000");
+}
+
+static void
+ide_omni_gutter_renderer_init (IdeOmniGutterRenderer *self)
+{
+  self->lines = g_array_new (FALSE, FALSE, sizeof (LineInfo));
+
+  g_signal_connect (self,
+                    "notify::view",
+                    G_CALLBACK (ide_omni_gutter_renderer_notify_view),
+                    NULL);
+
+  self->buffer_signals = dzl_signal_group_new (IDE_TYPE_BUFFER);
+
+  dzl_signal_group_connect_swapped (self->buffer_signals,
+                                    "notify::file",
+                                    G_CALLBACK (ide_omni_gutter_renderer_notify_file),
+                                    self);
+
+  dzl_signal_group_connect_swapped (self->buffer_signals,
+                                    "changed",
+                                    G_CALLBACK (ide_omni_gutter_renderer_buffer_changed),
+                                    self);
+
+  self->view_signals = dzl_signal_group_new (IDE_TYPE_SOURCE_VIEW);
+
+  g_signal_connect_swapped (self->view_signals,
+                            "bind",
+                            G_CALLBACK (ide_omni_gutter_renderer_bind),
+                            self);
+
+  dzl_signal_group_connect_swapped (self->view_signals,
+                                    "notify::buffer",
+                                    G_CALLBACK (ide_omni_gutter_renderer_notify_buffer),
+                                    self);
+
+  dzl_signal_group_connect_swapped (self->view_signals,
+                                    "notify::font-desc",
+                                    G_CALLBACK (ide_omni_gutter_renderer_notify_font_desc),
+                                    self);
+}
+
+IdeOmniGutterRenderer *
+ide_omni_gutter_renderer_new (void)
+{
+  return g_object_new (IDE_TYPE_OMNI_GUTTER_RENDERER, NULL);
+}
diff --git a/libide/debugger/ide-debugger-editor-view-addin.h b/libide/sourceview/ide-omni-gutter-renderer.h
similarity index 63%
rename from libide/debugger/ide-debugger-editor-view-addin.h
rename to libide/sourceview/ide-omni-gutter-renderer.h
index 2e221ca..b666daa 100644
--- a/libide/debugger/ide-debugger-editor-view-addin.h
+++ b/libide/sourceview/ide-omni-gutter-renderer.h
@@ -1,4 +1,4 @@
-/* ide-debugger-editor-view-addin.h
+/* ide-omni-gutter-renderer.h
  *
  * Copyright (C) 2017 Christian Hergert <chergert redhat com>
  *
@@ -16,14 +16,19 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#pragma once
+#ifndef IDE_OMNI_GUTTER_RENDERER_H
+#define IDE_OMNI_GUTTER_RENDERER_H
 
-#include "editor/ide-editor-view-addin.h"
+#include <gtksourceview/gtksource.h>
 
 G_BEGIN_DECLS
 
-#define IDE_TYPE_DEBUGGER_EDITOR_VIEW_ADDIN (ide_debugger_editor_view_addin_get_type())
+#define IDE_TYPE_OMNI_GUTTER_RENDERER (ide_omni_gutter_renderer_get_type())
 
-G_DECLARE_FINAL_TYPE (IdeDebuggerEditorViewAddin, ide_debugger_editor_view_addin, IDE, 
DEBUGGER_EDITOR_VIEW_ADDIN, GObject)
+G_DECLARE_FINAL_TYPE (IdeOmniGutterRenderer, ide_omni_gutter_renderer, IDE, OMNI_GUTTER_RENDERER, 
GtkSourceGutterRenderer)
+
+IdeOmniGutterRenderer *ide_omni_gutter_renderer_new (void);
 
 G_END_DECLS
+
+#endif /* IDE_OMNI_GUTTER_RENDERER_H */
diff --git a/libide/sourceview/ide-source-view.c b/libide/sourceview/ide-source-view.c
index b763bf1..7730d4a 100644
--- a/libide/sourceview/ide-source-view.c
+++ b/libide/sourceview/ide-source-view.c
@@ -48,8 +48,7 @@
 #include "sourceview/ide-completion-provider.h"
 #include "sourceview/ide-cursor.h"
 #include "sourceview/ide-indenter.h"
-#include "sourceview/ide-line-change-gutter-renderer.h"
-#include "sourceview/ide-line-diagnostics-gutter-renderer.h"
+#include "sourceview/ide-omni-gutter-renderer.h"
 #include "sourceview/ide-source-iter.h"
 #include "sourceview/ide-source-view-capture.h"
 #include "sourceview/ide-source-view-mode.h"
@@ -94,8 +93,6 @@ typedef struct
   GtkCssProvider              *css_provider;
   PangoFontDescription        *font_desc;
   IdeExtensionAdapter         *indenter_adapter;
-  GtkSourceGutterRenderer     *line_change_renderer;
-  GtkSourceGutterRenderer     *line_diagnostics_renderer;
   IdeSourceViewCapture        *capture;
   gchar                       *display_name;
   IdeSourceViewMode           *mode;
@@ -1415,11 +1412,10 @@ ide_source_view__buffer_notify_highlight_diagnostics_cb (IdeSourceView *self,
                                                          GParamSpec    *pspec,
                                                          IdeBuffer     *buffer)
 {
-  IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
-
   g_assert (IDE_IS_SOURCE_VIEW (self));
   g_assert (IDE_IS_BUFFER (buffer));
 
+#if 0
   if (priv->line_diagnostics_renderer != NULL)
     {
       gboolean visible;
@@ -1429,21 +1425,20 @@ ide_source_view__buffer_notify_highlight_diagnostics_cb (IdeSourceView *self,
                     "visible", visible,
                     NULL);
     }
+#endif
 }
 
 static void
 ide_source_view__buffer_line_flags_changed_cb (IdeSourceView *self,
                                                IdeBuffer     *buffer)
 {
-  IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
-
   IDE_ENTRY;
 
   g_assert (IDE_IS_SOURCE_VIEW (self));
   g_assert (IDE_IS_BUFFER (buffer));
 
-  gtk_source_gutter_renderer_queue_draw (priv->line_change_renderer);
-  gtk_source_gutter_renderer_queue_draw (priv->line_diagnostics_renderer);
+  gtk_source_gutter_queue_draw (gtk_source_view_get_gutter (GTK_SOURCE_VIEW (self),
+                                                            GTK_TEXT_WINDOW_LEFT));
 
   IDE_EXIT;
 }
@@ -4492,9 +4487,7 @@ ide_source_view_constructed (GObject *object)
 {
   IdeSourceView *self = (IdeSourceView *)object;
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
-  GtkSourceGutter *gutter;
   GtkSourceCompletion *completion;
-  gboolean visible;
 
   G_OBJECT_CLASS (ide_source_view_parent_class)->constructed (object);
 
@@ -4519,31 +4512,19 @@ ide_source_view_constructed (GObject *object)
                            self,
                            G_CONNECT_SWAPPED | G_CONNECT_AFTER);
 
-  gutter = gtk_source_view_get_gutter (GTK_SOURCE_VIEW (self), GTK_TEXT_WINDOW_LEFT);
-
-  priv->line_change_renderer = g_object_new (IDE_TYPE_LINE_CHANGE_GUTTER_RENDERER,
-                                             "show-line-deletions", TRUE,
-                                             "size", 2,
-                                             "visible", priv->show_line_changes,
-                                             "xpad", 3,
-                                             NULL);
-  g_object_ref (priv->line_change_renderer);
-  gtk_source_gutter_insert (gutter, priv->line_change_renderer, 0);
-
-  visible = ((priv->buffer != NULL) &&
-             priv->show_line_diagnostics &&
-             ide_buffer_get_highlight_diagnostics (priv->buffer));
-  priv->line_diagnostics_renderer = g_object_new (IDE_TYPE_LINE_DIAGNOSTICS_GUTTER_RENDERER,
-                                                  "size", 16,
-                                                  "visible", visible,
-                                                  "xpad", 2,
-                                                  NULL);
-  g_object_ref (priv->line_diagnostics_renderer);
-  gtk_source_gutter_insert (gutter, priv->line_diagnostics_renderer, -100);
-  g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SHOW_LINE_DIAGNOSTICS]);
-
   priv->definition_src_location = NULL;
   ide_source_view_reset_definition_highlight (self);
+
+  {
+    IdeOmniGutterRenderer *renderer;
+    GtkSourceGutter *gutter = gtk_source_view_get_gutter (GTK_SOURCE_VIEW (self), GTK_TEXT_WINDOW_LEFT);
+
+    renderer = g_object_new (IDE_TYPE_OMNI_GUTTER_RENDERER,
+                             "size", 20,
+                             "visible", TRUE,
+                             NULL);
+    gtk_source_gutter_insert (gutter, GTK_SOURCE_GUTTER_RENDERER (renderer), 1000);
+  }
 }
 
 static void
@@ -6287,8 +6268,6 @@ ide_source_view_dispose (GObject *object)
 
   g_clear_object (&priv->capture);
   g_clear_object (&priv->indenter_adapter);
-  g_clear_object (&priv->line_change_renderer);
-  g_clear_object (&priv->line_diagnostics_renderer);
   g_clear_object (&priv->snippets_provider);
   g_clear_object (&priv->css_provider);
   g_clear_object (&priv->mode);
@@ -7711,8 +7690,7 @@ ide_source_view_set_show_line_changes (IdeSourceView *self,
   if (show_line_changes != priv->show_line_changes)
     {
       priv->show_line_changes = show_line_changes;
-      if (priv->line_change_renderer)
-        gtk_source_gutter_renderer_set_visible (priv->line_change_renderer, show_line_changes);
+      /* TODO: Update omni renderer */
       g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SHOW_LINE_CHANGES]);
     }
 }
@@ -7739,16 +7717,16 @@ ide_source_view_set_show_line_diagnostics (IdeSourceView *self,
 
   if (show_line_diagnostics != priv->show_line_diagnostics)
     {
-      gboolean visible;
-
       priv->show_line_diagnostics = show_line_diagnostics;
 
+#if 0
       if ((priv->buffer != NULL) && (priv->line_diagnostics_renderer != NULL))
         {
           visible = (priv->show_line_diagnostics &&
                      ide_buffer_get_highlight_diagnostics (priv->buffer));
           gtk_source_gutter_renderer_set_visible (priv->line_diagnostics_renderer, visible);
         }
+#endif
 
       g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SHOW_LINE_CHANGES]);
     }


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