From 51029c20b1163a70897660d190593d5cc8c0ba35 Mon Sep 17 00:00:00 2001 From: Cody Russell Date: Wed, 20 Jan 2010 23:43:05 -0600 Subject: Use GtkOffscreenWindow to manage rendering of the scale. --- src/idoscalemenuitem.c | 235 +++++++++++++------------------------------------ 1 file changed, 59 insertions(+), 176 deletions(-) diff --git a/src/idoscalemenuitem.c b/src/idoscalemenuitem.c index dd13b53..1a842e6 100644 --- a/src/idoscalemenuitem.c +++ b/src/idoscalemenuitem.c @@ -23,10 +23,6 @@ #include #include "idoscalemenuitem.h" -static void ido_scale_menu_item_size_request (GtkWidget *widget, - GtkRequisition *requisition); -static void ido_scale_menu_item_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); static GObject* ido_scale_menu_item_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_params); @@ -42,25 +38,23 @@ static void ido_scale_menu_item_forall (GtkContainer gboolean include_internals, GtkCallback callback, gpointer data); -static void ido_scale_menu_item_construct_child (IdoScaleMenuItem *item); 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); struct _IdoScaleMenuItemPrivate { GtkWidget *scale; GtkAdjustment *adjustment; + GtkWidget *offscreen; }; enum { PROP_0, - PROP_MIN, - PROP_MAX, - PROP_STEP, - PROP_VALUE, PROP_ADJUSTMENT }; @@ -96,14 +90,12 @@ ido_scale_menu_item_class_init (IdoScaleMenuItemClass *item_class) container_class->forall = ido_scale_menu_item_forall; - widget_class->size_request = ido_scale_menu_item_size_request; - widget_class->size_allocate = ido_scale_menu_item_size_allocate; - 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->expose_event = ido_scale_menu_item_expose; gobject_class->constructor = ido_scale_menu_item_constructor; gobject_class->set_property = ido_scale_menu_item_set_property; @@ -141,14 +133,7 @@ ido_scale_menu_item_set_property (GObject *object, switch (prop_id) { case PROP_ADJUSTMENT: - if (!priv->scale) - { - priv->adjustment = g_value_get_object (value); - priv->scale = gtk_hscale_new (priv->adjustment); - gtk_scale_set_draw_value (GTK_SCALE (priv->scale), FALSE); - } - - ido_scale_menu_item_construct_child (menu_item); + gtk_range_set_adjustment (GTK_RANGE (priv->scale), g_value_get_object (value)); break; @@ -180,6 +165,40 @@ ido_scale_menu_item_get_property (GObject *object, } } +static gboolean +offscreen_damage (GtkWidget *widget, + GdkEventExpose *event, + GtkWidget *menuitem) +{ + gtk_widget_queue_draw (menuitem); + + return TRUE; +} + +static gboolean +ido_scale_menu_item_expose (GtkWidget *widget, + GdkEventExpose *event) +{ + IdoScaleMenuItemPrivate *priv = GET_PRIVATE (widget); + + if (GTK_WIDGET_DRAWABLE (widget)) + { + GdkPixbuf *pixbuf = gtk_offscreen_window_get_pixbuf (GTK_OFFSCREEN_WINDOW (priv->offscreen)); + + gdk_draw_pixbuf (widget->window, + widget->style->black_gc, + pixbuf, + 0, 0, + widget->allocation.x, widget->allocation.y, + gdk_pixbuf_get_width (pixbuf), + gdk_pixbuf_get_height (pixbuf), + GDK_RGB_DITHER_NORMAL, + 0, 0); + } + + return TRUE; +} + static GObject* ido_scale_menu_item_constructor (GType type, guint n_construct_properties, @@ -194,10 +213,21 @@ ido_scale_menu_item_constructor (GType type, priv = GET_PRIVATE (object); - if (priv->scale != NULL) - { - ido_scale_menu_item_construct_child (IDO_SCALE_MENU_ITEM (object)); - } + priv->offscreen = gtk_offscreen_window_new (); + + priv->scale = gtk_hscale_new_with_range (0.0, 100.0, 1.0); + gtk_scale_set_draw_value (GTK_SCALE (priv->scale), FALSE); + gtk_widget_set_size_request (priv->scale, 95, 21); + gtk_container_add (GTK_CONTAINER (priv->offscreen), priv->scale); + gtk_widget_show (priv->scale); + gtk_widget_show (priv->offscreen); + + gtk_widget_queue_draw (priv->offscreen); + + g_signal_connect (priv->offscreen, + "damage-event", + G_CALLBACK (offscreen_damage), + object); return object; } @@ -220,123 +250,15 @@ ido_scale_menu_item_forall (GtkContainer *container, (* callback) (priv->scale, data); } -static void -ido_scale_menu_item_size_request (GtkWidget *widget, - GtkRequisition *requisition) -{ - IdoScaleMenuItem *item; - IdoScaleMenuItemPrivate *priv; - GtkWidget *parent; - GtkPackDirection dir; - gint child_width = 0; - gint child_height = 0; - - parent = gtk_widget_get_parent (widget); - item = IDO_SCALE_MENU_ITEM (widget); - priv = GET_PRIVATE (item); - - if (GTK_IS_MENU_BAR (parent)) - dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent)); - else - dir = GTK_PACK_DIRECTION_LTR; - - if (priv->scale && GTK_WIDGET_VISIBLE (priv->scale)) - { - GtkRequisition child_requisition; - - gtk_widget_size_request (priv->scale, - &child_requisition); - - child_width = child_requisition.width; - child_height = child_requisition.height; - } - - GTK_WIDGET_CLASS (ido_scale_menu_item_parent_class)->size_request (widget, requisition); - - if (dir == GTK_PACK_DIRECTION_LTR || dir == GTK_PACK_DIRECTION_RTL) - requisition->height = MAX (requisition->height, child_height); - else - requisition->width = MAX (requisition->width, child_width); -} - -static void -ido_scale_menu_item_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - IdoScaleMenuItem *item; - IdoScaleMenuItemPrivate *priv; - GtkWidget *parent; - GtkPackDirection dir; - - item = IDO_SCALE_MENU_ITEM (widget); - priv = GET_PRIVATE (item); - parent = gtk_widget_get_parent (widget); - - if (GTK_IS_MENU_BAR (parent)) - dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent)); - else - dir = GTK_PACK_DIRECTION_LTR; - - GTK_WIDGET_CLASS (ido_scale_menu_item_parent_class)->size_allocate (widget, allocation); - - if (priv->scale && GTK_WIDGET_VISIBLE (priv->scale)) - { - GtkRequisition child_requisition; - GtkAllocation child_allocation; - gint x, y, offset; - - gtk_widget_get_child_requisition (priv->scale, - &child_requisition); - - if (dir == GTK_PACK_DIRECTION_LTR || dir == GTK_PACK_DIRECTION_RTL) - { - offset = GTK_CONTAINER (item)->border_width + widget->style->xthickness; - - if ((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) == - (dir == GTK_PACK_DIRECTION_LTR)) - { - x = offset + (GTK_MENU_ITEM (item)->toggle_size - child_requisition.width) / 2; - } - else - { - // TODO rtl - } - } - else - { - offset = GTK_CONTAINER (item)->border_width + widget->style->ythickness; - - // TODO vertical - } - - y = widget->allocation.height / 2 - child_requisition.height / 2; - - child_allocation.width = allocation->width; - child_allocation.height = child_requisition.height; - child_allocation.x = widget->allocation.x + MAX (x, 0); - child_allocation.y = widget->allocation.y + MAX (y, 0); - - gtk_widget_size_allocate (priv->scale, &child_allocation); - } -} - static gboolean ido_scale_menu_item_button_press_event (GtkWidget *menuitem, GdkEventButton *event) { GtkWidget *scale = GET_PRIVATE (IDO_SCALE_MENU_ITEM (menuitem))->scale; - event->x = 0; - event->y = 0; - - //gtk_grab_add (scale); - //gtk_grab_remove (menuitem->parent); - gtk_widget_event (scale, (GdkEvent *)event); - //g_signal_stop_emission_by_name (menuitem->parent, "hide"); - - return FALSE; + return TRUE; } static gboolean @@ -344,11 +266,14 @@ ido_scale_menu_item_button_release_event (GtkWidget *menuitem, GdkEventButton *event) { GtkWidget *scale = GET_PRIVATE (IDO_SCALE_MENU_ITEM (menuitem))->scale; + GdkWindow *tmp = event->window; - //gtk_grab_remove (scale); + event->window = GTK_RANGE (scale)->event_window; gtk_widget_event (scale, (GdkEvent *) event); + event->window = tmp; + return TRUE; } @@ -362,48 +287,6 @@ ido_scale_menu_item_motion_notify_event (GtkWidget *menuitem, return TRUE; } -static void -ido_scale_menu_item_construct_child (IdoScaleMenuItem *item) -{ - IdoScaleMenuItemPrivate *priv = GET_PRIVATE (item); - GtkWidget *scale = NULL; - - if (priv->scale) - { - scale = g_object_ref (priv->scale); - if (scale->parent) - { - gtk_container_remove (GTK_CONTAINER (scale->parent), scale); - } - } - - priv->scale = NULL; - - priv->scale = gtk_hscale_new (priv->adjustment); - gtk_widget_set_can_focus (priv->scale, TRUE); - gtk_scale_set_draw_value (GTK_SCALE (priv->scale), FALSE); - - if (GTK_BIN (item)->child) - gtk_container_remove (GTK_CONTAINER (item), - GTK_BIN (item)->child); - - if (scale) - { - priv->scale = scale; - g_object_set (priv->scale, - "visible", TRUE, - "no-show-all", TRUE, - NULL); - - gtk_container_add (GTK_CONTAINER (item), scale); - gtk_widget_show_all (scale); - - g_object_unref (scale); - - return; - } -} - /** * ido_scale_menu_item_new: -- cgit v1.2.3