1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* rbcellrendererpixbuf.c
4 * arch-tag: Implementation of Rhythmbox pixbuf GtkTreeView cell renderer
6 * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
7 * Copyright (C) 2002 Jorn Baayen <jorn@nl.linux.org>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
22 * Boston, MA 02110-1301 USA.
26 #include <libgnome/gnome-i18n.h>
28 #include <gtk/gtktreeview.h>
29 #include <gtk/gtkiconfactory.h>
31 #include "rb-cell-renderer-pixbuf.h"
32 #include "rb-cut-and-paste-code.h"
34 static void rb_cell_renderer_pixbuf_get_property (GObject
*object
,
38 static void rb_cell_renderer_pixbuf_set_property (GObject
*object
,
42 static void rb_cell_renderer_pixbuf_init (RBCellRendererPixbuf
*celltext
);
43 static void rb_cell_renderer_pixbuf_class_init (RBCellRendererPixbufClass
*class);
44 static void rb_cell_renderer_pixbuf_get_size (GtkCellRenderer
*cell
,
46 GdkRectangle
*rectangle
,
51 static void rb_cell_renderer_pixbuf_render (GtkCellRenderer
*cell
,
54 GdkRectangle
*background_area
,
55 GdkRectangle
*cell_area
,
56 GdkRectangle
*expose_area
,
58 static gboolean
rb_cell_renderer_pixbuf_activate (GtkCellRenderer
*cell
,
62 GdkRectangle
*background_area
,
63 GdkRectangle
*cell_area
,
64 GtkCellRendererState flags
);
77 G_DEFINE_TYPE (RBCellRendererPixbuf
, rb_cell_renderer_pixbuf
, GTK_TYPE_CELL_RENDERER
)
79 static guint rb_cell_renderer_pixbuf_signals
[LAST_SIGNAL
] = { 0 };
82 rb_cell_renderer_pixbuf_init (RBCellRendererPixbuf
*cellpixbuf
)
85 /* set the renderer able to be activated */
86 GTK_CELL_RENDERER (cellpixbuf
)->mode
= GTK_CELL_RENDERER_MODE_ACTIVATABLE
;
90 rb_cell_renderer_pixbuf_class_init (RBCellRendererPixbufClass
*class)
92 GObjectClass
*object_class
= G_OBJECT_CLASS (class);
93 GtkCellRendererClass
*cell_class
= GTK_CELL_RENDERER_CLASS (class);
95 object_class
->get_property
= rb_cell_renderer_pixbuf_get_property
;
96 object_class
->set_property
= rb_cell_renderer_pixbuf_set_property
;
98 cell_class
->get_size
= rb_cell_renderer_pixbuf_get_size
;
99 cell_class
->render
= rb_cell_renderer_pixbuf_render
;
100 cell_class
->activate
= rb_cell_renderer_pixbuf_activate
;
102 g_object_class_install_property (object_class
,
104 g_param_spec_object ("pixbuf",
106 _("The pixbuf to render."),
111 rb_cell_renderer_pixbuf_signals
[PIXBUF_CLICKED
] =
112 g_signal_new ("pixbuf-clicked",
113 G_OBJECT_CLASS_TYPE (object_class
),
115 G_STRUCT_OFFSET (RBCellRendererPixbufClass
, pixbuf_clicked
),
117 g_cclosure_marshal_VOID__STRING
,
124 rb_cell_renderer_pixbuf_get_property (GObject
*object
,
129 RBCellRendererPixbuf
*cellpixbuf
= RB_CELL_RENDERER_PIXBUF (object
);
134 g_value_set_object (value
,
135 cellpixbuf
->pixbuf
? G_OBJECT (cellpixbuf
->pixbuf
) : NULL
);
138 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, param_id
, pspec
);
144 rb_cell_renderer_pixbuf_set_property (GObject
*object
,
150 RBCellRendererPixbuf
*cellpixbuf
= RB_CELL_RENDERER_PIXBUF (object
);
155 pixbuf
= (GdkPixbuf
*) g_value_get_object (value
);
157 g_object_ref (G_OBJECT (pixbuf
));
158 if (cellpixbuf
->pixbuf
)
159 g_object_unref (G_OBJECT (cellpixbuf
->pixbuf
));
160 cellpixbuf
->pixbuf
= pixbuf
;
163 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, param_id
, pspec
);
169 * rb_cell_renderer_pixbuf_new:
171 * Creates a new #RBCellRendererPixbuf. Adjust rendering
172 * parameters using object properties. Object properties can be set
173 * globally (with g_object_set()). Also, with #RBTreeViewColumn, you
174 * can bind a property to a value in a #RBTreeModel. For example, you
175 * can bind the "pixbuf" property on the cell renderer to a pixbuf value
176 * in the model, thus rendering a different image in each row of the
179 * Return value: the new cell renderer
182 rb_cell_renderer_pixbuf_new (void)
184 return GTK_CELL_RENDERER (gtk_type_new (rb_cell_renderer_pixbuf_get_type ()));
188 rb_cell_renderer_pixbuf_get_size (GtkCellRenderer
*cell
,
190 GdkRectangle
*cell_area
,
196 RBCellRendererPixbuf
*cellpixbuf
= (RBCellRendererPixbuf
*) cell
;
197 gint pixbuf_width
= 0;
198 gint pixbuf_height
= 0;
202 if (cellpixbuf
->pixbuf
)
204 pixbuf_width
= gdk_pixbuf_get_width (cellpixbuf
->pixbuf
);
205 pixbuf_height
= gdk_pixbuf_get_height (cellpixbuf
->pixbuf
);
208 calc_width
= (gint
) GTK_CELL_RENDERER (cellpixbuf
)->xpad
* 2 + pixbuf_width
;
209 calc_height
= (gint
) GTK_CELL_RENDERER (cellpixbuf
)->ypad
* 2 + pixbuf_height
;
211 if (x_offset
) *x_offset
= 0;
212 if (y_offset
) *y_offset
= 0;
214 if (cell_area
&& pixbuf_width
> 0 && pixbuf_height
> 0)
218 *x_offset
= GTK_CELL_RENDERER (cellpixbuf
)->xalign
* (cell_area
->width
- calc_width
- (2 * GTK_CELL_RENDERER (cellpixbuf
)->xpad
));
219 *x_offset
= MAX (*x_offset
, 0) + GTK_CELL_RENDERER (cellpixbuf
)->xpad
;
223 *y_offset
= GTK_CELL_RENDERER (cellpixbuf
)->yalign
* (cell_area
->height
- calc_height
- (2 * GTK_CELL_RENDERER (cellpixbuf
)->ypad
));
224 *y_offset
= MAX (*y_offset
, 0) + GTK_CELL_RENDERER (cellpixbuf
)->ypad
;
232 *height
= calc_height
;
236 rb_cell_renderer_pixbuf_render (GtkCellRenderer
*cell
,
239 GdkRectangle
*background_area
,
240 GdkRectangle
*cell_area
,
241 GdkRectangle
*expose_area
,
245 RBCellRendererPixbuf
*cellpixbuf
= (RBCellRendererPixbuf
*) cell
;
246 GdkRectangle pix_rect
;
247 GdkRectangle draw_rect
;
250 if ((flags
& GTK_CELL_RENDERER_SELECTED
) == GTK_CELL_RENDERER_SELECTED
)
252 if (GTK_WIDGET_HAS_FOCUS (widget
))
253 state
= GTK_STATE_SELECTED
;
255 state
= GTK_STATE_ACTIVE
;
259 if (GTK_WIDGET_STATE (widget
) == GTK_STATE_INSENSITIVE
)
260 state
= GTK_STATE_INSENSITIVE
;
262 state
= GTK_STATE_NORMAL
;
265 if (!cellpixbuf
->pixbuf
)
268 rb_cell_renderer_pixbuf_get_size (cell
, widget
, cell_area
,
274 pix_rect
.x
+= cell_area
->x
;
275 pix_rect
.y
+= cell_area
->y
;
276 pix_rect
.width
-= cell
->xpad
* 2;
277 pix_rect
.height
-= cell
->ypad
* 2;
279 if (gdk_rectangle_intersect (cell_area
, &pix_rect
, &draw_rect
))
280 gdk_pixbuf_render_to_drawable_alpha (cellpixbuf
->pixbuf
,
282 /* pixbuf 0, 0 is at pix_rect.x, pix_rect.y */
283 draw_rect
.x
- pix_rect
.x
,
284 draw_rect
.y
- pix_rect
.y
,
289 GDK_PIXBUF_ALPHA_FULL
,
291 GDK_RGB_DITHER_NORMAL
,
296 rb_cell_renderer_pixbuf_activate (GtkCellRenderer
*cell
,
300 GdkRectangle
*background_area
,
301 GdkRectangle
*cell_area
,
302 GtkCellRendererState flags
)
304 int mouse_x
, mouse_y
, icon_width
;
305 RBCellRendererPixbuf
*cellpixbuf
= (RBCellRendererPixbuf
*) cell
;
307 g_return_val_if_fail (RB_IS_CELL_RENDERER_PIXBUF (cellpixbuf
), FALSE
);
309 gtk_icon_size_lookup (GTK_ICON_SIZE_MENU
, &icon_width
, NULL
);
310 gtk_widget_get_pointer (widget
, &mouse_x
, &mouse_y
);
311 gtk_tree_view_widget_to_tree_coords (GTK_TREE_VIEW (widget
),
317 /* ensure the user clicks within the good cell */
318 if (mouse_x
- cell_area
->x
>= 0
319 && mouse_x
- cell_area
->x
<= cell_area
->width
) {
320 g_signal_emit (G_OBJECT (cellpixbuf
), rb_cell_renderer_pixbuf_signals
[PIXBUF_CLICKED
], 0, path
);