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