[gitg] Use GtkSourceGutter API to render diff line numbers



commit 19396f8fb0335fffb3f842f83c4ea2b0159de699
Author: Jesse van den Kieboom <jessevdk gnome org>
Date:   Mon Jan 11 21:56:53 2010 +0100

    Use GtkSourceGutter API to render diff line numbers

 gitg/Makefile.am               |    2 +
 gitg/gitg-diff-line-renderer.c |  255 ++++++++++++++++++++++++++++++
 gitg/gitg-diff-line-renderer.h |   36 +++++
 gitg/gitg-diff-view.c          |  342 +++++++++++++++++-----------------------
 gitg/gitg-window.ui            |    4 +-
 5 files changed, 441 insertions(+), 198 deletions(-)
---
diff --git a/gitg/Makefile.am b/gitg/Makefile.am
index a7961fb..5a5fe54 100644
--- a/gitg/Makefile.am
+++ b/gitg/Makefile.am
@@ -24,6 +24,7 @@ NOINST_H_FILES = 			\
 	gitg-commit-view.h		\
 	gitg-data-binding.h		\
 	gitg-debug.h			\
+	gitg-diff-line-renderer.h	\
 	gitg-diff-view.h		\
 	gitg-dirs.h			\
 	gitg-dnd.h			\
@@ -58,6 +59,7 @@ gitg_SOURCES = 				\
 	gitg-commit-view.c		\
 	gitg-data-binding.c		\
 	gitg-debug.c			\
+	gitg-diff-line-renderer.c	\
 	gitg-diff-view.c		\
 	gitg-dirs.c			\
 	gitg-dnd.c			\
