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>
25 #include "empathy-cell-renderer-text.h"
27 #include <tp-account-widgets/tpaw-utils.h>
29 #include "empathy-utils.h"
31 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyCellRendererText)
34 TpConnectionPresenceType presence_type
;
44 } EmpathyCellRendererTextPriv
;
46 static void cell_renderer_text_finalize (GObject
*object
);
47 static void cell_renderer_text_get_property (GObject
*object
,
51 static void cell_renderer_text_set_property (GObject
*object
,
55 static void cell_renderer_text_render (GtkCellRenderer
*cell
,
58 const GdkRectangle
*background_area
,
59 const GdkRectangle
*cell_area
,
60 GtkCellRendererState flags
);
61 static void cell_renderer_text_update_text (EmpathyCellRendererText
*cell
,
76 G_DEFINE_TYPE (EmpathyCellRendererText
, empathy_cell_renderer_text
, GTK_TYPE_CELL_RENDERER_TEXT
);
79 cell_renderer_text_get_preferred_height_for_width (GtkCellRenderer
*renderer
,
85 EmpathyCellRendererText
*self
= EMPATHY_CELL_RENDERER_TEXT (renderer
);
86 EmpathyCellRendererTextPriv
*priv
= GET_PRIV (self
);
88 /* Only update if not already valid so we get the right size. */
89 cell_renderer_text_update_text (self
, widget
, priv
->is_selected
);
91 GTK_CELL_RENDERER_CLASS (empathy_cell_renderer_text_parent_class
)->
92 get_preferred_height_for_width (renderer
, widget
, width
,
93 minimum_size
, natural_size
);
98 empathy_cell_renderer_text_class_init (EmpathyCellRendererTextClass
*klass
)
100 GObjectClass
*object_class
;
101 GtkCellRendererClass
*cell_class
;
104 object_class
= G_OBJECT_CLASS (klass
);
105 cell_class
= GTK_CELL_RENDERER_CLASS (klass
);
107 object_class
->finalize
= cell_renderer_text_finalize
;
109 object_class
->get_property
= cell_renderer_text_get_property
;
110 object_class
->set_property
= cell_renderer_text_set_property
;
112 cell_class
->get_preferred_height_for_width
= cell_renderer_text_get_preferred_height_for_width
;
113 cell_class
->render
= cell_renderer_text_render
;
115 spec
= g_param_spec_string ("name", "Name", "Contact name", NULL
,
116 G_PARAM_READWRITE
| G_PARAM_STATIC_STRINGS
);
117 g_object_class_install_property (object_class
, PROP_NAME
, spec
);
119 spec
= g_param_spec_uint ("presence-type", "TpConnectionPresenceType",
120 "The contact's presence type",
121 0, G_MAXUINT
, /* Telepathy enum, can be extended */
122 TP_CONNECTION_PRESENCE_TYPE_UNKNOWN
,
123 G_PARAM_READWRITE
| G_PARAM_STATIC_STRINGS
);
124 g_object_class_install_property (object_class
, PROP_PRESENCE_TYPE
,
127 spec
= g_param_spec_string ("status", "Status message",
128 "Contact's custom status message", NULL
,
129 G_PARAM_READWRITE
| G_PARAM_STATIC_STRINGS
);
130 g_object_class_install_property (object_class
, PROP_STATUS
, spec
);
132 spec
= g_param_spec_boolean ("is-group", "Is group",
133 "Whether this cell is a group", FALSE
,
134 G_PARAM_READWRITE
| G_PARAM_STATIC_STRINGS
);
135 g_object_class_install_property (object_class
, PROP_IS_GROUP
, spec
);
137 spec
= g_param_spec_boolean ("compact", "Compact",
138 "TRUE to show the status alongside the contact name;"
139 "FALSE to show it on its own line",
140 FALSE
, G_PARAM_READWRITE
| G_PARAM_STATIC_STRINGS
);
141 g_object_class_install_property (object_class
, PROP_COMPACT
, spec
);
143 spec
= g_param_spec_boxed ("client-types", "Contact client types",
144 "Client types of the contact",
145 G_TYPE_STRV
, G_PARAM_READWRITE
| G_PARAM_STATIC_STRINGS
);
146 g_object_class_install_property (object_class
, PROP_CLIENT_TYPES
, spec
);
148 g_type_class_add_private (object_class
, sizeof (EmpathyCellRendererTextPriv
));
152 empathy_cell_renderer_text_init (EmpathyCellRendererText
*cell
)
154 EmpathyCellRendererTextPriv
*priv
= G_TYPE_INSTANCE_GET_PRIVATE (cell
,
155 EMPATHY_TYPE_CELL_RENDERER_TEXT
, EmpathyCellRendererTextPriv
);
159 "ellipsize", PANGO_ELLIPSIZE_END
,
162 priv
->name
= g_strdup ("");
163 priv
->status
= g_strdup ("");
164 priv
->compact
= FALSE
;
168 cell_renderer_text_finalize (GObject
*object
)
170 EmpathyCellRendererText
*cell
;
171 EmpathyCellRendererTextPriv
*priv
;
173 cell
= EMPATHY_CELL_RENDERER_TEXT (object
);
174 priv
= GET_PRIV (cell
);
177 g_free (priv
->status
);
178 g_strfreev (priv
->types
);
180 (G_OBJECT_CLASS (empathy_cell_renderer_text_parent_class
)->finalize
) (object
);
184 cell_renderer_text_get_property (GObject
*object
,
189 EmpathyCellRendererText
*cell
;
190 EmpathyCellRendererTextPriv
*priv
;
192 cell
= EMPATHY_CELL_RENDERER_TEXT (object
);
193 priv
= GET_PRIV (cell
);
197 g_value_set_string (value
, priv
->name
);
199 case PROP_PRESENCE_TYPE
:
200 g_value_set_uint (value
, priv
->presence_type
);
203 g_value_set_string (value
, priv
->status
);
206 g_value_set_boolean (value
, priv
->is_group
);
209 g_value_set_boolean (value
, priv
->compact
);
211 case PROP_CLIENT_TYPES
:
212 g_value_set_boxed (value
, priv
->types
);
215 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, param_id
, pspec
);
221 cell_renderer_text_set_property (GObject
*object
,
226 EmpathyCellRendererText
*cell
;
227 EmpathyCellRendererTextPriv
*priv
;
230 cell
= EMPATHY_CELL_RENDERER_TEXT (object
);
231 priv
= GET_PRIV (cell
);
236 str
= g_value_get_string (value
);
237 priv
->name
= g_strdup (str
? str
: "");
238 g_strdelimit (priv
->name
, "\n\r\t", ' ');
239 priv
->is_valid
= FALSE
;
241 case PROP_PRESENCE_TYPE
:
242 priv
->presence_type
= g_value_get_uint (value
);
243 priv
->is_valid
= FALSE
;
246 g_free (priv
->status
);
247 str
= g_value_get_string (value
);
248 priv
->status
= g_strdup (str
? str
: "");
249 g_strdelimit (priv
->status
, "\n\r\t", ' ');
250 priv
->is_valid
= FALSE
;
253 priv
->is_group
= g_value_get_boolean (value
);
254 priv
->is_valid
= FALSE
;
257 priv
->compact
= g_value_get_boolean (value
);
258 priv
->is_valid
= FALSE
;
260 case PROP_CLIENT_TYPES
:
261 g_strfreev (priv
->types
);
262 priv
->types
= g_value_dup_boxed (value
);
263 priv
->is_valid
= FALSE
;
266 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, param_id
, pspec
);
272 cell_renderer_text_render (GtkCellRenderer
*cell
,
275 const GdkRectangle
*background_area
,
276 const GdkRectangle
*cell_area
,
277 GtkCellRendererState flags
)
279 EmpathyCellRendererText
*celltext
;
281 celltext
= EMPATHY_CELL_RENDERER_TEXT (cell
);
283 cell_renderer_text_update_text (celltext
,
285 (flags
& GTK_CELL_RENDERER_SELECTED
));
287 (GTK_CELL_RENDERER_CLASS (empathy_cell_renderer_text_parent_class
)->render
) (
296 cell_renderer_text_update_text (EmpathyCellRendererText
*cell
,
300 EmpathyCellRendererTextPriv
*priv
;
301 PangoFontDescription
*font_desc
;
302 PangoAttrList
*attr_list
;
303 PangoAttribute
*attr_color
= NULL
, *attr_size
;
304 GtkStyleContext
*style
;
308 priv
= GET_PRIV (cell
);
310 if (priv
->is_valid
&& priv
->is_selected
== selected
) {
314 if (priv
->is_group
) {
317 "weight", PANGO_WEIGHT_BOLD
,
324 priv
->is_selected
= selected
;
325 priv
->is_valid
= TRUE
;
329 style
= gtk_widget_get_style_context (widget
);
331 attr_list
= pango_attr_list_new ();
333 gtk_style_context_save (style
);
335 gtk_style_context_set_state (style
, GTK_STATE_FLAG_NORMAL
);
336 gtk_style_context_get (style
, GTK_STATE_FLAG_NORMAL
,
340 font_size
= pango_font_description_get_size (font_desc
);
341 pango_font_description_free (font_desc
);
342 attr_size
= pango_attr_size_new (font_size
/ 1.2);
343 attr_size
->start_index
= strlen (priv
->name
) + 1;
344 attr_size
->end_index
= -1;
345 pango_attr_list_insert (attr_list
, attr_size
);
350 gtk_style_context_get_color (style
, GTK_STATE_FLAG_NORMAL
, &color
);
352 attr_color
= pango_attr_foreground_new (color
.red
* 0xffff,
353 color
.green
* 0xffff,
354 color
.blue
* 0xffff);
355 attr_color
->start_index
= attr_size
->start_index
;
356 attr_color
->end_index
= -1;
357 pango_attr_list_insert (attr_list
, attr_color
);
360 gtk_style_context_restore (style
);
363 if (TPAW_STR_EMPTY (priv
->status
)) {
364 str
= g_strdup (priv
->name
);
366 str
= g_strdup_printf ("%s %s", priv
->name
, priv
->status
);
369 const gchar
*status
= priv
->status
;
370 gboolean on_a_phone
= FALSE
;
372 if (TPAW_STR_EMPTY (priv
->status
)) {
373 status
= empathy_presence_get_default_message (priv
->presence_type
);
376 if (!priv
->is_group
&&
377 empathy_client_types_contains_mobile_device (priv
->types
)) {
379 /* We want the phone black. */
381 attr_color
->start_index
+= 3;
385 str
= g_strdup (priv
->name
);
387 str
= g_strdup_printf ("%s\n%s%s", priv
->name
,
388 on_a_phone
? "☎ " : "",
394 "weight", PANGO_WEIGHT_NORMAL
,
396 "attributes", attr_list
,
402 pango_attr_list_unref (attr_list
);
404 priv
->is_selected
= selected
;
405 priv
->is_valid
= TRUE
;
409 empathy_cell_renderer_text_new (void)
411 return g_object_new (EMPATHY_TYPE_CELL_RENDERER_TEXT
, NULL
);