1 /* GTK - The GIMP Toolkit
3 * Copyright (C) 2010 Intel Corporation
4 * Copyright (C) 2010 RedHat, Inc.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
20 * Emmanuele Bassi <ebassi@linux.intel.com>
21 * Matthias Clasen <mclasen@redhat.com>
23 * Based on similar code from Mx.
28 * @Short_Description: A "light switch" style toggle
30 * @See_Also: #GtkToggleButton
32 * #GtkSwitch is a widget that has two states: on or off. The user can control
33 * which state should be active by clicking the empty area, or by dragging the
39 #include "gtkswitch.h"
41 #include "gtkactivatable.h"
43 #include "gtkprivate.h"
44 #include "gtktoggleaction.h"
45 #include "gtkwidget.h"
46 #include "gtkmarshalers.h"
47 #include "gtkapplicationprivate.h"
48 #include "gtkactionable.h"
49 #include "a11y/gtkswitchaccessible.h"
50 #include "gtkactionhelper.h"
54 #define DEFAULT_SLIDER_WIDTH (36)
55 #define DEFAULT_SLIDER_HEIGHT (22)
57 struct _GtkSwitchPrivate
59 GdkWindow *event_window;
61 GtkActionHelper *action_helper;
69 guint is_dragging : 1;
72 guint use_action_appearance : 1;
80 PROP_USE_ACTION_APPEARANCE,
92 static guint signals[LAST_SIGNAL] = { 0 };
94 static GParamSpec *switch_props[LAST_PROP] = { NULL, };
96 static void gtk_switch_actionable_iface_init (GtkActionableInterface *iface);
97 static void gtk_switch_activatable_interface_init (GtkActivatableIface *iface);
99 G_DEFINE_TYPE_WITH_CODE (GtkSwitch, gtk_switch, GTK_TYPE_WIDGET,
100 G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIONABLE,
101 gtk_switch_actionable_iface_init)
102 G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
103 gtk_switch_activatable_interface_init));
106 gtk_switch_button_press (GtkWidget *widget,
107 GdkEventButton *event)
109 GtkSwitchPrivate *priv = GTK_SWITCH (widget)->priv;
110 GtkAllocation allocation;
112 gtk_widget_get_allocation (widget, &allocation);
116 /* if the event occurred in the "off" area, then this
119 if (event->x <= allocation.width / 2)
121 priv->in_press = TRUE;
125 priv->offset = event->x - allocation.width / 2;
129 /* if the event occurred in the "on" area, then this
132 if (event->x >= allocation.width / 2)
134 priv->in_press = TRUE;
138 priv->offset = event->x;
141 priv->drag_start = event->x;
143 g_object_get (gtk_widget_get_settings (widget),
144 "gtk-dnd-drag-threshold", &priv->drag_threshold,
151 gtk_switch_motion (GtkWidget *widget,
152 GdkEventMotion *event)
154 GtkSwitchPrivate *priv = GTK_SWITCH (widget)->priv;
156 /* if this is a direct toggle we don't handle motion */
160 if (ABS (event->x - priv->drag_start) < priv->drag_threshold)
163 if (event->state & GDK_BUTTON1_MASK)
165 gint position = event->x - priv->offset;
166 GtkAllocation allocation;
167 GtkStyleContext *context;
170 gint width, focus_width, focus_pad;
172 gtk_widget_style_get (widget,
173 "focus-line-width", &focus_width,
174 "focus-padding", &focus_pad,
177 context = gtk_widget_get_style_context (widget);
178 state = gtk_widget_get_state_flags (widget);
180 gtk_style_context_save (context);
181 gtk_style_context_add_class (context, GTK_STYLE_CLASS_SLIDER);
182 gtk_style_context_get_padding (context, state, &padding);
183 gtk_style_context_restore (context);
185 gtk_widget_get_allocation (widget, &allocation);
187 width = allocation.width - 2 * (focus_width + focus_pad);
189 /* constrain the handle within the trough width */
190 if (position > (width / 2) - padding.right)
191 priv->handle_x = width / 2 - padding.right;
192 else if (position < padding.left)
195 priv->handle_x = position;
197 priv->is_dragging = TRUE;
199 /* we need to redraw the handle */
200 gtk_widget_queue_draw (widget);
209 gtk_switch_button_release (GtkWidget *widget,
210 GdkEventButton *event)
212 GtkSwitchPrivate *priv = GTK_SWITCH (widget)->priv;
213 GtkAllocation allocation;
215 gtk_widget_get_allocation (widget, &allocation);
217 /* dragged toggles have a "soft" grab, so we don't care whether we
218 * are in the switch or not when the button is released; we do care
219 * for direct toggles, instead
221 if (!priv->is_dragging && !priv->in_switch)
227 priv->in_press = FALSE;
228 gtk_switch_set_active (GTK_SWITCH (widget), !priv->is_active);
233 /* toggle the switch if the handle was clicked but a drag had not been
235 if (!priv->is_dragging && !priv->in_press)
237 gtk_switch_set_active (GTK_SWITCH (widget), !priv->is_active);
243 if (priv->is_dragging)
245 priv->is_dragging = FALSE;
247 /* if half the handle passed the middle of the switch, then we
248 * consider it to be on
250 if ((priv->handle_x + (allocation.width / 4)) >= (allocation.width / 2))
252 gtk_switch_set_active (GTK_SWITCH (widget), TRUE);
253 priv->handle_x = allocation.width / 2;
257 gtk_switch_set_active (GTK_SWITCH (widget), FALSE);
261 gtk_widget_queue_draw (widget);
270 gtk_switch_enter (GtkWidget *widget,
271 GdkEventCrossing *event)
273 GtkSwitchPrivate *priv = GTK_SWITCH (widget)->priv;
275 if (event->window == priv->event_window)
276 priv->in_switch = TRUE;
282 gtk_switch_leave (GtkWidget *widget,
283 GdkEventCrossing *event)
285 GtkSwitchPrivate *priv = GTK_SWITCH (widget)->priv;
287 if (event->window == priv->event_window)
288 priv->in_switch = FALSE;
294 gtk_switch_activate (GtkSwitch *sw)
296 GtkSwitchPrivate *priv = sw->priv;
298 gtk_switch_set_active (sw, !priv->is_active);
302 gtk_switch_get_preferred_width (GtkWidget *widget,
306 GtkStyleContext *context;
309 gint width, slider_width, focus_width, focus_pad;
311 PangoRectangle logical_rect;
313 context = gtk_widget_get_style_context (widget);
314 state = gtk_style_context_get_state (context);
316 gtk_style_context_save (context);
318 gtk_style_context_add_class (context, GTK_STYLE_CLASS_SLIDER);
319 gtk_style_context_get_padding (context, state, &padding);
321 width = padding.left + padding.right;
323 gtk_style_context_restore (context);
325 gtk_widget_style_get (widget,
326 "slider-width", &slider_width,
327 "focus-line-width", &focus_width,
328 "focus-padding", &focus_pad,
331 width += 2 * (focus_width + focus_pad);
333 /* Translators: if the "on" state label requires more than three
334 * glyphs then use MEDIUM VERTICAL BAR (U+2759) as the text for
337 layout = gtk_widget_create_pango_layout (widget, C_("switch", "ON"));
338 pango_layout_get_extents (layout, NULL, &logical_rect);
339 pango_extents_to_pixels (&logical_rect, NULL);
340 width += MAX (logical_rect.width, slider_width);
342 /* Translators: if the "off" state label requires more than three
343 * glyphs then use WHITE CIRCLE (U+25CB) as the text for the state
345 pango_layout_set_text (layout, C_("switch", "OFF"), -1);
346 pango_layout_get_extents (layout, NULL, &logical_rect);
347 pango_extents_to_pixels (&logical_rect, NULL);
348 width += MAX (logical_rect.width, slider_width);
350 g_object_unref (layout);
360 gtk_switch_get_preferred_height (GtkWidget *widget,
364 GtkStyleContext *context;
367 gint height, focus_width, focus_pad;
369 PangoRectangle logical_rect;
372 context = gtk_widget_get_style_context (widget);
373 state = gtk_style_context_get_state (context);
375 gtk_style_context_save (context);
377 gtk_style_context_add_class (context, GTK_STYLE_CLASS_SLIDER);
378 gtk_style_context_get_padding (context, state, &padding);
380 height = padding.top + padding.bottom;
382 gtk_style_context_restore (context);
384 gtk_widget_style_get (widget,
385 "focus-line-width", &focus_width,
386 "focus-padding", &focus_pad,
389 height += 2 * (focus_width + focus_pad);
391 str = g_strdup_printf ("%s%s",
393 C_("switch", "OFF"));
395 layout = gtk_widget_create_pango_layout (widget, str);
396 pango_layout_get_extents (layout, NULL, &logical_rect);
397 pango_extents_to_pixels (&logical_rect, NULL);
398 height += MAX (DEFAULT_SLIDER_HEIGHT, logical_rect.height);
400 g_object_unref (layout);
411 gtk_switch_size_allocate (GtkWidget *widget,
412 GtkAllocation *allocation)
414 GtkSwitchPrivate *priv = GTK_SWITCH (widget)->priv;
416 gtk_widget_set_allocation (widget, allocation);
418 if (gtk_widget_get_realized (widget))
419 gdk_window_move_resize (priv->event_window,
427 gtk_switch_realize (GtkWidget *widget)
429 GtkSwitchPrivate *priv = GTK_SWITCH (widget)->priv;
430 GdkWindow *parent_window;
431 GdkWindowAttr attributes;
432 gint attributes_mask;
433 GtkAllocation allocation;
435 gtk_widget_set_realized (widget, TRUE);
436 parent_window = gtk_widget_get_parent_window (widget);
437 gtk_widget_set_window (widget, parent_window);
438 g_object_ref (parent_window);
440 gtk_widget_get_allocation (widget, &allocation);
442 attributes.window_type = GDK_WINDOW_CHILD;
443 attributes.wclass = GDK_INPUT_ONLY;
444 attributes.x = allocation.x;
445 attributes.y = allocation.y;
446 attributes.width = allocation.width;
447 attributes.height = allocation.height;
448 attributes.event_mask = gtk_widget_get_events (widget);
449 attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
450 GDK_BUTTON_RELEASE_MASK |
451 GDK_BUTTON1_MOTION_MASK |
452 GDK_POINTER_MOTION_HINT_MASK |
453 GDK_POINTER_MOTION_MASK |
454 GDK_ENTER_NOTIFY_MASK |
455 GDK_LEAVE_NOTIFY_MASK);
456 attributes_mask = GDK_WA_X | GDK_WA_Y;
458 priv->event_window = gdk_window_new (parent_window,
461 gtk_widget_register_window (widget, priv->event_window);
465 gtk_switch_unrealize (GtkWidget *widget)
467 GtkSwitchPrivate *priv = GTK_SWITCH (widget)->priv;
469 if (priv->event_window != NULL)
471 gtk_widget_unregister_window (widget, priv->event_window);
472 gdk_window_destroy (priv->event_window);
473 priv->event_window = NULL;
476 GTK_WIDGET_CLASS (gtk_switch_parent_class)->unrealize (widget);
480 gtk_switch_map (GtkWidget *widget)
482 GtkSwitchPrivate *priv = GTK_SWITCH (widget)->priv;
484 GTK_WIDGET_CLASS (gtk_switch_parent_class)->map (widget);
486 if (priv->event_window)
487 gdk_window_show (priv->event_window);
491 gtk_switch_unmap (GtkWidget *widget)
493 GtkSwitchPrivate *priv = GTK_SWITCH (widget)->priv;
495 if (priv->event_window)
496 gdk_window_hide (priv->event_window);
498 GTK_WIDGET_CLASS (gtk_switch_parent_class)->unmap (widget);
502 gtk_switch_paint_handle (GtkWidget *widget,
506 GtkStyleContext *context = gtk_widget_get_style_context (widget);
508 gtk_style_context_save (context);
509 gtk_style_context_add_class (context, GTK_STYLE_CLASS_SLIDER);
511 gtk_render_slider (context, cr,
513 box->width, box->height,
514 GTK_ORIENTATION_HORIZONTAL);
516 gtk_style_context_restore (context);
520 gtk_switch_draw (GtkWidget *widget,
523 GtkSwitchPrivate *priv = GTK_SWITCH (widget)->priv;
524 GtkStyleContext *context;
528 gint label_x, label_y;
531 gint focus_width, focus_pad;
532 gint x, y, width, height;
534 gtk_widget_style_get (widget,
535 "focus-line-width", &focus_width,
536 "focus-padding", &focus_pad,
539 context = gtk_widget_get_style_context (widget);
540 state = gtk_widget_get_state_flags (widget);
542 gtk_style_context_save (context);
544 gtk_style_context_add_class (context, GTK_STYLE_CLASS_SLIDER);
546 gtk_style_context_get_padding (context, state, &padding);
548 gtk_style_context_restore (context);
552 width = gtk_widget_get_allocated_width (widget);
553 height = gtk_widget_get_allocated_height (widget);
555 if (gtk_widget_has_visible_focus (widget))
556 gtk_render_focus (context, cr, x, y, width, height);
558 x += focus_width + focus_pad;
559 y += focus_width + focus_pad;
560 width -= 2 * (focus_width + focus_pad);
561 height -= 2 * (focus_width + focus_pad);
563 gtk_style_context_save (context);
564 gtk_style_context_add_class (context, GTK_STYLE_CLASS_TROUGH);
566 gtk_render_background (context, cr, x, y, width, height);
567 gtk_render_frame (context, cr, x, y, width, height);
569 width -= padding.left + padding.right;
570 height -= padding.top + padding.bottom;
576 handle.width = width / 2;
577 handle.height = height;
579 /* Translators: if the "on" state label requires more than three
580 * glyphs then use MEDIUM VERTICAL BAR (U+2759) as the text for
583 layout = gtk_widget_create_pango_layout (widget, C_("switch", "ON"));
585 pango_layout_get_extents (layout, NULL, &rect);
586 pango_extents_to_pixels (&rect, NULL);
588 label_x = x + ((width / 2) - rect.width) / 2;
589 label_y = y + (height - rect.height) / 2;
591 gtk_render_layout (context, cr, label_x, label_y, layout);
593 g_object_unref (layout);
595 /* Translators: if the "off" state label requires more than three
596 * glyphs then use WHITE CIRCLE (U+25CB) as the text for the state
598 layout = gtk_widget_create_pango_layout (widget, C_("switch", "OFF"));
600 pango_layout_get_extents (layout, NULL, &rect);
601 pango_extents_to_pixels (&rect, NULL);
603 label_x = x + (width / 2) + ((width / 2) - rect.width) / 2;
604 label_y = y + (height - rect.height) / 2;
606 gtk_render_layout (context, cr, label_x, label_y, layout);
608 g_object_unref (layout);
610 if (priv->is_dragging)
611 handle.x = x + priv->handle_x;
612 else if (priv->is_active)
613 handle.x = x + width - handle.width;
617 gtk_style_context_restore (context);
619 gtk_switch_paint_handle (widget, cr, &handle);
625 gtk_switch_set_related_action (GtkSwitch *sw,
628 GtkSwitchPrivate *priv = sw->priv;
630 if (priv->action == action)
633 gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (sw), action);
635 priv->action = action;
639 gtk_switch_set_use_action_appearance (GtkSwitch *sw,
640 gboolean use_appearance)
642 GtkSwitchPrivate *priv = sw->priv;
644 if (priv->use_action_appearance != use_appearance)
646 priv->use_action_appearance = use_appearance;
648 gtk_activatable_sync_action_properties (GTK_ACTIVATABLE (sw), priv->action);
653 gtk_switch_set_action_name (GtkActionable *actionable,
654 const gchar *action_name)
656 GtkSwitch *sw = GTK_SWITCH (actionable);
658 if (!sw->priv->action_helper)
659 sw->priv->action_helper = gtk_action_helper_new (actionable);
661 gtk_action_helper_set_action_name (sw->priv->action_helper, action_name);
665 gtk_switch_set_action_target_value (GtkActionable *actionable,
666 GVariant *action_target)
668 GtkSwitch *sw = GTK_SWITCH (actionable);
670 if (!sw->priv->action_helper)
671 sw->priv->action_helper = gtk_action_helper_new (actionable);
673 gtk_action_helper_set_action_target_value (sw->priv->action_helper, action_target);
677 gtk_switch_get_action_name (GtkActionable *actionable)
679 GtkSwitch *sw = GTK_SWITCH (actionable);
681 return gtk_action_helper_get_action_name (sw->priv->action_helper);
685 gtk_switch_get_action_target_value (GtkActionable *actionable)
687 GtkSwitch *sw = GTK_SWITCH (actionable);
689 return gtk_action_helper_get_action_target_value (sw->priv->action_helper);
693 gtk_switch_actionable_iface_init (GtkActionableInterface *iface)
695 iface->get_action_name = gtk_switch_get_action_name;
696 iface->set_action_name = gtk_switch_set_action_name;
697 iface->get_action_target_value = gtk_switch_get_action_target_value;
698 iface->set_action_target_value = gtk_switch_set_action_target_value;
702 gtk_switch_set_property (GObject *gobject,
707 GtkSwitch *sw = GTK_SWITCH (gobject);
712 gtk_switch_set_active (sw, g_value_get_boolean (value));
715 case PROP_RELATED_ACTION:
716 gtk_switch_set_related_action (sw, g_value_get_object (value));
719 case PROP_USE_ACTION_APPEARANCE:
720 gtk_switch_set_use_action_appearance (sw, g_value_get_boolean (value));
723 case PROP_ACTION_NAME:
724 gtk_switch_set_action_name (GTK_ACTIONABLE (sw), g_value_get_string (value));
727 case PROP_ACTION_TARGET:
728 gtk_switch_set_action_target_value (GTK_ACTIONABLE (sw), g_value_get_variant (value));
732 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
737 gtk_switch_get_property (GObject *gobject,
742 GtkSwitchPrivate *priv = GTK_SWITCH (gobject)->priv;
747 g_value_set_boolean (value, priv->is_active);
750 case PROP_RELATED_ACTION:
751 g_value_set_object (value, priv->action);
754 case PROP_USE_ACTION_APPEARANCE:
755 g_value_set_boolean (value, priv->use_action_appearance);
758 case PROP_ACTION_NAME:
759 g_value_set_string (value, gtk_action_helper_get_action_name (priv->action_helper));
762 case PROP_ACTION_TARGET:
763 g_value_set_variant (value, gtk_action_helper_get_action_target_value (priv->action_helper));
767 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
772 gtk_switch_dispose (GObject *object)
774 GtkSwitchPrivate *priv = GTK_SWITCH (object)->priv;
776 g_clear_object (&priv->action_helper);
780 gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (object), NULL);
784 G_OBJECT_CLASS (gtk_switch_parent_class)->dispose (object);
788 gtk_switch_class_init (GtkSwitchClass *klass)
790 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
791 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
792 gpointer activatable_iface;
794 g_type_class_add_private (klass, sizeof (GtkSwitchPrivate));
796 activatable_iface = g_type_default_interface_peek (GTK_TYPE_ACTIVATABLE);
797 switch_props[PROP_RELATED_ACTION] =
798 g_param_spec_override ("related-action",
799 g_object_interface_find_property (activatable_iface,
802 switch_props[PROP_USE_ACTION_APPEARANCE] =
803 g_param_spec_override ("use-action-appearance",
804 g_object_interface_find_property (activatable_iface,
805 "use-action-appearance"));
810 * Whether the #GtkSwitch widget is in its on or off state.
812 switch_props[PROP_ACTIVE] =
813 g_param_spec_boolean ("active",
815 P_("Whether the switch is on or off"),
817 GTK_PARAM_READWRITE);
819 gobject_class->set_property = gtk_switch_set_property;
820 gobject_class->get_property = gtk_switch_get_property;
821 gobject_class->dispose = gtk_switch_dispose;
823 g_object_class_install_properties (gobject_class, LAST_PROP, switch_props);
825 widget_class->get_preferred_width = gtk_switch_get_preferred_width;
826 widget_class->get_preferred_height = gtk_switch_get_preferred_height;
827 widget_class->size_allocate = gtk_switch_size_allocate;
828 widget_class->realize = gtk_switch_realize;
829 widget_class->unrealize = gtk_switch_unrealize;
830 widget_class->map = gtk_switch_map;
831 widget_class->unmap = gtk_switch_unmap;
832 widget_class->draw = gtk_switch_draw;
833 widget_class->button_press_event = gtk_switch_button_press;
834 widget_class->button_release_event = gtk_switch_button_release;
835 widget_class->motion_notify_event = gtk_switch_motion;
836 widget_class->enter_notify_event = gtk_switch_enter;
837 widget_class->leave_notify_event = gtk_switch_leave;
839 klass->activate = gtk_switch_activate;
842 * GtkSwitch:slider-width:
844 * The minimum width of the #GtkSwitch handle, in pixels.
846 gtk_widget_class_install_style_property (widget_class,
847 g_param_spec_int ("slider-width",
849 P_("The minimum width of the handle"),
850 DEFAULT_SLIDER_WIDTH, G_MAXINT,
851 DEFAULT_SLIDER_WIDTH,
852 GTK_PARAM_READABLE));
855 * GtkSwitch::activate:
856 * @widget: the object which received the signal.
858 * The ::activate signal on GtkSwitch is an action signal and
859 * emitting it causes the switch to animate.
860 * Applications should never connect to this signal, but use the
861 * notify::active signal.
864 g_signal_new (I_("activate"),
865 G_OBJECT_CLASS_TYPE (gobject_class),
866 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
867 G_STRUCT_OFFSET (GtkSwitchClass, activate),
869 _gtk_marshal_VOID__VOID,
871 widget_class->activate_signal = signals[ACTIVATE];
873 g_object_class_override_property (gobject_class, PROP_ACTION_NAME, "action-name");
874 g_object_class_override_property (gobject_class, PROP_ACTION_TARGET, "action-target");
876 gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_SWITCH_ACCESSIBLE);
880 gtk_switch_init (GtkSwitch *self)
882 self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTK_TYPE_SWITCH, GtkSwitchPrivate);
883 self->priv->use_action_appearance = TRUE;
884 gtk_widget_set_has_window (GTK_WIDGET (self), FALSE);
885 gtk_widget_set_can_focus (GTK_WIDGET (self), TRUE);
891 * Creates a new #GtkSwitch widget.
893 * Return value: the newly created #GtkSwitch instance
898 gtk_switch_new (void)
900 return g_object_new (GTK_TYPE_SWITCH, NULL);
904 * gtk_switch_set_active:
906 * @is_active: %TRUE if @sw should be active, and %FALSE otherwise
908 * Changes the state of @sw to the desired one.
913 gtk_switch_set_active (GtkSwitch *sw,
916 GtkSwitchPrivate *priv;
918 g_return_if_fail (GTK_IS_SWITCH (sw));
920 is_active = !!is_active;
924 if (priv->is_active != is_active)
926 AtkObject *accessible;
928 priv->is_active = is_active;
930 g_object_notify_by_pspec (G_OBJECT (sw), switch_props[PROP_ACTIVE]);
932 if (priv->action_helper)
933 gtk_action_helper_activate (priv->action_helper);
936 gtk_action_activate (priv->action);
938 accessible = gtk_widget_get_accessible (GTK_WIDGET (sw));
939 atk_object_notify_state_change (accessible, ATK_STATE_CHECKED, priv->is_active);
942 gtk_widget_set_state_flags (GTK_WIDGET (sw), GTK_STATE_FLAG_ACTIVE, FALSE);
944 gtk_widget_unset_state_flags (GTK_WIDGET (sw), GTK_STATE_FLAG_ACTIVE);
946 gtk_widget_queue_draw (GTK_WIDGET (sw));
951 * gtk_switch_get_active:
954 * Gets whether the #GtkSwitch is in its "on" or "off" state.
956 * Return value: %TRUE if the #GtkSwitch is active, and %FALSE otherwise
961 gtk_switch_get_active (GtkSwitch *sw)
963 g_return_val_if_fail (GTK_IS_SWITCH (sw), FALSE);
965 return sw->priv->is_active;
969 gtk_switch_update (GtkActivatable *activatable,
971 const gchar *property_name)
973 if (strcmp (property_name, "visible") == 0)
975 if (gtk_action_is_visible (action))
976 gtk_widget_show (GTK_WIDGET (activatable));
978 gtk_widget_hide (GTK_WIDGET (activatable));
980 else if (strcmp (property_name, "sensitive") == 0)
982 gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action));
984 else if (strcmp (property_name, "active") == 0)
986 gtk_action_block_activate (action);
987 gtk_switch_set_active (GTK_SWITCH (activatable), gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
988 gtk_action_unblock_activate (action);
993 gtk_switch_sync_action_properties (GtkActivatable *activatable,
999 if (gtk_action_is_visible (action))
1000 gtk_widget_show (GTK_WIDGET (activatable));
1002 gtk_widget_hide (GTK_WIDGET (activatable));
1004 gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action));
1006 gtk_action_block_activate (action);
1007 gtk_switch_set_active (GTK_SWITCH (activatable), gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
1008 gtk_action_unblock_activate (action);
1012 gtk_switch_activatable_interface_init (GtkActivatableIface *iface)
1014 iface->update = gtk_switch_update;
1015 iface->sync_action_properties = gtk_switch_sync_action_properties;