diff --git a/gitg/gitg-diff-line-renderer.c b/gitg/gitg-diff-line-renderer.c
new file mode 100644
index 0000000..37e9a1e
--- /dev/null
+++ b/gitg/gitg-diff-line-renderer.c
@@ -0,0 +1,255 @@
+#include "gitg-diff-line-renderer.h"
+
+#define GITG_DIFF_LINE_RENDERER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GITG_TYPE_DIFF_LINE_RENDERER, GitgDiffLineRendererPrivate))
+
+#ifndef MAX
+#define MAX(a, b) (a > b ? a : b)
+#endif
+
+#ifndef MIN
+#define MIN(a, b) (a < b ? a : b)
+#endif
+
+/* Properties */
+enum
+{
+	PROP_0,
+	PROP_LINE_OLD,
+	PROP_LINE_NEW
+};
+
+struct _GitgDiffLineRendererPrivate
+{
+	gint line_old;
+	gint line_new;
+};
+
+G_DEFINE_TYPE (GitgDiffLineRenderer, gitg_diff_line_renderer, GTK_TYPE_CELL_RENDERER)
+
+static void
+gitg_diff_line_renderer_finalize (GObject *object)
+{
+	G_OBJECT_CLASS (gitg_diff_line_renderer_parent_class)->finalize (object);
+}
+
+static void
+gitg_diff_line_renderer_set_property (GObject      *object,
+                                      guint         prop_id,
+                                      const GValue *value,
+                                      GParamSpec   *pspec)
+{
+	GitgDiffLineRenderer *self = GITG_DIFF_LINE_RENDERER (object);
+	
+	switch (prop_id)
+	{
+		case PROP_LINE_OLD:
+			self->priv->line_old = g_value_get_int (value);
+		break;
+		case PROP_LINE_NEW:
+			self->priv->line_new = g_value_get_int (value);
+		break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gitg_diff_line_renderer_get_property (GObject    *object,
+                                      guint       prop_id,
+                                      GValue     *value,
+                                      GParamSpec *pspec)
+{
+	GitgDiffLineRenderer *self = GITG_DIFF_LINE_RENDERER (object);
+	
+	switch (prop_id)
+	{
+		case PROP_LINE_OLD:
+			g_value_set_int (value, self->priv->line_old);
+		break;
+		case PROP_LINE_NEW:
+			g_value_set_int (value, self->priv->line_new);
+		break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gitg_diff_line_renderer_render_impl (GtkCellRenderer      *cell,
+                                     GdkDrawable          *window,
+                                     GtkWidget            *widget,
+                                     GdkRectangle         *background_area,
+                                     GdkRectangle         *cell_area,
+                                     GdkRectangle         *expose_area,
+                                     GtkCellRendererState  flags)
+{
+	GitgDiffLineRenderer *lr = GITG_DIFF_LINE_RENDERER (cell);
+
+	/* Render new/old in the cell area */
+	gchar old_str[16];
+	gchar new_str[16];
+	guint xpad;
+	guint ypad;
+
+	PangoLayout *layout = gtk_widget_create_pango_layout (widget, "");
+	pango_layout_set_width (layout, cell_area->width / 2);
+
+	pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT);
+
+	if (lr->priv->line_old >= 0)
+	{
+		g_snprintf (old_str, sizeof (old_str), "%d", lr->priv->line_old);
+	}
+	else
+	{
+		*old_str = '\0';
+	}
+
+	if (lr->priv->line_new >= 0)
+	{
+		g_snprintf (new_str, sizeof (old_str), "%d", lr->priv->line_new);
+	}
+	else
+	{
+		*new_str = '\0';
+	}
+
+	g_object_get (cell, "xpad", &xpad, "ypad", &ypad, NULL);
+
+	pango_layout_set_text (layout, old_str, -1);
+	gtk_paint_layout (widget->style,
+	                  window,
+	                  GTK_WIDGET_STATE (widget),
+	                  FALSE,
+	                  NULL,
+	                  widget,
+	                  NULL,
+	                  cell_area->x + cell_area->width / 2 - 1 - xpad,
+	                  cell_area->y,
+	                  layout);
+
+	pango_layout_set_text (layout, new_str, -1);
+	gtk_paint_layout (widget->style,
+	                  window,
+	                  GTK_WIDGET_STATE (widget),
+	                  FALSE,
+	                  NULL,
+	                  widget,
+	                  NULL,
+	                  cell_area->x + cell_area->width - xpad,
+	                  cell_area->y,
+	                  layout);
+
+	g_object_unref (layout);
+
+	gtk_paint_vline (widget->style,
+	                 window,
+	                 GTK_WIDGET_STATE (widget),
+	                 NULL,
+	                 widget,
+	                 NULL,
+	                 background_area->y,
+	                 background_area->y + background_area->height,
+	                 background_area->x + background_area->width / 2);
+}
+
+static void
+gitg_diff_line_renderer_get_size_impl (GtkCellRenderer *cell,
+                                       GtkWidget       *widget,
+                                       GdkRectangle    *cell_area,
+                                       gint            *x_offset,
+                                       gint            *y_offset,
+                                       gint            *width,
+                                       gint            *height)
+{
+	GitgDiffLineRenderer *lr = GITG_DIFF_LINE_RENDERER (cell);
+
+	/* Get size of this rendering */
+	PangoLayout *layout;
+	gchar str[16];
+	gint pixel_width;
+	gint pixel_height;
+	guint xpad;
+	guint ypad;
+
+	g_snprintf(str, sizeof(str), "%d", MAX(MAX(99, lr->priv->line_old), lr->priv->line_new));
+	layout = gtk_widget_create_pango_layout (widget, str);
+	pango_layout_get_pixel_size(layout, &pixel_width, &pixel_height);
+
+	g_object_get (cell, "xpad", &xpad, "ypad", &ypad, NULL);
+
+	pixel_width = pixel_width * 2 + xpad * 4 + 3;
+	pixel_height += ypad * 2;
+
+	if (width)
+	{
+		*width = pixel_width;
+	}
+
+	if (height)
+	{
+		*height = pixel_height;
+	}
+
+	if (x_offset)
+	{
+		*x_offset = 0;
+	}
+
+	if (y_offset)
+	{
+		*y_offset = 0;
+	}
+
+	g_object_unref (G_OBJECT (layout));
+}
+
+static void
+gitg_diff_line_renderer_class_init (GitgDiffLineRendererClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	GtkCellRendererClass *cell_renderer_class = GTK_CELL_RENDERER_CLASS (klass);
+
+	cell_renderer_class->render = gitg_diff_line_renderer_render_impl;
+	cell_renderer_class->get_size = gitg_diff_line_renderer_get_size_impl;
+
+	object_class->finalize = gitg_diff_line_renderer_finalize;
+	object_class->set_property = gitg_diff_line_renderer_set_property;
+	object_class->get_property = gitg_diff_line_renderer_get_property;
+
+	g_object_class_install_property (object_class,
+	                                 PROP_LINE_OLD,
+	                                 g_param_spec_int ("line-old",
+	                                                   "Line Old",
+	                                                   "Line Old",
+	                                                   -1,
+	                                                   G_MAXINT,
+	                                                   -1,
+	                                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+	g_object_class_install_property (object_class,
+	                                 PROP_LINE_NEW,
+	                                 g_param_spec_int ("line-new",
+	                                                   "Line New",
+	                                                   "Line New",
+	                                                   -1,
+	                                                   G_MAXINT,
+	                                                   -1,
+	                                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+	g_type_class_add_private (object_class, sizeof(GitgDiffLineRendererPrivate));
+}
+
+static void
+gitg_diff_line_renderer_init (GitgDiffLineRenderer *self)
+{
+	self->priv = GITG_DIFF_LINE_RENDERER_GET_PRIVATE (self);
+}
+
+GitgDiffLineRenderer *
+gitg_diff_line_renderer_new ()
+{
+	return g_object_new (GITG_TYPE_DIFF_LINE_RENDERER, NULL);
+}
diff --git a/gitg/gitg-diff-line-renderer.h b/gitg/gitg-diff-line-renderer.h
new file mode 100644
index 0000000..006cb25
--- /dev/null
+++ b/gitg/gitg-diff-line-renderer.h
@@ -0,0 +1,36 @@
+#ifndef __GITG_DIFF_LINE_RENDERER_H__
+#define __GITG_DIFF_LINE_RENDERER_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GITG_TYPE_DIFF_LINE_RENDERER			(gitg_diff_line_renderer_get_type ())
+#define GITG_DIFF_LINE_RENDERER(obj)			(G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_DIFF_LINE_RENDERER, GitgDiffLineRenderer))
+#define GITG_DIFF_LINE_RENDERER_CONST(obj)		(G_TYPE_CHECK_INSTANCE_CAST ((obj), GITG_TYPE_DIFF_LINE_RENDERER, GitgDiffLineRenderer const))
+#define GITG_DIFF_LINE_RENDERER_CLASS(klass)	(G_TYPE_CHECK_CLASS_CAST ((klass), GITG_TYPE_DIFF_LINE_RENDERER, GitgDiffLineRendererClass))
+#define GITG_IS_DIFF_LINE_RENDERER(obj)			(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GITG_TYPE_DIFF_LINE_RENDERER))
+#define GITG_IS_DIFF_LINE_RENDERER_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass), GITG_TYPE_DIFF_LINE_RENDERER))
+#define GITG_DIFF_LINE_RENDERER_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj), GITG_TYPE_DIFF_LINE_RENDERER, GitgDiffLineRendererClass))
+
+typedef struct _GitgDiffLineRenderer		GitgDiffLineRenderer;
+typedef struct _GitgDiffLineRendererClass	GitgDiffLineRendererClass;
+typedef struct _GitgDiffLineRendererPrivate	GitgDiffLineRendererPrivate;
+
+struct _GitgDiffLineRenderer {
+	GtkCellRenderer parent;
+	
+	GitgDiffLineRendererPrivate *priv;
+};
+
+struct _GitgDiffLineRendererClass {
+	GtkCellRendererClass parent_class;
+};
+
+GType gitg_diff_line_renderer_get_type (void) G_GNUC_CONST;
+GitgDiffLineRenderer *gitg_diff_line_renderer_new (void);
+
+
+G_END_DECLS
+
+#endif /* __GITG_DIFF_LINE_RENDERER_H__ */
diff --git a/gitg/gitg-diff-view.c b/gitg/gitg-diff-view.c
index e0befdd..b02410c 100644
--- a/gitg/gitg-diff-view.c
+++ b/gitg/gitg-diff-view.c
@@ -22,6 +22,8 @@
 
 #include "gitg-diff-view.h"
 #include "gitg-types.h"
+#include "gitg-diff-line-renderer.h"
+
 #include <string.h>
 #include <stdlib.h>
 
@@ -40,6 +42,17 @@
 static void on_buffer_insert_text(GtkTextBuffer *buffer, GtkTextIter *iter, gchar const *text, gint len, GitgDiffView *view);
 static void on_buffer_delete_range(GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, GitgDiffView *view);
 
+static void
+line_renderer_size_func (GtkSourceGutter *gutter,
+                         GtkCellRenderer *cell,
+                         GitgDiffView    *view);
+static void
+line_renderer_data_func (GtkSourceGutter *gutter,
+                         GtkCellRenderer *cell,
+                         gint             line_number,
+                         gboolean         current_line,
+                         GitgDiffView    *view);
+
 static gboolean on_idle_scan(GitgDiffView *view);
 
 /* Signals */
@@ -98,6 +111,12 @@ struct _GitgDiffViewPrivate
 	gboolean diff_enabled;
 	GtkTextBuffer *current_buffer;
 	GtkTextTag *invisible_tag;
+
+	GitgDiffLineRenderer *line_renderer;
+
+	Region *lines_current_region;
+	gint lines_previous_line;
+	guint lines_counters[2];
 };
 
 G_DEFINE_TYPE(GitgDiffView, gitg_diff_view, GTK_TYPE_SOURCE_VIEW)
@@ -151,14 +170,14 @@ regions_free(GitgDiffView *view, gboolean remove_signals)
 }
 
 static void
-gitg_diff_view_finalize(GObject *object)
+gitg_diff_view_finalize (GObject *object)
 {
-	GitgDiffView *view = GITG_DIFF_VIEW(object);
+	GitgDiffView *view = GITG_DIFF_VIEW (object);
 
-	regions_free(view, TRUE);
-	g_sequence_free(view->priv->regions_index);
+	regions_free (view, TRUE);
+	g_sequence_free (view->priv->regions_index);
 
-	G_OBJECT_CLASS(gitg_diff_view_parent_class)->finalize(object);
+	G_OBJECT_CLASS (gitg_diff_view_parent_class)->finalize (object);
 }
 
 static void
@@ -201,6 +220,12 @@ gitg_diff_view_get_property(GObject *object, guint prop_id, GValue *value, GPara
 }
 
 static void
+gitg_diff_view_constructed (GObject *object)
+{
+	g_object_set (object, "show-line-numbers", FALSE, NULL);
+}
+
+static void
 gitg_diff_view_class_init(GitgDiffViewClass *klass)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS(klass);
@@ -210,6 +235,8 @@ gitg_diff_view_class_init(GitgDiffViewClass *klass)
 	object_class->set_property = gitg_diff_view_set_property;
 	object_class->get_property = gitg_diff_view_get_property;
 
+	object_class->constructed = gitg_diff_view_constructed;
+
 	widget_class->expose_event = gitg_diff_view_expose;
 
 	diff_view_signals[HEADER_ADDED] =
@@ -259,88 +286,42 @@ on_buffer_set(GitgDiffView *self, GParamSpec *spec, gpointer userdata)
 }
 
 static void
-gitg_diff_view_init(GitgDiffView *self)
-{
-	self->priv = GITG_DIFF_VIEW_GET_PRIVATE(self);
-
-	self->priv->regions_index = g_sequence_new(NULL);
-
-	g_signal_connect(self, "notify::buffer", G_CALLBACK(on_buffer_set), NULL);
-}
-
-GitgDiffView*
-gitg_diff_view_new()
-{
-	return g_object_new(GITG_TYPE_DIFF_VIEW, NULL);
-}
-
-/* This function is taken from gtk+/tests/testtext.c */
-static void
-get_lines (GtkTextView *text_view, gint first_y, gint last_y, GArray *buffer_coords, GArray *line_heights, GArray *numbers, gint *countp)
+gitg_diff_view_init (GitgDiffView *self)
 {
-	GtkTextIter iter;
-	gint count;
-	gint size;
-	gint last_line_num = -1;
-
-	g_array_set_size(buffer_coords, 0);
-	g_array_set_size(numbers, 0);
-
-	if (line_heights != NULL)
-		g_array_set_size(line_heights, 0);
-
-	/* Get iter at first y */
-	gtk_text_view_get_line_at_y(text_view, &iter, first_y, NULL);
+	GtkSourceGutter *gutter;
 
-	/* For each iter, get its location and add it to the arrays.
-	 * Stop when we pass last_y */
-	count = 0;
-  	size = 0;
+	self->priv = GITG_DIFF_VIEW_GET_PRIVATE (self);
 
-  	while (!gtk_text_iter_is_end(&iter))
-    {
-		gint y, height;
+	self->priv->regions_index = g_sequence_new (NULL);
+	self->priv->line_renderer = gitg_diff_line_renderer_new ();
 
-		gtk_text_view_get_line_yrange(text_view, &iter, &y, &height);
+	g_object_set (self->priv->line_renderer, "xpad", 2, NULL);
 
-		g_array_append_val(buffer_coords, y);
+	gutter = gtk_source_view_get_gutter (GTK_SOURCE_VIEW (self), GTK_TEXT_WINDOW_LEFT);
 
-		if (line_heights)
-			g_array_append_val(line_heights, height);
+	gtk_source_gutter_insert (gutter,
+	                          GTK_CELL_RENDERER (self->priv->line_renderer),
+	                          0);
 
-		last_line_num = gtk_text_iter_get_line(&iter);
-		g_array_append_val(numbers, last_line_num);
+	gtk_source_gutter_set_cell_data_func (gutter,
+	                                      GTK_CELL_RENDERER (self->priv->line_renderer),
+	                                      (GtkSourceGutterDataFunc)line_renderer_data_func,
+	                                      self,
+	                                      NULL);
 
-		++count;
+	gtk_source_gutter_set_cell_size_func (gutter,
+	                                      GTK_CELL_RENDERER (self->priv->line_renderer),
+	                                      (GtkSourceGutterSizeFunc)line_renderer_size_func,
+	                                      self,
+	                                      NULL);
 
-		if ((y + height) >= last_y)
-			break;
-
-		gtk_text_iter_forward_line(&iter);
-	}
-
-	if (gtk_text_iter_is_end(&iter))
-    {
-		gint y, height;
-		gint line_num;
-
-		gtk_text_view_get_line_yrange(text_view, &iter, &y, &height);
-
-		line_num = gtk_text_iter_get_line(&iter);
-
-		if (line_num != last_line_num)
-		{
-			g_array_append_val(buffer_coords, y);
-
-			if (line_heights)
-				g_array_append_val(line_heights, height);
-
-			g_array_append_val(numbers, line_num);
-			++count;
-		}
-	}
+	g_signal_connect (self, "notify::buffer", G_CALLBACK (on_buffer_set), NULL);
+}
 
-	*countp = count;
+GitgDiffView *
+gitg_diff_view_new ()
+{
+	return g_object_new (GITG_TYPE_DIFF_VIEW, NULL);
 }
 
 static gint
@@ -353,13 +334,17 @@ index_compare(gconstpointer a, gconstpointer b, gpointer userdata)
 }
 
 static void
-ensure_max_line(GitgDiffView *view, Hunk *hunk)
+ensure_max_line (GitgDiffView *view, Hunk *hunk)
 {
 	guint num = hunk->region.next ? hunk->region.next->line - hunk->region.line : 0;
-	guint m = MAX(hunk->new + num, hunk->old + num);
+	guint m = MAX (hunk->new + num, hunk->old + num);
 
 	if (m > view->priv->max_line_count)
+	{
 		view->priv->max_line_count = m;
+
+		gtk_source_gutter_queue_draw (gtk_source_view_get_gutter (GTK_SOURCE_VIEW (view), GTK_TEXT_WINDOW_LEFT));
+	}
 }
 
 static void
@@ -371,7 +356,9 @@ add_region(GitgDiffView *view, Region *region)
 		region->prev = view->priv->last_region;
 
 		if (view->priv->last_region->type == GITG_DIFF_ITER_TYPE_HUNK)
+		{
 			ensure_max_line(view, (Hunk *)view->priv->last_region);
+		}
 	}
 	else
 	{
@@ -387,9 +374,13 @@ add_region(GitgDiffView *view, Region *region)
 	iter.userdata2 = region;
 
 	if (region->type == GITG_DIFF_ITER_TYPE_HEADER)
+	{
 		g_signal_emit(view, diff_view_signals[HEADER_ADDED], 0, &iter);
+	}
 	else if (region->type == GITG_DIFF_ITER_TYPE_HUNK)
+	{
 		g_signal_emit(view, diff_view_signals[HUNK_ADDED], 0, &iter);
+	}
 }
 
 static void
@@ -407,7 +398,9 @@ parse_hunk_info(Hunk *hunk, GtkTextIter *iter)
 	gchar *new = g_utf8_strchr(text, -1, '+');
 
 	if (!old || !new)
+	{
 		return;
+	}
 
 	hunk->old = atoi(old + 1);
 	hunk->new = atoi(new + 1);
@@ -429,12 +422,16 @@ ensure_scan(GitgDiffView *view, guint last_line)
 		GtkTextIter end = iter;
 
 		if (!gtk_text_iter_forward_line(&iter))
+		{
 			break;
+		}
 
 		++view->priv->last_scan_line;
 
 		if (!gtk_text_iter_forward_chars(&end, 3))
+		{
 			continue;
+		}
 
 		gchar *text = gtk_text_iter_get_text(&start, &end);
 
@@ -457,7 +454,9 @@ ensure_scan(GitgDiffView *view, guint last_line)
 		g_free(text);
 
 		if (!gtk_text_iter_forward_chars(&end, 7))
+		{
 			continue;
+		}
 
 		text = gtk_text_iter_get_text(&start, &end);
 
@@ -479,7 +478,9 @@ ensure_scan(GitgDiffView *view, guint last_line)
 	}
 
 	if (view->priv->last_region && view->priv->last_region->type == GITG_DIFF_ITER_TYPE_HUNK)
+	{
 		ensure_max_line(view, (Hunk *)view->priv->last_region);
+	}
 }
 
 static Region *
