[empathy/gnome-2-28: 5/18] Add a "show-on-select" property.



commit 1dd41a76187e118d29be310e9f715e8baa4eeeec
Author: Cosimo Cecchi <cosimoc gnome org>
Date:   Tue Sep 29 17:30:23 2009 +0200

    Add a "show-on-select" property.
    
    This implies copying the render function from gtkcellrendererpixbuf.c
    and modifying it slightly.

 libempathy-gtk/empathy-cell-renderer-activatable.c |  342 ++++++++++++++++----
 libempathy-gtk/empathy-cell-renderer-activatable.h |    1 +
 2 files changed, 283 insertions(+), 60 deletions(-)
---
diff --git a/libempathy-gtk/empathy-cell-renderer-activatable.c b/libempathy-gtk/empathy-cell-renderer-activatable.c
index 6c79826..29393f1 100644
--- a/libempathy-gtk/empathy-cell-renderer-activatable.c
+++ b/libempathy-gtk/empathy-cell-renderer-activatable.c
@@ -1,7 +1,6 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
  * Copyright (C) 2007 Raphael Slinckx <raphael slinckx net>
- * Copyright (C) 2007-2008 Collabora Ltd.
+ * Copyright (C) 2007-2009 Collabora Ltd.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -18,100 +17,323 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  *
  * Authors: Raphael Slinckx <raphael slinckx net>
+ *          Cosimo Cecchi   <cosimo cecchi collabora co uk>
  */
 
+#include <config.h>
+
 #include <gtk/gtk.h>
 
+#include <libempathy/empathy-utils.h>
+
 #include "empathy-cell-renderer-activatable.h"
 
-static void     empathy_cell_renderer_activatable_init       (EmpathyCellRendererActivatable      *cell);
-static void     empathy_cell_renderer_activatable_class_init (EmpathyCellRendererActivatableClass *klass);
-static gboolean cell_renderer_activatable_activate           (GtkCellRenderer                     *cell,
-							      GdkEvent                            *event,
-							      GtkWidget                           *widget,
-							      const gchar                         *path,
-							      GdkRectangle                        *background_area,
-							      GdkRectangle                        *cell_area,
-							      GtkCellRendererState                 flags);
+enum {
+  PATH_ACTIVATED,
+  LAST_SIGNAL
+};
 
 enum {
-	PATH_ACTIVATED,
-	LAST_SIGNAL
+  PROP_SHOW_ON_SELECT = 1
 };
 
+typedef struct {
+  gboolean show_on_select;
+} EmpathyCellRendererActivatablePriv;
+
 static guint signals[LAST_SIGNAL];
 
-G_DEFINE_TYPE (EmpathyCellRendererActivatable, empathy_cell_renderer_activatable, GTK_TYPE_CELL_RENDERER_PIXBUF)
+G_DEFINE_TYPE (EmpathyCellRendererActivatable,
+    empathy_cell_renderer_activatable, GTK_TYPE_CELL_RENDERER_PIXBUF)
+
+#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyCellRendererActivatable)
 
 static void
 empathy_cell_renderer_activatable_init (EmpathyCellRendererActivatable *cell)
 {
-	g_object_set (cell,
-		      "xpad", 0,
-		      "ypad", 0,
-		      "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE,
-		      "follow-state", TRUE,
-		      NULL);
+  cell->priv = G_TYPE_INSTANCE_GET_PRIVATE (cell,
+      EMPATHY_TYPE_CELL_RENDERER_ACTIVATABLE,
+      EmpathyCellRendererActivatablePriv);
+
+  g_object_set (cell,
+      "xpad", 0,
+      "ypad", 0,
+      "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE,
+      "follow-state", TRUE,
+      NULL);
+}
+
+static void
+cell_renderer_activatable_get_property (GObject *object,
+    guint prop_id,
+    GValue *value,
+    GParamSpec *pspec)
+{
+  EmpathyCellRendererActivatablePriv *priv = GET_PRIV (object);
+
+  switch (prop_id)
+    {
+      case PROP_SHOW_ON_SELECT:
+        g_value_set_boolean (value, priv->show_on_select);
+        break;
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+        break;
+    }
 }
 
 static void
