[gitg/gtk3] Make the line renderer usable.



commit f5f38a07cff18f48cd2c7045947716c6405cdd19
Author: Ignacio Casal Quinteiro <icq gnome org>
Date:   Thu Feb 24 12:18:47 2011 +0100

    Make the line renderer usable.
    
    It probably needs some more polishing but it is currently working and
    better something than anything :)

 gitg/gitg-diff-line-renderer.c |  275 +++++++++++++++++++++++++++-------------
 1 files changed, 188 insertions(+), 87 deletions(-)
---
diff --git a/gitg/gitg-diff-line-renderer.c b/gitg/gitg-diff-line-renderer.c
index f1ba96e..ee83de2 100644
--- a/gitg/gitg-diff-line-renderer.c
+++ b/gitg/gitg-diff-line-renderer.c
@@ -39,6 +39,13 @@ struct _GitgDiffLineRendererPrivate
 	gint line_old;
 	gint line_new;
 	gchar *label;
+	gint num_digits;
+
+	PangoLayout *cached_layout;
+	PangoAttribute *fg_attr;
+	PangoAttrList *cached_attr_list;
+
+	glong changed_handler_id;
 };
 
 G_DEFINE_TYPE (GitgDiffLineRenderer, gitg_diff_line_renderer, GTK_TYPE_SOURCE_GUTTER_RENDERER)
@@ -95,25 +102,56 @@ gitg_diff_line_renderer_get_property (GObject    *object,
 }
 
 static void
-gitg_diff_line_renderer_constructed (GObject *object)
+gitg_diff_line_renderer_finalize (GObject *object)
 {
-	/*GitgDiffLineRenderer *self = GITG_DIFF_LINE_RENDERER (object);*/
+	GitgDiffLineRenderer *self = GITG_DIFF_LINE_RENDERER (object);
 
-	G_OBJECT_CLASS (gitg_diff_line_renderer_parent_class)->constructed (object);
+	g_free (self->priv->label);
+
+	G_OBJECT_CLASS (gitg_diff_line_renderer_parent_class)->finalize (object);
 }
 
 static void
-gitg_diff_line_renderer_dispose (GObject *object)
+create_layout (GitgDiffLineRenderer *renderer,
+               GtkWidget            *widget)
 {
-	GitgDiffLineRenderer *self = GITG_DIFF_LINE_RENDERER (object);
+	PangoLayout *layout;
+	PangoAttribute *attr;
+	GtkStyleContext *context;
+	GdkRGBA color;
+	PangoAttrList *attr_list;
 
-	if (self->priv->label != NULL)
-	{
-		g_free (self->priv->label);
-		self->priv->label = NULL;
-	}
+	layout = gtk_widget_create_pango_layout (widget, NULL);
+
+	context = gtk_widget_get_style_context (widget);
+	gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, &color);
+
+	attr = pango_attr_foreground_new (color.red * 65535,
+	                                  color.green * 65535,
+	                                  color.blue * 65535);
 
-	G_OBJECT_CLASS (gitg_diff_line_renderer_parent_class)->dispose (object);
+	attr->start_index = 0;
+	attr->end_index = G_MAXINT;
+
+	attr_list = pango_attr_list_new ();
+	pango_attr_list_insert (attr_list, attr);
+
+	renderer->priv->fg_attr = attr;
+	renderer->priv->cached_layout = layout;
+	renderer->priv->cached_attr_list = attr_list;
+}
+
+static void
+gitg_diff_line_renderer_begin (GtkSourceGutterRenderer      *renderer,
+                               cairo_t                      *cr,
+                               GdkRectangle                 *background_area,
+                               GdkRectangle                 *cell_area,
+                               GtkTextIter                  *start,
+                               GtkTextIter                  *end)
+{
+	GitgDiffLineRenderer *lr = GITG_DIFF_LINE_RENDERER (renderer);
+
+	create_layout (lr, GTK_WIDGET (gtk_source_gutter_renderer_get_view (renderer)));
 }
 
 static void