@@ -491,14 +492,18 @@ find_current_region(GitgDiffView *view, guint line)
 	iter = g_sequence_search(view->priv->regions_index, &tmp, index_compare, NULL);
 
 	if (!iter || g_sequence_iter_is_begin(iter))
+	{
 		return NULL;
+	}
 
 	if (!g_sequence_iter_is_end(iter))
 	{
 		Region *ret = (Region *)g_sequence_get(iter); 
 
 		if (ret->line == line)
+		{
 			return ret->visible ? ret : NULL;
+		}
 	}
 
 	Region *ret = (Region *)g_sequence_get(g_sequence_iter_prev(iter));
@@ -513,8 +518,11 @@ line_has_prefix(GitgDiffView *view, guint line, gchar const *prefix)
 	gtk_text_buffer_get_iter_at_line(view->priv->current_buffer, &iter, line);
 
 	GtkTextIter end = iter;
+
 	if (!gtk_text_iter_forward_chars(&end, g_utf8_strlen(prefix, -1)))
+	{
 		return FALSE;
+	}
 
 	gchar *text = gtk_text_iter_get_text(&iter, &end);
 	gboolean ret = g_str_has_prefix(text, prefix);
@@ -553,146 +561,88 @@ get_initial_counters(GitgDiffView *view, Region *region, guint line, guint count
 }
 
 static void
