1 /* gtkcellrenderertoggle.c
2 * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
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.
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.
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.
22 #include "gtkcellrenderertoggle.h"
24 #include "gtkmarshalers.h"
25 #include "gtkprivate.h"
26 #include "gtktreeprivate.h"
30 * SECTION:gtkcellrenderertoggle
31 * @Short_description: Renders a toggle button in a cell
32 * @Title: GtkCellRendererToggle
34 * #GtkCellRendererToggle renders a toggle button in a cell. The
35 * button is drawn as a radio or a checkbutton, depending on the
36 * #GtkCellRendererToggle:radio property.
37 * When activated, it emits the #GtkCellRendererToggle::toggled signal.
41 static void gtk_cell_renderer_toggle_get_property (GObject *object,
45 static void gtk_cell_renderer_toggle_set_property (GObject *object,
49 static void gtk_cell_renderer_toggle_get_size (GtkCellRenderer *cell,
51 const GdkRectangle *cell_area,
56 static void gtk_cell_renderer_toggle_render (GtkCellRenderer *cell,
59 const GdkRectangle *background_area,
60 const GdkRectangle *cell_area,
61 GtkCellRendererState flags);
62 static gboolean gtk_cell_renderer_toggle_activate (GtkCellRenderer *cell,
66 const GdkRectangle *background_area,
67 const GdkRectangle *cell_area,
68 GtkCellRendererState flags);
85 #define TOGGLE_WIDTH 16
87 static guint toggle_cell_signals[LAST_SIGNAL] = { 0 };
89 struct _GtkCellRendererTogglePrivate
94 guint activatable : 1;
95 guint inconsistent : 1;
100 G_DEFINE_TYPE (GtkCellRendererToggle, gtk_cell_renderer_toggle, GTK_TYPE_CELL_RENDERER)
104 gtk_cell_renderer_toggle_init (GtkCellRendererToggle *celltoggle)
106 GtkCellRendererTogglePrivate *priv;
108 celltoggle->priv = G_TYPE_INSTANCE_GET_PRIVATE (celltoggle,
109 GTK_TYPE_CELL_RENDERER_TOGGLE,
110 GtkCellRendererTogglePrivate);
111 priv = celltoggle->priv;
113 priv->activatable = TRUE;
114 priv->active = FALSE;
117 g_object_set (celltoggle, "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE, NULL);
118 gtk_cell_renderer_set_padding (GTK_CELL_RENDERER (celltoggle), 2, 2);
120 priv->indicator_size = TOGGLE_WIDTH;
121 priv->inconsistent = FALSE;
125 gtk_cell_renderer_toggle_class_init (GtkCellRendererToggleClass *class)
127 GObjectClass *object_class = G_OBJECT_CLASS (class);
128 GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class);
130 object_class->get_property = gtk_cell_renderer_toggle_get_property;
131 object_class->set_property = gtk_cell_renderer_toggle_set_property;
133 cell_class->get_size = gtk_cell_renderer_toggle_get_size;
134 cell_class->render = gtk_cell_renderer_toggle_render;
135 cell_class->activate = gtk_cell_renderer_toggle_activate;
137 g_object_class_install_property (object_class,
139 g_param_spec_boolean ("active",
141 P_("The toggle state of the button"),
143 GTK_PARAM_READWRITE));
145 g_object_class_install_property (object_class,
147 g_param_spec_boolean ("inconsistent",
148 P_("Inconsistent state"),
149 P_("The inconsistent state of the button"),
151 GTK_PARAM_READWRITE));
153 g_object_class_install_property (object_class,
155 g_param_spec_boolean ("activatable",
157 P_("The toggle button can be activated"),
159 GTK_PARAM_READWRITE));
161 g_object_class_install_property (object_class,
163 g_param_spec_boolean ("radio",
165 P_("Draw the toggle button as a radio button"),
167 GTK_PARAM_READWRITE));
169 g_object_class_install_property (object_class,
171 g_param_spec_int ("indicator-size",
172 P_("Indicator size"),
173 P_("Size of check or radio indicator"),
177 GTK_PARAM_READWRITE));
181 * GtkCellRendererToggle::toggled:
182 * @cell_renderer: the object which received the signal
183 * @path: string representation of #GtkTreePath describing the
186 * The ::toggled signal is emitted when the cell is toggled.
188 toggle_cell_signals[TOGGLED] =
189 g_signal_new (I_("toggled"),
190 G_OBJECT_CLASS_TYPE (object_class),
192 G_STRUCT_OFFSET (GtkCellRendererToggleClass, toggled),
194 _gtk_marshal_VOID__STRING,
198 g_type_class_add_private (object_class, sizeof (GtkCellRendererTogglePrivate));
202 gtk_cell_renderer_toggle_get_property (GObject *object,
207 GtkCellRendererToggle *celltoggle = GTK_CELL_RENDERER_TOGGLE (object);
208 GtkCellRendererTogglePrivate *priv = celltoggle->priv;
213 g_value_set_boolean (value, priv->active);
215 case PROP_INCONSISTENT:
216 g_value_set_boolean (value, priv->inconsistent);
218 case PROP_ACTIVATABLE:
219 g_value_set_boolean (value, priv->activatable);
222 g_value_set_boolean (value, priv->radio);
224 case PROP_INDICATOR_SIZE:
225 g_value_set_int (value, priv->indicator_size);
228 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
235 gtk_cell_renderer_toggle_set_property (GObject *object,
240 GtkCellRendererToggle *celltoggle = GTK_CELL_RENDERER_TOGGLE (object);
241 GtkCellRendererTogglePrivate *priv = celltoggle->priv;
246 priv->active = g_value_get_boolean (value);
248 case PROP_INCONSISTENT:
249 priv->inconsistent = g_value_get_boolean (value);
251 case PROP_ACTIVATABLE:
252 priv->activatable = g_value_get_boolean (value);
255 priv->radio = g_value_get_boolean (value);
257 case PROP_INDICATOR_SIZE:
258 priv->indicator_size = g_value_get_int (value);
261 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
267 * gtk_cell_renderer_toggle_new:
269 * Creates a new #GtkCellRendererToggle. Adjust rendering
270 * parameters using object properties. Object properties can be set
271 * globally (with g_object_set()). Also, with #GtkTreeViewColumn, you
272 * can bind a property to a value in a #GtkTreeModel. For example, you
273 * can bind the "active" property on the cell renderer to a boolean value
274 * in the model, thus causing the check button to reflect the state of
277 * Return value: the new cell renderer
280 gtk_cell_renderer_toggle_new (void)
282 return g_object_new (GTK_TYPE_CELL_RENDERER_TOGGLE, NULL);
286 gtk_cell_renderer_toggle_get_size (GtkCellRenderer *cell,
288 const GdkRectangle *cell_area,
294 GtkCellRendererTogglePrivate *priv;
299 priv = GTK_CELL_RENDERER_TOGGLE (cell)->priv;
301 gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
302 calc_width = xpad * 2 + priv->indicator_size;
303 calc_height = ypad * 2 + priv->indicator_size;
309 *height = calc_height;
313 gfloat xalign, yalign;
315 gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);
319 *x_offset = ((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ?
320 (1.0 - xalign) : xalign) * (cell_area->width - calc_width);
321 *x_offset = MAX (*x_offset, 0);
325 *y_offset = yalign * (cell_area->height - calc_height);
326 *y_offset = MAX (*y_offset, 0);
331 if (x_offset) *x_offset = 0;
332 if (y_offset) *y_offset = 0;
337 gtk_cell_renderer_toggle_render (GtkCellRenderer *cell,
340 const GdkRectangle *background_area,
341 const GdkRectangle *cell_area,
342 GtkCellRendererState flags)
344 GtkCellRendererToggle *celltoggle = GTK_CELL_RENDERER_TOGGLE (cell);
345 GtkCellRendererTogglePrivate *priv = celltoggle->priv;
346 GtkStyleContext *context;
348 gint x_offset, y_offset;
352 context = gtk_widget_get_style_context (widget);
353 gtk_cell_renderer_toggle_get_size (cell, widget, cell_area,
354 &x_offset, &y_offset,
356 gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
360 if (width <= 0 || height <= 0)
363 if (!priv->activatable)
364 state = GTK_STATE_FLAG_INSENSITIVE;
366 state = gtk_cell_renderer_get_state (cell, widget, flags);
368 if (priv->inconsistent)
369 state |= GTK_STATE_FLAG_INCONSISTENT;
370 else if (priv->active)
371 state |= GTK_STATE_FLAG_ACTIVE;
375 gdk_cairo_rectangle (cr, cell_area);
378 gtk_style_context_save (context);
379 gtk_style_context_set_state (context, state);
383 gtk_style_context_add_class (context, GTK_STYLE_CLASS_RADIO);
384 gtk_render_option (context, cr,
385 cell_area->x + x_offset + xpad,
386 cell_area->y + y_offset + ypad,
391 gtk_style_context_add_class (context, GTK_STYLE_CLASS_CHECK);
392 gtk_render_check (context, cr,
393 cell_area->x + x_offset + xpad,
394 cell_area->y + y_offset + ypad,
398 gtk_style_context_restore (context);
403 gtk_cell_renderer_toggle_activate (GtkCellRenderer *cell,
407 const GdkRectangle *background_area,
408 const GdkRectangle *cell_area,
409 GtkCellRendererState flags)
411 GtkCellRendererTogglePrivate *priv;
412 GtkCellRendererToggle *celltoggle;
414 celltoggle = GTK_CELL_RENDERER_TOGGLE (cell);
415 priv = celltoggle->priv;
417 if (priv->activatable)
419 g_signal_emit (cell, toggle_cell_signals[TOGGLED], 0, path);
427 * gtk_cell_renderer_toggle_set_radio:
428 * @toggle: a #GtkCellRendererToggle
429 * @radio: %TRUE to make the toggle look like a radio button
431 * If @radio is %TRUE, the cell renderer renders a radio toggle
432 * (i.e. a toggle in a group of mutually-exclusive toggles).
433 * If %FALSE, it renders a check toggle (a standalone boolean option).
434 * This can be set globally for the cell renderer, or changed just
435 * before rendering each cell in the model (for #GtkTreeView, you set
436 * up a per-row setting using #GtkTreeViewColumn to associate model
437 * columns with cell renderer properties).
440 gtk_cell_renderer_toggle_set_radio (GtkCellRendererToggle *toggle,
443 GtkCellRendererTogglePrivate *priv;
445 g_return_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (toggle));
453 * gtk_cell_renderer_toggle_get_radio:
454 * @toggle: a #GtkCellRendererToggle
456 * Returns whether we're rendering radio toggles rather than checkboxes.
458 * Return value: %TRUE if we're rendering radio toggles rather than checkboxes
461 gtk_cell_renderer_toggle_get_radio (GtkCellRendererToggle *toggle)
463 g_return_val_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (toggle), FALSE);
465 return toggle->priv->radio;
469 * gtk_cell_renderer_toggle_get_active:
470 * @toggle: a #GtkCellRendererToggle
472 * Returns whether the cell renderer is active. See
473 * gtk_cell_renderer_toggle_set_active().
475 * Return value: %TRUE if the cell renderer is active.
478 gtk_cell_renderer_toggle_get_active (GtkCellRendererToggle *toggle)
480 g_return_val_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (toggle), FALSE);
482 return toggle->priv->active;
486 * gtk_cell_renderer_toggle_set_active:
487 * @toggle: a #GtkCellRendererToggle.
488 * @setting: the value to set.
490 * Activates or deactivates a cell renderer.
493 gtk_cell_renderer_toggle_set_active (GtkCellRendererToggle *toggle,
496 g_return_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (toggle));
498 g_object_set (toggle, "active", setting ? TRUE : FALSE, NULL);
502 * gtk_cell_renderer_toggle_get_activatable:
503 * @toggle: a #GtkCellRendererToggle
505 * Returns whether the cell renderer is activatable. See
506 * gtk_cell_renderer_toggle_set_activatable().
508 * Return value: %TRUE if the cell renderer is activatable.
513 gtk_cell_renderer_toggle_get_activatable (GtkCellRendererToggle *toggle)
515 g_return_val_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (toggle), FALSE);
517 return toggle->priv->activatable;
521 * gtk_cell_renderer_toggle_set_activatable:
522 * @toggle: a #GtkCellRendererToggle.
523 * @setting: the value to set.
525 * Makes the cell renderer activatable.
530 gtk_cell_renderer_toggle_set_activatable (GtkCellRendererToggle *toggle,
533 GtkCellRendererTogglePrivate *priv;
535 g_return_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (toggle));
539 if (priv->activatable != setting)
541 priv->activatable = setting ? TRUE : FALSE;
542 g_object_notify (G_OBJECT (toggle), "activatable");