X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkswitch.c;h=dfcfedc4bd351664ebbe959f2ceb984646212547;hb=aaedf5a35219b034a244730564b8fdf2b7d32540;hp=ceb2c6f51ebf9568a4f913b0ab67920bb671a7cc;hpb=b80fb88aff51b6d464c3a62663eb6bce33d3ce08;p=~andy%2Fgtk diff --git a/gtk/gtkswitch.c b/gtk/gtkswitch.c index ceb2c6f51..dfcfedc4b 100644 --- a/gtk/gtkswitch.c +++ b/gtk/gtkswitch.c @@ -14,9 +14,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 . * * Author: * Emmanuele Bassi @@ -40,14 +38,16 @@ #include "gtkswitch.h" -#include "gtkaccessibleprivate.h" #include "gtkactivatable.h" #include "gtkintl.h" #include "gtkprivate.h" #include "gtktoggleaction.h" #include "gtkwidget.h" #include "gtkmarshalers.h" +#include "gtkapplicationprivate.h" +#include "gtkactionable.h" #include "a11y/gtkswitchaccessible.h" +#include "gtkactionhelper.h" #include @@ -58,6 +58,7 @@ struct _GtkSwitchPrivate { GdkWindow *event_window; GtkAction *action; + GtkActionHelper *action_helper; gint handle_x; gint offset; @@ -77,7 +78,9 @@ enum PROP_ACTIVE, PROP_RELATED_ACTION, PROP_USE_ACTION_APPEARANCE, - LAST_PROP + LAST_PROP, + PROP_ACTION_NAME, + PROP_ACTION_TARGET }; enum @@ -90,9 +93,12 @@ static guint signals[LAST_SIGNAL] = { 0 }; static GParamSpec *switch_props[LAST_PROP] = { NULL, }; +static void gtk_switch_actionable_iface_init (GtkActionableInterface *iface); static void gtk_switch_activatable_interface_init (GtkActivatableIface *iface); G_DEFINE_TYPE_WITH_CODE (GtkSwitch, gtk_switch, GTK_TYPE_WIDGET, + G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIONABLE, + gtk_switch_actionable_iface_init) G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE, gtk_switch_activatable_interface_init)); @@ -113,7 +119,7 @@ gtk_switch_button_press (GtkWidget *widget, if (event->x <= allocation.width / 2) { priv->in_press = TRUE; - return FALSE; + return TRUE; } priv->offset = event->x - allocation.width / 2; @@ -126,7 +132,7 @@ gtk_switch_button_press (GtkWidget *widget, if (event->x >= allocation.width / 2) { priv->in_press = TRUE; - return FALSE; + return TRUE; } priv->offset = event->x; @@ -138,7 +144,7 @@ gtk_switch_button_press (GtkWidget *widget, "gtk-dnd-drag-threshold", &priv->drag_threshold, NULL); - return FALSE; + return TRUE; } static gboolean @@ -297,7 +303,6 @@ gtk_switch_get_preferred_width (GtkWidget *widget, gint *minimum, gint *natural) { - GtkSwitchPrivate *priv = GTK_SWITCH (widget)->priv; GtkStyleContext *context; GtkStateFlags state; GtkBorder padding; @@ -306,14 +311,10 @@ gtk_switch_get_preferred_width (GtkWidget *widget, PangoRectangle logical_rect; context = gtk_widget_get_style_context (widget); - state = gtk_widget_get_state_flags (widget); - - if (priv->is_active) - state |= GTK_STATE_FLAG_ACTIVE; + state = gtk_style_context_get_state (context); gtk_style_context_save (context); - gtk_style_context_set_state (context, state); gtk_style_context_add_class (context, GTK_STYLE_CLASS_SLIDER); gtk_style_context_get_padding (context, state, &padding); @@ -360,7 +361,6 @@ gtk_switch_get_preferred_height (GtkWidget *widget, gint *minimum, gint *natural) { - GtkSwitchPrivate *priv = GTK_SWITCH (widget)->priv; GtkStyleContext *context; GtkStateFlags state; GtkBorder padding; @@ -370,14 +370,10 @@ gtk_switch_get_preferred_height (GtkWidget *widget, gchar *str; context = gtk_widget_get_style_context (widget); - state = gtk_widget_get_state_flags (widget); - - if (priv->is_active) - state |= GTK_STATE_FLAG_ACTIVE; + state = gtk_style_context_get_state (context); gtk_style_context_save (context); - gtk_style_context_set_state (context, state); gtk_style_context_add_class (context, GTK_STYLE_CLASS_SLIDER); gtk_style_context_get_padding (context, state, &padding); @@ -462,7 +458,7 @@ gtk_switch_realize (GtkWidget *widget) priv->event_window = gdk_window_new (parent_window, &attributes, attributes_mask); - gdk_window_set_user_data (priv->event_window, widget); + gtk_widget_register_window (widget, priv->event_window); } static void @@ -472,7 +468,7 @@ gtk_switch_unrealize (GtkWidget *widget) if (priv->event_window != NULL) { - gdk_window_set_user_data (priv->event_window, NULL); + gtk_widget_unregister_window (widget, priv->event_window); gdk_window_destroy (priv->event_window); priv->event_window = NULL; } @@ -507,17 +503,9 @@ gtk_switch_paint_handle (GtkWidget *widget, cairo_t *cr, GdkRectangle *box) { - GtkSwitchPrivate *priv = GTK_SWITCH (widget)->priv; GtkStyleContext *context = gtk_widget_get_style_context (widget); - GtkStateFlags state; - - state = gtk_widget_get_state_flags (widget); - - if (priv->is_active) - state |= GTK_STATE_FLAG_ACTIVE; gtk_style_context_save (context); - gtk_style_context_set_state (context, state); gtk_style_context_add_class (context, GTK_STYLE_CLASS_SLIDER); gtk_render_slider (context, cr, @@ -536,15 +524,12 @@ gtk_switch_draw (GtkWidget *widget, GtkStyleContext *context; GdkRectangle handle; PangoLayout *layout; - PangoFontDescription *desc; - const PangoFontDescription *style_desc; PangoRectangle rect; gint label_x, label_y; - GtkStateFlags state; GtkBorder padding; + GtkStateFlags state; gint focus_width, focus_pad; gint x, y, width, height; - gint font_size, style_font_size; gtk_widget_style_get (widget, "focus-line-width", &focus_width, @@ -554,12 +539,8 @@ gtk_switch_draw (GtkWidget *widget, context = gtk_widget_get_style_context (widget); state = gtk_widget_get_state_flags (widget); - if (priv->is_active) - state |= GTK_STATE_FLAG_ACTIVE; - gtk_style_context_save (context); - gtk_style_context_set_state (context, state); gtk_style_context_add_class (context, GTK_STYLE_CLASS_SLIDER); gtk_style_context_get_padding (context, state, &padding); @@ -571,7 +552,7 @@ gtk_switch_draw (GtkWidget *widget, width = gtk_widget_get_allocated_width (widget); height = gtk_widget_get_allocated_height (widget); - if (gtk_widget_has_focus (widget)) + if (gtk_widget_has_visible_focus (widget)) gtk_render_focus (context, cr, x, y, width, height); x += focus_width + focus_pad; @@ -581,7 +562,6 @@ gtk_switch_draw (GtkWidget *widget, gtk_style_context_save (context); gtk_style_context_add_class (context, GTK_STYLE_CLASS_TROUGH); - gtk_style_context_set_state (context, state); gtk_render_background (context, cr, x, y, width, height); gtk_render_frame (context, cr, x, y, width, height); @@ -602,20 +582,6 @@ gtk_switch_draw (GtkWidget *widget, */ layout = gtk_widget_create_pango_layout (widget, C_("switch", "ON")); - /* FIXME: this should be really done in the theme, but overriding font size - * from it doesn't currently work. So we have to hardcode this here and - * below for the "OFF" label. - */ - desc = pango_font_description_new (); - - style_desc = gtk_style_context_get_font (context, state); - style_font_size = pango_font_description_get_size (style_desc); - font_size = MAX (style_font_size - 1 * PANGO_SCALE, ceil (style_font_size * PANGO_SCALE_SMALL)); - - pango_font_description_set_size (desc, font_size); - - pango_layout_set_font_description (layout, desc); - pango_layout_get_extents (layout, NULL, &rect); pango_extents_to_pixels (&rect, NULL); @@ -630,7 +596,6 @@ gtk_switch_draw (GtkWidget *widget, * glyphs then use WHITE CIRCLE (U+25CB) as the text for the state */ layout = gtk_widget_create_pango_layout (widget, C_("switch", "OFF")); - pango_layout_set_font_description (layout, desc); pango_layout_get_extents (layout, NULL, &rect); pango_extents_to_pixels (&rect, NULL); @@ -653,8 +618,6 @@ gtk_switch_draw (GtkWidget *widget, gtk_switch_paint_handle (widget, cr, &handle); - pango_font_description_free (desc); - return FALSE; } @@ -686,6 +649,55 @@ gtk_switch_set_use_action_appearance (GtkSwitch *sw, } } +static void +gtk_switch_set_action_name (GtkActionable *actionable, + const gchar *action_name) +{ + GtkSwitch *sw = GTK_SWITCH (actionable); + + if (!sw->priv->action_helper) + sw->priv->action_helper = gtk_action_helper_new (actionable); + + gtk_action_helper_set_action_name (sw->priv->action_helper, action_name); +} + +static void +gtk_switch_set_action_target_value (GtkActionable *actionable, + GVariant *action_target) +{ + GtkSwitch *sw = GTK_SWITCH (actionable); + + if (!sw->priv->action_helper) + sw->priv->action_helper = gtk_action_helper_new (actionable); + + gtk_action_helper_set_action_target_value (sw->priv->action_helper, action_target); +} + +static const gchar * +gtk_switch_get_action_name (GtkActionable *actionable) +{ + GtkSwitch *sw = GTK_SWITCH (actionable); + + return gtk_action_helper_get_action_name (sw->priv->action_helper); +} + +static GVariant * +gtk_switch_get_action_target_value (GtkActionable *actionable) +{ + GtkSwitch *sw = GTK_SWITCH (actionable); + + return gtk_action_helper_get_action_target_value (sw->priv->action_helper); +} + +static void +gtk_switch_actionable_iface_init (GtkActionableInterface *iface) +{ + iface->get_action_name = gtk_switch_get_action_name; + iface->set_action_name = gtk_switch_set_action_name; + iface->get_action_target_value = gtk_switch_get_action_target_value; + iface->set_action_target_value = gtk_switch_set_action_target_value; +} + static void gtk_switch_set_property (GObject *gobject, guint prop_id, @@ -708,6 +720,14 @@ gtk_switch_set_property (GObject *gobject, gtk_switch_set_use_action_appearance (sw, g_value_get_boolean (value)); break; + case PROP_ACTION_NAME: + gtk_switch_set_action_name (GTK_ACTIONABLE (sw), g_value_get_string (value)); + break; + + case PROP_ACTION_TARGET: + gtk_switch_set_action_target_value (GTK_ACTIONABLE (sw), g_value_get_variant (value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); } @@ -735,6 +755,14 @@ gtk_switch_get_property (GObject *gobject, g_value_set_boolean (value, priv->use_action_appearance); break; + case PROP_ACTION_NAME: + g_value_set_string (value, gtk_action_helper_get_action_name (priv->action_helper)); + break; + + case PROP_ACTION_TARGET: + g_value_set_variant (value, gtk_action_helper_get_action_target_value (priv->action_helper)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); } @@ -745,6 +773,8 @@ gtk_switch_dispose (GObject *object) { GtkSwitchPrivate *priv = GTK_SWITCH (object)->priv; + g_clear_object (&priv->action_helper); + if (priv->action) { gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (object), NULL); @@ -840,6 +870,9 @@ gtk_switch_class_init (GtkSwitchClass *klass) G_TYPE_NONE, 0); widget_class->activate_signal = signals[ACTIVATE]; + g_object_class_override_property (gobject_class, PROP_ACTION_NAME, "action-name"); + g_object_class_override_property (gobject_class, PROP_ACTION_TARGET, "action-target"); + gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_SWITCH_ACCESSIBLE); } @@ -891,27 +924,24 @@ gtk_switch_set_active (GtkSwitch *sw, if (priv->is_active != is_active) { AtkObject *accessible; - GtkWidget *widget; - GtkStyleContext *context; - widget = GTK_WIDGET (sw); priv->is_active = is_active; g_object_notify_by_pspec (G_OBJECT (sw), switch_props[PROP_ACTIVE]); + if (priv->action_helper) + gtk_action_helper_activate (priv->action_helper); + if (priv->action) gtk_action_activate (priv->action); accessible = gtk_widget_get_accessible (GTK_WIDGET (sw)); atk_object_notify_state_change (accessible, ATK_STATE_CHECKED, priv->is_active); - if (gtk_widget_get_realized (widget)) - { - context = gtk_widget_get_style_context (widget); - gtk_style_context_notify_state_change (context, - gtk_widget_get_window (widget), - NULL, GTK_STATE_ACTIVE, is_active); - } + if (priv->is_active) + gtk_widget_set_state_flags (GTK_WIDGET (sw), GTK_STATE_FLAG_ACTIVE, FALSE); + else + gtk_widget_unset_state_flags (GTK_WIDGET (sw), GTK_STATE_FLAG_ACTIVE); gtk_widget_queue_draw (GTK_WIDGET (sw)); }