1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2004-2007 Imendio AB
4 * Copyright (C) 2010 Collabora Ltd
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301 USA
21 * Authors: Mikael Hallendal <micke@imendio.com>
26 #include "libempathy/empathy-utils.h"
27 #include "empathy-cell-renderer-text.h"
29 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyCellRendererText)
32 TpConnectionPresenceType presence_type;
42 } EmpathyCellRendererTextPriv;
44 static void cell_renderer_text_finalize (GObject *object);
45 static void cell_renderer_text_get_property (GObject *object,
49 static void cell_renderer_text_set_property (GObject *object,
53 static void cell_renderer_text_render (GtkCellRenderer *cell,
56 const GdkRectangle *background_area,
57 const GdkRectangle *cell_area,
58 GtkCellRendererState flags);
59 static void cell_renderer_text_update_text (EmpathyCellRendererText *cell,
74 G_DEFINE_TYPE (EmpathyCellRendererText, empathy_cell_renderer_text, GTK_TYPE_CELL_RENDERER_TEXT);
77 cell_renderer_text_get_preferred_height_for_width (GtkCellRenderer *renderer,
83 EmpathyCellRendererText *self = EMPATHY_CELL_RENDERER_TEXT (renderer);
84 EmpathyCellRendererTextPriv *priv = GET_PRIV (self);
86 /* Only update if not already valid so we get the right size. */
87 cell_renderer_text_update_text (self, widget, priv->is_selected);
89 GTK_CELL_RENDERER_CLASS (empathy_cell_renderer_text_parent_class)->
90 get_preferred_height_for_width (renderer, widget, width,
91 minimum_size, natural_size);
96 empathy_cell_renderer_text_class_init (EmpathyCellRendererTextClass *klass)
98 GObjectClass *object_class;
99 GtkCellRendererClass *cell_class;
102 object_class = G_OBJECT_CLASS (klass);
103 cell_class = GTK_CELL_RENDERER_CLASS (klass);
105 object_class->finalize = cell_renderer_text_finalize;
107 object_class->get_property = cell_renderer_text_get_property;
108 object_class->set_property = cell_renderer_text_set_property;
110 cell_class->get_preferred_height_for_width = cell_renderer_text_get_preferred_height_for_width;
111 cell_class->render = cell_renderer_text_render;
113 spec = g_param_spec_string ("name", "Name", "Contact name", NULL,
114 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
115 g_object_class_install_property (object_class, PROP_NAME, spec);
117 spec = g_param_spec_uint ("presence-type", "TpConnectionPresenceType",
118 "The contact's presence type",
119 0, G_MAXUINT, /* Telepathy enum, can be extended */
120 TP_CONNECTION_PRESENCE_TYPE_UNKNOWN,
121 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
122 g_object_class_install_property (object_class, PROP_PRESENCE_TYPE,
125 spec = g_param_spec_string ("status", "Status message",
126 "Contact's custom status message", NULL,
127 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
128 g_object_class_install_property (object_class, PROP_STATUS, spec);
130 spec = g_param_spec_boolean ("is-group", "Is group",
131 "Whether this cell is a group", FALSE,
132 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
133 g_object_class_install_property (object_class, PROP_IS_GROUP, spec);
135 spec = g_param_spec_boolean ("compact", "Compact",
136 "TRUE to show the status alongside the contact name;"
137 "FALSE to show it on its own line",
138 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
139 g_object_class_install_property (object_class, PROP_COMPACT, spec);
141 spec = g_param_spec_boxed ("client-types", "Contact client types",
142 "Client types of the contact",
143 G_TYPE_STRV, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
144 g_object_class_install_property (object_class, PROP_CLIENT_TYPES, spec);
146 g_type_class_add_private (object_class, sizeof (EmpathyCellRendererTextPriv));
150 empathy_cell_renderer_text_init (EmpathyCellRendererText *cell)
152 EmpathyCellRendererTextPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (cell,
153 EMPATHY_TYPE_CELL_RENDERER_TEXT, EmpathyCellRendererTextPriv);
157 "ellipsize", PANGO_ELLIPSIZE_END,
160 priv->name = g_strdup ("");
161 priv->status = g_strdup ("");
162 priv->compact = FALSE;
166 cell_renderer_text_finalize (GObject *object)
168 EmpathyCellRendererText *cell;
169 EmpathyCellRendererTextPriv *priv;
171 cell = EMPATHY_CELL_RENDERER_TEXT (object);
172 priv = GET_PRIV (cell);
175 g_free (priv->status);
176 g_strfreev (priv->types);
178 (G_OBJECT_CLASS (empathy_cell_renderer_text_parent_class)->finalize) (object);
182 cell_renderer_text_get_property (GObject *object,
187 EmpathyCellRendererText *cell;
188 EmpathyCellRendererTextPriv *priv;
190 cell = EMPATHY_CELL_RENDERER_TEXT (object);
191 priv = GET_PRIV (cell);
195 g_value_set_string (value, priv->name);
197 case PROP_PRESENCE_TYPE:
198 g_value_set_uint (value, priv->presence_type);
201 g_value_set_string (value, priv->status);
204 g_value_set_boolean (value, priv->is_group);
207 g_value_set_boolean (value, priv->compact);
209 case PROP_CLIENT_TYPES:
210 g_value_set_boxed (value, priv->types);
213 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
219 cell_renderer_text_set_property (GObject *object,
224 EmpathyCellRendererText *cell;
225 EmpathyCellRendererTextPriv *priv;
228 cell = EMPATHY_CELL_RENDERER_TEXT (object);
229 priv = GET_PRIV (cell);
234 str = g_value_get_string (value);
235 priv->name = g_strdup (str ? str : "");
236 g_strdelimit (priv->name, "\n\r\t", ' ');
237 priv->is_valid = FALSE;
239 case PROP_PRESENCE_TYPE:
240 priv->presence_type = g_value_get_uint (value);
241 priv->is_valid = FALSE;
244 g_free (priv->status);
245 str = g_value_get_string (value);
246 priv->status = g_strdup (str ? str : "");
247 g_strdelimit (priv->status, "\n\r\t", ' ');
248 priv->is_valid = FALSE;
251 priv->is_group = g_value_get_boolean (value);
252 priv->is_valid = FALSE;
255 priv->compact = g_value_get_boolean (value);
256 priv->is_valid = FALSE;
258 case PROP_CLIENT_TYPES:
259 g_strfreev (priv->types);
260 priv->types = g_value_dup_boxed (value);
261 priv->is_valid = FALSE;
264 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
270 cell_renderer_text_render (GtkCellRenderer *cell,
273 const GdkRectangle *background_area,
274 const GdkRectangle *cell_area,
275 GtkCellRendererState flags)
277 EmpathyCellRendererText *celltext;
279 celltext = EMPATHY_CELL_RENDERER_TEXT (cell);
281 cell_renderer_text_update_text (celltext,
283 (flags & GTK_CELL_RENDERER_SELECTED));
285 (GTK_CELL_RENDERER_CLASS (empathy_cell_renderer_text_parent_class)->render) (
294 cell_renderer_text_update_text (EmpathyCellRendererText *cell,
298 EmpathyCellRendererTextPriv *priv;
299 const PangoFontDescription *font_desc;
300 PangoAttrList *attr_list;
301 PangoAttribute *attr_color = NULL, *attr_size;
302 GtkStyleContext *style;
306 priv = GET_PRIV (cell);
308 if (priv->is_valid && priv->is_selected == selected) {
312 if (priv->is_group) {
315 "weight", PANGO_WEIGHT_BOLD,
322 priv->is_selected = selected;
323 priv->is_valid = TRUE;
327 style = gtk_widget_get_style_context (widget);
329 attr_list = pango_attr_list_new ();
331 font_desc = gtk_style_context_get_font (style, GTK_STATE_FLAG_NORMAL);
332 font_size = pango_font_description_get_size (font_desc);
333 attr_size = pango_attr_size_new (font_size / 1.2);
334 attr_size->start_index = strlen (priv->name) + 1;
335 attr_size->end_index = -1;
336 pango_attr_list_insert (attr_list, attr_size);
341 gtk_style_context_get_color (style, 0, &color);
343 attr_color = pango_attr_foreground_new (color.red * 0xffff,
344 color.green * 0xffff,
345 color.blue * 0xffff);
346 attr_color->start_index = attr_size->start_index;
347 attr_color->end_index = -1;
348 pango_attr_list_insert (attr_list, attr_color);
352 if (EMP_STR_EMPTY (priv->status)) {
353 str = g_strdup (priv->name);
355 str = g_strdup_printf ("%s %s", priv->name, priv->status);
358 const gchar *status = priv->status;
359 gboolean on_a_phone = FALSE;
361 if (EMP_STR_EMPTY (priv->status)) {
362 status = empathy_presence_get_default_message (priv->presence_type);
365 if (!priv->is_group &&
366 empathy_client_types_contains_mobile_device (priv->types)) {
368 /* We want the phone black. */
370 attr_color->start_index += 3;
374 str = g_strdup (priv->name);
376 str = g_strdup_printf ("%s\n%s%s", priv->name,
377 on_a_phone ? "☎ " : "",
383 "weight", PANGO_WEIGHT_NORMAL,
385 "attributes", attr_list,
391 pango_attr_list_unref (attr_list);
393 priv->is_selected = selected;
394 priv->is_valid = TRUE;
398 empathy_cell_renderer_text_new (void)
400 return g_object_new (EMPATHY_TYPE_CELL_RENDERER_TEXT, NULL);