X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkcellrenderertoggle.c;h=f94ff2a71a04b09382fb2c7b698bd7712cff0034;hb=cb27c4b08c278ac7e8a882b638dbf30acd1436cf;hp=3831bfee3378e8f0697db8de81b0519e94857215;hpb=ba8f8b4dd85409cb5c2df2db7eedbe3b90827512;p=~andy%2Fgtk diff --git a/gtk/gtkcellrenderertoggle.c b/gtk/gtkcellrenderertoggle.c index 3831bfee3..f94ff2a71 100644 --- a/gtk/gtkcellrenderertoggle.c +++ b/gtk/gtkcellrenderertoggle.c @@ -12,16 +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 "config.h" #include -#include -#include +#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, @@ -31,29 +45,26 @@ 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, - guint flags); + 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, - guint flags); + const GdkRectangle *background_area, + const GdkRectangle *cell_area, + GtkCellRendererState flags); enum { @@ -62,53 +73,51 @@ enum { }; enum { - PROP_ZERO, + PROP_0, PROP_ACTIVATABLE, PROP_ACTIVE, - PROP_RADIO + PROP_RADIO, + PROP_INCONSISTENT, + PROP_INDICATOR_SIZE }; - -#define TOGGLE_WIDTH 12 +#define TOGGLE_WIDTH 16 static guint toggle_cell_signals[LAST_SIGNAL] = { 0 }; - -GtkType -gtk_cell_renderer_toggle_get_type (void) +struct _GtkCellRendererTogglePrivate { - static GtkType cell_toggle_type = 0; + gint indicator_size; - 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); - } + guint active : 1; + guint activatable : 1; + guint inconsistent : 1; + guint radio : 1; +}; + + +G_DEFINE_TYPE (GtkCellRendererToggle, gtk_cell_renderer_toggle, GTK_TYPE_CELL_RENDERER) - 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 @@ -127,39 +136,67 @@ gtk_cell_renderer_toggle_class_init (GtkCellRendererToggleClass *class) g_object_class_install_property (object_class, PROP_ACTIVE, g_param_spec_boolean ("active", - _("Toggle state"), - _("The toggle state of the button"), + 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, + g_param_spec_boolean ("inconsistent", + P_("Inconsistent state"), + P_("The inconsistent state of the button"), + FALSE, + GTK_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_ACTIVATABLE, g_param_spec_boolean ("activatable", - _("Activatable"), - _("The toggle button can be activated"), + 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, g_param_spec_boolean ("radio", - _("Radio state"), - _("Draw the toggle button as a radio button"), + 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)); + + /** + * GtkCellRendererToggle::toggled: + * @cell_renderer: the object which received the signal + * @path: string representation of #GtkTreePath describing the + * event location + * + * The ::toggled signal is emitted when the cell is toggled. + **/ toggle_cell_signals[TOGGLED] = - gtk_signal_new ("toggled", - GTK_RUN_LAST, - GTK_CLASS_TYPE (object_class), - GTK_SIGNAL_OFFSET (GtkCellRendererToggleClass, toggled), - _gtk_marshal_VOID__STRING, - GTK_TYPE_NONE, 1, - GTK_TYPE_STRING); + g_signal_new (I_("toggled"), + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkCellRendererToggleClass, toggled), + NULL, NULL, + _gtk_marshal_VOID__STRING, + G_TYPE_NONE, 1, + 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 @@ -169,17 +206,24 @@ gtk_cell_renderer_toggle_get_property (GObject *object, GParamSpec *pspec) { GtkCellRendererToggle *celltoggle = GTK_CELL_RENDERER_TOGGLE (object); - + GtkCellRendererTogglePrivate *priv = celltoggle->priv; + 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); @@ -195,20 +239,24 @@ gtk_cell_renderer_toggle_set_property (GObject *object, GParamSpec *pspec) { GtkCellRendererToggle *celltoggle = GTK_CELL_RENDERER_TOGGLE (object); - + GtkCellRendererTogglePrivate *priv = celltoggle->priv; + 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); 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); @@ -218,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 @@ -226,29 +274,34 @@ 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 * gtk_cell_renderer_toggle_new (void) { - return GTK_CELL_RENDERER (gtk_type_new (gtk_cell_renderer_toggle_get_type ())); + return g_object_new (GTK_TYPE_CELL_RENDERER_TOGGLE, NULL); } 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; + + priv = GTK_CELL_RENDERER_TOGGLE (cell)->priv; - calc_width = (gint) cell->xpad * 2 + TOGGLE_WIDTH; - calc_height = (gint) cell->ypad * 2 + TOGGLE_WIDTH; + 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; @@ -258,97 +311,115 @@ 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 = cell->xalign * (cell_area->width - calc_width); + *x_offset = ((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ? + (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, - GdkWindow *window, - GtkWidget *widget, - GdkRectangle *background_area, - GdkRectangle *cell_area, - GdkRectangle *expose_area, - guint flags) +gtk_cell_renderer_toggle_render (GtkCellRenderer *cell, + cairo_t *cr, + GtkWidget *widget, + const GdkRectangle *background_area, + const GdkRectangle *cell_area, + GtkCellRendererState flags) { - GtkCellRendererToggle *celltoggle = (GtkCellRendererToggle *) cell; + 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; - + 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; - shadow = celltoggle->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT; + state = gtk_cell_renderer_get_state (cell, widget, flags); - 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; - } + if (!priv->activatable) + state |= GTK_STATE_FLAG_INSENSITIVE; + + state &= ~(GTK_STATE_FLAG_INCONSISTENT | GTK_STATE_FLAG_ACTIVE); + + if (priv->inconsistent) + state |= GTK_STATE_FLAG_INCONSISTENT; + else if (priv->active) + state |= GTK_STATE_FLAG_ACTIVE; - if (celltoggle->radio) + cairo_save (cr); + + 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, - cell_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, - cell_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 -gtk_cell_renderer_toggle_activate (GtkCellRenderer *cell, - GdkEvent *event, - GtkWidget *widget, - const gchar *path, - GdkRectangle *background_area, - GdkRectangle *cell_area, - guint flags) +gtk_cell_renderer_toggle_activate (GtkCellRenderer *cell, + GdkEvent *event, + GtkWidget *widget, + const gchar *path, + 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) { - gtk_signal_emit (GTK_OBJECT (cell), toggle_cell_signals[TOGGLED], path); + g_signal_emit (cell, toggle_cell_signals[TOGGLED], 0, path); return TRUE; } @@ -372,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 **/ @@ -390,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; } /** @@ -407,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; } /** @@ -423,5 +498,50 @@ gtk_cell_renderer_toggle_set_active (GtkCellRendererToggle *toggle, { g_return_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (toggle)); - g_object_set (G_OBJECT (toggle), "active", setting?TRUE:FALSE, NULL); + 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"); + } }