1 /* -*- Mode: C; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 3 -*- */
2 
3 /*
4  * Copyright (C) 2002 Takuro Ashie
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (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
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  *
20  * $Id: gimv_cell_pixmap.c,v 1.1 2003/07/06 16:46:21 makeinu Exp $
21  */
22 
23 /*
24  *  These codes are based on gtk/gtkcellrendererpixbuf.c in gtk+-2.0.6
25  *  Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
26  */
27 
28 #include "gimv_cell_pixmap.h"
29 
30 #if (GTK_MAJOR_VERSION >= 2)
31 
32 #include <stdlib.h>
33 #include "intl.h"
34 
35 static void gimv_cell_renderer_pixmap_get_property  (GObject                    *object,
36                                                      guint                       param_id,
37                                                      GValue                     *value,
38                                                      GParamSpec                 *pspec);
39 static void gimv_cell_renderer_pixmap_set_property  (GObject                    *object,
40                                                      guint                       param_id,
41                                                      const GValue               *value,
42                                                      GParamSpec                 *pspec);
43 static void gimv_cell_renderer_pixmap_init          (GimvCellRendererPixmap      *celltext);
44 static void gimv_cell_renderer_pixmap_class_init    (GimvCellRendererPixmapClass *class);
45 static void gimv_cell_renderer_pixmap_get_size      (GtkCellRenderer            *cell,
46                                                      GtkWidget                  *widget,
47                                                      GdkRectangle               *rectangle,
48                                                      gint                       *x_offset,
49                                                      gint                       *y_offset,
50                                                      gint                       *width,
51                                                      gint                       *height);
52 static void gimv_cell_renderer_pixmap_render        (GtkCellRenderer            *cell,
53                                                      GdkWindow                  *window,
54                                                      GtkWidget                  *widget,
55                                                      GdkRectangle               *background_area,
56                                                      GdkRectangle               *cell_area,
57                                                      GdkRectangle               *expose_area,
58                                                      guint                       flags);
59 
60 
61 enum {
62    PROP_ZERO,
63    PROP_PIXMAP,
64    PROP_MASK,
65    PROP_PIXMAP_EXPANDER_OPEN,
66    PROP_MASK_EXPANDER_OPEN,
67    PROP_PIXMAP_EXPANDER_CLOSED,
68    PROP_MASK_EXPANDER_CLOSED
69 };
70 
71 
72 GtkType
gimv_cell_renderer_pixmap_get_type(void)73 gimv_cell_renderer_pixmap_get_type (void)
74 {
75    static GtkType cell_pixmap_type = 0;
76 
77    if (!cell_pixmap_type) {
78       static const GTypeInfo cell_pixmap_info = {
79          sizeof (GimvCellRendererPixmapClass),
80          NULL,		/* base_init */
81          NULL,		/* base_finalize */
82          (GClassInitFunc) gimv_cell_renderer_pixmap_class_init,
83          NULL,		/* class_finalize */
84          NULL,		/* class_data */
85          sizeof (GimvCellRendererPixmap),
86          0,       /* n_preallocs */
87          (GInstanceInitFunc) gimv_cell_renderer_pixmap_init,
88       };
89 
90       cell_pixmap_type = g_type_register_static (GTK_TYPE_CELL_RENDERER,
91                                                  "Gimvcellrendererpixmap",
92                                                  &cell_pixmap_info, 0);
93    }
94 
95    return cell_pixmap_type;
96 }
97 
98 
99 static void
gimv_cell_renderer_pixmap_init(GimvCellRendererPixmap * cellpixmap)100 gimv_cell_renderer_pixmap_init (GimvCellRendererPixmap *cellpixmap)
101 {
102 }
103 
104 
105 static void
gimv_cell_renderer_pixmap_class_init(GimvCellRendererPixmapClass * class)106 gimv_cell_renderer_pixmap_class_init (GimvCellRendererPixmapClass *class)
107 {
108    GObjectClass *object_class       = G_OBJECT_CLASS (class);
109    GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
110 
111    object_class->get_property       = gimv_cell_renderer_pixmap_get_property;
112    object_class->set_property       = gimv_cell_renderer_pixmap_set_property;
113 
114    cell_class->get_size             = gimv_cell_renderer_pixmap_get_size;
115    cell_class->render               = gimv_cell_renderer_pixmap_render;
116 
117    g_object_class_install_property (object_class,
118                                     PROP_PIXMAP,
119                                     g_param_spec_object ("pixmap",
120                                                          _("Pixmap Object"),
121                                                          _("The pixmap to render."),
122                                                          GDK_TYPE_PIXMAP,
123                                                          G_PARAM_READABLE |
124                                                          G_PARAM_WRITABLE));
125 
126    g_object_class_install_property (object_class,
127                                     PROP_MASK,
128                                     g_param_spec_object ("mask",
129                                                          _("Mask Object"),
130                                                          _("The mask to render."),
131                                                          GDK_TYPE_PIXMAP,
132                                                          G_PARAM_READABLE |
133                                                          G_PARAM_WRITABLE));
134 
135    g_object_class_install_property (object_class,
136                                     PROP_PIXMAP_EXPANDER_OPEN,
137                                     g_param_spec_object ("pixmap_expander_open",
138                                                          _("Pixmap Expander Open"),
139                                                          _("Pixmap for open expander."),
140                                                          GDK_TYPE_PIXMAP,
141                                                          G_PARAM_READABLE |
142                                                          G_PARAM_WRITABLE));
143 
144    g_object_class_install_property (object_class,
145                                     PROP_MASK_EXPANDER_OPEN,
146                                     g_param_spec_object ("mask_expander_open",
147                                                          _("Mask Expander Open"),
148                                                          _("Mask for open expander."),
149                                                          GDK_TYPE_PIXMAP,
150                                                          G_PARAM_READABLE |
151                                                          G_PARAM_WRITABLE));
152 
153    g_object_class_install_property (object_class,
154                                     PROP_PIXMAP_EXPANDER_CLOSED,
155                                     g_param_spec_object ("pixmap_expander_closed",
156                                                          _("Pixmap Expander Closed"),
157                                                          _("Pixmap for closed expander."),
158                                                          GDK_TYPE_PIXMAP,
159                                                          G_PARAM_READABLE |
160                                                          G_PARAM_WRITABLE));
161 
162    g_object_class_install_property (object_class,
163                                     PROP_MASK_EXPANDER_CLOSED,
164                                     g_param_spec_object ("mask_expander_closed",
165                                                          _("Mask Expander Closed"),
166                                                          _("Mask for closed expander."),
167                                                          GDK_TYPE_PIXMAP,
168                                                          G_PARAM_READABLE |
169                                                          G_PARAM_WRITABLE));
170 }
171 
172 
173 static void
gimv_cell_renderer_pixmap_get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)174 gimv_cell_renderer_pixmap_get_property (GObject        *object,
175                                         guint           param_id,
176                                         GValue         *value,
177                                         GParamSpec     *pspec)
178 {
179    GimvCellRendererPixmap *cellpixmap = GIMV_CELL_RENDERER_PIXMAP (object);
180 
181    switch (param_id) {
182    case PROP_PIXMAP:
183       g_value_set_object (value,
184                           cellpixmap->pixmap
185                           ? G_OBJECT (cellpixmap->pixmap) : NULL);
186       break;
187    case PROP_MASK:
188       g_value_set_object (value,
189                           cellpixmap->mask
190                           ? G_OBJECT (cellpixmap->mask) : NULL);
191       break;
192    case PROP_PIXMAP_EXPANDER_OPEN:
193       g_value_set_object (value,
194                           cellpixmap->pixmap_expander_open
195                           ? G_OBJECT (cellpixmap->pixmap_expander_open) : NULL);
196       break;
197    case PROP_MASK_EXPANDER_OPEN:
198       g_value_set_object (value,
199                           cellpixmap->mask_expander_open
200                           ? G_OBJECT (cellpixmap->mask_expander_open) : NULL);
201       break;
202    case PROP_PIXMAP_EXPANDER_CLOSED:
203       g_value_set_object (value,
204                           cellpixmap->pixmap_expander_closed
205                           ? G_OBJECT (cellpixmap->pixmap_expander_closed) : NULL);
206       break;
207    case PROP_MASK_EXPANDER_CLOSED:
208       g_value_set_object (value,
209                           cellpixmap->mask_expander_closed
210                           ? G_OBJECT (cellpixmap->mask_expander_closed) : NULL);
211       break;
212    default:
213       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
214       break;
215    }
216 }
217 
218 
219 static void
gimv_cell_renderer_pixmap_set_property(GObject * object,guint param_id,const GValue * value,GParamSpec * pspec)220 gimv_cell_renderer_pixmap_set_property (GObject      *object,
221                                         guint         param_id,
222                                         const GValue *value,
223                                         GParamSpec   *pspec)
224 {
225    GdkPixmap *pixmap;
226    GdkBitmap *mask;
227    GimvCellRendererPixmap *cellpixmap = GIMV_CELL_RENDERER_PIXMAP (object);
228 
229    switch (param_id) {
230    case PROP_PIXMAP:
231       pixmap = (GdkPixmap*) g_value_get_object (value);
232       if (pixmap)
233          g_object_ref (G_OBJECT (pixmap));
234       if (cellpixmap->pixmap)
235          g_object_unref (G_OBJECT (cellpixmap->pixmap));
236       cellpixmap->pixmap = pixmap;
237       break;
238    case PROP_MASK:
239       mask = (GdkBitmap*) g_value_get_object (value);
240       if (mask)
241          g_object_ref (G_OBJECT (mask));
242       if (cellpixmap->mask)
243          g_object_unref (G_OBJECT (cellpixmap->mask));
244       cellpixmap->mask = mask;
245       break;
246    case PROP_PIXMAP_EXPANDER_OPEN:
247       pixmap = (GdkPixmap*) g_value_get_object (value);
248       if (pixmap)
249          g_object_ref (G_OBJECT (pixmap));
250       if (cellpixmap->pixmap_expander_open)
251          g_object_unref (G_OBJECT (cellpixmap->pixmap_expander_open));
252       cellpixmap->pixmap_expander_open = pixmap;
253       break;
254    case PROP_MASK_EXPANDER_OPEN:
255       mask = (GdkBitmap*) g_value_get_object (value);
256       if (mask)
257          g_object_ref (G_OBJECT (mask));
258       if (cellpixmap->mask_expander_open)
259          g_object_unref (G_OBJECT (cellpixmap->mask_expander_open));
260       cellpixmap->mask_expander_open = mask;
261       break;
262    case PROP_PIXMAP_EXPANDER_CLOSED:
263       pixmap = (GdkPixmap*) g_value_get_object (value);
264       if (pixmap)
265          g_object_ref (G_OBJECT (pixmap));
266       if (cellpixmap->pixmap_expander_closed)
267          g_object_unref (G_OBJECT (cellpixmap->pixmap_expander_closed));
268       cellpixmap->pixmap_expander_closed = pixmap;
269       break;
270    case PROP_MASK_EXPANDER_CLOSED:
271       mask = (GdkBitmap*) g_value_get_object (value);
272       if (mask)
273          g_object_ref (G_OBJECT (mask));
274       if (cellpixmap->mask_expander_closed)
275          g_object_unref (G_OBJECT (cellpixmap->mask_expander_closed));
276       cellpixmap->mask_expander_closed = mask;
277       break;
278    default:
279       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
280       break;
281    }
282 }
283 
284 
285 GtkCellRenderer *
gimv_cell_renderer_pixmap_new(void)286 gimv_cell_renderer_pixmap_new (void)
287 {
288    return GTK_CELL_RENDERER (g_object_new (gimv_cell_renderer_pixmap_get_type (), NULL));
289 }
290 
291 
292 static void
gimv_cell_renderer_pixmap_get_size(GtkCellRenderer * cell,GtkWidget * widget,GdkRectangle * cell_area,gint * x_offset,gint * y_offset,gint * width,gint * height)293 gimv_cell_renderer_pixmap_get_size (GtkCellRenderer *cell,
294                                     GtkWidget       *widget,
295                                     GdkRectangle    *cell_area,
296                                     gint            *x_offset,
297                                     gint            *y_offset,
298                                     gint            *width,
299                                     gint            *height)
300 {
301    GimvCellRendererPixmap *cellpixmap = (GimvCellRendererPixmap *) cell;
302    gint pixmap_width = 0;
303    gint pixmap_height = 0;
304    gint calc_width;
305    gint calc_height;
306 
307    if (cellpixmap->pixmap) {
308       gdk_drawable_get_size (cellpixmap->pixmap, &pixmap_width, &pixmap_height);
309    }
310    if (cellpixmap->pixmap_expander_open) {
311       gint w, h;
312       gdk_drawable_get_size (cellpixmap->pixmap_expander_open, &w, &h);
313       pixmap_width  = MAX (pixmap_width,  w);
314       pixmap_height = MAX (pixmap_height, h);
315    }
316    if (cellpixmap->pixmap_expander_closed) {
317       gint w, h;
318       gdk_drawable_get_size (cellpixmap->pixmap_expander_closed, &w, &h);
319       pixmap_width  = MAX (pixmap_width,  w);
320       pixmap_height = MAX (pixmap_height, h);
321    }
322 
323    calc_width  = (gint) GTK_CELL_RENDERER (cellpixmap)->xpad * 2 + pixmap_width;
324    calc_height = (gint) GTK_CELL_RENDERER (cellpixmap)->ypad * 2 + pixmap_height;
325 
326    if (x_offset) *x_offset = 0;
327    if (y_offset) *y_offset = 0;
328 
329    if (cell_area && pixmap_width > 0 && pixmap_height > 0) {
330       if (x_offset) {
331          *x_offset = GTK_CELL_RENDERER (cellpixmap)->xalign
332             * (cell_area->width - calc_width - (2 * GTK_CELL_RENDERER (cellpixmap)->xpad));
333          *x_offset = MAX (*x_offset, 0) + GTK_CELL_RENDERER (cellpixmap)->xpad;
334       }
335       if (y_offset) {
336          *y_offset = GTK_CELL_RENDERER (cellpixmap)->yalign
337             * (cell_area->height - calc_height - (2 * GTK_CELL_RENDERER (cellpixmap)->ypad));
338          *y_offset = MAX (*y_offset, 0) + GTK_CELL_RENDERER (cellpixmap)->ypad;
339       }
340    }
341 
342    if (width)
343       *width = calc_width;
344 
345    if (height)
346       *height = calc_height;
347 }
348 
349 
350 static void
gimv_cell_renderer_pixmap_render(GtkCellRenderer * cell,GdkWindow * window,GtkWidget * widget,GdkRectangle * background_area,GdkRectangle * cell_area,GdkRectangle * expose_area,guint flags)351 gimv_cell_renderer_pixmap_render (GtkCellRenderer    *cell,
352                                   GdkWindow          *window,
353                                   GtkWidget          *widget,
354                                   GdkRectangle       *background_area,
355                                   GdkRectangle       *cell_area,
356                                   GdkRectangle       *expose_area,
357                                   guint               flags)
358 
359 {
360    GimvCellRendererPixmap *cellpixmap = (GimvCellRendererPixmap *) cell;
361    GdkPixmap *pixmap;
362    GdkBitmap *mask;
363    GdkRectangle pix_rect;
364    GdkRectangle draw_rect;
365    GdkGC *gc;
366 
367    pixmap = cellpixmap->pixmap;
368    mask   = cellpixmap->mask;
369    if (cell->is_expander) {
370       if (cell->is_expanded &&
371           cellpixmap->pixmap_expander_open != NULL)
372       {
373          pixmap = cellpixmap->pixmap_expander_open;
374          mask   = cellpixmap->mask_expander_open;
375       } else if (!cell->is_expanded &&
376                  cellpixmap->pixmap_expander_closed != NULL)
377       {
378          pixmap = cellpixmap->pixmap_expander_closed;
379          mask   = cellpixmap->mask_expander_closed;
380       }
381    }
382 
383    if (!pixmap) return;
384 
385    gimv_cell_renderer_pixmap_get_size (cell, widget, cell_area,
386                                        &pix_rect.x,
387                                        &pix_rect.y,
388                                        &pix_rect.width,
389                                        &pix_rect.height);
390 
391    pix_rect.x += cell_area->x;
392    pix_rect.y += cell_area->y;
393    pix_rect.width -= cell->xpad * 2;
394    pix_rect.height -= cell->ypad * 2;
395 
396    if (!gdk_rectangle_intersect (cell_area, &pix_rect, &draw_rect)) return;
397 
398    gc = widget->style->fg_gc[GTK_STATE_NORMAL];
399 
400    if (mask) {
401       gdk_gc_set_clip_mask (gc, mask);
402       gdk_gc_set_clip_origin (gc, pix_rect.x, pix_rect.y);
403    }
404 
405    gdk_draw_pixmap(window,
406                    gc,
407                    pixmap,
408                    draw_rect.x - pix_rect.x,
409                    draw_rect.y - pix_rect.y,
410                    draw_rect.x,
411                    draw_rect.y,
412                    draw_rect.width,
413                    draw_rect.height);
414 
415    if (mask) {
416       gdk_gc_set_clip_mask (gc, NULL);
417       gdk_gc_set_clip_origin (gc, 0, 0);
418    }
419 }
420 
421 #endif /* (GTK_MAJOR_VERSION >= 2) */
422