]> git.0d.be Git - empathy.git/blobdiff - libempathy-gtk/empathy-cell-renderer-text.c
use the 48x48 version of the local-xmpp icon
[empathy.git] / libempathy-gtk / empathy-cell-renderer-text.c
index e3dd27d30cc861a1aececc434253792036e5b0a4..d52abb4851fcc434b25be04cec0cedcc8e0fcadc 100644 (file)
@@ -1,6 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
  * Copyright (C) 2004-2007 Imendio AB
+ * Copyright (C) 2010 Collabora Ltd
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyCellRendererText)
 typedef struct {
        gchar    *name;
+       TpConnectionPresenceType presence_type;
        gchar    *status;
        gboolean  is_group;
 
        gboolean  is_valid;
        gboolean  is_selected;
 
-       gboolean  show_status;
+       gchar   **types;
+
+       gboolean  compact;
 } EmpathyCellRendererTextPriv;
 
 static void cell_renderer_text_finalize          (GObject                     *object);
@@ -48,19 +52,11 @@ static void cell_renderer_text_set_property      (GObject                     *o
                                                  guint                        param_id,
                                                  const GValue                *value,
                                                  GParamSpec                  *pspec);
-static void cell_renderer_text_get_size          (GtkCellRenderer             *cell,
-                                                 GtkWidget                   *widget,
-                                                 GdkRectangle                *cell_area,
-                                                 gint                        *x_offset,
-                                                 gint                        *y_offset,
-                                                 gint                        *width,
-                                                 gint                        *height);
 static void cell_renderer_text_render            (GtkCellRenderer             *cell,
-                                                 GdkDrawable                 *window,
+                                                 cairo_t *cr,
                                                  GtkWidget                   *widget,
-                                                 GdkRectangle                *background_area,
-                                                 GdkRectangle                *cell_area,
-                                                 GdkRectangle                *expose_area,
+                                                 const GdkRectangle          *background_area,
+                                                 const GdkRectangle          *cell_area,
                                                  GtkCellRendererState         flags);
 static void cell_renderer_text_update_text       (EmpathyCellRendererText      *cell,
                                                  GtkWidget                   *widget,
@@ -70,18 +66,40 @@ static void cell_renderer_text_update_text       (EmpathyCellRendererText      *
 enum {
        PROP_0,
        PROP_NAME,
+       PROP_PRESENCE_TYPE,
        PROP_STATUS,
        PROP_IS_GROUP,
-       PROP_SHOW_STATUS,
+       PROP_COMPACT,
+       PROP_CLIENT_TYPES
 };
 
 G_DEFINE_TYPE (EmpathyCellRendererText, empathy_cell_renderer_text, GTK_TYPE_CELL_RENDERER_TEXT);
 
+static void
+cell_renderer_text_get_preferred_height_for_width (GtkCellRenderer *renderer,
+                                                               GtkWidget *widget,
+                                                               gint width,
+                                                               gint *minimum_size,
+                                                               gint *natural_size)
+{
+       EmpathyCellRendererText *self = EMPATHY_CELL_RENDERER_TEXT (renderer);
+       EmpathyCellRendererTextPriv *priv = GET_PRIV (self);
+
+       /* Only update if not already valid so we get the right size. */
+       cell_renderer_text_update_text (self, widget, priv->is_selected);
+
+       GTK_CELL_RENDERER_CLASS (empathy_cell_renderer_text_parent_class)->
+                       get_preferred_height_for_width (renderer, widget, width,
+                                       minimum_size, natural_size);
+}
+
+
 static void
 empathy_cell_renderer_text_class_init (EmpathyCellRendererTextClass *klass)
 {
        GObjectClass         *object_class;
        GtkCellRendererClass *cell_class;
+       GParamSpec           *spec;
 
        object_class = G_OBJECT_CLASS (klass);
        cell_class = GTK_CELL_RENDERER_CLASS (klass);
@@ -91,37 +109,41 @@ empathy_cell_renderer_text_class_init (EmpathyCellRendererTextClass *klass)
        object_class->get_property = cell_renderer_text_get_property;
        object_class->set_property = cell_renderer_text_set_property;
 
-       cell_class->get_size = cell_renderer_text_get_size;
+       cell_class->get_preferred_height_for_width = cell_renderer_text_get_preferred_height_for_width;
        cell_class->render = cell_renderer_text_render;
 
-       g_object_class_install_property (object_class,
-                                        PROP_NAME,
-                                        g_param_spec_string ("name",
-                                                             "Name",
-                                                             "Contact name",
-                                                             NULL,
-                                                             G_PARAM_READWRITE));
-       g_object_class_install_property (object_class,
-                                        PROP_STATUS,
-                                        g_param_spec_string ("status",
-                                                             "Status",
-                                                             "Contact status string",
-                                                             NULL,
-                                                             G_PARAM_READWRITE));
-       g_object_class_install_property (object_class,
-                                        PROP_IS_GROUP,
-                                        g_param_spec_boolean ("is_group",
-                                                              "Is group",
-                                                              "Whether this cell is a group",
-                                                              FALSE,
-                                                              G_PARAM_READWRITE));
-       g_object_class_install_property (object_class,
-                                        PROP_SHOW_STATUS,
-                                        g_param_spec_boolean ("show-status",
-                                                              "Show status",
-                                                              "Whether to show the status line",
-                                                              TRUE,
-                                                              G_PARAM_READWRITE));
+       spec = g_param_spec_string ("name", "Name", "Contact name", NULL,
+               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+       g_object_class_install_property (object_class, PROP_NAME, spec);
+
+       spec = g_param_spec_uint ("presence-type", "TpConnectionPresenceType",
+               "The contact's presence type",
+               0, G_MAXUINT, /* Telepathy enum, can be extended */
+               TP_CONNECTION_PRESENCE_TYPE_UNKNOWN,
+               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+       g_object_class_install_property (object_class, PROP_PRESENCE_TYPE,
+               spec);
+
+       spec = g_param_spec_string ("status", "Status message",
+               "Contact's custom status message", NULL,
+               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+       g_object_class_install_property (object_class, PROP_STATUS, spec);
+
+       spec = g_param_spec_boolean ("is-group", "Is group",
+               "Whether this cell is a group", FALSE,
+               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+       g_object_class_install_property (object_class, PROP_IS_GROUP, spec);
+
+       spec = g_param_spec_boolean ("compact", "Compact",
+               "TRUE to show the status alongside the contact name;"
+               "FALSE to show it on its own line",
+               FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+       g_object_class_install_property (object_class, PROP_COMPACT, spec);
+
+       spec = g_param_spec_boxed ("client-types", "Contact client types",
+               "Client types of the contact",
+               G_TYPE_STRV, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+       g_object_class_install_property (object_class, PROP_CLIENT_TYPES, spec);
 
        g_type_class_add_private (object_class, sizeof (EmpathyCellRendererTextPriv));
 }
@@ -139,7 +161,7 @@ empathy_cell_renderer_text_init (EmpathyCellRendererText *cell)
 
        priv->name = g_strdup ("");
        priv->status = g_strdup ("");
-       priv->show_status = TRUE;
+       priv->compact = FALSE;
 }
 
 static void
@@ -153,6 +175,7 @@ cell_renderer_text_finalize (GObject *object)
 
        g_free (priv->name);
        g_free (priv->status);
+       g_strfreev (priv->types);
 
        (G_OBJECT_CLASS (empathy_cell_renderer_text_parent_class)->finalize) (object);
 }
@@ -173,14 +196,20 @@ cell_renderer_text_get_property (GObject    *object,
        case PROP_NAME:
                g_value_set_string (value, priv->name);
                break;
+       case PROP_PRESENCE_TYPE:
+               g_value_set_uint (value, priv->presence_type);
+               break;
        case PROP_STATUS:
                g_value_set_string (value, priv->status);
                break;
        case PROP_IS_GROUP:
                g_value_set_boolean (value, priv->is_group);
                break;
-       case PROP_SHOW_STATUS:
-               g_value_set_boolean (value, priv->show_status);
+       case PROP_COMPACT:
+               g_value_set_boolean (value, priv->compact);
+               break;
+       case PROP_CLIENT_TYPES:
+               g_value_set_boxed (value, priv->types);
                break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
@@ -209,6 +238,10 @@ cell_renderer_text_set_property (GObject      *object,
                g_strdelimit (priv->name, "\n\r\t", ' ');
                priv->is_valid = FALSE;
                break;
+       case PROP_PRESENCE_TYPE:
+               priv->presence_type = g_value_get_uint (value);
+               priv->is_valid = FALSE;
+               break;
        case PROP_STATUS:
                g_free (priv->status);
                str = g_value_get_string (value);
@@ -220,8 +253,13 @@ cell_renderer_text_set_property (GObject      *object,
                priv->is_group = g_value_get_boolean (value);
                priv->is_valid = FALSE;
                break;
-       case PROP_SHOW_STATUS:
-               priv->show_status = g_value_get_boolean (value);
+       case PROP_COMPACT:
+               priv->compact = g_value_get_boolean (value);
+               priv->is_valid = FALSE;
+               break;
+       case PROP_CLIENT_TYPES:
+               g_strfreev (priv->types);
+               priv->types = g_value_dup_boxed (value);
                priv->is_valid = FALSE;
                break;
        default:
@@ -230,37 +268,12 @@ cell_renderer_text_set_property (GObject      *object,
        }
 }
 
-static void
-cell_renderer_text_get_size (GtkCellRenderer *cell,
-                            GtkWidget       *widget,
-                            GdkRectangle    *cell_area,
-                            gint            *x_offset,
-                            gint            *y_offset,
-                            gint            *width,
-                            gint            *height)
-{
-       EmpathyCellRendererText     *celltext;
-       EmpathyCellRendererTextPriv *priv;
-
-       celltext = EMPATHY_CELL_RENDERER_TEXT (cell);
-       priv = GET_PRIV (cell);
-
-       /* Only update if not already valid so we get the right size. */
-       cell_renderer_text_update_text (celltext, widget, priv->is_selected);
-
-       (GTK_CELL_RENDERER_CLASS (empathy_cell_renderer_text_parent_class)->get_size) (cell, widget,
-                                                                                     cell_area,
-                                                                                     x_offset, y_offset,
-                                                                                     width, height);
-}
-
 static void
 cell_renderer_text_render (GtkCellRenderer      *cell,
-                          GdkWindow            *window,
+                          cairo_t *cr,
                           GtkWidget            *widget,
-                          GdkRectangle         *background_area,
-                          GdkRectangle         *cell_area,
-                          GdkRectangle         *expose_area,
+                          const GdkRectangle   *background_area,
+                          const GdkRectangle   *cell_area,
                           GtkCellRendererState  flags)
 {
        EmpathyCellRendererText *celltext;
@@ -272,11 +285,11 @@ cell_renderer_text_render (GtkCellRenderer      *cell,
                                        (flags & GTK_CELL_RENDERER_SELECTED));
 
        (GTK_CELL_RENDERER_CLASS (empathy_cell_renderer_text_parent_class)->render) (
-               cell, window,
+               cell, cr,
                widget,
                background_area,
                cell_area,
-               expose_area, flags);
+               flags);
 }
 
 static void
@@ -285,10 +298,12 @@ cell_renderer_text_update_text (EmpathyCellRendererText *cell,
                                gboolean                selected)
 {
        EmpathyCellRendererTextPriv *priv;
+       const PangoFontDescription *font_desc;
        PangoAttrList              *attr_list;
-       PangoAttribute             *attr_color, *attr_size;
-       GtkStyle                   *style;
+       PangoAttribute             *attr_color = NULL, *attr_size;
+       GtkStyleContext            *style;
        gchar                      *str;
+       gint                        font_size;
 
        priv = GET_PRIV (cell);
 
@@ -311,30 +326,58 @@ cell_renderer_text_update_text (EmpathyCellRendererText *cell,
                return;
        }
 
-       style = gtk_widget_get_style (widget);
+       style = gtk_widget_get_style_context (widget);
 
        attr_list = pango_attr_list_new ();
 
-       attr_size = pango_attr_size_new (pango_font_description_get_size (style->font_desc) / 1.2);
+       font_desc = gtk_style_context_get_font (style, GTK_STATE_FLAG_NORMAL);
+       font_size = pango_font_description_get_size (font_desc);
+       attr_size = pango_attr_size_new (font_size / 1.2);
        attr_size->start_index = strlen (priv->name) + 1;
        attr_size->end_index = -1;
        pango_attr_list_insert (attr_list, attr_size);
 
        if (!selected) {
-               GdkColor color;
+               GdkRGBA color;
 
-               color = style->text_aa[GTK_STATE_NORMAL];
+               gtk_style_context_get_color (style, 0, &color);
 
-               attr_color = pango_attr_foreground_new (color.red, color.green, color.blue);
+               attr_color = pango_attr_foreground_new (color.red * 0xffff,
+                                                       color.green * 0xffff,
+                                                       color.blue * 0xffff);
                attr_color->start_index = attr_size->start_index;
                attr_color->end_index = -1;
                pango_attr_list_insert (attr_list, attr_color);
        }
 
-       if (!priv->status || !priv->status[0] || !priv->show_status) {
-               str = g_strdup (priv->name);
+       if (priv->compact) {
+               if (EMP_STR_EMPTY (priv->status)) {
+                       str = g_strdup (priv->name);
+               } else {
+                       str = g_strdup_printf ("%s %s", priv->name, priv->status);
+               }
        } else {
-               str = g_strdup_printf ("%s\n%s", priv->name, priv->status);
+               const gchar *status = priv->status;
+               gboolean on_a_phone = FALSE;
+
+               if (EMP_STR_EMPTY (priv->status)) {
+                       status = empathy_presence_get_default_message (priv->presence_type);
+               }
+
+               if (!priv->is_group && priv->types != NULL && g_strv_length (priv->types) > 0
+                   && !tp_strdiff (priv->types[0], "phone")) {
+                       on_a_phone = TRUE;
+                       /* We want the phone black. */
+                       if (attr_color)
+                               attr_color->start_index += 3;
+               }
+
+               if (status == NULL)
+                       str = g_strdup (priv->name);
+               else
+                       str = g_strdup_printf ("%s\n%s%s", priv->name,
+                                              on_a_phone ? "☎  " : "",
+                                              status);
        }
 
        g_object_set (cell,