]> Pileus Git - ~andy/gtk/blob - gtk/gtkcellrendererpixbuf.c
Apply patch from Lee Mallabone to add object properties.
[~andy/gtk] / gtk / gtkcellrendererpixbuf.c
1 /* gtkcellrendererpixbuf.c
2  * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include <stdlib.h>
21 #include "gtkcellrendererpixbuf.h"
22 #include "gtkintl.h"
23
24 static void gtk_cell_renderer_pixbuf_get_property  (GObject                    *object,
25                                                     guint                       param_id,
26                                                     GValue                     *value,
27                                                     GParamSpec                 *pspec,
28                                                     const gchar                *trailer);
29 static void gtk_cell_renderer_pixbuf_set_property  (GObject                    *object,
30                                                     guint                       param_id,
31                                                     const GValue               *value,
32                                                     GParamSpec                 *pspec,
33                                                     const gchar                *trailer);
34 static void gtk_cell_renderer_pixbuf_init       (GtkCellRendererPixbuf      *celltext);
35 static void gtk_cell_renderer_pixbuf_class_init (GtkCellRendererPixbufClass *class);
36 static void gtk_cell_renderer_pixbuf_get_size   (GtkCellRenderer            *cell,
37                                                  GtkWidget                  *widget,
38                                                  gint                       *width,
39                                                  gint                       *height);
40 static void gtk_cell_renderer_pixbuf_render     (GtkCellRenderer            *cell,
41                                                  GdkWindow                  *window,
42                                                  GtkWidget                  *widget,
43                                                  GdkRectangle               *background_area,
44                                                  GdkRectangle               *cell_area,
45                                                  GdkRectangle               *expose_area,
46                                                  guint                       flags);
47
48
49 enum {
50         PROP_ZERO,
51         PROP_PIXBUF
52 };
53
54
55 GtkType
56 gtk_cell_renderer_pixbuf_get_type (void)
57 {
58         static GtkType cell_pixbuf_type = 0;
59
60         if (!cell_pixbuf_type)
61         {
62                 static const GTypeInfo cell_pixbuf_info =
63                 {
64                         sizeof (GtkCellRendererPixbufClass),
65                         NULL,           /* base_init */
66                         NULL,           /* base_finalize */
67                         (GClassInitFunc) gtk_cell_renderer_pixbuf_class_init,
68                         NULL,           /* class_finalize */
69                         NULL,           /* class_data */
70                         sizeof (GtkCellRendererPixbuf),
71                         0,              /* n_preallocs */
72                         (GInstanceInitFunc) gtk_cell_renderer_pixbuf_init,
73                 };
74
75                 cell_pixbuf_type = g_type_register_static (GTK_TYPE_CELL_RENDERER, "GtkCellRendererPixbuf", &cell_pixbuf_info, 0);
76         }
77
78         return cell_pixbuf_type;
79 }
80
81 static void
82 gtk_cell_renderer_pixbuf_init (GtkCellRendererPixbuf *cellpixbuf)
83 {
84 }
85
86 static void
87 gtk_cell_renderer_pixbuf_class_init (GtkCellRendererPixbufClass *class)
88 {
89         GObjectClass *object_class = G_OBJECT_CLASS (class);
90         GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
91
92         object_class->get_property = gtk_cell_renderer_pixbuf_get_property;
93         object_class->set_property = gtk_cell_renderer_pixbuf_set_property;
94
95         cell_class->get_size = gtk_cell_renderer_pixbuf_get_size;
96         cell_class->render = gtk_cell_renderer_pixbuf_render;
97
98         g_object_class_install_property (object_class,
99                                          PROP_PIXBUF,
100                                          g_param_spec_object ("pixbuf",
101                                                               _("Pixbuf Object"),
102                                                               _("The pixbuf to render."),
103                                                               GDK_TYPE_PIXBUF,
104                                                               G_PARAM_READABLE |
105                                                               G_PARAM_WRITABLE));
106 }
107
108 static void
109 gtk_cell_renderer_pixbuf_get_property (GObject        *object,
110                                        guint           param_id,
111                                        GValue         *value,
112                                        GParamSpec     *pspec,
113                                        const gchar    *trailer)
114 {
115   GtkCellRendererPixbuf *cellpixbuf = GTK_CELL_RENDERER_PIXBUF (object);
116   
117   switch (param_id)
118     {
119     case PROP_PIXBUF:
120       g_value_set_object (value,
121                           cellpixbuf->pixbuf ? G_OBJECT (cellpixbuf->pixbuf) : NULL);
122       break;
123     default:
124       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
125       break;
126     }
127 }
128
129
130 static void
131 gtk_cell_renderer_pixbuf_set_property (GObject      *object,
132                                        guint         param_id,
133                                        const GValue *value,
134                                        GParamSpec   *pspec,
135                                        const gchar  *trailer)
136 {
137   GdkPixbuf *pixbuf;
138   GtkCellRendererPixbuf *cellpixbuf = GTK_CELL_RENDERER_PIXBUF (object);
139   
140   switch (param_id)
141     {
142     case PROP_PIXBUF:
143       pixbuf = (GdkPixbuf*) g_value_get_object (value);
144       if (pixbuf)
145         g_object_ref (G_OBJECT (pixbuf));
146       if (cellpixbuf->pixbuf)
147         g_object_unref (G_OBJECT (cellpixbuf->pixbuf));
148       cellpixbuf->pixbuf = pixbuf;
149       g_object_notify (object, "pixbuf");
150       break;
151     default:
152       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
153       break;
154     }
155 }
156
157 /**
158  * gtk_cell_renderer_pixbuf_new:
159  * 
160  * Creates a new #GtkCellRendererPixbuf. Adjust rendering
161  * parameters using object properties. Object properties can be set
162  * globally (with g_object_set()). Also, with #GtkTreeViewColumn, you
163  * can bind a property to a value in a #GtkTreeModel. For example, you
164  * can bind the "pixbuf" property on the cell renderer to a pixbuf value
165  * in the model, thus rendering a different image in each row of the
166  * #GtkTreeView.
167  * 
168  * Return value: the new cell renderer
169  **/
170 GtkCellRenderer *
171 gtk_cell_renderer_pixbuf_new (void)
172 {
173   return GTK_CELL_RENDERER (gtk_type_new (gtk_cell_renderer_pixbuf_get_type ()));
174 }
175
176 static void
177 gtk_cell_renderer_pixbuf_get_size (GtkCellRenderer *cell,
178                                    GtkWidget       *widget,
179                                    gint            *width,
180                                    gint            *height)
181 {
182   GtkCellRendererPixbuf *cellpixbuf = (GtkCellRendererPixbuf *) cell;
183   
184   if (width)
185     *width = (gint) GTK_CELL_RENDERER (cellpixbuf)->xpad * 2 +
186       (cellpixbuf->pixbuf ? gdk_pixbuf_get_width (cellpixbuf->pixbuf) : 0);
187   
188   if (height)
189     *height = (gint) GTK_CELL_RENDERER (cellpixbuf)->ypad * 2 +
190       (cellpixbuf->pixbuf ? gdk_pixbuf_get_height (cellpixbuf->pixbuf) : 0);
191 }
192
193 static void
194 gtk_cell_renderer_pixbuf_render (GtkCellRenderer    *cell,
195                                  GdkWindow          *window,
196                                  GtkWidget          *widget,
197                                  GdkRectangle       *background_area,
198                                  GdkRectangle       *cell_area,
199                                  GdkRectangle       *expose_area,
200                                  guint               flags)
201
202 {
203   GtkCellRendererPixbuf *cellpixbuf = (GtkCellRendererPixbuf *) cell;
204   GdkPixbuf *pixbuf;
205   guchar *pixels;
206   gint rowstride;
207   gint real_xoffset;
208   gint real_yoffset;
209   GdkRectangle pix_rect;
210   GdkRectangle draw_rect;
211
212   pixbuf = cellpixbuf->pixbuf;
213
214   if (!pixbuf)
215     return;
216
217   rowstride = gdk_pixbuf_get_rowstride (pixbuf);
218   pixels = gdk_pixbuf_get_pixels (pixbuf);
219
220   real_xoffset = GTK_CELL_RENDERER (cellpixbuf)->xalign * (cell_area->width - gdk_pixbuf_get_width (pixbuf) - (2 * GTK_CELL_RENDERER (cellpixbuf)->xpad));
221   real_xoffset = MAX (real_xoffset, 0) + GTK_CELL_RENDERER (cellpixbuf)->xpad;
222   real_yoffset = GTK_CELL_RENDERER (cellpixbuf)->yalign * (cell_area->height - gdk_pixbuf_get_height (pixbuf) - (2 * GTK_CELL_RENDERER (cellpixbuf)->ypad));
223   real_yoffset = MAX (real_yoffset, 0) + GTK_CELL_RENDERER (cellpixbuf)->ypad;
224
225   pix_rect.x = cell_area->x + real_xoffset;
226   pix_rect.y = cell_area->y + real_yoffset;
227   pix_rect.width = gdk_pixbuf_get_width (pixbuf);
228   pix_rect.height = gdk_pixbuf_get_height (pixbuf);
229
230   if (gdk_rectangle_intersect (cell_area, &pix_rect, &draw_rect))
231     gdk_pixbuf_render_to_drawable_alpha (pixbuf,
232                                          window,
233                                          /* pixbuf 0, 0 is at pix_rect.x, pix_rect.y */
234                                          draw_rect.x - pix_rect.x,
235                                          draw_rect.y - pix_rect.y,
236                                          draw_rect.x,
237                                          draw_rect.y,
238                                          draw_rect.width,
239                                          draw_rect.height,
240                                          GDK_PIXBUF_ALPHA_FULL,
241                                          0,
242                                          GDK_RGB_DITHER_NORMAL,
243                                          0, 0);
244 }