]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-cell-renderer-expander.c
Update Simplified Chinese translation.
[empathy.git] / libempathy-gtk / empathy-cell-renderer-expander.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2006-2007 Imendio AB
4  * Copyright (C) 2007-2011 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: Kristian Rietveld <kris@imendio.com>
22  */
23
24 #include <gtk/gtk.h>
25
26 #include <libempathy/empathy-utils.h>
27 #include "empathy-cell-renderer-expander.h"
28
29 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyCellRendererExpander)
30 typedef struct {
31         GtkExpanderStyle     expander_style;
32         gint                 expander_size;
33
34         guint                activatable : 1;
35 } EmpathyCellRendererExpanderPriv;
36
37 enum {
38         PROP_0,
39         PROP_EXPANDER_STYLE,
40         PROP_EXPANDER_SIZE,
41         PROP_ACTIVATABLE
42 };
43
44 static void     empathy_cell_renderer_expander_get_property (GObject                         *object,
45                                                             guint                            param_id,
46                                                             GValue                          *value,
47                                                             GParamSpec                      *pspec);
48 static void     empathy_cell_renderer_expander_set_property (GObject                         *object,
49                                                             guint                            param_id,
50                                                             const GValue                    *value,
51                                                             GParamSpec                      *pspec);
52 static void     empathy_cell_renderer_expander_finalize     (GObject                         *object);
53 static void     empathy_cell_renderer_expander_get_size     (GtkCellRenderer                 *cell,
54                                                             GtkWidget                       *widget,
55                                                             const GdkRectangle              *cell_area,
56                                                             gint                            *x_offset,
57                                                             gint                            *y_offset,
58                                                             gint                            *width,
59                                                             gint                            *height);
60 static void     empathy_cell_renderer_expander_render       (GtkCellRenderer                 *cell,
61                                                             cairo_t *cr,
62                                                             GtkWidget                       *widget,
63                                                             const GdkRectangle              *background_area,
64                                                             const GdkRectangle              *cell_area,
65                                                             GtkCellRendererState             flags);
66 static gboolean empathy_cell_renderer_expander_activate     (GtkCellRenderer                 *cell,
67                                                             GdkEvent                        *event,
68                                                             GtkWidget                       *widget,
69                                                             const gchar                     *path,
70                                                             const GdkRectangle              *background_area,
71                                                             const GdkRectangle              *cell_area,
72                                                             GtkCellRendererState             flags);
73
74 G_DEFINE_TYPE (EmpathyCellRendererExpander, empathy_cell_renderer_expander, GTK_TYPE_CELL_RENDERER)
75
76 static void
77 empathy_cell_renderer_expander_init (EmpathyCellRendererExpander *expander)
78 {
79         EmpathyCellRendererExpanderPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (expander,
80                 EMPATHY_TYPE_CELL_RENDERER_EXPANDER, EmpathyCellRendererExpanderPriv);
81
82         expander->priv = priv;
83         priv->expander_style = GTK_EXPANDER_COLLAPSED;
84         priv->expander_size = 12;
85         priv->activatable = TRUE;
86
87         g_object_set (expander,
88                       "xpad", 2,
89                       "ypad", 2,
90                       "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE,
91                       NULL);
92 }
93
94 static void
95 empathy_cell_renderer_expander_class_init (EmpathyCellRendererExpanderClass *klass)
96 {
97         GObjectClass         *object_class;
98         GtkCellRendererClass *cell_class;
99
100         object_class  = G_OBJECT_CLASS (klass);
101         cell_class = GTK_CELL_RENDERER_CLASS (klass);
102
103         object_class->finalize = empathy_cell_renderer_expander_finalize;
104
105         object_class->get_property = empathy_cell_renderer_expander_get_property;
106         object_class->set_property = empathy_cell_renderer_expander_set_property;
107
108         cell_class->get_size = empathy_cell_renderer_expander_get_size;
109         cell_class->render = empathy_cell_renderer_expander_render;
110         cell_class->activate = empathy_cell_renderer_expander_activate;
111
112         g_object_class_install_property (object_class,
113                                          PROP_EXPANDER_STYLE,
114                                          g_param_spec_enum ("expander-style",
115                                                             "Expander Style",
116                                                             "Style to use when painting the expander",
117                                                             GTK_TYPE_EXPANDER_STYLE,
118                                                             GTK_EXPANDER_COLLAPSED,
119                                                             G_PARAM_READWRITE));
120
121         g_object_class_install_property (object_class,
122                                          PROP_EXPANDER_SIZE,
123                                          g_param_spec_int ("expander-size",
124                                                            "Expander Size",
125                                                            "The size of the expander",
126                                                            0,
127                                                            G_MAXINT,
128                                                            12,
129                                                            G_PARAM_READWRITE));
130
131         g_object_class_install_property (object_class,
132                                          PROP_ACTIVATABLE,
133                                          g_param_spec_boolean ("activatable",
134                                                                "Activatable",
135                                                                "The expander can be activated",
136                                                                TRUE,
137                                                                G_PARAM_READWRITE));
138
139         g_type_class_add_private (object_class, sizeof (EmpathyCellRendererExpanderPriv));
140 }
141
142 static void
143 empathy_cell_renderer_expander_get_property (GObject    *object,
144                                             guint       param_id,
145                                             GValue     *value,
146                                             GParamSpec *pspec)
147 {
148         EmpathyCellRendererExpander     *expander;
149         EmpathyCellRendererExpanderPriv *priv;
150
151         expander = EMPATHY_CELL_RENDERER_EXPANDER (object);
152         priv = GET_PRIV (expander);
153
154         switch (param_id) {
155         case PROP_EXPANDER_STYLE:
156                 g_value_set_enum (value, priv->expander_style);
157                 break;
158
159         case PROP_EXPANDER_SIZE:
160                 g_value_set_int (value, priv->expander_size);
161                 break;
162
163         case PROP_ACTIVATABLE:
164                 g_value_set_boolean (value, priv->activatable);
165                 break;
166
167         default:
168                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
169                 break;
170         }
171 }
172
173 static void
174 empathy_cell_renderer_expander_set_property (GObject      *object,
175                                             guint         param_id,
176                                             const GValue *value,
177                                             GParamSpec   *pspec)
178 {
179         EmpathyCellRendererExpander     *expander;
180         EmpathyCellRendererExpanderPriv *priv;
181
182         expander = EMPATHY_CELL_RENDERER_EXPANDER (object);
183         priv = GET_PRIV (expander);
184
185         switch (param_id) {
186         case PROP_EXPANDER_STYLE:
187                 priv->expander_style = g_value_get_enum (value);
188                 break;
189
190         case PROP_EXPANDER_SIZE:
191                 priv->expander_size = g_value_get_int (value);
192                 break;
193
194         case PROP_ACTIVATABLE:
195                 priv->activatable = g_value_get_boolean (value);
196                 break;
197
198         default:
199                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
200                 break;
201         }
202 }
203
204 static void
205 empathy_cell_renderer_expander_finalize (GObject *object)
206 {
207         EmpathyCellRendererExpanderPriv *priv;
208
209         priv = GET_PRIV (object);
210
211         (* G_OBJECT_CLASS (empathy_cell_renderer_expander_parent_class)->finalize) (object);
212 }
213
214 GtkCellRenderer *
215 empathy_cell_renderer_expander_new (void)
216 {
217         return g_object_new (EMPATHY_TYPE_CELL_RENDERER_EXPANDER, NULL);
218 }
219
220 static void
221 empathy_cell_renderer_expander_get_size (GtkCellRenderer    *cell,
222                                         GtkWidget          *widget,
223                                         const GdkRectangle *cell_area,
224                                         gint               *x_offset,
225                                         gint               *y_offset,
226                                         gint               *width,
227                                         gint               *height)
228 {
229         EmpathyCellRendererExpander     *expander;
230         EmpathyCellRendererExpanderPriv *priv;
231         gfloat xalign, yalign;
232         guint xpad, ypad;
233
234         expander = (EmpathyCellRendererExpander *) cell;
235         priv = GET_PRIV (expander);
236
237         g_object_get (cell,
238                       "xalign", &xalign,
239                       "yalign", &yalign,
240                       "xpad", &xpad,
241                       "ypad", &ypad,
242                       NULL);
243
244         if (cell_area) {
245                 if (x_offset) {
246                         *x_offset = xalign * (cell_area->width - (priv->expander_size + (2 * xpad)));
247                         *x_offset = MAX (*x_offset, 0);
248                 }
249
250                 if (y_offset) {
251                         *y_offset = yalign * (cell_area->height - (priv->expander_size + (2 * ypad)));
252                         *y_offset = MAX (*y_offset, 0);
253                 }
254         } else {
255                 if (x_offset)
256                         *x_offset = 0;
257
258                 if (y_offset)
259                         *y_offset = 0;
260         }
261
262         if (width)
263                 *width = xpad * 2 + priv->expander_size;
264
265         if (height)
266                 *height = ypad * 2 + priv->expander_size;
267 }
268
269 static void
270 empathy_cell_renderer_expander_render (GtkCellRenderer      *cell,
271                                       cairo_t *cr,
272                                       GtkWidget            *widget,
273                                       const GdkRectangle   *background_area,
274                                       const GdkRectangle   *cell_area,
275                                       GtkCellRendererState  flags)
276 {
277         EmpathyCellRendererExpander     *expander;
278         EmpathyCellRendererExpanderPriv *priv;
279         gint                            x_offset, y_offset;
280         guint                           xpad, ypad;
281         GtkStyleContext                 *style;
282
283         expander = (EmpathyCellRendererExpander *) cell;
284         priv = GET_PRIV (expander);
285
286         empathy_cell_renderer_expander_get_size (cell, widget,
287                                                 (GdkRectangle *) cell_area,
288                                                 &x_offset, &y_offset,
289                                                 NULL, NULL);
290
291         g_object_get (cell,
292                       "xpad", &xpad,
293                       "ypad", &ypad,
294                       NULL);
295
296         style = gtk_widget_get_style_context (widget);
297
298         gtk_style_context_save (style);
299
300         if (priv->expander_style == GTK_EXPANDER_COLLAPSED)
301                 gtk_style_context_set_state (style, GTK_STATE_NORMAL);
302         else
303                 gtk_style_context_set_state (style, GTK_STATE_ACTIVE);
304
305         gtk_render_expander (style,
306                              cr,
307                              cell_area->x + x_offset + xpad,
308                              cell_area->y + y_offset + ypad,
309                              priv->expander_size,
310                              priv->expander_size);
311
312         gtk_style_context_restore (style);
313 }
314
315 static gboolean
316 empathy_cell_renderer_expander_activate (GtkCellRenderer      *cell,
317                                         GdkEvent             *event,
318                                         GtkWidget            *widget,
319                                         const gchar          *path_string,
320                                         const GdkRectangle   *background_area,
321                                         const GdkRectangle   *cell_area,
322                                         GtkCellRendererState  flags)
323 {
324         EmpathyCellRendererExpander     *expander;
325         EmpathyCellRendererExpanderPriv *priv;
326         GtkTreePath                    *path;
327
328         expander = EMPATHY_CELL_RENDERER_EXPANDER (cell);
329         priv = GET_PRIV (cell);
330
331         if (!GTK_IS_TREE_VIEW (widget) || !priv->activatable)
332                 return FALSE;
333
334         path = gtk_tree_path_new_from_string (path_string);
335
336         if (gtk_tree_path_get_depth (path) > 1) {
337                 gtk_tree_path_free (path);
338                 return TRUE;
339         }
340
341         if (gtk_tree_view_row_expanded (GTK_TREE_VIEW (widget), path)) {
342                 gtk_tree_view_collapse_row (GTK_TREE_VIEW (widget), path);
343         } else {
344                 gtk_tree_view_expand_row (GTK_TREE_VIEW (widget), path, FALSE);
345         }
346
347         gtk_tree_path_free (path);
348
349         return TRUE;
350 }