@@ -160,8 +198,7 @@ render_label (GtkSourceGutterRenderer      *renderer,
 	GdkRGBA fg_color, bg_color;
 
 	widget = GTK_WIDGET (gtk_source_gutter_renderer_get_view (renderer));
-
-	layout = gtk_widget_create_pango_layout (widget, "");
+	layout = lr->priv->cached_layout;
 
 	pango_layout_set_markup (layout, lr->priv->label, -1);
 	pango_layout_set_width (layout, cell_area->width);
@@ -220,14 +257,13 @@ render_lines (GtkSourceGutterRenderer      *renderer,
 	/* Render new/old in the cell area */
 	gchar old_str[16];
 	gchar new_str[16];
-	guint xpad;
-	guint ypad;
+	PangoLayout *layout;
 	GtkWidget *widget;
 	GtkStyleContext *style_context;
 
 	widget = GTK_WIDGET (gtk_source_gutter_renderer_get_view (renderer));
+	layout = lr->priv->cached_layout;
 
-	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);
@@ -250,42 +286,38 @@ render_lines (GtkSourceGutterRenderer      *renderer,
 		*new_str = '\0';
 	}
 
-	g_object_get (lr, "xpad", &xpad, "ypad", &ypad, NULL);
-
 	pango_layout_set_text (layout, old_str, -1);
 	style_context = gtk_widget_get_style_context (widget);
 
 	gtk_render_layout (style_context,
 	                   ctx,
-	                   cell_area->x + cell_area->width / 2 - 1 - xpad,
+	                   cell_area->x + cell_area->width / 2 - 1,
 	                   cell_area->y,
 	                   layout);
 
 	pango_layout_set_text (layout, new_str, -1);
 	gtk_render_layout (style_context,
 	                   ctx,
-	                   cell_area->x + cell_area->width - xpad,
+	                   cell_area->x + cell_area->width,
 	                   cell_area->y,
 	                   layout);
 
-	g_object_unref (layout);
-
 	gtk_render_line (style_context,
 	                 ctx,
 	                 background_area->x + background_area->width / 2,
-	                 background_area->y,
-	                 background_area->y + background_area->height,
-	                 background_area->x + background_area->width / 2);
+	                 background_area->y - 1,
+	                 background_area->x + background_area->width / 2,
+	                 background_area->y + background_area->height);
 }
 
 static void
-gitg_diff_line_renderer_draw_impl (GtkSourceGutterRenderer      *renderer,
-                                   cairo_t                      *ctx,
-                                   GdkRectangle                 *background_area,
-                                   GdkRectangle                 *cell_area,
-                                   GtkTextIter                  *start,
-                                   GtkTextIter                  *end,
-                                   GtkSourceGutterRendererState  renderer_state)
+gitg_diff_line_renderer_draw (GtkSourceGutterRenderer      *renderer,
+                              cairo_t                      *ctx,
+                              GdkRectangle                 *background_area,
+                              GdkRectangle                 *cell_area,
+                              GtkTextIter                  *start,
+                              GtkTextIter                  *end,
+                              GtkSourceGutterRendererState  renderer_state)
 {
 	GitgDiffLineRenderer *lr = GITG_DIFF_LINE_RENDERER (renderer);
 
@@ -320,99 +352,168 @@ gitg_diff_line_renderer_draw_impl (GtkSourceGutterRenderer      *renderer,
 		              renderer_state);
 	}
 }
-/*
+
 static void
-gitg_diff_line_renderer_get_size_impl (GtkSourceGutterRenderer *renderer,
-                                       GtkWidget               *widget,
-                                       GdkRectangle            *cell_area,
-                                       gint                    *x_offset,
-                                       gint                    *y_offset,
-                                       gint                    *width,
-                                       gint                    *height)
+gitg_diff_line_renderer_end (GtkSourceGutterRenderer *renderer)
 {
 	GitgDiffLineRenderer *lr = GITG_DIFF_LINE_RENDERER (renderer);
 
-	/ Get size of this rendering /
+	g_object_unref (lr->priv->cached_layout);
+	lr->priv->cached_layout = NULL;
+
+	pango_attr_list_unref (lr->priv->cached_attr_list);
+	lr->priv->cached_attr_list = NULL;
+
+	lr->priv->fg_attr = NULL;
+}
+
+static void
+measure_text (GitgDiffLineRenderer *lr,
+              const gchar          *markup,
+              const gchar          *text,
+              gint                 *width,
+              gint                 *height)
+{
 	PangoLayout *layout;
-	gchar str[16];
-	gint pixel_width;
-	gint pixel_height;
-	guint xpad;
-	guint ypad;
+	gint w;
+	gint h;
+	GtkSourceGutterRenderer *r;
+	GtkTextView *view;
 
-	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);
+	r = GTK_SOURCE_GUTTER_RENDERER (lr);
+	view = gtk_source_gutter_renderer_get_view (r);
 
-	g_object_get (lr, "xpad", &xpad, "ypad", &ypad, NULL);
-	pixel_width += pixel_width + xpad * 2 + 3;
+	layout = gtk_widget_create_pango_layout (GTK_WIDGET (view), NULL);
 
-	if (lr->priv->label)
+	if (markup)
 	{
-		PangoLayout *lbl_layout;
-		gint lbl_pixel_width;
-		gint lbl_pixel_height;
+		pango_layout_set_markup (layout,
+		                         markup,
+		                         -1);
+	}
+	else
+	{
+		pango_layout_set_text (layout,
+		                       text,
+		                       -1);
+	}
+
+	pango_layout_get_size (layout, &w, &h);
 
-		lbl_layout = gtk_widget_create_pango_layout (widget,
-		                                             "");
+	if (width)
+	{
+		*width = w / PANGO_SCALE;
+	}
 
-		pango_layout_set_markup (lbl_layout, lr->priv->label, -1);
+	if (height)
+	{
+		*height = h / PANGO_SCALE;
+	}
 
-		pango_layout_get_pixel_size (lbl_layout,
-		                             &lbl_pixel_width,
-		                             &lbl_pixel_height);
+	g_object_unref (layout);
+}
 
-		lbl_pixel_width += 4;
+static void
+recalculate_size (GitgDiffLineRenderer *lr)
+{
+	/* Get size of this rendering */
+	gint num_digits, num;
 
