]> Pileus Git - ~andy/gtk/blob - gtk/gtkcellrendererpixbuf.c
CVS is doing its broken pipe thing, this is more of the previous commit
[~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       break;
150     default:
151       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
152       break;
153     }
154 }
155
156 /**
157  * gtk_cell_renderer_pixbuf_new:
158  * 
159  * Creates a new #GtkCellRendererPixbuf. Adjust rendering
160  * parameters using object properties. Object properties can be set
161  * globally (with g_object_set()). Also, with #GtkTreeViewColumn, you
162  * can bind a property to a value in a #GtkTreeModel. For example, you
163  * can bind the "pixbuf" property on the cell renderer to a pixbuf value
164  * in the model, thus rendering a different image in each row of the
165  * #GtkTreeView.
166  * 
167  * Return value: the new cell renderer
168  **/
169 GtkCellRenderer *
170 gtk_cell_renderer_pixbuf_new (void)
171 {
172   return GTK_CELL_RENDERER (gtk_type_new (gtk_cell_renderer_pixbuf_get_type ()));
173 }
174
175 static void
176 gtk_cell_renderer_pixbuf_get_size (GtkCellRenderer *cell,
177                                    GtkWidget       *widget,
178                                    gint            *width,
179                                    gint            *height)
180 {
181   GtkCellRendererPixbuf *cellpixbuf = (GtkCellRendererPixbuf *) cell;
182   
183   if (width)
184     *width = (gint) GTK_CELL_RENDERER (cellpixbuf)->xpad * 2 +
185       (cellpixbuf->pixbuf ? gdk_pixbuf_get_width (cellpixbuf->pixbuf) : 0);
186   
187   if (height)
188     *height = (gint) GTK_CELL_RENDERER (cellpixbuf)->ypad * 2 +
189       (cellpixbuf->pixbuf ? gdk_pixbuf_get_height (cellpixbuf->pixbuf) : 0);
190 }
191
192 static void
193 gtk_cell_renderer_pixbuf_render (GtkCellRenderer    *cell,
194                                  GdkWindow          *window,
195                                  GtkWidget          *widget,
196                                  GdkRectangle       *background_area,
197                                  GdkRectangle       *cell_area,
198                                  GdkRectangle       *expose_area,
199                                  guint               flags)
200
201 {
202   GtkCellRendererPixbuf *cellpixbuf = (GtkCellRendererPixbuf *) cell;
203   GdkPixbuf *pixbuf;
204   guchar *pixels;
205   gint rowstride;
206   gint real_xoffset;
207   gint real_yoffset;
208   GdkRectangle pix_rect;
209   GdkRectangle draw_rect;
210
211   pixbuf = cellpixbuf->pixbuf;
212
213   if (!pixbuf)
214     return;
215
216   rowstride = gdk_pixbuf_get_rowstride (pixbuf);
217   pixels = gdk_pixbuf_get_pixels (pixbuf);
218
219   real_xoffset = GTK_CELL_RENDERER (cellpixbuf)->xalign * (cell_area->width - gdk_pixbuf_get_width (pixbuf) - (2 * GTK_CELL_RENDERER (cellpixbuf)->xpad));
220   real_xoffset = MAX (real_xoffset, 0) + GTK_CELL_RENDERER (cellpixbuf)->xpad;
221   real_yoffset = GTK_CELL_RENDERER (cellpixbuf)->yalign * (cell_area->height - gdk_pixbuf_get_height (pixbuf) - (2 * GTK_CELL_RENDERER (cellpixbuf)->ypad));
222   real_yoffset = MAX (real_yoffset, 0) + GTK_CELL_RENDERER (cellpixbuf)->ypad;
223
224   pix_rect.x = cell_area->x + real_xoffset;
225   pix_rect.y = cell_area->y + real_yoffset;
226   pix_rect.width = gdk_pixbuf_get_width (pixbuf);
227   pix_rect.height = gdk_pixbuf_get_height (pixbuf);
228
229   if (gdk_rectangle_intersect (cell_area, &pix_rect, &draw_rect))
230     gdk_pixbuf_render_to_drawable_alpha (pixbuf,
231                                          window,
232                                          /* pixbuf 0, 0 is at pix_rect.x, pix_rect.y */
233                                          draw_rect.x - pix_rect.x,
234                                          draw_rect.y - pix_rect.y,
235                                          draw_rect.x,
236                                          draw_rect.y,
237                                          draw_rect.width,
238                                          draw_rect.height,
239                                          GDK_PIXBUF_ALPHA_FULL,
240                                          0,
241                                          GDK_RGB_DITHER_NORMAL,
242                                          0, 0);
243 }