-empathy_cell_renderer_activatable_class_init (EmpathyCellRendererActivatableClass *klass)
+cell_renderer_activatable_set_property (GObject *object,
+    guint prop_id,
+    const GValue *value,
+    GParamSpec *pspec)
 {
-	GtkCellRendererClass *cell_class;
-
-	cell_class = GTK_CELL_RENDERER_CLASS (klass);
-	cell_class->activate = cell_renderer_activatable_activate;
-
-	signals[PATH_ACTIVATED] =
-		g_signal_new ("path-activated",
-			      G_TYPE_FROM_CLASS (klass),
-			      G_SIGNAL_RUN_LAST,
-			      0,
-			      NULL, NULL,
-			      g_cclosure_marshal_VOID__STRING,
-			      G_TYPE_NONE,
-			      1, G_TYPE_STRING);
+  EmpathyCellRendererActivatablePriv *priv = GET_PRIV (object);
+
+  switch (prop_id)
+    {
+      case PROP_SHOW_ON_SELECT:
+        priv->show_on_select = g_value_get_boolean (value);
+        break;
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+        break;
+    }
 }
 
 GtkCellRenderer *
 empathy_cell_renderer_activatable_new (void)
 {
-	return g_object_new (EMPATHY_TYPE_CELL_RENDERER_ACTIVATABLE, NULL);
+  return g_object_new (EMPATHY_TYPE_CELL_RENDERER_ACTIVATABLE, NULL);
 }
 
 static gboolean
 cell_renderer_activatable_activate (GtkCellRenderer      *cell,
-				    GdkEvent             *event,
-				    GtkWidget            *widget,
-				    const gchar          *path_string,
-				    GdkRectangle         *background_area,
-				    GdkRectangle         *cell_area,
-				    GtkCellRendererState  flags)
+    GdkEvent *event,
+    GtkWidget *widget,
+    const gchar *path_string,
+    GdkRectangle *background_area,
+    GdkRectangle *cell_area,
+    GtkCellRendererState  flags)
 {
-	EmpathyCellRendererActivatable *activatable;
-	gint                            ex, ey, bx, by, bw, bh;
+  EmpathyCellRendererActivatable *activatable;
+  gint ex, ey, bx, by, bw, bh;
 
-	activatable = EMPATHY_CELL_RENDERER_ACTIVATABLE (cell);
+  activatable = EMPATHY_CELL_RENDERER_ACTIVATABLE (cell);
 
-	if (!GTK_IS_TREE_VIEW (widget) || event == NULL ||
-	    event->type != GDK_BUTTON_PRESS) {
-		return FALSE;
-	}
+  if (!GTK_IS_TREE_VIEW (widget) || event == NULL ||
+      event->type != GDK_BUTTON_PRESS) {
+    return FALSE;
+  }
 
-	ex  = (gint) ((GdkEventButton *) event)->x;
-	ey  = (gint) ((GdkEventButton *) event)->y;
-	bx = background_area->x;
-	by = background_area->y;
-	bw = background_area->width;
-	bh = background_area->height;
+  ex  = (gint) ((GdkEventButton *) event)->x;
+  ey  = (gint) ((GdkEventButton *) event)->y;
+  bx = background_area->x;
+  by = background_area->y;
+  bw = background_area->width;
+  bh = background_area->height;
+
+  if (ex < bx || ex > (bx+bw) || ey < by || ey > (by+bh)){
+    /* Click wasn't on the icon */
+    return FALSE;
+  }
+
+  g_signal_emit (activatable, signals[PATH_ACTIVATED], 0, path_string);
+
+  return TRUE;
+}
+
+/* copied from gtkcellrendererpixbuf.c */
+
+static GdkPixbuf *
+create_colorized_pixbuf (GdkPixbuf *src,
+    GdkColor  *new_color)
+{
+  gint i, j;
+  gint width, height, has_alpha, src_row_stride, dst_row_stride;
+  gint red_value, green_value, blue_value;
+  guchar *target_pixels;
+  guchar *original_pixels;
+  guchar *pixsrc;
+  guchar *pixdest;
+  GdkPixbuf *dest;
+
+  red_value = new_color->red / 255.0;
+  green_value = new_color->green / 255.0;
+  blue_value = new_color->blue / 255.0;
+
+  dest = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (src),
+      gdk_pixbuf_get_has_alpha (src),
+      gdk_pixbuf_get_bits_per_sample (src),
+      gdk_pixbuf_get_width (src),
+      gdk_pixbuf_get_height (src));
+
+  has_alpha = gdk_pixbuf_get_has_alpha (src);
+  width = gdk_pixbuf_get_width (src);
+  height = gdk_pixbuf_get_height (src);
+  src_row_stride = gdk_pixbuf_get_rowstride (src);
+  dst_row_stride = gdk_pixbuf_get_rowstride (dest);
+  target_pixels = gdk_pixbuf_get_pixels (dest);
+  original_pixels = gdk_pixbuf_get_pixels (src);
+
+  for (i = 0; i < height; i++)
+    {
+      pixdest = target_pixels + i*dst_row_stride;
+      pixsrc = original_pixels + i*src_row_stride;
+      for (j = 0; j < width; j++)
+        {
+          *pixdest++ = (*pixsrc++ * red_value) >> 8;
+          *pixdest++ = (*pixsrc++ * green_value) >> 8;
+          *pixdest++ = (*pixsrc++ * blue_value) >> 8;
+          if (has_alpha)
+            *pixdest++ = *pixsrc++;
+        }
+    }
+
+  return dest;
+}
 