-		if (lbl_pixel_width > pixel_width)
-		{
-			pixel_width = lbl_pixel_width;
-		}
+	num_digits = 0;
+	num = lr->priv->line_old;
 
-		if (lbl_pixel_height > pixel_height)
-		{
-			pixel_height = lbl_pixel_height;
-		}
+	while (num > 0)
+	{
+		num /= 10;
+		++num_digits;
 	}
 
-	pixel_width += xpad * 2;
-	pixel_height += ypad * 2;
+	num = lr->priv->line_new;
 
-	if (width)
+	while (num > 0)
 	{
-		*width = pixel_width;
+		num /= 10;
+		++num_digits;
 	}
 
-	if (height)
+	num_digits = MAX (num_digits, 2);
+
+	if (num_digits != lr->priv->num_digits)
 	{
-		*height = pixel_height;
+		gchar *markup;
+		gint size;
+
+		lr->priv->num_digits = num_digits;
+
+		markup = g_strdup_printf ("<b>%d   %d</b>",
+		                          lr->priv->line_old,
+		                          lr->priv->line_new);
+
+		measure_text (lr, markup, NULL, &size, NULL);
+		g_free (markup);
+
+		gtk_source_gutter_renderer_set_size (GTK_SOURCE_GUTTER_RENDERER (lr),
+		                                     size);
 	}
+}
+
+static void
+on_buffer_changed (GtkSourceBuffer      *buffer,
+                   GitgDiffLineRenderer *renderer)
+{
+	recalculate_size (renderer);
+}
+
+static void
+gitg_diff_line_renderer_change_buffer (GtkSourceGutterRenderer *renderer,
+                                       GtkTextBuffer           *old_buffer)
+{
+	GitgDiffLineRenderer *lr;
+	GtkTextView *view;
 
-	if (x_offset)
+	lr = GITG_DIFF_LINE_RENDERER (renderer);
+
+	if (old_buffer)
 	{
-		*x_offset = 0;
+		g_signal_handler_disconnect (old_buffer,
+		                             lr->priv->changed_handler_id);
 	}
 
-	if (y_offset)
+	view = gtk_source_gutter_renderer_get_view (renderer);
+
+	if (view)
 	{
-		*y_offset = 0;
-	}
+		GtkTextBuffer *buffer;
 
-	g_object_unref (G_OBJECT (layout));
-}*/
+		buffer = gtk_text_view_get_buffer (view);
+
+		if (buffer)
+		{
+			lr->priv->changed_handler_id =
+				g_signal_connect (buffer,
+				                  "changed",
+				                  G_CALLBACK (on_buffer_changed),
+				                  lr);
+
+			recalculate_size (lr);
+		}
+	}
+}
 
 static void
 gitg_diff_line_renderer_class_init (GitgDiffLineRendererClass *klass)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	GtkSourceGutterRendererClass *gutter_renderer_class = GTK_SOURCE_GUTTER_RENDERER_CLASS (klass);
+	GtkSourceGutterRendererClass *renderer_class = GTK_SOURCE_GUTTER_RENDERER_CLASS (klass);
 
-	gutter_renderer_class->draw = gitg_diff_line_renderer_draw_impl;
+	renderer_class->begin = gitg_diff_line_renderer_begin;
+	renderer_class->draw = gitg_diff_line_renderer_draw;
+	renderer_class->end= gitg_diff_line_renderer_end;
+	renderer_class->change_buffer = gitg_diff_line_renderer_change_buffer;
 
 	object_class->set_property = gitg_diff_line_renderer_set_property;
 	object_class->get_property = gitg_diff_line_renderer_get_property;
-	object_class->constructed = gitg_diff_line_renderer_constructed;
-	object_class->dispose = gitg_diff_line_renderer_dispose;
+	object_class->finalize = gitg_diff_line_renderer_finalize;
 
 	g_object_class_install_property (object_class,
 	                                 PROP_LINE_OLD,



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