X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkcellrenderertoggle.c;h=f94ff2a71a04b09382fb2c7b698bd7712cff0034;hb=e09957a47da9425cc26d1b33cb4e9cc3e92e9ac7;hp=084d3d4afab146dd9806fabf3b6ca72b89f841c8;hpb=3612aee5857360cf6dcde2be79a6d60bebf4f8bb;p=~andy%2Fgtk diff --git a/gtk/gtkcellrenderertoggle.c b/gtk/gtkcellrenderertoggle.c index 084d3d4af..f94ff2a71 100644 --- a/gtk/gtkcellrenderertoggle.c +++ b/gtk/gtkcellrenderertoggle.c @@ -12,18 +12,30 @@ * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ -#include +#include "config.h" #include -#include "gtkalias.h" #include "gtkcellrenderertoggle.h" #include "gtkintl.h" #include "gtkmarshalers.h" +#include "gtkprivate.h" #include "gtktreeprivate.h" +#include "a11y/gtkbooleancellaccessible.h" + + +/** + * SECTION:gtkcellrenderertoggle + * @Short_description: Renders a toggle button in a cell + * @Title: GtkCellRendererToggle + * + * #GtkCellRendererToggle renders a toggle button in a cell. The + * button is drawn as a radio or a checkbutton, depending on the + * #GtkCellRendererToggle:radio property. + * When activated, it emits the #GtkCellRendererToggle::toggled signal. + */ + static void gtk_cell_renderer_toggle_get_property (GObject *object, guint param_id, @@ -33,28 +45,25 @@ static void gtk_cell_renderer_toggle_set_property (GObject * guint param_id, const GValue *value, GParamSpec *pspec); -static void gtk_cell_renderer_toggle_init (GtkCellRendererToggle *celltext); -static void gtk_cell_renderer_toggle_class_init (GtkCellRendererToggleClass *class); static void gtk_cell_renderer_toggle_get_size (GtkCellRenderer *cell, GtkWidget *widget, - GdkRectangle *cell_area, + const GdkRectangle *cell_area, gint *x_offset, gint *y_offset, gint *width, gint *height); static void gtk_cell_renderer_toggle_render (GtkCellRenderer *cell, - GdkWindow *window, + cairo_t *cr, GtkWidget *widget, - GdkRectangle *background_area, - GdkRectangle *cell_area, - GdkRectangle *expose_area, + const GdkRectangle *background_area, + const GdkRectangle *cell_area, GtkCellRendererState flags); static gboolean gtk_cell_renderer_toggle_activate (GtkCellRenderer *cell, GdkEvent *event, GtkWidget *widget, const gchar *path, - GdkRectangle *background_area, - GdkRectangle *cell_area, + const GdkRectangle *background_area, + const GdkRectangle *cell_area, GtkCellRendererState flags); @@ -64,63 +73,51 @@ enum { }; enum { - PROP_ZERO, + PROP_0, PROP_ACTIVATABLE, PROP_ACTIVE, PROP_RADIO, - PROP_INCONSISTENT + PROP_INCONSISTENT, + PROP_INDICATOR_SIZE }; -#define TOGGLE_WIDTH 12 +#define TOGGLE_WIDTH 16 static guint toggle_cell_signals[LAST_SIGNAL] = { 0 }; -#define GTK_CELL_RENDERER_TOGGLE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_CELL_RENDERER_TOGGLE, GtkCellRendererTogglePrivate)) - -typedef struct _GtkCellRendererTogglePrivate GtkCellRendererTogglePrivate; struct _GtkCellRendererTogglePrivate { + gint indicator_size; + + guint active : 1; + guint activatable : 1; guint inconsistent : 1; + guint radio : 1; }; -GType -gtk_cell_renderer_toggle_get_type (void) -{ - static GType cell_toggle_type = 0; +G_DEFINE_TYPE (GtkCellRendererToggle, gtk_cell_renderer_toggle, GTK_TYPE_CELL_RENDERER) - if (!cell_toggle_type) - { - static const GTypeInfo cell_toggle_info = - { - sizeof (GtkCellRendererToggleClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) gtk_cell_renderer_toggle_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GtkCellRendererToggle), - 0, /* n_preallocs */ - (GInstanceInitFunc) gtk_cell_renderer_toggle_init, - }; - - cell_toggle_type = - g_type_register_static (GTK_TYPE_CELL_RENDERER, "GtkCellRendererToggle", - &cell_toggle_info, 0); - } - - return cell_toggle_type; -} static void gtk_cell_renderer_toggle_init (GtkCellRendererToggle *celltoggle) { - celltoggle->activatable = TRUE; - celltoggle->active = FALSE; - celltoggle->radio = FALSE; - GTK_CELL_RENDERER (celltoggle)->mode = GTK_CELL_RENDERER_MODE_ACTIVATABLE; - GTK_CELL_RENDERER (celltoggle)->xpad = 2; - GTK_CELL_RENDERER (celltoggle)->ypad = 2; + GtkCellRendererTogglePrivate *priv; + + celltoggle->priv = G_TYPE_INSTANCE_GET_PRIVATE (celltoggle, + GTK_TYPE_CELL_RENDERER_TOGGLE, + GtkCellRendererTogglePrivate); + priv = celltoggle->priv; + + priv->activatable = TRUE; + priv->active = FALSE; + priv->radio = FALSE; + + g_object_set (celltoggle, "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE, NULL); + gtk_cell_renderer_set_padding (GTK_CELL_RENDERER (celltoggle), 2, 2); + + priv->indicator_size = TOGGLE_WIDTH; + priv->inconsistent = FALSE; } static void @@ -142,8 +139,7 @@ gtk_cell_renderer_toggle_class_init (GtkCellRendererToggleClass *class) P_("Toggle state"), P_("The toggle state of the button"), FALSE, - G_PARAM_READABLE | - G_PARAM_WRITABLE)); + GTK_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_INCONSISTENT, @@ -151,8 +147,7 @@ gtk_cell_renderer_toggle_class_init (GtkCellRendererToggleClass *class) P_("Inconsistent state"), P_("The inconsistent state of the button"), FALSE, - G_PARAM_READABLE | - G_PARAM_WRITABLE)); + GTK_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_ACTIVATABLE, @@ -160,8 +155,7 @@ gtk_cell_renderer_toggle_class_init (GtkCellRendererToggleClass *class) P_("Activatable"), P_("The toggle button can be activated"), TRUE, - G_PARAM_READABLE | - G_PARAM_WRITABLE)); + GTK_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_RADIO, @@ -169,8 +163,17 @@ gtk_cell_renderer_toggle_class_init (GtkCellRendererToggleClass *class) P_("Radio state"), P_("Draw the toggle button as a radio button"), FALSE, - G_PARAM_READABLE | - G_PARAM_WRITABLE)); + GTK_PARAM_READWRITE)); + + g_object_class_install_property (object_class, + PROP_INDICATOR_SIZE, + g_param_spec_int ("indicator-size", + P_("Indicator size"), + P_("Size of check or radio indicator"), + 0, + G_MAXINT, + TOGGLE_WIDTH, + GTK_PARAM_READWRITE)); /** @@ -182,7 +185,7 @@ gtk_cell_renderer_toggle_class_init (GtkCellRendererToggleClass *class) * The ::toggled signal is emitted when the cell is toggled. **/ toggle_cell_signals[TOGGLED] = - g_signal_new ("toggled", + g_signal_new (I_("toggled"), G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GtkCellRendererToggleClass, toggled), @@ -192,6 +195,8 @@ gtk_cell_renderer_toggle_class_init (GtkCellRendererToggleClass *class) G_TYPE_STRING); g_type_class_add_private (object_class, sizeof (GtkCellRendererTogglePrivate)); + + gtk_cell_renderer_class_set_accessible_type (cell_class, GTK_TYPE_BOOLEAN_CELL_ACCESSIBLE); } static void @@ -201,23 +206,24 @@ gtk_cell_renderer_toggle_get_property (GObject *object, GParamSpec *pspec) { GtkCellRendererToggle *celltoggle = GTK_CELL_RENDERER_TOGGLE (object); - GtkCellRendererTogglePrivate *priv; + GtkCellRendererTogglePrivate *priv = celltoggle->priv; - priv = GTK_CELL_RENDERER_TOGGLE_GET_PRIVATE (object); - switch (param_id) { case PROP_ACTIVE: - g_value_set_boolean (value, celltoggle->active); + g_value_set_boolean (value, priv->active); break; case PROP_INCONSISTENT: g_value_set_boolean (value, priv->inconsistent); break; case PROP_ACTIVATABLE: - g_value_set_boolean (value, celltoggle->activatable); + g_value_set_boolean (value, priv->activatable); break; case PROP_RADIO: - g_value_set_boolean (value, celltoggle->radio); + g_value_set_boolean (value, priv->radio); + break; + case PROP_INDICATOR_SIZE: + g_value_set_int (value, priv->indicator_size); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); @@ -233,27 +239,24 @@ gtk_cell_renderer_toggle_set_property (GObject *object, GParamSpec *pspec) { GtkCellRendererToggle *celltoggle = GTK_CELL_RENDERER_TOGGLE (object); - GtkCellRendererTogglePrivate *priv; + GtkCellRendererTogglePrivate *priv = celltoggle->priv; - priv = GTK_CELL_RENDERER_TOGGLE_GET_PRIVATE (object); - switch (param_id) { case PROP_ACTIVE: - celltoggle->active = g_value_get_boolean (value); - g_object_notify (G_OBJECT(object), "active"); + priv->active = g_value_get_boolean (value); break; case PROP_INCONSISTENT: priv->inconsistent = g_value_get_boolean (value); - g_object_notify (G_OBJECT (object), "inconsistent"); break; case PROP_ACTIVATABLE: - celltoggle->activatable = g_value_get_boolean (value); - g_object_notify (G_OBJECT(object), "activatable"); + priv->activatable = g_value_get_boolean (value); break; case PROP_RADIO: - celltoggle->radio = g_value_get_boolean (value); - g_object_notify (G_OBJECT(object), "radio"); + priv->radio = g_value_get_boolean (value); + break; + case PROP_INDICATOR_SIZE: + priv->indicator_size = g_value_get_int (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); @@ -263,7 +266,7 @@ gtk_cell_renderer_toggle_set_property (GObject *object, /** * gtk_cell_renderer_toggle_new: - * + * * Creates a new #GtkCellRendererToggle. Adjust rendering * parameters using object properties. Object properties can be set * globally (with g_object_set()). Also, with #GtkTreeViewColumn, you @@ -271,7 +274,7 @@ gtk_cell_renderer_toggle_set_property (GObject *object, * can bind the "active" property on the cell renderer to a boolean value * in the model, thus causing the check button to reflect the state of * the model. - * + * * Return value: the new cell renderer **/ GtkCellRenderer * @@ -281,19 +284,24 @@ gtk_cell_renderer_toggle_new (void) } static void -gtk_cell_renderer_toggle_get_size (GtkCellRenderer *cell, - GtkWidget *widget, - GdkRectangle *cell_area, - gint *x_offset, - gint *y_offset, - gint *width, - gint *height) +gtk_cell_renderer_toggle_get_size (GtkCellRenderer *cell, + GtkWidget *widget, + const GdkRectangle *cell_area, + gint *x_offset, + gint *y_offset, + gint *width, + gint *height) { + GtkCellRendererTogglePrivate *priv; gint calc_width; gint calc_height; + gint xpad, ypad; - calc_width = (gint) cell->xpad * 2 + TOGGLE_WIDTH; - calc_height = (gint) cell->ypad * 2 + TOGGLE_WIDTH; + priv = GTK_CELL_RENDERER_TOGGLE (cell)->priv; + + gtk_cell_renderer_get_padding (cell, &xpad, &ypad); + calc_width = xpad * 2 + priv->indicator_size; + calc_height = ypad * 2 + priv->indicator_size; if (width) *width = calc_width; @@ -303,91 +311,95 @@ gtk_cell_renderer_toggle_get_size (GtkCellRenderer *cell, if (cell_area) { + gfloat xalign, yalign; + + gtk_cell_renderer_get_alignment (cell, &xalign, &yalign); + if (x_offset) { *x_offset = ((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ? - (1.0 - cell->xalign) : cell->xalign) * (cell_area->width - calc_width); + (1.0 - xalign) : xalign) * (cell_area->width - calc_width); *x_offset = MAX (*x_offset, 0); } if (y_offset) { - *y_offset = cell->yalign * (cell_area->height - calc_height); + *y_offset = yalign * (cell_area->height - calc_height); *y_offset = MAX (*y_offset, 0); } } + else + { + if (x_offset) *x_offset = 0; + if (y_offset) *y_offset = 0; + } } static void gtk_cell_renderer_toggle_render (GtkCellRenderer *cell, - GdkDrawable *window, + cairo_t *cr, GtkWidget *widget, - GdkRectangle *background_area, - GdkRectangle *cell_area, - GdkRectangle *expose_area, + const GdkRectangle *background_area, + const GdkRectangle *cell_area, GtkCellRendererState flags) { - GtkCellRendererToggle *celltoggle = (GtkCellRendererToggle *) cell; - GtkCellRendererTogglePrivate *priv; + GtkCellRendererToggle *celltoggle = GTK_CELL_RENDERER_TOGGLE (cell); + GtkCellRendererTogglePrivate *priv = celltoggle->priv; + GtkStyleContext *context; gint width, height; gint x_offset, y_offset; - GtkShadowType shadow; - GtkStateType state = 0; - - priv = GTK_CELL_RENDERER_TOGGLE_GET_PRIVATE (cell); + gint xpad, ypad; + GtkStateFlags state; + context = gtk_widget_get_style_context (widget); gtk_cell_renderer_toggle_get_size (cell, widget, cell_area, &x_offset, &y_offset, &width, &height); - width -= cell->xpad*2; - height -= cell->ypad*2; + gtk_cell_renderer_get_padding (cell, &xpad, &ypad); + width -= xpad * 2; + height -= ypad * 2; if (width <= 0 || height <= 0) return; + state = gtk_cell_renderer_get_state (cell, widget, flags); + + if (!priv->activatable) + state |= GTK_STATE_FLAG_INSENSITIVE; + + state &= ~(GTK_STATE_FLAG_INCONSISTENT | GTK_STATE_FLAG_ACTIVE); + if (priv->inconsistent) - shadow = GTK_SHADOW_ETCHED_IN; - else - shadow = celltoggle->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT; + state |= GTK_STATE_FLAG_INCONSISTENT; + else if (priv->active) + state |= GTK_STATE_FLAG_ACTIVE; - if (!cell->sensitive) - { - state = GTK_STATE_INSENSITIVE; - } - else if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED) - { - if (GTK_WIDGET_HAS_FOCUS (widget)) - state = GTK_STATE_SELECTED; - else - state = GTK_STATE_ACTIVE; - } - else - { - if (celltoggle->activatable) - state = GTK_STATE_NORMAL; - else - state = GTK_STATE_INSENSITIVE; - } + cairo_save (cr); - if (celltoggle->radio) + gdk_cairo_rectangle (cr, cell_area); + cairo_clip (cr); + + gtk_style_context_save (context); + gtk_style_context_set_state (context, state); + + if (priv->radio) { - gtk_paint_option (widget->style, - window, - state, shadow, - expose_area, widget, "cellradio", - cell_area->x + x_offset + cell->xpad, - cell_area->y + y_offset + cell->ypad, - width - 1, height - 1); + gtk_style_context_add_class (context, GTK_STYLE_CLASS_RADIO); + gtk_render_option (context, cr, + cell_area->x + x_offset + xpad, + cell_area->y + y_offset + ypad, + width, height); } else { - gtk_paint_check (widget->style, - window, - state, shadow, - expose_area, widget, "cellcheck", - cell_area->x + x_offset + cell->xpad, - cell_area->y + y_offset + cell->ypad, - width - 1, height - 1); + gtk_style_context_add_class (context, GTK_STYLE_CLASS_CHECK); + gtk_render_check (context, cr, + cell_area->x + x_offset + xpad, + cell_area->y + y_offset + ypad, + width, height); } + + gtk_style_context_restore (context); + cairo_restore (cr); } static gint @@ -395,14 +407,17 @@ gtk_cell_renderer_toggle_activate (GtkCellRenderer *cell, GdkEvent *event, GtkWidget *widget, const gchar *path, - GdkRectangle *background_area, - GdkRectangle *cell_area, + const GdkRectangle *background_area, + const GdkRectangle *cell_area, GtkCellRendererState flags) { + GtkCellRendererTogglePrivate *priv; GtkCellRendererToggle *celltoggle; - + celltoggle = GTK_CELL_RENDERER_TOGGLE (cell); - if (celltoggle->activatable) + priv = celltoggle->priv; + + if (priv->activatable) { g_signal_emit (cell, toggle_cell_signals[TOGGLED], 0, path); return TRUE; @@ -428,16 +443,20 @@ void gtk_cell_renderer_toggle_set_radio (GtkCellRendererToggle *toggle, gboolean radio) { + GtkCellRendererTogglePrivate *priv; + g_return_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (toggle)); - toggle->radio = radio; + priv = toggle->priv; + + priv->radio = radio; } /** * gtk_cell_renderer_toggle_get_radio: * @toggle: a #GtkCellRendererToggle * - * Returns wether we're rendering radio toggles rather than checkboxes. + * Returns whether we're rendering radio toggles rather than checkboxes. * * Return value: %TRUE if we're rendering radio toggles rather than checkboxes **/ @@ -446,7 +465,7 @@ gtk_cell_renderer_toggle_get_radio (GtkCellRendererToggle *toggle) { g_return_val_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (toggle), FALSE); - return toggle->radio; + return toggle->priv->radio; } /** @@ -463,7 +482,7 @@ gtk_cell_renderer_toggle_get_active (GtkCellRendererToggle *toggle) { g_return_val_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (toggle), FALSE); - return toggle->active; + return toggle->priv->active; } /** @@ -481,3 +500,48 @@ gtk_cell_renderer_toggle_set_active (GtkCellRendererToggle *toggle, g_object_set (toggle, "active", setting ? TRUE : FALSE, NULL); } + +/** + * gtk_cell_renderer_toggle_get_activatable: + * @toggle: a #GtkCellRendererToggle + * + * Returns whether the cell renderer is activatable. See + * gtk_cell_renderer_toggle_set_activatable(). + * + * Return value: %TRUE if the cell renderer is activatable. + * + * Since: 2.18 + **/ +gboolean +gtk_cell_renderer_toggle_get_activatable (GtkCellRendererToggle *toggle) +{ + g_return_val_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (toggle), FALSE); + + return toggle->priv->activatable; +} + +/** + * gtk_cell_renderer_toggle_set_activatable: + * @toggle: a #GtkCellRendererToggle. + * @setting: the value to set. + * + * Makes the cell renderer activatable. + * + * Since: 2.18 + **/ +void +gtk_cell_renderer_toggle_set_activatable (GtkCellRendererToggle *toggle, + gboolean setting) +{ + GtkCellRendererTogglePrivate *priv; + + g_return_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (toggle)); + + priv = toggle->priv; + + if (priv->activatable != setting) + { + priv->activatable = setting ? TRUE : FALSE; + g_object_notify (G_OBJECT (toggle), "activatable"); + } +}