[gitg] Added getting/rendering GitgRef from renderer at specific position



commit e0713585d764a1c0d67c5ad99ee1a258910aeb6e
Author: Jesse van den Kieboom <jessevdk gnome org>
Date:   Sun Jun 28 23:47:25 2009 +0200

    Added getting/rendering GitgRef from renderer at specific position
    
    This adds two functions. One to get a GitgRef at a certain position from
    the GitgCellRendererPath, the other draws a GitgRef as drawn in the
    renderer and returns it as a GdkPixbuf

 gitg/gitg-cell-renderer-path.c |   35 ++++++
 gitg/gitg-cell-renderer-path.h |    4 +
 gitg/gitg-label-renderer.c     |  245 +++++++++++++++++++++++++++++++++-------
 gitg/gitg-label-renderer.h     |    5 +
 4 files changed, 246 insertions(+), 43 deletions(-)
---
diff --git a/gitg/gitg-cell-renderer-path.c b/gitg/gitg-cell-renderer-path.c
index 57c6773..a4d6508 100644
--- a/gitg/gitg-cell-renderer-path.c
+++ b/gitg/gitg-cell-renderer-path.c
@@ -54,6 +54,8 @@ struct _GitgCellRendererPathPrivate
 	guint lane_width;
 	guint triangle_width;
 	guint dot_width;
+	
+	gint last_height;
 };
 
 static GtkCellRendererTextClass *parent_class = NULL;