-paint_line_numbers(GitgDiffView *view, GdkEventExpose *event)
+line_renderer_size_func (GtkSourceGutter *gutter,
+                         GtkCellRenderer *cell,
+                         GitgDiffView    *view)
 {
-	GtkTextView *text_view;
-	GdkWindow *win;
-	PangoLayout *layout;
-	GArray *numbers;
-	GArray *pixels;
-	gchar str_old[16];  /* we don't expect more than ten million lines ;-) */
-	gchar str_new[16];
-	gint y1, y2;
-	gint count;
-	gint margin_width;
-	gint text_width;
-	gint i;
-	GtkTextIter cur;
-
-	text_view = GTK_TEXT_VIEW(view);
-	win = gtk_text_view_get_window(text_view, GTK_TEXT_WINDOW_LEFT);
-
-	y1 = event->area.y;
-	y2 = y1 + event->area.height;
-
-	/* get the extents of the line printing */
-	gtk_text_view_window_to_buffer_coords(text_view, GTK_TEXT_WINDOW_LEFT, 0, y1, NULL, &y1);
-	gtk_text_view_window_to_buffer_coords(text_view, GTK_TEXT_WINDOW_LEFT, 0, y2, NULL, &y2);
-
-	numbers = g_array_new(FALSE, FALSE, sizeof(gint));
-	pixels = g_array_new(FALSE, FALSE, sizeof(gint));
-
-	/* get the line numbers and y coordinates. */
-	get_lines(text_view, y1, y2, pixels, NULL, numbers, &count);
-
-	/* A zero-lined document should display a "1"; we don't need to worry about
-	scrolling effects of the text widget in this special case */
-
-	if (count == 0)
-	{
-		gint y = 0;
-		gint n = 0;
-		count = 1;
-		g_array_append_val(pixels, y);
-		g_array_append_val(numbers, n);
-	}
-
-	/* Ensure scanned until last needed line */
-	guint last = g_array_index(numbers, gint, count - 1);
-	ensure_scan(view, last);
-
-	/* set size */
-	g_snprintf(str_old, sizeof(str_old), "%d", MAX(99, view->priv->max_line_count));
-	layout = gtk_widget_create_pango_layout(GTK_WIDGET(view), str_old);
-
-	pango_layout_get_pixel_size(layout, &text_width, NULL);
-
-	/* determine the width of the left margin. */
-	margin_width = text_width * 2 + 9;
-
-	guint extra_width = 0;
-
-	if (gtk_source_view_get_show_line_marks(GTK_SOURCE_VIEW(view)))
-		extra_width = 20;
-
-	pango_layout_set_width(layout, text_width);
-	pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT);
+	g_object_set (cell,
+	              "line_old", view->priv->max_line_count,
+	              "line_new", view->priv->max_line_count,
+	              NULL);
+}
 
