diff options
-rw-r--r-- | example/menus.c | 5 | ||||
-rw-r--r-- | src/idoscalemenuitem.c | 220 | ||||
-rw-r--r-- | src/idoscalemenuitem.h | 18 |
3 files changed, 202 insertions, 41 deletions
diff --git a/example/menus.c b/example/menus.c index 9877d5e..28b505b 100644 --- a/example/menus.c +++ b/example/menus.c @@ -12,6 +12,7 @@ main (int argc, char *argv[]) GtkWidget *menuitem; GtkWidget *root; GtkWidget *menubar; + GtkWidget *image; gtk_init (&argc, &argv); @@ -39,6 +40,10 @@ main (int argc, char *argv[]) gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); menuitem = ido_scale_menu_item_new_with_range ("Volume", 0, 100, 1); + image = ido_scale_menu_item_get_primary_image (IDO_SCALE_MENU_ITEM (menuitem)); + gtk_image_set_from_stock (GTK_IMAGE (image), GTK_STOCK_NEW, GTK_ICON_SIZE_MENU); + image = ido_scale_menu_item_get_secondary_image (IDO_SCALE_MENU_ITEM (menuitem)); + gtk_image_set_from_stock (GTK_IMAGE (image), GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); menuitem = ido_entry_menu_item_new (); diff --git a/src/idoscalemenuitem.c b/src/idoscalemenuitem.c index 08f54e7..2f9cb4e 100644 --- a/src/idoscalemenuitem.c +++ b/src/idoscalemenuitem.c @@ -26,35 +26,46 @@ #include <gtk/gtk.h> #include "idoscalemenuitem.h" -static GObject* ido_scale_menu_item_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam *construct_params); -static void ido_scale_menu_item_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -static void ido_scale_menu_item_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); -static void ido_scale_menu_item_forall (GtkContainer *container, - gboolean include_internals, - GtkCallback callback, - gpointer data); -static gboolean ido_scale_menu_item_button_press_event (GtkWidget *menuitem, - GdkEventButton *event); -static gboolean ido_scale_menu_item_button_release_event (GtkWidget *menuitem, - GdkEventButton *event); -static gboolean ido_scale_menu_item_motion_notify_event (GtkWidget *menuitem, - GdkEventMotion *event); -static gboolean ido_scale_menu_item_expose (GtkWidget *widget, - GdkEventExpose *event); +static GObject* ido_scale_menu_item_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_params); +static void ido_scale_menu_item_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void ido_scale_menu_item_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void ido_scale_menu_item_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer data); +static gboolean ido_scale_menu_item_button_press_event (GtkWidget *menuitem, + GdkEventButton *event); +static gboolean ido_scale_menu_item_button_release_event (GtkWidget *menuitem, + GdkEventButton *event); +static gboolean ido_scale_menu_item_motion_notify_event (GtkWidget *menuitem, + GdkEventMotion *event); +static gboolean ido_scale_menu_item_expose (GtkWidget *widget, + GdkEventExpose *event); +static void ido_scale_menu_item_primary_image_notify (GtkImage *image, + GParamSpec *pspec, + IdoScaleMenuItem *item); +static void ido_scale_menu_item_secondary_image_notify (GtkImage *image, + GParamSpec *pspec, + IdoScaleMenuItem *item); struct _IdoScaleMenuItemPrivate { GtkWidget *scale; GtkAdjustment *adjustment; GtkWidget *offscreen; + GtkWidget *primary_image; + GtkWidget *secondary_image; + GtkWidget *hbox; GtkAllocation child_allocation; + gdouble left_padding; + gdouble right_padding; }; enum { @@ -90,25 +101,44 @@ ido_scale_menu_item_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { IdoScaleMenuItemPrivate *priv = GET_PRIVATE (widget); - GtkRequisition child_requisition; + GtkRequisition primary_image_req; + GtkRequisition secondary_image_req; gint horizontal_padding; + gint primary_padding, secondary_padding; GTK_WIDGET_CLASS (ido_scale_menu_item_parent_class)->size_allocate (widget, allocation); - gtk_widget_get_child_requisition (priv->scale, &child_requisition); + gtk_widget_get_child_requisition (priv->primary_image, &primary_image_req); + gtk_widget_get_child_requisition (priv->secondary_image, &secondary_image_req); gtk_widget_style_get (widget, "horizontal-padding", &horizontal_padding, NULL); + primary_padding = GTK_WIDGET_VISIBLE (priv->primary_image) ? primary_image_req.width : 0; + secondary_padding += GTK_WIDGET_VISIBLE (priv->secondary_image) ? secondary_image_req.width : 0; + + priv->left_padding = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR ? primary_padding : secondary_padding; + + if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) + { + priv->left_padding = primary_padding; + priv->right_padding = secondary_padding; + } + else + { + priv->left_padding = secondary_padding; + priv->right_padding = primary_padding; + } + priv->child_allocation.x = GTK_CONTAINER (widget)->border_width + widget->style->xthickness; priv->child_allocation.y = GTK_CONTAINER (widget)->border_width + widget->style->ythickness; priv->child_allocation.x += horizontal_padding; - priv->child_allocation.x += GTK_MENU_ITEM (widget)->toggle_size; priv->child_allocation.width = MAX (1, (gint)allocation->width - priv->child_allocation.x * 2); + priv->child_allocation.width -= (primary_padding + secondary_padding); priv->child_allocation.height = MAX (1, (gint)allocation->height - priv->child_allocation.y * 2); gtk_widget_set_size_request (priv->scale, priv->child_allocation.width, -1); @@ -243,6 +273,7 @@ ido_scale_menu_item_constructor (GType type, GObjectConstructParam *construct_params) { GObject *object; + GtkWidget *hbox; IdoScaleMenuItemPrivate *priv; object = G_OBJECT_CLASS (ido_scale_menu_item_parent_class)->constructor (type, @@ -255,10 +286,30 @@ ido_scale_menu_item_constructor (GType type, priv->scale = gtk_hscale_new_with_range (0.0, 100.0, 1.0); gtk_scale_set_draw_value (GTK_SCALE (priv->scale), FALSE); - gtk_container_add (GTK_CONTAINER (priv->offscreen), priv->scale); gtk_widget_show (priv->scale); gtk_widget_show (priv->offscreen); + hbox = gtk_hbox_new (FALSE, 0); + gtk_container_add (GTK_CONTAINER (priv->offscreen), hbox); + + priv->primary_image = gtk_image_new (); + g_signal_connect (priv->primary_image, "notify", + G_CALLBACK (ido_scale_menu_item_primary_image_notify), + object); + + priv->secondary_image = gtk_image_new (); + g_signal_connect (priv->secondary_image, "notify", + G_CALLBACK (ido_scale_menu_item_secondary_image_notify), + object); + + gtk_box_pack_start (GTK_BOX (hbox), priv->primary_image, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox), priv->scale, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox), priv->secondary_image, FALSE, FALSE, 0); + + priv->hbox = hbox; + + gtk_widget_show (priv->hbox); + gtk_widget_queue_draw (priv->offscreen); g_signal_connect (priv->offscreen, @@ -287,15 +338,29 @@ ido_scale_menu_item_forall (GtkContainer *container, (* callback) (priv->scale, data); } +static void +translate_event_coordinates (GtkWidget *widget, + gdouble in_x, + gdouble *out_x) +{ + IdoScaleMenuItemPrivate *priv = GET_PRIVATE (widget); + + *out_x = in_x - priv->child_allocation.x - priv->left_padding; +} + static gboolean ido_scale_menu_item_button_press_event (GtkWidget *menuitem, GdkEventButton *event) { IdoScaleMenuItemPrivate *priv = GET_PRIVATE (menuitem); GtkWidget *scale = priv->scale; + gdouble x; - event->x -= priv->child_allocation.x; - event->x_root -= priv->child_allocation.x; + translate_event_coordinates (menuitem, event->x, &x); + event->x = x; + + translate_event_coordinates (menuitem, event->x_root, &x); + event->x_root = x; gtk_widget_event (scale, ((GdkEvent *)(void*)(event))); @@ -310,10 +375,49 @@ ido_scale_menu_item_button_release_event (GtkWidget *menuitem, IdoScaleMenuItemPrivate *priv = GET_PRIVATE (menuitem); GtkWidget *scale = priv->scale; GdkWindow *tmp = event->window; + gdouble x; + + 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)); + } + else + { + gtk_adjustment_set_value (adj, gtk_adjustment_get_upper (adj)); + } + + return TRUE; + } + + 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)); + } + else + { + gtk_adjustment_set_value (adj, gtk_adjustment_get_lower (adj)); + } + + return TRUE; + } event->window = GTK_RANGE (scale)->event_window; - event->x -= priv->child_allocation.x; - event->x_root -= priv->child_allocation.x; + + translate_event_coordinates (menuitem, event->x, &x); + event->x = x; + + translate_event_coordinates (menuitem, event->x_root, &x); + event->x_root= x; gtk_widget_event (scale, ((GdkEvent *)(void*)(event))); @@ -329,9 +433,13 @@ ido_scale_menu_item_motion_notify_event (GtkWidget *menuitem, { IdoScaleMenuItemPrivate *priv = GET_PRIVATE (menuitem); GtkWidget *scale = priv->scale; + gdouble x; - event->x -= priv->child_allocation.x; - event->x_root -= priv->child_allocation.x; + translate_event_coordinates (menuitem, event->x, &x); + event->x = x; + + translate_event_coordinates (menuitem, event->x_root, &x); + event->x_root= x; gtk_widget_event (scale, ((GdkEvent *)(void*)(event))); @@ -339,6 +447,27 @@ ido_scale_menu_item_motion_notify_event (GtkWidget *menuitem, return TRUE; } +static void +ido_scale_menu_item_primary_image_notify (GtkImage *image, + GParamSpec *pspec, + IdoScaleMenuItem *item) +{ + if (gtk_image_get_storage_type (image) == GTK_IMAGE_EMPTY) + gtk_widget_hide (GTK_WIDGET (image)); + else + gtk_widget_show (GTK_WIDGET (image)); +} + +static void +ido_scale_menu_item_secondary_image_notify (GtkImage *image, + GParamSpec *pspec, + IdoScaleMenuItem *item) +{ + if (gtk_image_get_storage_type (image) == GTK_IMAGE_EMPTY) + gtk_widget_hide (GTK_WIDGET (image)); + else + gtk_widget_show (GTK_WIDGET (image)); +} /** * ido_scale_menu_item_new: @@ -393,4 +522,29 @@ ido_scale_menu_item_get_scale (IdoScaleMenuItem *menuitem) return priv->scale; } +GtkWidget * +ido_scale_menu_item_get_primary_image (IdoScaleMenuItem *menuitem) +{ + IdoScaleMenuItemPrivate *priv; + + g_return_val_if_fail (IDO_IS_SCALE_MENU_ITEM (menuitem), NULL); + + priv = GET_PRIVATE (menuitem); + + return priv->primary_image; +} + +GtkWidget * +ido_scale_menu_item_get_secondary_image (IdoScaleMenuItem *menuitem) +{ + IdoScaleMenuItemPrivate *priv; + + g_return_val_if_fail (IDO_IS_SCALE_MENU_ITEM (menuitem), NULL); + + priv = GET_PRIVATE (menuitem); + + return priv->secondary_image; +} + + #define __IDO_SCALE_MENU_ITEM_C__ diff --git a/src/idoscalemenuitem.h b/src/idoscalemenuitem.h index 4d43e96..46fa6a4 100644 --- a/src/idoscalemenuitem.h +++ b/src/idoscalemenuitem.h @@ -55,14 +55,16 @@ struct _IdoScaleMenuItemClass }; -GType ido_scale_menu_item_get_type (void) G_GNUC_CONST; -GtkWidget *ido_scale_menu_item_new (const gchar *label, - GtkAdjustment *adjustment); -GtkWidget *ido_scale_menu_item_new_with_range (const gchar *label, - gdouble min, - gdouble max, - gdouble step); -GtkWidget *ido_scale_menu_item_get_scale (IdoScaleMenuItem *menuitem); +GType ido_scale_menu_item_get_type (void) G_GNUC_CONST; +GtkWidget *ido_scale_menu_item_new (const gchar *label, + GtkAdjustment *adjustment); +GtkWidget *ido_scale_menu_item_new_with_range (const gchar *label, + gdouble min, + gdouble max, + gdouble step); +GtkWidget *ido_scale_menu_item_get_scale (IdoScaleMenuItem *menuitem); +GtkWidget *ido_scale_menu_item_get_primary_image (IdoScaleMenuItem *menuitem); +GtkWidget *ido_scale_menu_item_get_secondary_image (IdoScaleMenuItem *menuitem); G_END_DECLS |