8 #include "ygtkcellrendererbutton.h"
11 #define INNER_BORDER 4
12 #define OUTER_BORDER 1
13 #define BORDER (INNER_BORDER+OUTER_BORDER)
15 #define PIXBUF_TEXT_SPACING 4
26 static guint toggle_cell_signal = 0;
32 bcell->active = FALSE;
33 GtkCellRenderer *cell = GTK_CELL_RENDERER (bcell);
34 g_object_set(cell,
"xpad", BORDER,
"ypad", BORDER,
"mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE, NULL);
35 bcell->icon_size = 16;
40 if (cell->icon_name) {
41 g_free (cell->icon_name);
42 cell->icon_name = NULL;
45 g_object_unref (cell->pixbuf);
50 static void ygtk_cell_renderer_button_finalize (GObject *
object)
53 unset_image_properties (ccell);
54 G_OBJECT_CLASS (ygtk_cell_renderer_button_parent_class)->finalize (
object);
57 static void ygtk_cell_renderer_button_get_property (GObject *
object,
58 guint param_id, GValue *value, GParamSpec *pspec)
60 if (pspec->owner_type == YGTK_TYPE_CELL_RENDERER_BUTTON) {
64 g_value_set_boolean (value, bcell->active);
67 g_value_set_object (value, G_OBJECT (bcell->pixbuf));
70 g_value_set_string (value, bcell->stock_id);
73 g_value_set_string (value, bcell->icon_name);
76 g_value_set_uint (value, bcell->icon_size);
81 G_OBJECT_CLASS (ygtk_cell_renderer_button_parent_class)->get_property (
82 object, param_id, value, pspec);
85 static void ygtk_cell_renderer_button_set_property (GObject *
object,
86 guint param_id,
const GValue *value, GParamSpec *pspec)
88 if (pspec->owner_type == YGTK_TYPE_CELL_RENDERER_BUTTON) {
92 bcell->active = g_value_get_boolean (value);
95 unset_image_properties (bcell);
96 bcell->pixbuf = (GdkPixbuf *) g_value_dup_object (value);
99 unset_image_properties (bcell);
100 bcell->stock_id = g_value_dup_string (value);
103 unset_image_properties (bcell);
104 bcell->icon_name = g_value_dup_string (value);
107 bcell->icon_size = g_value_get_uint (value);
112 G_OBJECT_CLASS (ygtk_cell_renderer_button_parent_class)->set_property (
113 object, param_id, value, pspec);
118 GtkCellRendererText *tcell = GTK_CELL_RENDERER_TEXT (bcell);
120 g_object_get (G_OBJECT (tcell),
"text", &text, NULL);
121 PangoLayout *layout = NULL;
123 layout = gtk_widget_create_pango_layout (widget, text);
131 if (!cell->pixbuf && (cell->icon_name || cell->stock_id)) {
132 if (cell->icon_name) {
133 GtkIconTheme *theme = gtk_icon_theme_get_default();
135 cell->pixbuf = gtk_icon_theme_load_icon (theme, cell->icon_name,
136 cell->icon_size, GTK_ICON_LOOKUP_FORCE_SIZE, &error);
138 g_warning (
"Couldn't load ygtk-cell-renderer-button icon: %s\nGtk: %s\n",
139 cell->icon_name, error->message);
142 cell->pixbuf = gtk_widget_render_icon_pixbuf (
143 widget, cell->stock_id, GTK_ICON_SIZE_BUTTON);
147 static void ygtk_cell_renderer_button_get_size_full (GtkCellRenderer *cell,
148 GtkWidget *widget,
const GdkRectangle *cell_area, gint *_xoffset, gint *_yoffset,
149 gint *_width, gint *_height, gint *_pixbuf_xoffset, gint *_pixbuf_yoffset,
150 gint *_pixbuf_width, gint *_pixbuf_height, gint *_text_xoffset, gint *_text_yoffset)
153 ensure_pixbuf (bcell, widget);
155 int pixbuf_width = 0, pixbuf_height = 0;
157 pixbuf_width = gdk_pixbuf_get_width (bcell->pixbuf);
158 pixbuf_height = gdk_pixbuf_get_height (bcell->pixbuf);
161 PangoLayout *layout = create_layout (bcell, widget);
162 int text_width = 0, text_height = 0;
165 pango_layout_get_pixel_extents (layout, NULL, &rect);
166 text_width = rect.x + rect.width;
167 text_height = rect.y + rect.height;
171 width = pixbuf_width + text_width;
172 if (pixbuf_width && text_width)
173 width += PIXBUF_TEXT_SPACING;
174 height = MAX (pixbuf_height, text_height);
176 gfloat xalign, yalign;
182 "ypad", &ypad, NULL);
185 gboolean reverse = gtk_widget_get_default_direction() == GTK_TEXT_DIR_RTL;
187 xalign = 1.0 - xalign;
189 int cell_width = cell_area->width - xpad*2,
190 cell_height = cell_area->height - ypad*2;
191 int xoffset = (xalign * (cell_width - width)) + xpad;
192 int yoffset = (yalign * (cell_height - height)) + ypad;
193 if (_xoffset) *_xoffset = xoffset;
194 if (_yoffset) *_yoffset = yoffset;
196 int text_x = xoffset, text_y;
197 if (pixbuf_width && !reverse)
198 text_x += (pixbuf_width + PIXBUF_TEXT_SPACING);
199 text_y = (yalign * (cell_height - text_height)) + ypad;
201 int pixbuf_x = xoffset, pixbuf_y;
202 if (text_width && reverse)
203 pixbuf_x += (text_width + PIXBUF_TEXT_SPACING);
204 pixbuf_y = (yalign * (cell_height - pixbuf_height)) + ypad;
206 if (_pixbuf_xoffset) *_pixbuf_xoffset = pixbuf_x;
207 if (_pixbuf_yoffset) *_pixbuf_yoffset = pixbuf_y;
208 if (_pixbuf_width) *_pixbuf_width = pixbuf_width;
209 if (_pixbuf_height) *_pixbuf_height = pixbuf_height;
210 if (_text_xoffset) *_text_xoffset = text_x;
211 if (_text_yoffset) *_text_yoffset = text_y;
214 if (_width) *_width = width + (xpad * 2);
215 if (_height) *_height = height + (ypad * 2);
218 static void ygtk_cell_renderer_button_get_size (GtkCellRenderer *cell,
219 GtkWidget *widget,
const GdkRectangle *cell_area, gint *xoffset, gint *yoffset,
220 gint *width, gint *height)
222 ygtk_cell_renderer_button_get_size_full (cell, widget, cell_area,
223 xoffset, yoffset, width, height, NULL, NULL, NULL, NULL, NULL, NULL);
226 static void ygtk_cell_renderer_button_render(
227 GtkCellRenderer *cell, cairo_t *cr, GtkWidget *widget,
228 const GdkRectangle *background_area,
const GdkRectangle *cell_area,
229 GtkCellRendererState flags)
233 GtkStateType state = GTK_STATE_NORMAL;
234 if (!gtk_cell_renderer_get_sensitive(cell) || gtk_widget_get_state (widget) == GTK_STATE_INSENSITIVE)
235 state = GTK_STATE_INSENSITIVE;
236 else if ((flags & GTK_CELL_RENDERER_PRELIT))
237 state = GTK_STATE_PRELIGHT;
239 state = GTK_STATE_ACTIVE;
241 GtkStyleContext *style = gtk_widget_get_style_context(widget);
242 gtk_style_context_save(style);
243 gtk_style_context_set_state(style, state);
244 gtk_style_context_add_class (style, GTK_STYLE_CLASS_BUTTON);
246 int text_xoffset, text_yoffset, pixbuf_xoffset, pixbuf_yoffset, pixbuf_width,
247 pixbuf_height, width, height;
248 ygtk_cell_renderer_button_get_size_full (cell, widget, cell_area,
249 NULL, NULL, &width, &height, &pixbuf_xoffset, &pixbuf_yoffset, &pixbuf_width,
250 &pixbuf_height, &text_xoffset, &text_yoffset);
252 int x = cell_area->x + OUTER_BORDER + 1;
253 int y = cell_area->y + (cell_area->height - height)/2 + OUTER_BORDER;
254 width -= OUTER_BORDER*2; height -= OUTER_BORDER*2;
256 gtk_render_background (style, cr, x, y, width, height);
257 gtk_render_frame (style, cr, x, y, width, height);
261 ensure_pixbuf (bcell, widget);
263 int _x = x + pixbuf_xoffset, _y = y + pixbuf_yoffset;
265 _x += DEPRESS_PAD; _y += DEPRESS_PAD;
267 gdk_cairo_set_source_pixbuf (cr, bcell->pixbuf, _x, _y);
268 cairo_rectangle (cr, _x, _y, pixbuf_width, pixbuf_height);
272 PangoLayout *layout = create_layout (bcell, widget);
274 int _x = cell_area->x + text_xoffset, _y = cell_area->y + text_yoffset;
276 _x += DEPRESS_PAD; _y += DEPRESS_PAD;
279 gtk_render_layout(style, cr, _x, _y, layout);
280 g_object_unref (G_OBJECT (layout));
283 gtk_style_context_restore(style);
286 static gboolean ygtk_cell_renderer_button_activate (GtkCellRenderer *cell,
287 GdkEvent *event, GtkWidget *widget,
const gchar *path,
const GdkRectangle *background_area,
288 const GdkRectangle *cell_area, GtkCellRendererState flags)
290 GdkEventButton *_event = &
event->button;
291 if (_event->x >= cell_area->x && _event->x <= cell_area->x + cell_area->width) {
292 g_signal_emit (cell, toggle_cell_signal, 0, path);
298 GtkCellRenderer *ygtk_cell_renderer_button_new (
void)
299 {
return g_object_new (YGTK_TYPE_CELL_RENDERER_BUTTON, NULL); }
302 {
return cell->active; }
306 GObjectClass *object_class = G_OBJECT_CLASS (
class);
307 object_class->get_property = ygtk_cell_renderer_button_get_property;
308 object_class->set_property = ygtk_cell_renderer_button_set_property;
309 object_class->finalize = ygtk_cell_renderer_button_finalize;
311 GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (
class);
312 cell_class->get_size = ygtk_cell_renderer_button_get_size;
313 cell_class->render = ygtk_cell_renderer_button_render;
314 cell_class->activate = ygtk_cell_renderer_button_activate;
316 GParamFlags readwrite_flag =
317 G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB;
318 g_object_class_install_property (object_class, PROP_ACTIVE,
319 g_param_spec_boolean (
"active",
"Toggle state",
"The toggle state of the button",
320 FALSE, readwrite_flag));
321 g_object_class_install_property (object_class, PROP_PIXBUF,
322 g_param_spec_object (
"pixbuf",
"Image",
"Side image", GDK_TYPE_PIXBUF, readwrite_flag));
323 g_object_class_install_property (object_class, PROP_ICON_NAME,
324 g_param_spec_string (
"icon-name",
"Icon name",
"Theme icon to render", NULL, readwrite_flag));
325 g_object_class_install_property (object_class, PROP_STOCK_ID,
326 g_param_spec_string (
"stock-id",
"Stock id",
"Stock icon to render", NULL, readwrite_flag));
327 g_object_class_install_property (object_class, PROP_ICON_SIZE,
328 g_param_spec_uint (
"icon-size",
"Size",
"Size of the icon to render",
329 0, G_MAXUINT, 22, readwrite_flag));
331 toggle_cell_signal = g_signal_new (
"toggled", G_OBJECT_CLASS_TYPE (object_class),
333 NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING);