]> Pileus Git - ~andy/gtk/blob - gtk/gtkcellrendererpixbuf.c
handle case where there are no rows in the model
[~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 GtkCellRenderer *
157 gtk_cell_renderer_pixbuf_new (void)
158 {
159   return GTK_CELL_RENDERER (gtk_type_new (gtk_cell_renderer_pixbuf_get_type ()));
160 }
161
162 static void
163 gtk_cell_renderer_pixbuf_get_size (GtkCellRenderer *cell,
164                                    GtkWidget       *widget,
165                                    gint            *width,
166                                    gint            *height)
167 {
168   GtkCellRendererPixbuf *cellpixbuf = (GtkCellRendererPixbuf *) cell;
169   
170   if (width)
171     *width = (gint) GTK_CELL_RENDERER (cellpixbuf)->xpad * 2 +
172       (cellpixbuf->pixbuf ? gdk_pixbuf_get_width (cellpixbuf->pixbuf) : 0);
173   
174   if (height)
175     *height = (gint) GTK_CELL_RENDERER (cellpixbuf)->ypad * 2 +
176       (cellpixbuf->pixbuf ? gdk_pixbuf_get_height (cellpixbuf->pixbuf) : 0);
177 }
178
179 static void
180 gtk_cell_renderer_pixbuf_render (GtkCellRenderer    *cell,
181                                  GdkWindow          *window,
182                                  GtkWidget          *widget,
183                                  GdkRectangle       *background_area,
184                                  GdkRectangle       *cell_area,
185                                  GdkRectangle       *expose_area,
186                                  guint               flags)
187
188 {
189   GtkCellRendererPixbuf *cellpixbuf = (GtkCellRendererPixbuf *) cell;
190   GdkPixbuf *pixbuf;
191   guchar *pixels;
192   gint rowstride;
193   gint real_xoffset;
194   gint real_yoffset;
195   GdkRectangle pix_rect;
196   GdkRectangle draw_rect;
197
198   pixbuf = cellpixbuf->pixbuf;
199
200   if (!pixbuf)
201     return;
202
203   rowstride = gdk_pixbuf_get_rowstride (pixbuf);
204   pixels = gdk_pixbuf_get_pixels (pixbuf);
205
206   real_xoffset = GTK_CELL_RENDERER (cellpixbuf)->xalign * (cell_area->width - gdk_pixbuf_get_width (pixbuf) - (2 * GTK_CELL_RENDERER (cellpixbuf)->xpad));
207   real_xoffset = MAX (real_xoffset, 0) + GTK_CELL_RENDERER (cellpixbuf)->xpad;
208   real_yoffset = GTK_CELL_RENDERER (cellpixbuf)->yalign * (cell_area->height - gdk_pixbuf_get_height (pixbuf) - (2 * GTK_CELL_RENDERER (cellpixbuf)->ypad));
209   real_yoffset = MAX (real_yoffset, 0) + GTK_CELL_RENDERER (cellpixbuf)->ypad;
210
211   pix_rect.x = cell_area->x + real_xoffset;
212   pix_rect.y = cell_area->y + real_yoffset;
213   pix_rect.width = gdk_pixbuf_get_width (pixbuf);
214   pix_rect.height = gdk_pixbuf_get_height (pixbuf);
215
216   if (gdk_rectangle_intersect (cell_area, &pix_rect, &draw_rect))
217     gdk_pixbuf_render_to_drawable_alpha (pixbuf,
218                                          window,
219                                          /* pixbuf 0, 0 is at pix_rect.x, pix_rect.y */
220                                          draw_rect.x - pix_rect.x,
221                                          draw_rect.y - pix_rect.y,
222                                          draw_rect.x,
223                                          draw_rect.y,
224                                          draw_rect.width,
225                                          draw_rect.height,
226                                          GDK_PIXBUF_ALPHA_FULL,
227                                          0,
228                                          GDK_RGB_DITHER_NORMAL,
229                                          0, 0);
230 }