-	if (ex < bx || ex > (bx+bw) || ey < by || ey > (by+bh)){
-		/* Click wasn't on the icon */
-		return FALSE;
+static void
+cell_renderer_activatable_render (
+    GtkCellRenderer      *cell,
+    GdkWindow            *window,
+    GtkWidget            *widget,
+    GdkRectangle         *background_area,
+    GdkRectangle         *cell_area,
+    GdkRectangle         *expose_area,
+    GtkCellRendererState  flags)
+{
+  GdkPixbuf *pixbuf;
+  GdkPixbuf *invisible = NULL;
+  GdkPixbuf *colorized = NULL;
+  GdkRectangle pix_rect;
+  GdkRectangle draw_rect;
+  GtkStyle *style;
+  gboolean follow_state;
+  cairo_t *cr;
+  int xpad, ypad;
+  EmpathyCellRendererActivatablePriv *priv = GET_PRIV (cell);
+
+  if (priv->show_on_select && !(flags & (GTK_CELL_RENDERER_SELECTED)))
+    return;
+
+  g_object_get (cell,
+      "follow-state", &follow_state,
+      "xpad", &xpad,
+      "ypad", &ypad,
+      "pixbuf", &pixbuf,
+      NULL);
+  style = gtk_widget_get_style (widget);
+
+  gtk_cell_renderer_get_size (cell, widget, cell_area,
+      &pix_rect.x,
+      &pix_rect.y,
+      &pix_rect.width,
+      &pix_rect.height);
+
+  pix_rect.x += cell_area->x + xpad;
+  pix_rect.y += cell_area->y + ypad;
+  pix_rect.width  -= xpad * 2;
+  pix_rect.height -= ypad * 2;
+
+  if (!gdk_rectangle_intersect (cell_area, &pix_rect, &draw_rect) ||
+      !gdk_rectangle_intersect (expose_area, &draw_rect, &draw_rect))
+    return;
+
+  if (GTK_WIDGET_STATE (widget) == GTK_STATE_INSENSITIVE || !cell->sensitive)
+    {
+      GtkIconSource *source;
+
+      source = gtk_icon_source_new ();
+      gtk_icon_source_set_pixbuf (source, pixbuf);
+      /* The size here is arbitrary; since size isn't
+       * wildcarded in the source, it isn't supposed to be
+       * scaled by the engine function
+       */
+      gtk_icon_source_set_size (source, GTK_ICON_SIZE_SMALL_TOOLBAR);
+      gtk_icon_source_set_size_wildcarded (source, FALSE);
+
+      invisible = gtk_style_render_icon (style,
+          source,
+          gtk_widget_get_direction (widget),
+          GTK_STATE_INSENSITIVE,
+          /* arbitrary */
+          (GtkIconSize)-1,
+          widget,
+          "gtkcellrendererpixbuf");
+
+      gtk_icon_source_free (source);
+
+      pixbuf = invisible;
+    }
+  else if (follow_state &&
+      (flags & (GTK_CELL_RENDERER_SELECTED|GTK_CELL_RENDERER_PRELIT)) != 0)
+    {
+      GtkStateType state;
+
+      if ((flags & GTK_CELL_RENDERER_SELECTED) != 0)
+	{
+	  if (GTK_WIDGET_HAS_FOCUS (widget))
+	    state = GTK_STATE_SELECTED;
+	  else
+	    state = GTK_STATE_ACTIVE;
 	}
+      else
+	state = GTK_STATE_PRELIGHT;
 
-	g_signal_emit (activatable, signals[PATH_ACTIVATED], 0, path_string);
+      colorized = create_colorized_pixbuf (pixbuf,
+          &style->base[state]);
 
-	return TRUE;
+      pixbuf = colorized;
+    }
+
+  cr = gdk_cairo_create (window);
+
+  gdk_cairo_set_source_pixbuf (cr, pixbuf, pix_rect.x, pix_rect.y);
+  gdk_cairo_rectangle (cr, &draw_rect);
+  cairo_fill (cr);
+
+  cairo_destroy (cr);
+
+  if (invisible != NULL)
+    g_object_unref (invisible);
+
+  if (colorized != NULL)
+    g_object_unref (colorized);
 }
 
+static void
+empathy_cell_renderer_activatable_class_init (
+    EmpathyCellRendererActivatableClass *klass)
+{
+  GtkCellRendererClass *cell_class;
+  GObjectClass *oclass;
+
+  oclass = G_OBJECT_CLASS (klass);
+  oclass->get_property = cell_renderer_activatable_get_property;
+  oclass->set_property = cell_renderer_activatable_set_property;
+
+  cell_class = GTK_CELL_RENDERER_CLASS (klass);
+  cell_class->activate = cell_renderer_activatable_activate;
+  cell_class->render = cell_renderer_activatable_render;
+
+  signals[PATH_ACTIVATED] =
+    g_signal_new ("path-activated",
+        G_TYPE_FROM_CLASS (klass),
+        G_SIGNAL_RUN_LAST,
+        0,
+        NULL, NULL,
+        g_cclosure_marshal_VOID__STRING,
+        G_TYPE_NONE,
+        1, G_TYPE_STRING);
+
+  g_object_class_install_property (oclass, PROP_SHOW_ON_SELECT,
+      g_param_spec_boolean ("show-on-select",
+          "Show on select",
+          "Whether the cell renderer should be shown only when it's selected",
+          FALSE,
+          G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE));
+
+  g_type_class_add_private (klass,
+      sizeof (EmpathyCellRendererActivatablePriv));
+}
diff --git a/libempathy-gtk/empathy-cell-renderer-activatable.h b/libempathy-gtk/empathy-cell-renderer-activatable.h
index d58a082..b4564ee 100644
--- a/libempathy-gtk/empathy-cell-renderer-activatable.h
+++ b/libempathy-gtk/empathy-cell-renderer-activatable.h
@@ -39,6 +39,7 @@ typedef struct _EmpathyCellRendererActivatableClass EmpathyCellRendererActivatab
 
 struct _EmpathyCellRendererActivatable {
   GtkCellRendererPixbuf parent;
+  gpointer priv;
 };
 
 struct _EmpathyCellRendererActivatableClass {



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