@@ -318,6 +320,8 @@ static void
 renderer_render(GtkCellRenderer *renderer, GdkDrawable *window, GtkWidget *widget, GdkRectangle *area, GdkRectangle *cell_area, GdkRectangle *expose_area, GtkCellRendererState flags)
 {
 	GitgCellRendererPath *self = GITG_CELL_RENDERER_PATH(renderer);
+	
+	self->priv->last_height = area->height;
 
 	cairo_t *cr = gdk_cairo_create(window);
 	
@@ -485,3 +489,34 @@ gitg_cell_renderer_path_new()
 {
 	return GTK_CELL_RENDERER(g_object_new(GITG_TYPE_CELL_RENDERER_PATH, NULL));
 }
+
+GitgRef *
+gitg_cell_renderer_path_get_ref_at_pos (GtkWidget *widget, GitgCellRendererPath *renderer, gint x, gint *hot_x)
+{
+	g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+	g_return_val_if_fail (GITG_IS_CELL_RENDERER_PATH (renderer), NULL);
+	
+	PangoFontDescription *font;
+	g_object_get (renderer, "font-desc", &font, NULL);
+	
+	gint offset = 0;
+	
+	if (is_dummy(renderer->priv->revision))
+		offset = renderer->priv->lane_width;
+	
+	x -= num_lanes(renderer) * renderer->priv->lane_width + offset;
+
+	return gitg_label_renderer_get_ref_at_pos (widget, font, renderer->priv->labels, x, hot_x);
+}
+
+GdkPixbuf *
+gitg_cell_renderer_path_render_ref (GtkWidget *widget, GitgCellRendererPath *renderer, GitgRef *ref, gint minwidth)
+{
+	g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+	g_return_val_if_fail (GITG_IS_CELL_RENDERER_PATH (renderer), NULL);
+
+	PangoFontDescription *font;
+	g_object_get(renderer, "font-desc", &font, NULL);
+	
+	return gitg_label_renderer_render_ref (widget, font, ref, renderer->priv->last_height, minwidth);
+}
diff --git a/gitg/gitg-cell-renderer-path.h b/gitg/gitg-cell-renderer-path.h
index c0b32f9..48f1d2c 100644
--- a/gitg/gitg-cell-renderer-path.h
+++ b/gitg/gitg-cell-renderer-path.h
@@ -24,6 +24,7 @@
 #define __GITG_CELL_RENDERER_PATH_H__
 
 #include <gtk/gtkcellrenderertext.h>
+#include "gitg-ref.h"
 
 G_BEGIN_DECLS
 
@@ -52,6 +53,9 @@ struct _GitgCellRendererPathClass {
 GType gitg_cell_renderer_path_get_type (void) G_GNUC_CONST;
 GtkCellRenderer *gitg_cell_renderer_path_new(void);
 
+GitgRef *gitg_cell_renderer_path_get_ref_at_pos (GtkWidget *widget, GitgCellRendererPath *renderer, gint x, gint *hot_x);
+GdkPixbuf *gitg_cell_renderer_path_render_ref (GtkWidget *widget, GitgCellRendererPath *renderer, GitgRef *ref, gint minwidth);
+
 G_END_DECLS
 
 #endif /* __GITG_CELL_RENDERER_PATH_H__ */
diff --git a/gitg/gitg-label-renderer.c b/gitg/gitg-label-renderer.c
index 43f5e92..9fc86cd 100644
--- a/gitg/gitg-label-renderer.c
+++ b/gitg/gitg-label-renderer.c
@@ -28,7 +28,22 @@
 #define MARGIN 3
 
 gint
-gitg_label_renderer_width(GtkWidget *widget, PangoFontDescription *font, GSList *labels)
+get_label_width (PangoLayout *layout, GitgRef *ref)
+{
+	gint w;
+	gchar *smaller = g_strdup_printf("<span size='smaller'>%s</span>", 
+	                                 gitg_ref_get_shortname(ref));
+
+	pango_layout_set_markup(layout, smaller, -1);
+	
+	pango_layout_get_pixel_size(layout, &w, NULL);
+	g_free(smaller);
+
+	return w + PADDING * 2;
+}
+
+gint
+gitg_label_renderer_width(GtkWidget *widget, PangoFontDescription *description, GSList *labels)
 {
 	gint width = 0;
 	GSList *item;
@@ -38,20 +53,11 @@ gitg_label_renderer_width(GtkWidget *widget, PangoFontDescription *font, GSList
 
 	PangoContext *ctx = gtk_widget_get_pango_context(widget);
 	PangoLayout *layout = pango_layout_new(ctx);
-	pango_layout_set_font_description(layout, font);
+	pango_layout_set_font_description(layout, description);
 	
 	for (item = labels; item; item = item->next)
 	{
-		gint w;
-		GitgRef *ref = (GitgRef *)item->data;
-		gchar *smaller = g_strdup_printf("<span size='smaller'>%s</span>", 
-		                                 gitg_ref_get_shortname(ref));
-		pango_layout_set_markup(layout, smaller, -1);
-		
-		pango_layout_get_pixel_size(layout, &w, NULL);
-		
-		width += w + PADDING * 2 + MARGIN;
-		g_free(smaller);
+		width += get_label_width (layout, GITG_REF (item->data)) + MARGIN;
 	}
 	
 	g_object_unref(layout);
@@ -78,27 +84,97 @@ rounded_rectangle(cairo_t *ctx, float x, float y, float width, float height, flo
 }
 
 static void
-set_source_for_ref_type(cairo_t *context, GitgRefType type)
+get_type_color (GitgRefType type, gdouble *r, gdouble *g, gdouble *b)
 {
 	switch (type)
 	{
 		case GITG_REF_TYPE_NONE:
-			cairo_set_source_rgb(context, 1, 1, 0.8);
+			*r = 1;
+			*g = 1;
+			*b = 0.8;
 		break;
 		case GITG_REF_TYPE_BRANCH:
-			cairo_set_source_rgb(context, 0.8, 1, 0.5);
+			*r = 0.8;
+			*g = 1;
+			*b = 0.5;
 		break;
 		case GITG_REF_TYPE_REMOTE:
-			cairo_set_source_rgb(context, 0.5, 0.8, 1);
+			*r = 0.5;
+			*g = 0.8;
+			*b = 1;
 		break;
 		case GITG_REF_TYPE_TAG:
-			cairo_set_source_rgb(context, 1, 1, 0);
+			*r = 1;
+			*g = 1;
+			*b = 0;
+		break;
+		default:
+			*r = 1;
+			*g = 1;
+			*b = 1;
 		break;
 	}
 }
 
+static void
+set_source_for_ref_type(cairo_t *context, GitgRef *ref, gboolean use_state)
+{
+	if (use_state)
+	{
+		GitgRefState state = gitg_ref_get_state (ref);
+		
+		if (state == GITG_REF_STATE_SELECTED)
+		{
+			cairo_set_source_rgb(context, 1, 1, 1);
+			return;
+		}
+		else if (state == GITG_REF_STATE_PRELIGHT)
+		{
+			gdouble r, g, b;
+			get_type_color (gitg_ref_get_ref_type (ref), &r, &g, &b);
+	
+			cairo_set_source_rgba(context, r, g, b, 0.3);
+			return;
+		}
+	}
+	
+	gdouble r, g, b;
+	get_type_color (gitg_ref_get_ref_type (ref), &r, &g, &b);
+	
+	cairo_set_source_rgb (context, r, g, b);
+}
+
+static gint
+render_label (cairo_t *context, PangoLayout *layout, GitgRef *ref, gint x, gint y, gint height, gboolean use_state)
+{
+	gint w;
+	gint h;
+	gchar *smaller = g_strdup_printf("<span size='smaller'>%s</span>", 
+	                                 gitg_ref_get_shortname(ref));
+	
+	pango_layout_set_markup(layout, smaller, -1);
+	pango_layout_get_pixel_size(layout, &w, &h);
+	
+	// draw rounded rectangle
+	rounded_rectangle(context, x + 0.5, y + MARGIN + 0.5, w + PADDING * 2, height - MARGIN * 2, 5);
+	
+	set_source_for_ref_type(context, ref, use_state);
+	cairo_fill_preserve(context);
+	
+	cairo_set_source_rgb(context, 0, 0, 0);
+	cairo_stroke(context);
+	
+	cairo_save(context);
+	cairo_translate(context, x + PADDING, y + (height - h) / 2.0 + 0.5);
+	pango_cairo_show_layout(context, layout);
+	cairo_restore(context);
+
+	g_free(smaller);
+	return w;
+}
+
 void
-gitg_label_renderer_draw(GtkWidget *widget, PangoFontDescription *font, cairo_t *context, GSList *labels, GdkRectangle *area)
+gitg_label_renderer_draw(GtkWidget *widget, PangoFontDescription *description, cairo_t *context, GSList *labels, GdkRectangle *area)
 {
 	GSList *item;
 	double pos = MARGIN + 0.5;
@@ -108,38 +184,121 @@ gitg_label_renderer_draw(GtkWidget *widget, PangoFontDescription *font, cairo_t
 
 	PangoContext *ctx = gtk_widget_get_pango_context(widget);
 	PangoLayout *layout = pango_layout_new(ctx);
+	pango_layout_set_font_description(layout, description);
+
+	for (item = labels; item; item = item->next)
+	{
+		gint w = render_label (context, layout, GITG_REF (item->data), pos, area->y, area->height, TRUE);
+		pos += w + PADDING * 2 + MARGIN;		
+	}
+	
+	g_object_unref(layout);
+	cairo_restore(context);
+}
+
+
+GitgRef *
+gitg_label_renderer_get_ref_at_pos (GtkWidget *widget, PangoFontDescription *font, GSList *labels, gint x, gint *hot_x)
+{
+	if (!labels)
+	{
+		return NULL;
+	}
+	
+	PangoContext *ctx = gtk_widget_get_pango_context(widget);
+	PangoLayout *layout = pango_layout_new(ctx);
 	pango_layout_set_font_description(layout, font);
 
+	gint start = MARGIN;
+	GitgRef *ret = NULL;
+	GSList *item;
+	
 	for (item = labels; item; item = item->next)
 	{
-		GitgRef *ref = (GitgRef *)item->data;
-		gint w;
-		gint h;
-		gchar *smaller = g_strdup_printf("<span size='smaller'>%s</span>", 
-		                                 gitg_ref_get_shortname(ref));
-		
-		pango_layout_set_markup(layout, smaller, -1);
-		pango_layout_get_pixel_size(layout, &w, &h);
-		
-		// draw rounded rectangle
-		rounded_rectangle(context, pos + 0.5, area->y + MARGIN + 0.5, w + PADDING * 2, area->height - MARGIN * 2, 5);
+		gint width = get_label_width (layout, GITG_REF (item->data));
 		
+		if (x >= start && x <= start + width)
+		{
+			ret = GITG_REF (item->data);
+			
+			if (hot_x)
+			{
+				*hot_x = x - start;
+			}
+			
+			break;
+		}
 		
-		set_source_for_ref_type(context, gitg_ref_get_ref_type(ref));
-		cairo_fill_preserve(context);
-		
-		cairo_set_source_rgb(context, 0, 0, 0);
-		cairo_stroke(context);
-		
-		cairo_save(context);
-		cairo_translate(context, pos + PADDING, area->y + (area->height - h) / 2.0 + 0.5);
-		pango_cairo_show_layout(context, layout);
-		cairo_restore(context);
-		
-		pos += w + PADDING * 2 + MARGIN;
-		g_free(smaller);
+		start += width + MARGIN;
 	}
 	
 	g_object_unref(layout);
-	cairo_restore(context);
+	return ret;
+}
+
+inline guint8
+convert_color_channel (guint8 src,
+                       guint8 alpha)
+{
+	return alpha ? src / (alpha / 255.0) : 0;
+}
+
+void
+convert_bgra_to_rgba (guint8 const  *src,
+                      guint8        *dst,
+                      gint           width,
+                      gint           height)
+{
+	guint8 const *src_pixel = src;
+	guint8 * dst_pixel = dst;
+	int y;
+
+	for (y = 0; y < height; y++)
+	{
+		int x;
+
+		for (x = 0; x < width; x++)
+		{
+			dst_pixel[0] = convert_color_channel (src_pixel[2],
+							                      src_pixel[3]);
+			dst_pixel[1] = convert_color_channel (src_pixel[1],
+							                      src_pixel[3]);
+			dst_pixel[2] = convert_color_channel (src_pixel[0],
+							                      src_pixel[3]);
+			dst_pixel[3] = src_pixel[3];
+
+			dst_pixel += 4;
+			src_pixel += 4;
+		}
+	}
+}
+
+GdkPixbuf *
+gitg_label_renderer_render_ref (GtkWidget *widget, PangoFontDescription *description, GitgRef *ref, gint height, gint minwidth)
+{
+	PangoContext *ctx = gtk_widget_get_pango_context(widget);
+	PangoLayout *layout = pango_layout_new(ctx);
+	pango_layout_set_font_description(layout, description);
+	
+	gint width = MAX(get_label_width (layout, ref), minwidth);
+	
+	cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width + 2, height + 2);
+	cairo_t *context = cairo_create (surface);
+	
+	cairo_set_line_width (context, 1);
+	
+	render_label (context, layout, ref, 1, 1, height, FALSE);
+	
+	guint8 *data = cairo_image_surface_get_data (surface);
+	GdkPixbuf *ret = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width + 2, height + 2);
+	guint8 *pixdata = gdk_pixbuf_get_pixels (ret);
+	
+	convert_bgra_to_rgba (data, pixdata, width + 2, height + 2);
+	
+	cairo_destroy (context);
+	cairo_surface_destroy (surface);
+
+	g_object_unref (layout);
+	
+	return ret;
 }
diff --git a/gitg/gitg-label-renderer.h b/gitg/gitg-label-renderer.h
index 373d9a0..2641d12 100644
--- a/gitg/gitg-label-renderer.h
+++ b/gitg/gitg-label-renderer.h
@@ -25,9 +25,14 @@
 
 #include <gtk/gtk.h>
 #include <pango/pango.h>
+#include "gitg-ref.h"
 
 gint gitg_label_renderer_width(GtkWidget *widget, PangoFontDescription *description, GSList *labels);
 void gitg_label_renderer_draw(GtkWidget *widget, PangoFontDescription *description, cairo_t *context, GSList *labels, GdkRectangle *area);
 
+GitgRef *gitg_label_renderer_get_ref_at_pos (GtkWidget *widget, PangoFontDescription *description, GSList *labels, gint x, gint *hot_x);
+
+GdkPixbuf *gitg_label_renderer_render_ref (GtkWidget *widget, PangoFontDescription *description, GitgRef *ref, gint height, gint minwidth);
+
 #endif /* __GITG_LABEL_RENDERER_H__ */
 



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