-	gtk_text_view_set_border_window_size(GTK_TEXT_VIEW(text_view), GTK_TEXT_WINDOW_LEFT, margin_width + extra_width);
-	gtk_text_buffer_get_iter_at_mark(text_view->buffer, &cur, gtk_text_buffer_get_insert(text_view->buffer));
+static void
+line_renderer_data_func (GtkSourceGutter *gutter,
+                         GtkCellRenderer *cell,
+                         gint             line_number,
+                         gboolean         current_line,
+                         GitgDiffView    *view)
+{
+	gint line_old = -1;
+	gint line_new = -1;
+	Region **current = &view->priv->lines_current_region;
 
-	Region *current = NULL;
-	guint counters[2];
+	ensure_scan (view, line_number);
 
-	for (i = 0; i < count; ++i)
+	if (!*current)
 	{
-		gint pos;
-		gint line_to_paint;
-
-		gtk_text_view_buffer_to_window_coords(text_view, GTK_TEXT_WINDOW_LEFT, 0, g_array_index(pixels, gint, i), NULL, &pos);
-		line_to_paint = g_array_index(numbers, gint, i);
+		*current = find_current_region (view, line_number);
 
-		if (!current)
+		if (*current)
 		{
-			current = find_current_region(view, line_to_paint);
-
-			if (current)
-				get_initial_counters(view, current, line_to_paint, counters);
+			get_initial_counters (view,
+			                      *current,
+			                      line_number,
+			                      view->priv->lines_counters);
 		}
+	}
 
-		*str_old = '\0';
-		*str_new = '\0';
+	if (*current &&
+	    (*current)->type == GITG_DIFF_ITER_TYPE_HUNK &&
+	    line_number != (*current)->line)
+	{
+		Hunk *hunk = (Hunk *)*current;
 
-		if (current && current->type == GITG_DIFF_ITER_TYPE_HUNK && line_to_paint != current->line)
+		if (draw_old (view, line_number))
 		{
-			Hunk *hunk = (Hunk *)current;
-
-			if (draw_old(view, line_to_paint))
-				g_snprintf(str_old, sizeof(str_old), "%d", hunk->old + counters[0]++);
-
-			if (draw_new(view, line_to_paint))
-				g_snprintf(str_new, sizeof(str_new), "%d", hunk->new + counters[1]++);
+			line_old = hunk->old + view->priv->lines_counters[0]++;
 		}
 
-		pango_layout_set_markup(layout, str_old, -1);
-		gtk_paint_layout(GTK_WIDGET(view)->style, win, GTK_WIDGET_STATE(view), FALSE, NULL, GTK_WIDGET(view), NULL, margin_width - 7 - text_width, pos, layout);
-
-		pango_layout_set_markup(layout, str_new, -1);
-		gtk_paint_layout(GTK_WIDGET(view)->style, win, GTK_WIDGET_STATE(view), FALSE, NULL, GTK_WIDGET(view), NULL, margin_width - 2, pos, layout);
-
-		if (current && current->next && line_to_paint == current->next->line - 1)
+		if (draw_new (view, line_number))
 		{
-			counters[0] = counters[1] = 0;
-			current = current->next->visible ? current->next : NULL;
+			line_new = hunk->new + view->priv->lines_counters[1]++;
 		}
 	}
 
-	gtk_paint_vline(GTK_WIDGET(view)->style, win, GTK_WIDGET_STATE(view), NULL, GTK_WIDGET(view), NULL, event->area.y, event->area.y + event->area.height, 4 + text_width);
+	g_object_set (cell, "line_old", line_old, "line_new", line_new, NULL);
 
-	g_array_free(pixels, TRUE);
-	g_array_free(numbers, TRUE);
-
-	g_object_unref(G_OBJECT(layout));
+	if (*current && (*current)->next && line_number == (*current)->next->line - 1)
+	{
+		view->priv->lines_counters[0] = view->priv->lines_counters[1] = 0;
+		*current = (*current)->next->visible ? (*current)->next : NULL;
+	}
 }
 
