diff options
Diffstat (limited to 'gtk2_ardour/gtkscrolledwindow.c')
-rw-r--r-- | gtk2_ardour/gtkscrolledwindow.c | 985 |
1 files changed, 718 insertions, 267 deletions
diff --git a/gtk2_ardour/gtkscrolledwindow.c b/gtk2_ardour/gtkscrolledwindow.c index 5e5f687c80..dcb6372afa 100644 --- a/gtk2_ardour/gtkscrolledwindow.c +++ b/gtk2_ardour/gtkscrolledwindow.c @@ -2,30 +2,36 @@ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public + * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. + * Lesser General Public License for more details. * - * You should have received a copy of the GNU Library General Public + * 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. */ /* - * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ +#include <config.h> +#include <math.h> +#include <gdk/gdkkeysyms.h> +#include <gtk/gtkbindings.h> +#include <gtk/gtkmarshalers.h> #include <gtk/gtkscrolledwindow.h> -#include <gtk/gtksignal.h> +#include <gtk/gtkintl.h> +#include <gtk/gtkalias.h> /* scrolled window policy and size requisition handling: @@ -35,7 +41,7 @@ * to be best suited to display its contents, including children. * the width and/or height reported from a widget upon size requisition * may be overidden by the user by specifying a width and/or height - * other than 0 through gtk_widget_set_size_request(). + * other than 0 through gtk_widget_set_usize(). * * a scrolled window needs (for imlementing all three policy types) to * request its width and height based on two different rationales. @@ -63,38 +69,50 @@ * under A) at least correspond to the space taken up by its scrollbars. */ -#define SCROLLBAR_SPACING(w) (GTK_SCROLLED_WINDOW_CLASS (GTK_OBJECT (w)->klass)->scrollbar_spacing) - #define DEFAULT_SCROLLBAR_SPACING 3 enum { - ARG_0, - ARG_HADJUSTMENT, - ARG_VADJUSTMENT, - ARG_HSCROLLBAR_POLICY, - ARG_VSCROLLBAR_POLICY, - ARG_WINDOW_PLACEMENT + PROP_0, + PROP_HADJUSTMENT, + PROP_VADJUSTMENT, + PROP_HSCROLLBAR_POLICY, + PROP_VSCROLLBAR_POLICY, + PROP_WINDOW_PLACEMENT, + PROP_SHADOW_TYPE, + PROP_LAST }; +/* Signals */ +enum +{ + SCROLL_CHILD, + MOVE_FOCUS_OUT, + LAST_SIGNAL +}; static void gtk_scrolled_window_class_init (GtkScrolledWindowClass *klass); static void gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window); -static void gtk_scrolled_window_set_arg (GtkObject *object, - GtkArg *arg, - guint arg_id); -static void gtk_scrolled_window_get_arg (GtkObject *object, - GtkArg *arg, - guint arg_id); static void gtk_scrolled_window_destroy (GtkObject *object); -static void gtk_scrolled_window_finalize (GtkObject *object); -static void gtk_scrolled_window_map (GtkWidget *widget); -static void gtk_scrolled_window_unmap (GtkWidget *widget); -static void gtk_scrolled_window_draw (GtkWidget *widget, - GdkRectangle *area); +static void gtk_scrolled_window_finalize (GObject *object); +static void gtk_scrolled_window_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void gtk_scrolled_window_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +static gint gtk_scrolled_window_expose (GtkWidget *widget, + GdkEventExpose *event); static void gtk_scrolled_window_size_request (GtkWidget *widget, GtkRequisition *requisition); static void gtk_scrolled_window_size_allocate (GtkWidget *widget, GtkAllocation *allocation); +static gint gtk_scrolled_window_scroll_event (GtkWidget *widget, + GdkEventScroll *event); +static gint gtk_scrolled_window_focus (GtkWidget *widget, + GtkDirectionType direction); static void gtk_scrolled_window_add (GtkContainer *container, GtkWidget *widget); static void gtk_scrolled_window_remove (GtkContainer *container, @@ -103,165 +121,219 @@ static void gtk_scrolled_window_forall (GtkContainer *cont gboolean include_internals, GtkCallback callback, gpointer callback_data); +static void gtk_scrolled_window_scroll_child (GtkScrolledWindow *scrolled_window, + GtkScrollType scroll, + gboolean horizontal); +static void gtk_scrolled_window_move_focus_out (GtkScrolledWindow *scrolled_window, + GtkDirectionType direction_type); + static void gtk_scrolled_window_relative_allocation(GtkWidget *widget, GtkAllocation *allocation); static void gtk_scrolled_window_adjustment_changed (GtkAdjustment *adjustment, gpointer data); - static GtkContainerClass *parent_class = NULL; +static guint signals[LAST_SIGNAL] = {0}; -GtkType +GType gtk_scrolled_window_get_type (void) { - static GtkType scrolled_window_type = 0; + static GType scrolled_window_type = 0; if (!scrolled_window_type) { - static const GtkTypeInfo scrolled_window_info = + static const GTypeInfo scrolled_window_info = { - "GtkScrolledWindow", - sizeof (GtkScrolledWindow), sizeof (GtkScrolledWindowClass), - (GtkClassInitFunc) gtk_scrolled_window_class_init, - (GtkObjectInitFunc) gtk_scrolled_window_init, - /* reserved_1 */ NULL, - /* reserved_2 */ NULL, - (GtkClassInitFunc) NULL, + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gtk_scrolled_window_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GtkScrolledWindow), + 0, /* n_preallocs */ + (GInstanceInitFunc) gtk_scrolled_window_init, }; - scrolled_window_type = gtk_type_unique (GTK_TYPE_BIN, &scrolled_window_info); + scrolled_window_type = + g_type_register_static (GTK_TYPE_BIN, "GtkScrolledWindow", + &scrolled_window_info, 0); } return scrolled_window_type; } static void +add_scroll_binding (GtkBindingSet *binding_set, + guint keyval, + GdkModifierType mask, + GtkScrollType scroll, + gboolean horizontal) +{ + guint keypad_keyval = keyval - GDK_Left + GDK_KP_Left; + + gtk_binding_entry_add_signal (binding_set, keyval, mask, + "scroll_child", 2, + GTK_TYPE_SCROLL_TYPE, scroll, + G_TYPE_BOOLEAN, horizontal); + gtk_binding_entry_add_signal (binding_set, keypad_keyval, mask, + "scroll_child", 2, + GTK_TYPE_SCROLL_TYPE, scroll, + G_TYPE_BOOLEAN, horizontal); +} + +static void +add_tab_bindings (GtkBindingSet *binding_set, + GdkModifierType modifiers, + GtkDirectionType direction) +{ + gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers, + "move_focus_out", 1, + GTK_TYPE_DIRECTION_TYPE, direction); + gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers, + "move_focus_out", 1, + GTK_TYPE_DIRECTION_TYPE, direction); +} + +static void gtk_scrolled_window_class_init (GtkScrolledWindowClass *class) { + GObjectClass *gobject_class = G_OBJECT_CLASS (class); GtkObjectClass *object_class; GtkWidgetClass *widget_class; GtkContainerClass *container_class; + GtkBindingSet *binding_set; object_class = (GtkObjectClass*) class; widget_class = (GtkWidgetClass*) class; container_class = (GtkContainerClass*) class; - parent_class = gtk_type_class (GTK_TYPE_BIN); - - gtk_object_add_arg_type ("GtkScrolledWindow::hadjustment", - GTK_TYPE_ADJUSTMENT, - GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT, - ARG_HADJUSTMENT); - gtk_object_add_arg_type ("GtkScrolledWindow::vadjustment", - GTK_TYPE_ADJUSTMENT, - GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT, - ARG_VADJUSTMENT); - gtk_object_add_arg_type ("GtkScrolledWindow::hscrollbar_policy", - GTK_TYPE_POLICY_TYPE, - GTK_ARG_READWRITE, - ARG_HSCROLLBAR_POLICY); - gtk_object_add_arg_type ("GtkScrolledWindow::vscrollbar_policy", - GTK_TYPE_POLICY_TYPE, - GTK_ARG_READWRITE, - ARG_VSCROLLBAR_POLICY); - gtk_object_add_arg_type ("GtkScrolledWindow::window_placement", - GTK_TYPE_CORNER_TYPE, - GTK_ARG_READWRITE, - ARG_WINDOW_PLACEMENT); - - object_class->set_arg = gtk_scrolled_window_set_arg; - object_class->get_arg = gtk_scrolled_window_get_arg; + + parent_class = g_type_class_peek_parent (class); + + gobject_class->finalize = gtk_scrolled_window_finalize; + gobject_class->set_property = gtk_scrolled_window_set_property; + gobject_class->get_property = gtk_scrolled_window_get_property; + object_class->destroy = gtk_scrolled_window_destroy; - object_class->finalize = gtk_scrolled_window_finalize; - widget_class->map = gtk_scrolled_window_map; - widget_class->unmap = gtk_scrolled_window_unmap; - widget_class->draw = gtk_scrolled_window_draw; + widget_class->expose_event = gtk_scrolled_window_expose; widget_class->size_request = gtk_scrolled_window_size_request; widget_class->size_allocate = gtk_scrolled_window_size_allocate; + widget_class->scroll_event = gtk_scrolled_window_scroll_event; + widget_class->focus = gtk_scrolled_window_focus; container_class->add = gtk_scrolled_window_add; container_class->remove = gtk_scrolled_window_remove; container_class->forall = gtk_scrolled_window_forall; - class->scrollbar_spacing = DEFAULT_SCROLLBAR_SPACING; -} - -static void -gtk_scrolled_window_set_arg (GtkObject *object, - GtkArg *arg, - guint arg_id) -{ - GtkScrolledWindow *scrolled_window; + class->scrollbar_spacing = -1; - scrolled_window = GTK_SCROLLED_WINDOW (object); + class->scroll_child = gtk_scrolled_window_scroll_child; + class->move_focus_out = gtk_scrolled_window_move_focus_out; + + g_object_class_install_property (gobject_class, + PROP_HADJUSTMENT, + g_param_spec_object ("hadjustment", + P_("Horizontal Adjustment"), + P_("The GtkAdjustment for the horizontal position"), + GTK_TYPE_ADJUSTMENT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (gobject_class, + PROP_VADJUSTMENT, + g_param_spec_object ("vadjustment", + P_("Vertical Adjustment"), + P_("The GtkAdjustment for the vertical position"), + GTK_TYPE_ADJUSTMENT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (gobject_class, + PROP_HSCROLLBAR_POLICY, + g_param_spec_enum ("hscrollbar_policy", + P_("Horizontal Scrollbar Policy"), + P_("When the horizontal scrollbar is displayed"), + GTK_TYPE_POLICY_TYPE, + GTK_POLICY_ALWAYS, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + g_object_class_install_property (gobject_class, + PROP_VSCROLLBAR_POLICY, + g_param_spec_enum ("vscrollbar_policy", + P_("Vertical Scrollbar Policy"), + P_("When the vertical scrollbar is displayed"), + GTK_TYPE_POLICY_TYPE, + GTK_POLICY_ALWAYS, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + + g_object_class_install_property (gobject_class, + PROP_WINDOW_PLACEMENT, + g_param_spec_enum ("window_placement", + P_("Window Placement"), + P_("Where the contents are located with respect to the scrollbars"), + GTK_TYPE_CORNER_TYPE, + GTK_CORNER_TOP_LEFT, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + g_object_class_install_property (gobject_class, + PROP_SHADOW_TYPE, + g_param_spec_enum ("shadow_type", + P_("Shadow Type"), + P_("Style of bevel around the contents"), + GTK_TYPE_SHADOW_TYPE, + GTK_SHADOW_NONE, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_int ("scrollbar_spacing", + P_("Scrollbar spacing"), + P_("Number of pixels between the scrollbars and the scrolled window"), + 0, + G_MAXINT, + DEFAULT_SCROLLBAR_SPACING, + G_PARAM_READABLE)); + + signals[SCROLL_CHILD] = + g_signal_new ("scroll_child", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GtkScrolledWindowClass, scroll_child), + NULL, NULL, + _gtk_marshal_VOID__ENUM_BOOLEAN, + G_TYPE_NONE, 2, + GTK_TYPE_SCROLL_TYPE, + G_TYPE_BOOLEAN); + signals[MOVE_FOCUS_OUT] = + g_signal_new ("move_focus_out", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GtkScrolledWindowClass, move_focus_out), + NULL, NULL, + _gtk_marshal_VOID__ENUM, + G_TYPE_NONE, 1, + GTK_TYPE_DIRECTION_TYPE); + + binding_set = gtk_binding_set_by_class (class); - switch (arg_id) - { - case ARG_HADJUSTMENT: - gtk_scrolled_window_set_hadjustment (scrolled_window, GTK_VALUE_POINTER (*arg)); - break; - case ARG_VADJUSTMENT: - gtk_scrolled_window_set_vadjustment (scrolled_window, GTK_VALUE_POINTER (*arg)); - break; - case ARG_HSCROLLBAR_POLICY: - gtk_scrolled_window_set_policy (scrolled_window, - GTK_VALUE_ENUM (*arg), - scrolled_window->vscrollbar_policy); - break; - case ARG_VSCROLLBAR_POLICY: - gtk_scrolled_window_set_policy (scrolled_window, - scrolled_window->hscrollbar_policy, - GTK_VALUE_ENUM (*arg)); - break; - case ARG_WINDOW_PLACEMENT: - gtk_scrolled_window_set_placement (scrolled_window, - GTK_VALUE_ENUM (*arg)); - break; - default: - break; - } -} + add_scroll_binding (binding_set, GDK_Left, GDK_CONTROL_MASK, GTK_SCROLL_STEP_BACKWARD, TRUE); + add_scroll_binding (binding_set, GDK_Right, GDK_CONTROL_MASK, GTK_SCROLL_STEP_FORWARD, TRUE); + add_scroll_binding (binding_set, GDK_Up, GDK_CONTROL_MASK, GTK_SCROLL_STEP_BACKWARD, FALSE); + add_scroll_binding (binding_set, GDK_Down, GDK_CONTROL_MASK, GTK_SCROLL_STEP_FORWARD, FALSE); -static void -gtk_scrolled_window_get_arg (GtkObject *object, - GtkArg *arg, - guint arg_id) -{ - GtkScrolledWindow *scrolled_window; + add_scroll_binding (binding_set, GDK_Page_Up, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_BACKWARD, TRUE); + add_scroll_binding (binding_set, GDK_Page_Down, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_FORWARD, TRUE); + add_scroll_binding (binding_set, GDK_Page_Up, 0, GTK_SCROLL_PAGE_BACKWARD, FALSE); + add_scroll_binding (binding_set, GDK_Page_Down, 0, GTK_SCROLL_PAGE_FORWARD, FALSE); - scrolled_window = GTK_SCROLLED_WINDOW (object); + add_scroll_binding (binding_set, GDK_Home, GDK_CONTROL_MASK, GTK_SCROLL_START, TRUE); + add_scroll_binding (binding_set, GDK_End, GDK_CONTROL_MASK, GTK_SCROLL_END, TRUE); + add_scroll_binding (binding_set, GDK_Home, 0, GTK_SCROLL_START, FALSE); + add_scroll_binding (binding_set, GDK_End, 0, GTK_SCROLL_END, FALSE); - switch (arg_id) - { - case ARG_HADJUSTMENT: - GTK_VALUE_POINTER (*arg) = gtk_scrolled_window_get_hadjustment (scrolled_window); - break; - case ARG_VADJUSTMENT: - GTK_VALUE_POINTER (*arg) = gtk_scrolled_window_get_vadjustment (scrolled_window); - break; - case ARG_HSCROLLBAR_POLICY: - GTK_VALUE_ENUM (*arg) = scrolled_window->hscrollbar_policy; - break; - case ARG_VSCROLLBAR_POLICY: - GTK_VALUE_ENUM (*arg) = scrolled_window->vscrollbar_policy; - break; - case ARG_WINDOW_PLACEMENT: - GTK_VALUE_ENUM (*arg) = scrolled_window->window_placement; - break; - default: - arg->type = GTK_TYPE_INVALID; - break; - } + add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD); + add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD); } static void gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window) { - GTK_WIDGET_SET_FLAGS (scrolled_window, GTK_NO_WINDOW); - - gtk_container_set_resize_mode (GTK_CONTAINER (scrolled_window), GTK_RESIZE_QUEUE); + GTK_WIDGET_SET_FLAGS (scrolled_window, GTK_NO_WINDOW | GTK_CAN_FOCUS); scrolled_window->hscrollbar = NULL; scrolled_window->vscrollbar = NULL; @@ -269,7 +341,9 @@ gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window) scrolled_window->vscrollbar_policy = GTK_POLICY_ALWAYS; scrolled_window->hscrollbar_visible = FALSE; scrolled_window->vscrollbar_visible = FALSE; + scrolled_window->focus_out = FALSE; scrolled_window->window_placement = GTK_CORNER_TOP_LEFT; + } GtkWidget* @@ -298,12 +372,11 @@ gtk_scrolled_window_set_hadjustment (GtkScrolledWindow *scrolled_window, { GtkBin *bin; - g_return_if_fail (scrolled_window != NULL); g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window)); if (hadjustment) g_return_if_fail (GTK_IS_ADJUSTMENT (hadjustment)); else - hadjustment = (GtkAdjustment*) gtk_object_new (GTK_TYPE_ADJUSTMENT, NULL); + hadjustment = (GtkAdjustment*) g_object_new (GTK_TYPE_ADJUSTMENT, NULL); bin = GTK_BIN (scrolled_window); @@ -315,7 +388,7 @@ gtk_scrolled_window_set_hadjustment (GtkScrolledWindow *scrolled_window, gtk_widget_pop_composite_child (); gtk_widget_set_parent (scrolled_window->hscrollbar, GTK_WIDGET (scrolled_window)); - gtk_widget_ref (scrolled_window->hscrollbar); + g_object_ref (scrolled_window->hscrollbar); gtk_widget_show (scrolled_window->hscrollbar); } else @@ -326,23 +399,25 @@ gtk_scrolled_window_set_hadjustment (GtkScrolledWindow *scrolled_window, if (old_adjustment == hadjustment) return; - gtk_signal_disconnect_by_func (GTK_OBJECT (old_adjustment), - GTK_SIGNAL_FUNC (gtk_scrolled_window_adjustment_changed), - scrolled_window); + g_signal_handlers_disconnect_by_func (old_adjustment, + gtk_scrolled_window_adjustment_changed, + scrolled_window); gtk_range_set_adjustment (GTK_RANGE (scrolled_window->hscrollbar), hadjustment); } hadjustment = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar)); - gtk_signal_connect (GTK_OBJECT (hadjustment), - "changed", - GTK_SIGNAL_FUNC (gtk_scrolled_window_adjustment_changed), - scrolled_window); + g_signal_connect (hadjustment, + "changed", + G_CALLBACK (gtk_scrolled_window_adjustment_changed), + scrolled_window); gtk_scrolled_window_adjustment_changed (hadjustment, scrolled_window); if (bin->child) gtk_widget_set_scroll_adjustments (bin->child, gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar)), gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar))); + + g_object_notify (G_OBJECT (scrolled_window), "hadjustment"); } void @@ -351,12 +426,11 @@ gtk_scrolled_window_set_vadjustment (GtkScrolledWindow *scrolled_window, { GtkBin *bin; - g_return_if_fail (scrolled_window != NULL); g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window)); if (vadjustment) g_return_if_fail (GTK_IS_ADJUSTMENT (vadjustment)); else - vadjustment = (GtkAdjustment*) gtk_object_new (GTK_TYPE_ADJUSTMENT, NULL); + vadjustment = (GtkAdjustment*) g_object_new (GTK_TYPE_ADJUSTMENT, NULL); bin = GTK_BIN (scrolled_window); @@ -368,7 +442,7 @@ gtk_scrolled_window_set_vadjustment (GtkScrolledWindow *scrolled_window, gtk_widget_pop_composite_child (); gtk_widget_set_parent (scrolled_window->vscrollbar, GTK_WIDGET (scrolled_window)); - gtk_widget_ref (scrolled_window->vscrollbar); + g_object_ref (scrolled_window->vscrollbar); gtk_widget_show (scrolled_window->vscrollbar); } else @@ -379,29 +453,30 @@ gtk_scrolled_window_set_vadjustment (GtkScrolledWindow *scrolled_window, if (old_adjustment == vadjustment) return; - gtk_signal_disconnect_by_func (GTK_OBJECT (old_adjustment), - GTK_SIGNAL_FUNC (gtk_scrolled_window_adjustment_changed), - scrolled_window); + g_signal_handlers_disconnect_by_func (old_adjustment, + gtk_scrolled_window_adjustment_changed, + scrolled_window); gtk_range_set_adjustment (GTK_RANGE (scrolled_window->vscrollbar), vadjustment); } vadjustment = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar)); - gtk_signal_connect (GTK_OBJECT (vadjustment), - "changed", - GTK_SIGNAL_FUNC (gtk_scrolled_window_adjustment_changed), - scrolled_window); + g_signal_connect (vadjustment, + "changed", + G_CALLBACK (gtk_scrolled_window_adjustment_changed), + scrolled_window); gtk_scrolled_window_adjustment_changed (vadjustment, scrolled_window); if (bin->child) gtk_widget_set_scroll_adjustments (bin->child, gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar)), gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar))); + + g_object_notify (G_OBJECT (scrolled_window), "vadjustment"); } GtkAdjustment* gtk_scrolled_window_get_hadjustment (GtkScrolledWindow *scrolled_window) { - g_return_val_if_fail (scrolled_window != NULL, NULL); g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window), NULL); return (scrolled_window->hscrollbar ? @@ -412,7 +487,6 @@ gtk_scrolled_window_get_hadjustment (GtkScrolledWindow *scrolled_window) GtkAdjustment* gtk_scrolled_window_get_vadjustment (GtkScrolledWindow *scrolled_window) { - g_return_val_if_fail (scrolled_window != NULL, NULL); g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window), NULL); return (scrolled_window->vscrollbar ? @@ -425,7 +499,8 @@ gtk_scrolled_window_set_policy (GtkScrolledWindow *scrolled_window, GtkPolicyType hscrollbar_policy, GtkPolicyType vscrollbar_policy) { - g_return_if_fail (scrolled_window != NULL); + GObject *object = G_OBJECT (scrolled_window); + g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window)); if ((scrolled_window->hscrollbar_policy != hscrollbar_policy) || @@ -435,14 +510,40 @@ gtk_scrolled_window_set_policy (GtkScrolledWindow *scrolled_window, scrolled_window->vscrollbar_policy = vscrollbar_policy; gtk_widget_queue_resize (GTK_WIDGET (scrolled_window)); + + g_object_freeze_notify (object); + g_object_notify (object, "hscrollbar-policy"); + g_object_notify (object, "vscrollbar-policy"); + g_object_thaw_notify (object); } } +/** + * gtk_scrolled_window_get_policy: + * @scrolled_window: a #GtkScrolledWindow + * @hscrollbar_policy: location to store the policy for the horizontal scrollbar, or %NULL. + * @vscrollbar_policy: location to store the policy for the horizontal scrollbar, or %NULL. + * + * Retrieves the current policy values for the horizontal and vertical + * scrollbars. See gtk_scrolled_window_set_policy(). + **/ +void +gtk_scrolled_window_get_policy (GtkScrolledWindow *scrolled_window, + GtkPolicyType *hscrollbar_policy, + GtkPolicyType *vscrollbar_policy) +{ + g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window)); + + if (hscrollbar_policy) + *hscrollbar_policy = scrolled_window->hscrollbar_policy; + if (vscrollbar_policy) + *vscrollbar_policy = scrolled_window->vscrollbar_policy; +} + void gtk_scrolled_window_set_placement (GtkScrolledWindow *scrolled_window, GtkCornerType window_placement) { - g_return_if_fail (scrolled_window != NULL); g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window)); if (scrolled_window->window_placement != window_placement) @@ -450,15 +551,79 @@ gtk_scrolled_window_set_placement (GtkScrolledWindow *scrolled_window, scrolled_window->window_placement = window_placement; gtk_widget_queue_resize (GTK_WIDGET (scrolled_window)); + + g_object_notify (G_OBJECT (scrolled_window), "window-placement"); } } +/** + * gtk_scrolled_window_get_placement: + * @scrolled_window: a #GtkScrolledWindow + * + * Gets the placement of the scrollbars for the scrolled window. See + * gtk_scrolled_window_set_placement(). + * + * Return value: the current placement value. + **/ +GtkCornerType +gtk_scrolled_window_get_placement (GtkScrolledWindow *scrolled_window) +{ + g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window), GTK_CORNER_TOP_LEFT); + + return scrolled_window->window_placement; +} + +/** + * gtk_scrolled_window_set_shadow_type: + * @scrolled_window: a #GtkScrolledWindow + * @type: kind of shadow to draw around scrolled window contents + * + * Changes the type of shadow drawn around the contents of + * @scrolled_window. + * + **/ +void +gtk_scrolled_window_set_shadow_type (GtkScrolledWindow *scrolled_window, + GtkShadowType type) +{ + g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window)); + g_return_if_fail (type >= GTK_SHADOW_NONE && type <= GTK_SHADOW_ETCHED_OUT); + + if (scrolled_window->shadow_type != type) + { + scrolled_window->shadow_type = type; + + if (GTK_WIDGET_DRAWABLE (scrolled_window)) + gtk_widget_queue_draw (GTK_WIDGET (scrolled_window)); + + gtk_widget_queue_resize (GTK_WIDGET (scrolled_window)); + + g_object_notify (G_OBJECT (scrolled_window), "shadow-type"); + } +} + +/** + * gtk_scrolled_window_get_shadow_type: + * @scrolled_window: a #GtkScrolledWindow + * + * Gets the shadow type of the scrolled window. See + * gtk_scrolled_window_set_shadow_type(). + * + * Return value: the current shadow type + **/ +GtkShadowType +gtk_scrolled_window_get_shadow_type (GtkScrolledWindow *scrolled_window) +{ + g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_NONE); + + return scrolled_window->shadow_type; +} + static void gtk_scrolled_window_destroy (GtkObject *object) { GtkScrolledWindow *scrolled_window; - g_return_if_fail (object != NULL); g_return_if_fail (GTK_IS_SCROLLED_WINDOW (object)); scrolled_window = GTK_SCROLLED_WINDOW (object); @@ -472,86 +637,132 @@ gtk_scrolled_window_destroy (GtkObject *object) } static void -gtk_scrolled_window_finalize (GtkObject *object) +gtk_scrolled_window_finalize (GObject *object) { - GtkScrolledWindow *scrolled_window; - - scrolled_window = GTK_SCROLLED_WINDOW (object); + GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (object); - gtk_widget_unref (scrolled_window->hscrollbar); - gtk_widget_unref (scrolled_window->vscrollbar); + g_object_unref (scrolled_window->hscrollbar); + g_object_unref (scrolled_window->vscrollbar); - GTK_OBJECT_CLASS (parent_class)->finalize (object); + G_OBJECT_CLASS (parent_class)->finalize (object); } static void -gtk_scrolled_window_map (GtkWidget *widget) +gtk_scrolled_window_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) { - GtkScrolledWindow *scrolled_window; - - g_return_if_fail (widget != NULL); - g_return_if_fail (GTK_IS_SCROLLED_WINDOW (widget)); - - scrolled_window = GTK_SCROLLED_WINDOW (widget); - - /* chain parent class handler to map self and child */ - GTK_WIDGET_CLASS (parent_class)->map (widget); - - if (GTK_WIDGET_VISIBLE (scrolled_window->hscrollbar) && - !GTK_WIDGET_MAPPED (scrolled_window->hscrollbar)) - gtk_widget_map (scrolled_window->hscrollbar); + GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (object); - if (GTK_WIDGET_VISIBLE (scrolled_window->vscrollbar) && - !GTK_WIDGET_MAPPED (scrolled_window->vscrollbar)) - gtk_widget_map (scrolled_window->vscrollbar); + switch (prop_id) + { + case PROP_HADJUSTMENT: + gtk_scrolled_window_set_hadjustment (scrolled_window, + g_value_get_object (value)); + break; + case PROP_VADJUSTMENT: + gtk_scrolled_window_set_vadjustment (scrolled_window, + g_value_get_object (value)); + break; + case PROP_HSCROLLBAR_POLICY: + gtk_scrolled_window_set_policy (scrolled_window, + g_value_get_enum (value), + scrolled_window->vscrollbar_policy); + break; + case PROP_VSCROLLBAR_POLICY: + gtk_scrolled_window_set_policy (scrolled_window, + scrolled_window->hscrollbar_policy, + g_value_get_enum (value)); + break; + case PROP_WINDOW_PLACEMENT: + gtk_scrolled_window_set_placement (scrolled_window, + g_value_get_enum (value)); + break; + case PROP_SHADOW_TYPE: + gtk_scrolled_window_set_shadow_type (scrolled_window, + g_value_get_enum (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } } static void -gtk_scrolled_window_unmap (GtkWidget *widget) +gtk_scrolled_window_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) { - GtkScrolledWindow *scrolled_window; - - g_return_if_fail (widget != NULL); - g_return_if_fail (GTK_IS_SCROLLED_WINDOW (widget)); - - scrolled_window = GTK_SCROLLED_WINDOW (widget); - - /* chain parent class handler to unmap self and child */ - GTK_WIDGET_CLASS (parent_class)->unmap (widget); + GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (object); - if (GTK_WIDGET_MAPPED (scrolled_window->hscrollbar)) - gtk_widget_unmap (scrolled_window->hscrollbar); - - if (GTK_WIDGET_MAPPED (scrolled_window->vscrollbar)) - gtk_widget_unmap (scrolled_window->vscrollbar); + switch (prop_id) + { + case PROP_HADJUSTMENT: + g_value_set_object (value, + G_OBJECT (gtk_scrolled_window_get_hadjustment (scrolled_window))); + break; + case PROP_VADJUSTMENT: + g_value_set_object (value, + G_OBJECT (gtk_scrolled_window_get_vadjustment (scrolled_window))); + break; + case PROP_HSCROLLBAR_POLICY: + g_value_set_enum (value, scrolled_window->hscrollbar_policy); + break; + case PROP_VSCROLLBAR_POLICY: + g_value_set_enum (value, scrolled_window->vscrollbar_policy); + break; + case PROP_WINDOW_PLACEMENT: + g_value_set_enum (value, scrolled_window->window_placement); + break; + case PROP_SHADOW_TYPE: + g_value_set_enum (value, scrolled_window->shadow_type); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } } static void -gtk_scrolled_window_draw (GtkWidget *widget, - GdkRectangle *area) +gtk_scrolled_window_paint (GtkWidget *widget, + GdkRectangle *area) { - GtkScrolledWindow *scrolled_window; - GtkBin *bin; - GdkRectangle child_area; + GtkAllocation relative_allocation; + GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget); - g_return_if_fail (widget != NULL); - g_return_if_fail (GTK_IS_SCROLLED_WINDOW (widget)); - g_return_if_fail (area != NULL); - - scrolled_window = GTK_SCROLLED_WINDOW (widget); - bin = GTK_BIN (widget); + if (scrolled_window->shadow_type != GTK_SHADOW_NONE) + { + gtk_scrolled_window_relative_allocation (widget, &relative_allocation); + + relative_allocation.x -= widget->style->xthickness; + relative_allocation.y -= widget->style->ythickness; + relative_allocation.width += 2 * widget->style->xthickness; + relative_allocation.height += 2 * widget->style->ythickness; + + gtk_paint_shadow (widget->style, widget->window, + GTK_STATE_NORMAL, scrolled_window->shadow_type, + area, widget, "scrolled_window", + widget->allocation.x + relative_allocation.x, + widget->allocation.y + relative_allocation.y, + relative_allocation.width, + relative_allocation.height); + } +} - if (bin->child && GTK_WIDGET_VISIBLE (bin->child) && - gtk_widget_intersect (bin->child, area, &child_area)) - gtk_widget_draw (bin->child, &child_area); - - if (GTK_WIDGET_VISIBLE (scrolled_window->hscrollbar) && - gtk_widget_intersect (scrolled_window->hscrollbar, area, &child_area)) - gtk_widget_draw (scrolled_window->hscrollbar, &child_area); - - if (GTK_WIDGET_VISIBLE (scrolled_window->vscrollbar) && - gtk_widget_intersect (scrolled_window->vscrollbar, area, &child_area)) - gtk_widget_draw (scrolled_window->vscrollbar, &child_area); +static gint +gtk_scrolled_window_expose (GtkWidget *widget, + GdkEventExpose *event) +{ + if (GTK_WIDGET_DRAWABLE (widget)) + { + gtk_scrolled_window_paint (widget, &event->area); + + (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event); + } + + return FALSE; } static void @@ -560,7 +771,6 @@ gtk_scrolled_window_forall (GtkContainer *container, GtkCallback callback, gpointer callback_data) { - g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_SCROLLED_WINDOW (container)); g_return_if_fail (callback != NULL); @@ -582,6 +792,127 @@ gtk_scrolled_window_forall (GtkContainer *container, } static void +gtk_scrolled_window_scroll_child (GtkScrolledWindow *scrolled_window, + GtkScrollType scroll, + gboolean horizontal) +{ + GtkAdjustment *adjustment = NULL; + + switch (scroll) + { + case GTK_SCROLL_STEP_UP: + scroll = GTK_SCROLL_STEP_BACKWARD; + horizontal = FALSE; + break; + case GTK_SCROLL_STEP_DOWN: + scroll = GTK_SCROLL_STEP_FORWARD; + horizontal = FALSE; + break; + case GTK_SCROLL_STEP_LEFT: + scroll = GTK_SCROLL_STEP_BACKWARD; + horizontal = TRUE; + break; + case GTK_SCROLL_STEP_RIGHT: + scroll = GTK_SCROLL_STEP_FORWARD; + horizontal = TRUE; + break; + case GTK_SCROLL_PAGE_UP: + scroll = GTK_SCROLL_PAGE_BACKWARD; + horizontal = FALSE; + break; + case GTK_SCROLL_PAGE_DOWN: + scroll = GTK_SCROLL_PAGE_FORWARD; + horizontal = FALSE; + break; + case GTK_SCROLL_PAGE_LEFT: + scroll = GTK_SCROLL_STEP_BACKWARD; + horizontal = TRUE; + break; + case GTK_SCROLL_PAGE_RIGHT: + scroll = GTK_SCROLL_STEP_FORWARD; + horizontal = TRUE; + break; + case GTK_SCROLL_STEP_BACKWARD: + case GTK_SCROLL_STEP_FORWARD: + case GTK_SCROLL_PAGE_BACKWARD: + case GTK_SCROLL_PAGE_FORWARD: + case GTK_SCROLL_START: + case GTK_SCROLL_END: + break; + default: + g_warning ("Invalid scroll type %d for GtkSpinButton::change-value", scroll); + return; + } + + if (horizontal) + { + if (scrolled_window->hscrollbar) + adjustment = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar)); + } + else + { + if (scrolled_window->vscrollbar) + adjustment = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar)); + } + + if (adjustment) + { + gdouble value = adjustment->value; + + switch (scroll) + { + case GTK_SCROLL_STEP_FORWARD: + value += adjustment->step_increment; + break; + case GTK_SCROLL_STEP_BACKWARD: + value -= adjustment->step_increment; + break; + case GTK_SCROLL_PAGE_FORWARD: + value += adjustment->page_increment; + break; + case GTK_SCROLL_PAGE_BACKWARD: + value -= adjustment->page_increment; + break; + case GTK_SCROLL_START: + value = adjustment->lower; + break; + case GTK_SCROLL_END: + value = adjustment->upper; + break; + default: + g_assert_not_reached (); + break; + } + + value = CLAMP (value, adjustment->lower, adjustment->upper - adjustment->page_size); + + gtk_adjustment_set_value (adjustment, value); + } +} + +static void +gtk_scrolled_window_move_focus_out (GtkScrolledWindow *scrolled_window, + GtkDirectionType direction_type) +{ + GtkWidget *toplevel; + + /* Focus out of the scrolled window entirely. We do this by setting + * a flag, then propagating the focus motion to the notebook. + */ + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (scrolled_window)); + if (!GTK_WIDGET_TOPLEVEL (toplevel)) + return; + + g_object_ref (scrolled_window); + + scrolled_window->focus_out = TRUE; + g_signal_emit_by_name (toplevel, "move_focus", direction_type); + scrolled_window->focus_out = FALSE; + + g_object_unref (scrolled_window); +} + +static void gtk_scrolled_window_size_request (GtkWidget *widget, GtkRequisition *requisition) { @@ -589,17 +920,19 @@ gtk_scrolled_window_size_request (GtkWidget *widget, GtkBin *bin; gint extra_width; gint extra_height; + gint scrollbar_spacing; GtkRequisition hscrollbar_requisition; GtkRequisition vscrollbar_requisition; GtkRequisition child_requisition; - g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_SCROLLED_WINDOW (widget)); g_return_if_fail (requisition != NULL); scrolled_window = GTK_SCROLLED_WINDOW (widget); bin = GTK_BIN (scrolled_window); + scrollbar_spacing = _gtk_scrolled_window_get_scrollbar_spacing (scrolled_window); + extra_width = 0; extra_height = 0; requisition->width = 0; @@ -612,20 +945,14 @@ gtk_scrolled_window_size_request (GtkWidget *widget, if (bin->child && GTK_WIDGET_VISIBLE (bin->child)) { - static guint quark_aux_info = 0; - - if (!quark_aux_info) - quark_aux_info = g_quark_from_static_string ("gtk-aux-info"); - gtk_widget_size_request (bin->child, &child_requisition); if (scrolled_window->hscrollbar_policy == GTK_POLICY_NEVER) requisition->width += child_requisition.width; else { - GtkWidgetAuxInfo *aux_info; + GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (bin->child, FALSE); - aux_info = gtk_object_get_data_by_id (GTK_OBJECT (bin->child), quark_aux_info); if (aux_info && aux_info->width > 0) { requisition->width += aux_info->width; @@ -636,12 +963,11 @@ gtk_scrolled_window_size_request (GtkWidget *widget, } // if (scrolled_window->vscrollbar_policy == GTK_POLICY_NEVER) -// requisition->height += child_requisition.height; +// requisition->height += child_requisition.height; // else { - GtkWidgetAuxInfo *aux_info; + GtkWidgetAuxInfo *aux_info = _gtk_widget_get_aux_info (bin->child, FALSE); - aux_info = gtk_object_get_data_by_id (GTK_OBJECT (bin->child), quark_aux_info); if (aux_info && aux_info->height > 0) { requisition->height += aux_info->height; @@ -657,7 +983,7 @@ gtk_scrolled_window_size_request (GtkWidget *widget, { requisition->width = MAX (requisition->width, hscrollbar_requisition.width); if (!extra_height || scrolled_window->hscrollbar_policy == GTK_POLICY_ALWAYS) - extra_height = SCROLLBAR_SPACING (scrolled_window) + hscrollbar_requisition.height; + extra_height = scrollbar_spacing + hscrollbar_requisition.height; } if (scrolled_window->vscrollbar_policy == GTK_POLICY_AUTOMATIC || @@ -665,11 +991,17 @@ gtk_scrolled_window_size_request (GtkWidget *widget, { requisition->height = MAX (requisition->height, vscrollbar_requisition.height); if (!extra_height || scrolled_window->vscrollbar_policy == GTK_POLICY_ALWAYS) - extra_width = SCROLLBAR_SPACING (scrolled_window) + vscrollbar_requisition.width; + extra_width = scrollbar_spacing + vscrollbar_requisition.width; } requisition->width += GTK_CONTAINER (widget)->border_width * 2 + MAX (0, extra_width); requisition->height += GTK_CONTAINER (widget)->border_width * 2 + MAX (0, extra_height); + + if (scrolled_window->shadow_type != GTK_SHADOW_NONE) + { + requisition->width += 2 * widget->style->xthickness; + requisition->height += 2 * widget->style->ythickness; + } } static void @@ -677,31 +1009,44 @@ gtk_scrolled_window_relative_allocation (GtkWidget *widget, GtkAllocation *allocation) { GtkScrolledWindow *scrolled_window; + gint scrollbar_spacing; g_return_if_fail (widget != NULL); g_return_if_fail (allocation != NULL); scrolled_window = GTK_SCROLLED_WINDOW (widget); + scrollbar_spacing = _gtk_scrolled_window_get_scrollbar_spacing (scrolled_window); allocation->x = GTK_CONTAINER (widget)->border_width; allocation->y = GTK_CONTAINER (widget)->border_width; + + if (scrolled_window->shadow_type != GTK_SHADOW_NONE) + { + allocation->x += widget->style->xthickness; + allocation->y += widget->style->ythickness; + } + allocation->width = MAX (1, (gint)widget->allocation.width - allocation->x * 2); allocation->height = MAX (1, (gint)widget->allocation.height - allocation->y * 2); if (scrolled_window->vscrollbar_visible) { GtkRequisition vscrollbar_requisition; + gboolean is_rtl; + gtk_widget_get_child_requisition (scrolled_window->vscrollbar, &vscrollbar_requisition); + is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL; - if (scrolled_window->window_placement == GTK_CORNER_TOP_RIGHT || - scrolled_window->window_placement == GTK_CORNER_BOTTOM_RIGHT) - allocation->x += (vscrollbar_requisition.width + - SCROLLBAR_SPACING (scrolled_window)); - - allocation->width = MAX (1, (gint)allocation->width - - ((gint)vscrollbar_requisition.width + - (gint)SCROLLBAR_SPACING (scrolled_window))); + if ((!is_rtl && + (scrolled_window->window_placement == GTK_CORNER_TOP_RIGHT || + scrolled_window->window_placement == GTK_CORNER_BOTTOM_RIGHT)) || + (is_rtl && + (scrolled_window->window_placement == GTK_CORNER_TOP_LEFT || + scrolled_window->window_placement == GTK_CORNER_BOTTOM_LEFT))) + allocation->x += (vscrollbar_requisition.width + scrollbar_spacing); + + allocation->width = MAX (1, allocation->width - (vscrollbar_requisition.width + scrollbar_spacing)); } if (scrolled_window->hscrollbar_visible) { @@ -711,12 +1056,9 @@ gtk_scrolled_window_relative_allocation (GtkWidget *widget, if (scrolled_window->window_placement == GTK_CORNER_BOTTOM_LEFT || scrolled_window->window_placement == GTK_CORNER_BOTTOM_RIGHT) - allocation->y += (hscrollbar_requisition.height + - SCROLLBAR_SPACING (scrolled_window)); + allocation->y += (hscrollbar_requisition.height + scrollbar_spacing); - allocation->height = MAX (1, (gint)allocation->height - - ((gint)hscrollbar_requisition.height + - (gint)SCROLLBAR_SPACING (scrolled_window))); + allocation->height = MAX (1, allocation->height - (hscrollbar_requisition.height + scrollbar_spacing)); } } @@ -728,14 +1070,16 @@ gtk_scrolled_window_size_allocate (GtkWidget *widget, GtkBin *bin; GtkAllocation relative_allocation; GtkAllocation child_allocation; + gint scrollbar_spacing; - g_return_if_fail (widget != NULL); g_return_if_fail (GTK_IS_SCROLLED_WINDOW (widget)); g_return_if_fail (allocation != NULL); scrolled_window = GTK_SCROLLED_WINDOW (widget); bin = GTK_BIN (scrolled_window); + scrollbar_spacing = _gtk_scrolled_window_get_scrollbar_spacing (scrolled_window); + widget->allocation = *allocation; if (scrolled_window->hscrollbar_policy == GTK_POLICY_ALWAYS) @@ -805,7 +1149,9 @@ gtk_scrolled_window_size_allocate (GtkWidget *widget, scrolled_window->window_placement == GTK_CORNER_TOP_RIGHT) child_allocation.y = (relative_allocation.y + relative_allocation.height + - SCROLLBAR_SPACING (scrolled_window)); + scrollbar_spacing + + (scrolled_window->shadow_type == GTK_SHADOW_NONE ? + 0 : widget->style->ythickness)); else child_allocation.y = GTK_CONTAINER (scrolled_window)->border_width; @@ -814,6 +1160,12 @@ gtk_scrolled_window_size_allocate (GtkWidget *widget, child_allocation.x += allocation->x; child_allocation.y += allocation->y; + if (scrolled_window->shadow_type != GTK_SHADOW_NONE) + { + child_allocation.x -= widget->style->xthickness; + child_allocation.width += 2 * widget->style->xthickness; + } + gtk_widget_size_allocate (scrolled_window->hscrollbar, &child_allocation); } else if (GTK_WIDGET_VISIBLE (scrolled_window->hscrollbar)) @@ -828,11 +1180,17 @@ gtk_scrolled_window_size_allocate (GtkWidget *widget, gtk_widget_get_child_requisition (scrolled_window->vscrollbar, &vscrollbar_requisition); - if (scrolled_window->window_placement == GTK_CORNER_TOP_LEFT || - scrolled_window->window_placement == GTK_CORNER_BOTTOM_LEFT) + if ((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL && + (scrolled_window->window_placement == GTK_CORNER_TOP_RIGHT || + scrolled_window->window_placement == GTK_CORNER_BOTTOM_RIGHT)) || + (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR && + (scrolled_window->window_placement == GTK_CORNER_TOP_LEFT || + scrolled_window->window_placement == GTK_CORNER_BOTTOM_LEFT))) child_allocation.x = (relative_allocation.x + relative_allocation.width + - SCROLLBAR_SPACING (scrolled_window)); + scrollbar_spacing + + (scrolled_window->shadow_type == GTK_SHADOW_NONE ? + 0 : widget->style->xthickness)); else child_allocation.x = GTK_CONTAINER (scrolled_window)->border_width; @@ -842,12 +1200,82 @@ gtk_scrolled_window_size_allocate (GtkWidget *widget, child_allocation.x += allocation->x; child_allocation.y += allocation->y; + if (scrolled_window->shadow_type != GTK_SHADOW_NONE) + { + child_allocation.y -= widget->style->ythickness; + child_allocation.height += 2 * widget->style->ythickness; + } + gtk_widget_size_allocate (scrolled_window->vscrollbar, &child_allocation); } else if (GTK_WIDGET_VISIBLE (scrolled_window->vscrollbar)) gtk_widget_hide (scrolled_window->vscrollbar); } +static gint +gtk_scrolled_window_scroll_event (GtkWidget *widget, + GdkEventScroll *event) +{ + GtkWidget *range; + + g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_DOWN) + range = GTK_SCROLLED_WINDOW (widget)->vscrollbar; + else + range = GTK_SCROLLED_WINDOW (widget)->hscrollbar; + + if (range && GTK_WIDGET_VISIBLE (range)) + { + GtkAdjustment *adj = GTK_RANGE (range)->adjustment; + gdouble delta, new_value; + + delta = _gtk_range_get_wheel_delta (GTK_RANGE (range), event->direction); + + new_value = CLAMP (adj->value + delta, adj->lower, adj->upper - adj->page_size); + + gtk_adjustment_set_value (adj, new_value); + + return TRUE; + } + + return FALSE; +} + +static gint +gtk_scrolled_window_focus (GtkWidget *widget, + GtkDirectionType direction) +{ + GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget); + gboolean had_focus_child = GTK_CONTAINER (widget)->focus_child != NULL; + + if (scrolled_window->focus_out) + { + scrolled_window->focus_out = FALSE; /* Clear this to catch the wrap-around case */ + return FALSE; + } + + if (gtk_widget_is_focus (widget)) + return FALSE; + + /* We only put the scrolled window itself in the focus chain if it + * isn't possible to focus any children. + */ + if (GTK_BIN (widget)->child) + { + if (gtk_widget_child_focus (GTK_BIN (widget)->child, direction)) + return TRUE; + } + + if (!had_focus_child) + { + gtk_widget_grab_focus (widget); + return TRUE; + } + else + return FALSE; +} static void gtk_scrolled_window_adjustment_changed (GtkAdjustment *adjustment, @@ -860,7 +1288,8 @@ gtk_scrolled_window_adjustment_changed (GtkAdjustment *adjustment, scrolled_win = GTK_SCROLLED_WINDOW (data); - if (adjustment == gtk_range_get_adjustment (GTK_RANGE (scrolled_win->hscrollbar))) + if (scrolled_win->hscrollbar && + adjustment == gtk_range_get_adjustment (GTK_RANGE (scrolled_win->hscrollbar))) { if (scrolled_win->hscrollbar_policy == GTK_POLICY_AUTOMATIC) { @@ -873,7 +1302,8 @@ gtk_scrolled_window_adjustment_changed (GtkAdjustment *adjustment, gtk_widget_queue_resize (GTK_WIDGET (scrolled_win)); } } - else if (adjustment == gtk_range_get_adjustment (GTK_RANGE (scrolled_win->vscrollbar))) + else if (scrolled_win->vscrollbar && + adjustment == gtk_range_get_adjustment (GTK_RANGE (scrolled_win->vscrollbar))) { if (scrolled_win->vscrollbar_policy == GTK_POLICY_AUTOMATIC) { @@ -909,24 +1339,12 @@ gtk_scrolled_window_add (GtkContainer *container, gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar)))) g_warning ("gtk_scrolled_window_add(): cannot add non scrollable widget " "use gtk_scrolled_window_add_with_viewport() instead"); - - if (GTK_WIDGET_REALIZED (child->parent)) - gtk_widget_realize (child); - - if (GTK_WIDGET_VISIBLE (child->parent) && GTK_WIDGET_VISIBLE (child)) - { - if (GTK_WIDGET_MAPPED (child->parent)) - gtk_widget_map (child); - - gtk_widget_queue_resize (child); - } } static void gtk_scrolled_window_remove (GtkContainer *container, GtkWidget *child) { - g_return_if_fail (container != NULL); g_return_if_fail (GTK_IS_SCROLLED_WINDOW (container)); g_return_if_fail (child != NULL); g_return_if_fail (GTK_BIN (container)->child == child); @@ -944,9 +1362,7 @@ gtk_scrolled_window_add_with_viewport (GtkScrolledWindow *scrolled_window, GtkBin *bin; GtkWidget *viewport; - g_return_if_fail (scrolled_window != NULL); g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window)); - g_return_if_fail (child != NULL); g_return_if_fail (GTK_IS_WIDGET (child)); g_return_if_fail (child->parent == NULL); @@ -970,3 +1386,38 @@ gtk_scrolled_window_add_with_viewport (GtkScrolledWindow *scrolled_window, gtk_widget_show (viewport); gtk_container_add (GTK_CONTAINER (viewport), child); } + +/** + * _gtk_scrolled_window_get_spacing: + * @scrolled_window: a scrolled window + * + * Gets the spacing between the scrolled window's scrollbars and + * the scrolled widget. Used by GtkCombo + * + * Return value: the spacing, in pixels. + **/ +gint +_gtk_scrolled_window_get_scrollbar_spacing (GtkScrolledWindow *scrolled_window) +{ + GtkScrolledWindowClass *class; + + g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window), 0); + + class = GTK_SCROLLED_WINDOW_GET_CLASS (scrolled_window); + + if (class->scrollbar_spacing >= 0) + return class->scrollbar_spacing; + else + { + gint scrollbar_spacing; + + gtk_widget_style_get (GTK_WIDGET (scrolled_window), + "scrollbar_spacing", &scrollbar_spacing, + NULL); + + return scrollbar_spacing; + } +} + +#define __GTK_SCROLLED_WINDOW_C__ +#include "gtkaliasdef.c" |