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