]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-cell-renderer-text.c
Use a temporary variable for param specs
[empathy.git] / libempathy-gtk / empathy-cell-renderer-text.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2004-2007 Imendio AB
4  * Copyright (C) 2010 Collabora Ltd
5  *
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.
10  *
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.
15  *
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
20  *
21  * Authors: Mikael Hallendal <micke@imendio.com>
22  */
23
24 #include "config.h"
25
26 #include <string.h>
27
28 #include <libempathy/empathy-utils.h>
29 #include "empathy-cell-renderer-text.h"
30
31 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyCellRendererText)
32 typedef struct {
33         gchar    *name;
34         gchar    *status;
35         gboolean  is_group;
36
37         gboolean  is_valid;
38         gboolean  is_selected;
39
40         gboolean  show_status;
41 } EmpathyCellRendererTextPriv;
42
43 static void cell_renderer_text_finalize          (GObject                     *object);
44 static void cell_renderer_text_get_property      (GObject                     *object,
45                                                   guint                        param_id,
46                                                   GValue                      *value,
47                                                   GParamSpec                  *pspec);
48 static void cell_renderer_text_set_property      (GObject                     *object,
49                                                   guint                        param_id,
50                                                   const GValue                *value,
51                                                   GParamSpec                  *pspec);
52 static void cell_renderer_text_get_size          (GtkCellRenderer             *cell,
53                                                   GtkWidget                   *widget,
54                                                   GdkRectangle                *cell_area,
55                                                   gint                        *x_offset,
56                                                   gint                        *y_offset,
57                                                   gint                        *width,
58                                                   gint                        *height);
59 static void cell_renderer_text_render            (GtkCellRenderer             *cell,
60                                                   GdkDrawable                 *window,
61                                                   GtkWidget                   *widget,
62                                                   GdkRectangle                *background_area,
63                                                   GdkRectangle                *cell_area,
64                                                   GdkRectangle                *expose_area,
65                                                   GtkCellRendererState         flags);
66 static void cell_renderer_text_update_text       (EmpathyCellRendererText      *cell,
67                                                   GtkWidget                   *widget,
68                                                   gboolean                     selected);
69
70 /* Properties */
71 enum {
72         PROP_0,
73         PROP_NAME,
74         PROP_STATUS,
75         PROP_IS_GROUP,
76         PROP_SHOW_STATUS,
77 };
78
79 G_DEFINE_TYPE (EmpathyCellRendererText, empathy_cell_renderer_text, GTK_TYPE_CELL_RENDERER_TEXT);
80
81 static void
82 empathy_cell_renderer_text_class_init (EmpathyCellRendererTextClass *klass)
83 {
84         GObjectClass         *object_class;
85         GtkCellRendererClass *cell_class;
86         GParamSpec           *spec;
87
88         object_class = G_OBJECT_CLASS (klass);
89         cell_class = GTK_CELL_RENDERER_CLASS (klass);
90
91         object_class->finalize = cell_renderer_text_finalize;
92
93         object_class->get_property = cell_renderer_text_get_property;
94         object_class->set_property = cell_renderer_text_set_property;
95
96         cell_class->get_size = cell_renderer_text_get_size;
97         cell_class->render = cell_renderer_text_render;
98
99         spec = g_param_spec_string ("name", "Name", "Contact name", NULL,
100                 G_PARAM_READWRITE);
101         g_object_class_install_property (object_class, PROP_NAME, spec);
102
103         spec = g_param_spec_string ("status", "Status",
104                 "Contact status string", NULL, G_PARAM_READWRITE);
105         g_object_class_install_property (object_class, PROP_STATUS, spec);
106
107         spec = g_param_spec_boolean ("is_group", "Is group",
108                 "Whether this cell is a group", FALSE, G_PARAM_READWRITE);
109         g_object_class_install_property (object_class, PROP_IS_GROUP, spec);
110
111         spec = g_param_spec_boolean ("show-status", "Show status",
112                 "Whether to show the status line", TRUE, G_PARAM_READWRITE);
113         g_object_class_install_property (object_class, PROP_SHOW_STATUS, spec);
114
115         g_type_class_add_private (object_class, sizeof (EmpathyCellRendererTextPriv));
116 }
117
118 static void
119 empathy_cell_renderer_text_init (EmpathyCellRendererText *cell)
120 {
121         EmpathyCellRendererTextPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (cell,
122                 EMPATHY_TYPE_CELL_RENDERER_TEXT, EmpathyCellRendererTextPriv);
123
124         cell->priv = priv;
125         g_object_set (cell,
126                       "ellipsize", PANGO_ELLIPSIZE_END,
127                       NULL);
128
129         priv->name = g_strdup ("");
130         priv->status = g_strdup ("");
131         priv->show_status = TRUE;
132 }
133
134 static void
135 cell_renderer_text_finalize (GObject *object)
136 {
137         EmpathyCellRendererText     *cell;
138         EmpathyCellRendererTextPriv *priv;
139
140         cell = EMPATHY_CELL_RENDERER_TEXT (object);
141         priv = GET_PRIV (cell);
142
143         g_free (priv->name);
144         g_free (priv->status);
145
146         (G_OBJECT_CLASS (empathy_cell_renderer_text_parent_class)->finalize) (object);
147 }
148
149 static void
150 cell_renderer_text_get_property (GObject    *object,
151                                  guint       param_id,
152                                  GValue     *value,
153                                  GParamSpec *pspec)
154 {
155         EmpathyCellRendererText     *cell;
156         EmpathyCellRendererTextPriv *priv;
157
158         cell = EMPATHY_CELL_RENDERER_TEXT (object);
159         priv = GET_PRIV (cell);
160
161         switch (param_id) {
162         case PROP_NAME:
163                 g_value_set_string (value, priv->name);
164                 break;
165         case PROP_STATUS:
166                 g_value_set_string (value, priv->status);
167                 break;
168         case PROP_IS_GROUP:
169                 g_value_set_boolean (value, priv->is_group);
170                 break;
171         case PROP_SHOW_STATUS:
172                 g_value_set_boolean (value, priv->show_status);
173                 break;
174         default:
175                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
176                 break;
177         }
178 }
179
180 static void
181 cell_renderer_text_set_property (GObject      *object,
182                                  guint         param_id,
183                                  const GValue *value,
184                                  GParamSpec   *pspec)
185 {
186         EmpathyCellRendererText     *cell;
187         EmpathyCellRendererTextPriv *priv;
188         const gchar                *str;
189
190         cell = EMPATHY_CELL_RENDERER_TEXT (object);
191         priv = GET_PRIV (cell);
192
193         switch (param_id) {
194         case PROP_NAME:
195                 g_free (priv->name);
196                 str = g_value_get_string (value);
197                 priv->name = g_strdup (str ? str : "");
198                 g_strdelimit (priv->name, "\n\r\t", ' ');
199                 priv->is_valid = FALSE;
200                 break;
201         case PROP_STATUS:
202                 g_free (priv->status);
203                 str = g_value_get_string (value);
204                 priv->status = g_strdup (str ? str : "");
205                 g_strdelimit (priv->status, "\n\r\t", ' ');
206                 priv->is_valid = FALSE;
207                 break;
208         case PROP_IS_GROUP:
209                 priv->is_group = g_value_get_boolean (value);
210                 priv->is_valid = FALSE;
211                 break;
212         case PROP_SHOW_STATUS:
213                 priv->show_status = g_value_get_boolean (value);
214                 priv->is_valid = FALSE;
215                 break;
216         default:
217                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
218                 break;
219         }
220 }
221
222 static void
223 cell_renderer_text_get_size (GtkCellRenderer *cell,
224                              GtkWidget       *widget,
225                              GdkRectangle    *cell_area,
226                              gint            *x_offset,
227                              gint            *y_offset,
228                              gint            *width,
229                              gint            *height)
230 {
231         EmpathyCellRendererText     *celltext;
232         EmpathyCellRendererTextPriv *priv;
233
234         celltext = EMPATHY_CELL_RENDERER_TEXT (cell);
235         priv = GET_PRIV (cell);
236
237         /* Only update if not already valid so we get the right size. */
238         cell_renderer_text_update_text (celltext, widget, priv->is_selected);
239
240         (GTK_CELL_RENDERER_CLASS (empathy_cell_renderer_text_parent_class)->get_size) (cell, widget,
241                                                                                       cell_area,
242                                                                                       x_offset, y_offset,
243                                                                                       width, height);
244 }
245
246 static void
247 cell_renderer_text_render (GtkCellRenderer      *cell,
248                            GdkWindow            *window,
249                            GtkWidget            *widget,
250                            GdkRectangle         *background_area,
251                            GdkRectangle         *cell_area,
252                            GdkRectangle         *expose_area,
253                            GtkCellRendererState  flags)
254 {
255         EmpathyCellRendererText *celltext;
256
257         celltext = EMPATHY_CELL_RENDERER_TEXT (cell);
258
259         cell_renderer_text_update_text (celltext,
260                                         widget,
261                                         (flags & GTK_CELL_RENDERER_SELECTED));
262
263         (GTK_CELL_RENDERER_CLASS (empathy_cell_renderer_text_parent_class)->render) (
264                 cell, window,
265                 widget,
266                 background_area,
267                 cell_area,
268                 expose_area, flags);
269 }
270
271 static void
272 cell_renderer_text_update_text (EmpathyCellRendererText *cell,
273                                 GtkWidget              *widget,
274                                 gboolean                selected)
275 {
276         EmpathyCellRendererTextPriv *priv;
277         PangoAttrList              *attr_list;
278         PangoAttribute             *attr_color, *attr_size;
279         GtkStyle                   *style;
280         gchar                      *str;
281
282         priv = GET_PRIV (cell);
283
284         if (priv->is_valid && priv->is_selected == selected) {
285                 return;
286         }
287
288         if (priv->is_group) {
289                 g_object_set (cell,
290                               "visible", TRUE,
291                               "weight", PANGO_WEIGHT_BOLD,
292                               "text", priv->name,
293                               "attributes", NULL,
294                               "xpad", 1,
295                               "ypad", 1,
296                               NULL);
297
298                 priv->is_selected = selected;
299                 priv->is_valid = TRUE;
300                 return;
301         }
302
303         style = gtk_widget_get_style (widget);
304
305         attr_list = pango_attr_list_new ();
306
307         attr_size = pango_attr_size_new (pango_font_description_get_size (style->font_desc) / 1.2);
308         attr_size->start_index = strlen (priv->name) + 1;
309         attr_size->end_index = -1;
310         pango_attr_list_insert (attr_list, attr_size);
311
312         if (!selected) {
313                 GdkColor color;
314
315                 color = style->text_aa[GTK_STATE_NORMAL];
316
317                 attr_color = pango_attr_foreground_new (color.red, color.green, color.blue);
318                 attr_color->start_index = attr_size->start_index;
319                 attr_color->end_index = -1;
320                 pango_attr_list_insert (attr_list, attr_color);
321         }
322
323         if (!priv->status || !priv->status[0] || !priv->show_status) {
324                 str = g_strdup (priv->name);
325         } else {
326                 str = g_strdup_printf ("%s\n%s", priv->name, priv->status);
327         }
328
329         g_object_set (cell,
330                       "visible", TRUE,
331                       "weight", PANGO_WEIGHT_NORMAL,
332                       "text", str,
333                       "attributes", attr_list,
334                       "xpad", 0,
335                       "ypad", 1,
336                       NULL);
337
338         g_free (str);
339         pango_attr_list_unref (attr_list);
340
341         priv->is_selected = selected;
342         priv->is_valid = TRUE;
343 }
344
345 GtkCellRenderer *
346 empathy_cell_renderer_text_new (void)
347 {
348         return g_object_new (EMPATHY_TYPE_CELL_RENDERER_TEXT, NULL);
349 }