-static gint 
-gitg_diff_view_expose(GtkWidget *widget, GdkEventExpose *event)
+static gint
+gitg_diff_view_expose (GtkWidget      *widget,
+                       GdkEventExpose *event)
 {
-	gboolean ret = FALSE;
-	GtkTextView *text_view = GTK_TEXT_VIEW(widget);
-	GitgDiffView *view = GITG_DIFF_VIEW(widget);
+	GitgDiffView *view = GITG_DIFF_VIEW (widget);
+
+	/* Prepare for new round of expose on the line renderer */
+	view->priv->lines_current_region = NULL;
+	view->priv->lines_previous_line = -1;
+	view->priv->lines_counters[0] = 0;
+	view->priv->lines_counters[1] = 0;
 
-	if (event->window == gtk_text_view_get_window(text_view, GTK_TEXT_WINDOW_LEFT) && 
-	    view->priv->diff_enabled && gtk_source_view_get_show_line_numbers(GTK_SOURCE_VIEW(view)))
+	if (GTK_WIDGET_CLASS (gitg_diff_view_parent_class)->expose_event)
 	{
-		paint_line_numbers(GITG_DIFF_VIEW(widget), event);
-		ret = TRUE;
+		return GTK_WIDGET_CLASS (gitg_diff_view_parent_class)->expose_event (widget, event);
+	}
+	else
+	{
+		return FALSE;
 	}
-
-	if (GTK_WIDGET_CLASS(gitg_diff_view_parent_class)->expose_event)
-		ret = ret || GTK_WIDGET_CLASS(gitg_diff_view_parent_class)->expose_event(widget, event);
-
-	return ret;
 }
 
 void
diff --git a/gitg/gitg-window.ui b/gitg/gitg-window.ui
index 04c02a1..0d7aa88 100644
--- a/gitg/gitg-window.ui
+++ b/gitg/gitg-window.ui
@@ -374,7 +374,7 @@
                                       <object class="GitgDiffView" id="revision_diff">
                                         <property name="editable">False</property>
                                         <property name="cursor_visible">False</property>
-                                        <property name="show_line_numbers">True</property>
+                                        <property name="show_line_numbers">False</property>
                                         <property name="tab_width">4</property>
                                       </object>
                                     </child>
@@ -574,7 +574,7 @@
                             <property name="left_margin">2</property>
                             <property name="right_margin">2</property>
                             <property name="cursor_visible">False</property>
-                            <property name="show_line_numbers">True</property>
+                            <property name="show_line_numbers">False</property>
                             <property name="tab_width">4</property>
                           </object>
                         </child>



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