[gitg] Added getting/rendering GitgRef from renderer at specific position
- From: Jesse van den Kieboom <jessevdk src gnome org>
- To: svn-commits-list gnome org
- Subject: [gitg] Added getting/rendering GitgRef from renderer at specific position
- Date: Sun, 5 Jul 2009 01:12:59 +0000 (UTC)
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]