root/trunk/src/modest-widgets/modest-vbox-cell-renderer.c

Revision 47 (checked in by pvanhoof, 1 year ago)

2007-11-06 Philip Van Hoof <pvanhoof@gnome.org>

        • The rows of the TMutFolderView are now a bit more nice. Code reused

from the Modest project.

        • The date-to-string function now takes into account today, and

displays just the time if we're trying to display a date/time of today.

Line 
1 /* Copyright (c) 2007, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include <config.h>
31
32 #include <glib/gi18n-lib.h>
33
34 #include <gtk/gtkwidget.h>
35
36 #include <modest-vbox-cell-renderer.h>
37
38 #define RENDERER_EXPAND_ATTRIBUTE "box-expand"
39
40 static GObjectClass *parent_class = NULL;
41
42
43 typedef struct _ModestVBoxCellRendererPrivate ModestVBoxCellRendererPrivate;
44
45 struct _ModestVBoxCellRendererPrivate
46 {
47         GList *renderers_list;
48 };
49
50 #define MODEST_VBOX_CELL_RENDERER_GET_PRIVATE(o)        \
51         (G_TYPE_INSTANCE_GET_PRIVATE ((o), MODEST_TYPE_VBOX_CELL_RENDERER, ModestVBoxCellRendererPrivate))
52
53 /* static guint signals[LAST_SIGNAL] = {0}; */
54
55 /* static functions: GObject */
56 static void modest_vbox_cell_renderer_instance_init (GTypeInstance *instance, gpointer g_class);
57 static void modest_vbox_cell_renderer_finalize (GObject *object);
58 static void modest_vbox_cell_renderer_class_init (ModestVBoxCellRendererClass *klass);
59
60 /* static functions: GtkCellRenderer */
61 static void modest_vbox_cell_renderer_get_size     (GtkCellRenderer       *cell,
62                                                     GtkWidget             *widget,
63                                                     GdkRectangle          *rectangle,
64                                                     gint                  *x_offset,
65                                                     gint                  *y_offset,
66                                                     gint                  *width,
67                                                     gint                  *height);
68 static void modest_vbox_cell_renderer_render       (GtkCellRenderer       *cell,
69                                                     GdkDrawable           *window,
70                                                     GtkWidget             *widget,
71                                                     GdkRectangle          *background_area,
72                                                     GdkRectangle          *cell_area,
73                                                     GdkRectangle          *expose_area,
74                                                     GtkCellRendererState  flags);
75                                                
76
77 /**
78  * modest_vbox_cell_renderer_new:
79  *
80  * Return value: a new #ModestVBoxCellRenderer instance implemented for Gtk+
81  **/
82 GtkCellRenderer*
83 modest_vbox_cell_renderer_new (void)
84 {
85         ModestVBoxCellRenderer *self = g_object_new (MODEST_TYPE_VBOX_CELL_RENDERER, NULL);
86
87         return GTK_CELL_RENDERER (self);
88 }
89
90 static void
91 modest_vbox_cell_renderer_instance_init (GTypeInstance *instance, gpointer g_class)
92 {
93         ModestVBoxCellRendererPrivate *priv = MODEST_VBOX_CELL_RENDERER_GET_PRIVATE (instance);
94
95         priv->renderers_list = NULL;
96        
97         return;
98 }
99
100 static void
101 modest_vbox_cell_renderer_finalize (GObject *object)
102 {
103         ModestVBoxCellRendererPrivate *priv = MODEST_VBOX_CELL_RENDERER_GET_PRIVATE (object);
104
105         if (priv->renderers_list != NULL) {
106                 g_list_foreach (priv->renderers_list, (GFunc) g_object_unref, NULL);
107                 g_list_free (priv->renderers_list);
108                 priv->renderers_list = NULL;
109         }
110
111         (*parent_class->finalize) (object);
112
113         return;
114 }
115
116 static void
117 modest_vbox_cell_renderer_class_init (ModestVBoxCellRendererClass *klass)
118 {
119         GObjectClass *object_class;
120         GtkCellRendererClass *renderer_class;
121
122         parent_class = g_type_class_peek_parent (klass);
123         object_class = (GObjectClass*) klass;
124         renderer_class = (GtkCellRendererClass*) klass;
125
126         object_class->finalize = modest_vbox_cell_renderer_finalize;
127         renderer_class->get_size = modest_vbox_cell_renderer_get_size;
128         renderer_class->render = modest_vbox_cell_renderer_render;
129
130         g_type_class_add_private (object_class, sizeof (ModestVBoxCellRendererPrivate));
131
132         return;
133 }
134
135 GType
136 modest_vbox_cell_renderer_get_type (void)
137 {
138         static GType type = 0;
139
140         if (G_UNLIKELY(type == 0))
141         {
142                 static const GTypeInfo info =
143                 {
144                   sizeof (ModestVBoxCellRendererClass),
145                   NULL,   /* base_init */
146                   NULL,   /* base_finalize */
147                   (GClassInitFunc) modest_vbox_cell_renderer_class_init,   /* class_init */
148                   NULL,   /* class_finalize */
149                   NULL,   /* class_data */
150                   sizeof (ModestVBoxCellRenderer),
151                   0,      /* n_preallocs */
152                   modest_vbox_cell_renderer_instance_init    /* instance_init */
153                 };
154
155                 type = g_type_register_static (GTK_TYPE_CELL_RENDERER,
156                         "ModestVBoxCellRenderer",
157                         &info, 0);
158
159         }
160
161         return type;
162 }
163
164
165 /**
166  * modest_vbox_cell_renderer_append:
167  * @vbox_renderer: a #ModestVBoxCellRenderer
168  * @cell: a #GtkCellRenderer
169  *
170  * Appends @cell to the end of the list of renderers shown in @vbox_renderer
171  */
172 void 
173 modest_vbox_cell_renderer_append (ModestVBoxCellRenderer *vbox_renderer,
174                                   GtkCellRenderer *cell,
175                                   gboolean expand)
176 {
177         ModestVBoxCellRendererPrivate *priv = MODEST_VBOX_CELL_RENDERER_GET_PRIVATE (vbox_renderer);
178        
179         priv->renderers_list = g_list_append (priv->renderers_list, cell);
180         g_object_set_data (G_OBJECT (cell), RENDERER_EXPAND_ATTRIBUTE, GINT_TO_POINTER (expand));
181
182 #if GLIB_CHECK_VERSION(2, 10, 0) /* g_object_ref_sink() was added in glib 2.10: */
183         g_object_ref_sink (G_OBJECT (cell));
184 #else
185         g_object_ref (G_OBJECT (cell));
186         gtk_object_sink (GTK_OBJECT (cell));
187 #endif
188 }
189
190 static void
191 modest_vbox_cell_renderer_get_size     (GtkCellRenderer       *cell,
192                                         GtkWidget             *widget,
193                                         GdkRectangle          *rectangle,
194                                         gint                  *x_offset,
195                                         gint                  *y_offset,
196                                         gint                  *width,
197                                         gint                  *height)
198 {
199         gint calc_width, calc_height;
200         gint full_width, full_height;
201         GList *node;
202         ModestVBoxCellRendererPrivate *priv = MODEST_VBOX_CELL_RENDERER_GET_PRIVATE (cell);
203
204         calc_width = 0;
205         calc_height = 0;
206
207         for (node = priv->renderers_list; node != NULL; node = g_list_next (node)) {
208                 gint renderer_width, renderer_height;
209                 GtkCellRenderer *renderer = (GtkCellRenderer *) node->data;
210
211                 gtk_cell_renderer_get_size (renderer, widget, NULL, NULL, NULL,
212                                             &renderer_width, &renderer_height);
213                 if ((renderer_width > 0)&&(renderer_height > 0)) {
214                         calc_width = MAX (calc_width, renderer_width);
215                         calc_height += renderer_height;
216                 }
217         }
218
219         full_width = (gint) cell->xpad * 2 + calc_width;
220         full_height = (gint) cell->ypad * 2 + calc_height;
221
222         if (rectangle && calc_width > 0 && calc_height > 0) {
223                 if (x_offset) {
224                         *x_offset = (((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ?
225                                       (1.0 - cell->xalign) : cell->xalign) *
226                                      (rectangle->width - full_width));
227                         *x_offset = MAX (*x_offset, 0);
228                 }
229                 if (y_offset) {
230                         *y_offset = ((cell->yalign) *
231                                      (rectangle->height - full_height));
232                         *y_offset = MAX (*y_offset, 0);
233                 }
234         } else {
235                 if (x_offset)
236                         *x_offset = 0;
237                 if (y_offset)
238                         *y_offset = 0;
239         }
240
241         if (width)
242                 *width = full_width;
243         if (height)
244                 *height = full_height;
245 }
246
247 static void
248 modest_vbox_cell_renderer_render       (GtkCellRenderer       *cell,
249                                         GdkDrawable           *window,
250                                         GtkWidget             *widget,
251                                         GdkRectangle          *background_area,
252                                         GdkRectangle          *cell_area,
253                                         GdkRectangle          *expose_area,
254                                         GtkCellRendererState  flags)
255 {
256         ModestVBoxCellRendererPrivate *priv = MODEST_VBOX_CELL_RENDERER_GET_PRIVATE (cell);
257         gint nvis_children = 0;
258         gint nexpand_children = 0;
259         GtkTextDirection direction;
260         GList *node = NULL;
261         GtkCellRenderer *child;
262         gint height, extra;
263         GtkRequisition req;
264        
265         direction = gtk_widget_get_direction (widget);
266         nvis_children = 0;
267         nexpand_children = 0;
268
269         /* first, retrieve the requisition of the children cell renderers */
270         modest_vbox_cell_renderer_get_size (cell, widget, NULL, NULL, NULL, &(req.width), &(req.height));
271
272         /* Counts visible and expandable children cell renderers */
273         for (node = priv->renderers_list; node != NULL; node = g_list_next (node)) {
274                 gboolean visible, expand;
275                 child = (GtkCellRenderer *) node->data;
276                 g_object_get (G_OBJECT (child), "visible", &visible, NULL);
277                 expand = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (child), RENDERER_EXPAND_ATTRIBUTE));
278                
279                 if (visible) {
280                         nvis_children += 1;
281                         if (expand)
282                                 nexpand_children += 1;
283                 }
284         }
285
286         if (nvis_children > 0) {
287                 gint x_pad, y_pad;
288                 gint y;
289                 GdkRectangle child_alloc;
290
291                 if (nexpand_children > 0) {
292                         height = cell_area->height - req.height;
293                         extra = height / nexpand_children;
294                 } else {
295                         height = 0;
296                         extra = 0;
297                 }
298
299                 g_object_get (cell, "xpad", &x_pad, "ypad", &y_pad, NULL);
300                 y = cell_area->y + y_pad;
301                 child_alloc.x = cell_area->x + x_pad;
302                 child_alloc.width = MAX (1, cell_area->width - x_pad * 2);
303
304                 for (node = priv->renderers_list; node != NULL; node = g_list_next (node)) {
305                         gboolean visible, expand;
306
307                         child = (GtkCellRenderer *) node->data;
308                         g_object_get (G_OBJECT (child), "visible", &visible, NULL);
309                         expand = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (child), RENDERER_EXPAND_ATTRIBUTE));
310
311                         if (visible) {
312                                 GtkRequisition child_req;
313                                 gint child_xpad, child_ypad;
314                                 GdkRectangle child_expose_area;
315
316                                 gtk_cell_renderer_get_size (child, widget, NULL, NULL, NULL, &(child_req.width), &(child_req.height));
317                                 g_object_get (child, "xpad", &child_xpad, "ypad", &child_ypad, NULL);
318
319                                 if (expand) {
320                                         if (nexpand_children == 1)
321                                                 child_req.height += height;
322                                         else
323                                                 child_req.height += extra;
324                                         nexpand_children -= 1;
325                                         height -= extra;
326                                 }
327
328                                 child_alloc.height = MAX (1, child_req.height);
329                                 child_alloc.y = y;
330
331                                 if (gdk_rectangle_intersect (&child_alloc, expose_area, &child_expose_area))
332                                         gtk_cell_renderer_render (child, window, widget, background_area, &child_alloc, &child_expose_area, flags);
333                                 y += child_req.height;
334                         }
335                 }
336         }
337        
338 }
Note: See TracBrowser for help on using the browser.