diff options
Diffstat (limited to 'src/idoscalemenuitem.c')
-rw-r--r-- | src/idoscalemenuitem.c | 261 |
1 files changed, 128 insertions, 133 deletions
diff --git a/src/idoscalemenuitem.c b/src/idoscalemenuitem.c index f973f52..4b60b8b 100644 --- a/src/idoscalemenuitem.c +++ b/src/idoscalemenuitem.c @@ -31,10 +31,6 @@ #include "idoscalemenuitem.h" #include "idotypebuiltins.h" -#ifdef USE_GTK3 -#include "idooffscreenproxy.h" -#endif - static void ido_scale_menu_item_set_property (GObject *object, guint prop_id, const GValue *value, @@ -59,16 +55,12 @@ static void ido_scale_menu_item_notify (IdoScaleMenuItem GParamSpec *pspec, gpointer user_data); static void update_packing (IdoScaleMenuItem *self, - IdoScaleMenuItemStyle style, - IdoScaleMenuItemStyle old_style); + IdoScaleMenuItemStyle style); +static void default_primary_clicked_handler (IdoScaleMenuItem *self); +static void default_secondary_clicked_handler (IdoScaleMenuItem *self); struct _IdoScaleMenuItemPrivate { GtkWidget *scale; - -#ifdef USE_GTK3 - GtkWidget *proxy; -#endif - GtkAdjustment *adjustment; GtkWidget *primary_image; GtkWidget *secondary_image; @@ -88,6 +80,8 @@ struct _IdoScaleMenuItemPrivate { enum { SLIDER_GRABBED, SLIDER_RELEASED, + PRIMARY_CLICKED, + SECONDARY_CLICKED, LAST_SIGNAL }; @@ -105,13 +99,6 @@ G_DEFINE_TYPE (IdoScaleMenuItem, ido_scale_menu_item, GTK_TYPE_MENU_ITEM) #define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), IDO_TYPE_SCALE_MENU_ITEM, IdoScaleMenuItemPrivate)) -static void -ido_scale_menu_item_state_changed (GtkWidget *widget, - GtkStateType previous_state) -{ - gtk_widget_set_state (widget, GTK_STATE_NORMAL); -} - static gboolean ido_scale_menu_item_scroll_event (GtkWidget *menuitem, GdkEventScroll *event) @@ -230,6 +217,21 @@ ido_scale_menu_item_toggle_size_allocate (IdoScaleMenuItem *item, priv->toggle_size = toggle_size; } +static gboolean +on_scale_button_press_or_release_event (GtkWidget * widget G_GNUC_UNUSED, + GdkEventButton * event, + gpointer unused G_GNUC_UNUSED) +{ + /* HACK: we want the behaviour you get with the middle button, so we + * mangle the event. clicking with other buttons moves the slider in + * step increments, clicking with the middle button moves the slider to + * the location of the click. */ + if (event->button == 1) + event->button = 2; + + return FALSE; +} + static void ido_scale_menu_item_constructed (GObject *object) { @@ -248,15 +250,12 @@ ido_scale_menu_item_constructed (GObject *object) priv->scale = ido_range_new (adj, range_style); g_object_ref (priv->scale); gtk_scale_set_draw_value (GTK_SCALE (priv->scale), FALSE); - -#ifdef USE_GTK3 - gtk_widget_set_can_focus (priv->scale, FALSE); - - priv->proxy = ido_offscreen_proxy_new (); - g_object_ref (priv->proxy); - gtk_container_add (GTK_CONTAINER (priv->proxy), priv->scale); -#endif + g_signal_connect (G_OBJECT (priv->scale), "button-press-event", + G_CALLBACK (on_scale_button_press_or_release_event), NULL); + g_signal_connect (G_OBJECT (priv->scale), "button-release-event", + G_CALLBACK (on_scale_button_press_or_release_event), NULL); + #ifdef USE_GTK3 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); #else @@ -278,7 +277,7 @@ ido_scale_menu_item_constructed (GObject *object) priv->hbox = hbox; - update_packing (self, priv->style, priv->style); + update_packing (self, priv->style); g_signal_connect (self, "toggle-size-allocate", G_CALLBACK (ido_scale_menu_item_toggle_size_allocate), @@ -289,6 +288,8 @@ ido_scale_menu_item_constructed (GObject *object) NULL); gtk_container_add (GTK_CONTAINER (self), hbox); + + gtk_widget_add_events (GTK_WIDGET(self), GDK_SCROLL_MASK); } static void @@ -297,11 +298,13 @@ ido_scale_menu_item_class_init (IdoScaleMenuItemClass *item_class) GObjectClass *gobject_class = G_OBJECT_CLASS (item_class); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (item_class); + item_class->primary_clicked = default_primary_clicked_handler; + item_class->secondary_clicked = default_secondary_clicked_handler; + widget_class->button_press_event = ido_scale_menu_item_button_press_event; widget_class->button_release_event = ido_scale_menu_item_button_release_event; widget_class->motion_notify_event = ido_scale_menu_item_motion_notify_event; widget_class->scroll_event = ido_scale_menu_item_scroll_event; - widget_class->state_changed = ido_scale_menu_item_state_changed; widget_class->size_allocate = ido_scale_menu_item_size_allocate; gobject_class->constructed = ido_scale_menu_item_constructed; @@ -358,95 +361,58 @@ ido_scale_menu_item_class_init (IdoScaleMenuItemClass *item_class) g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + signals[PRIMARY_CLICKED] = g_signal_new ("primary-clicked", + G_TYPE_FROM_CLASS (item_class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, + G_STRUCT_OFFSET (IdoScaleMenuItemClass, primary_clicked), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, /* return type */ + 0 /* n_params */); + + signals[SECONDARY_CLICKED] = g_signal_new ("secondary-clicked", + G_TYPE_FROM_CLASS (item_class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, + G_STRUCT_OFFSET (IdoScaleMenuItemClass, secondary_clicked), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, /* return type */ + 0 /* n_params */); + g_type_class_add_private (item_class, sizeof (IdoScaleMenuItemPrivate)); } static void -update_packing (IdoScaleMenuItem *self, IdoScaleMenuItemStyle style, IdoScaleMenuItemStyle old_style) +update_packing (IdoScaleMenuItem *self, IdoScaleMenuItemStyle style) { IdoScaleMenuItemPrivate *priv = GET_PRIVATE (self); + GtkBox * box = GTK_BOX (priv->hbox); GtkContainer *container = GTK_CONTAINER (priv->hbox); - if (style != old_style) - { - switch (old_style) - { - case IDO_SCALE_MENU_ITEM_STYLE_NONE: -#ifdef USE_GTK3 - gtk_container_remove (container, priv->proxy); -#else - gtk_container_remove (container, priv->scale); -#endif - break; - - case IDO_SCALE_MENU_ITEM_STYLE_IMAGE: - gtk_container_remove (container, priv->primary_image); - gtk_container_remove (container, priv->secondary_image); -#ifdef USE_GTK3 - gtk_container_remove (container, priv->proxy); -#else - gtk_container_remove (container, priv->scale); -#endif - break; - - case IDO_SCALE_MENU_ITEM_STYLE_LABEL: - gtk_container_remove (container, priv->primary_label); - gtk_container_remove (container, priv->secondary_label); -#ifdef USE_GTK3 - gtk_container_remove (container, priv->proxy); -#else - gtk_container_remove (container, priv->scale); -#endif - break; - - default: -#ifdef USE_GTK3 - gtk_container_remove (container, priv->proxy); -#else - gtk_container_remove (container, priv->scale); -#endif - break; - } - } + /* remove the old layout */ + GList * children = gtk_container_get_children (container); + GList * l; + for (l=children; l!=NULL; l=l->next) + gtk_container_remove (container, l->data); + g_list_free (children); + /* add the new layout */ switch (style) { - case IDO_SCALE_MENU_ITEM_STYLE_NONE: -#ifdef USE_GTK3 - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->proxy, FALSE, FALSE, 0); -#else - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->scale, FALSE, FALSE, 0); -#endif - break; - case IDO_SCALE_MENU_ITEM_STYLE_IMAGE: - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->primary_image, FALSE, FALSE, 0); - -#ifdef USE_GTK3 - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->proxy, FALSE, FALSE, 0); -#else - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->scale, FALSE, FALSE, 0); -#endif - - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->secondary_image, FALSE, FALSE, 0); + gtk_box_pack_start (box, priv->primary_image, FALSE, FALSE, 0); + gtk_box_pack_start (box, priv->scale, FALSE, FALSE, 0); + gtk_box_pack_start (box, priv->secondary_image, FALSE, FALSE, 0); break; case IDO_SCALE_MENU_ITEM_STYLE_LABEL: - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->primary_label, FALSE, FALSE, 0); -#ifdef USE_GTK3 - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->proxy, FALSE, FALSE, 0); -#else - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->scale, FALSE, FALSE, 0); -#endif - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->secondary_label, FALSE, FALSE, 0); + gtk_box_pack_start (box, priv->primary_label, FALSE, FALSE, 0); + gtk_box_pack_start (box, priv->scale, FALSE, FALSE, 0); + gtk_box_pack_start (box, priv->secondary_label, FALSE, FALSE, 0); break; default: -#ifdef USE_GTK3 - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->proxy, FALSE, FALSE, 0); -#else - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->scale, FALSE, FALSE, 0); -#endif + gtk_box_pack_start (box, priv->scale, FALSE, FALSE, 0); break; } @@ -579,64 +545,50 @@ static gboolean ido_scale_menu_item_button_release_event (GtkWidget *menuitem, GdkEventButton *event) { + IdoScaleMenuItem *item = IDO_SCALE_MENU_ITEM (menuitem); IdoScaleMenuItemPrivate *priv = GET_PRIVATE (menuitem); GtkWidget *scale = priv->scale; gdouble x; + /* if user clicked to the left of the scale... */ if (event->x > priv->child_allocation.x && event->x < priv->child_allocation.x + priv->left_padding) { - GtkAdjustment *adj = gtk_range_get_adjustment (GTK_RANGE (priv->scale)); - if (gtk_widget_get_direction (menuitem) == GTK_TEXT_DIR_LTR) { - gtk_adjustment_set_value (adj, gtk_adjustment_get_lower (adj)); + ido_scale_menu_item_primary_clicked (item); } else { - gtk_adjustment_set_value (adj, gtk_adjustment_get_upper (adj)); + ido_scale_menu_item_secondary_clicked (item); } - - if (priv->grabbed) - { - priv->grabbed = FALSE; - g_signal_emit (menuitem, signals[SLIDER_RELEASED], 0); - } - - return TRUE; } - if (event->x < priv->child_allocation.x + priv->child_allocation.width + priv->right_padding + priv->left_padding && + /* if user clicked to the right of the scale... */ + else if (event->x < priv->child_allocation.x + priv->child_allocation.width + priv->right_padding + priv->left_padding && event->x > priv->child_allocation.x + priv->child_allocation.width + priv->left_padding) { - GtkAdjustment *adj = gtk_range_get_adjustment (GTK_RANGE (priv->scale)); - if (gtk_widget_get_direction (menuitem) == GTK_TEXT_DIR_LTR) { - gtk_adjustment_set_value (adj, gtk_adjustment_get_upper (adj)); + ido_scale_menu_item_secondary_clicked (item); } else { - gtk_adjustment_set_value (adj, gtk_adjustment_get_lower (adj)); + ido_scale_menu_item_primary_clicked (item); } - - if (priv->grabbed) - { - priv->grabbed = FALSE; - g_signal_emit (menuitem, signals[SLIDER_RELEASED], 0); - } - - return TRUE; } - translate_event_coordinates (menuitem, event->x, &x); - event->x = x; + /* user clicked on the scale... */ + else + { + translate_event_coordinates (menuitem, event->x, &x); + event->x = x; - translate_event_coordinates (menuitem, event->x_root, &x); - event->x_root= x; + translate_event_coordinates (menuitem, event->x_root, &x); + event->x_root= x; - gtk_widget_event (scale, - ((GdkEvent *)(void*)(event))); + gtk_widget_event (scale, (GdkEvent*)event); + } if (priv->grabbed) { @@ -812,16 +764,14 @@ ido_scale_menu_item_set_style (IdoScaleMenuItem *menuitem, IdoScaleMenuItemStyle style) { IdoScaleMenuItemPrivate *priv; - IdoScaleMenuItemStyle old_style; g_return_if_fail (IDO_IS_SCALE_MENU_ITEM (menuitem)); priv = GET_PRIVATE (menuitem); - old_style = priv->style; priv->style = style; - update_packing (menuitem, style, old_style); + update_packing (menuitem, style); } /** @@ -958,5 +908,50 @@ ido_scale_menu_item_set_secondary_label (IdoScaleMenuItem *menuitem, } } +/** + * ido_scale_menu_item_primary_clicked: + * @menuitem: the #IdoScaleMenuItem + * + * Emits the "primary-clicked" signal. + * + * The default handler for this signal lowers the scale's + * adjustment to its lower bound. + */ +void +ido_scale_menu_item_primary_clicked (IdoScaleMenuItem * item) +{ + g_signal_emit (item, signals[PRIMARY_CLICKED], 0); +} +static void +default_primary_clicked_handler (IdoScaleMenuItem * item) +{ + g_debug ("%s: setting scale to lower bound", G_STRFUNC); + IdoScaleMenuItemPrivate * priv = GET_PRIVATE (item); + GtkAdjustment *adj = gtk_range_get_adjustment (GTK_RANGE (priv->scale)); + gtk_adjustment_set_value (adj, gtk_adjustment_get_lower (adj)); +} + +/** + * ido_scale_menu_item_primary_clicked: + * @menuitem: the #IdoScaleMenuItem + * + * Emits the "primary-clicked" signal. + * + * The default handler for this signal raises the scale's + * adjustment to its upper bound. + */ +void +ido_scale_menu_item_secondary_clicked (IdoScaleMenuItem * item) +{ + g_signal_emit (item, signals[SECONDARY_CLICKED], 0); +} +static void +default_secondary_clicked_handler (IdoScaleMenuItem * item) +{ + g_debug ("%s: setting scale to upper bound", G_STRFUNC); + IdoScaleMenuItemPrivate * priv = GET_PRIVATE (item); + GtkAdjustment *adj = gtk_range_get_adjustment (GTK_RANGE (priv->scale)); + gtk_adjustment_set_value (adj, gtk_adjustment_get_upper (adj)); +} #define __IDO_SCALE_MENU_ITEM_C__ |