diff options
author | Matthias Clasen <mclasen@redhat.com> | 2006-03-20 19:17:59 +0000 |
---|---|---|
committer | Matthias Clasen <matthiasc@src.gnome.org> | 2006-03-20 19:17:59 +0000 |
commit | 5e66f6aa7545e4eb3e2a4f53b14ce329901427c1 (patch) | |
tree | 326f6ddb588dc60416ea56cf8062fd1663edf893 /gtk/gtkscrolledwindow.c | |
parent | 6aee75af24813b913a97f1abf4c9dae58eb477b0 (diff) | |
download | gtk+-5e66f6aa7545e4eb3e2a4f53b14ce329901427c1.tar.gz |
Add a window-placement-set property and a gtk-scrolled-window-placement
2006-03-20 Matthias Clasen <mclasen@redhat.com>
* gtk/gtk.symbols:
* gtk/gtkscrolledwindow.h:
* gtk/gtkscrolledwindow.c: Add a window-placement-set property
and a gtk-scrolled-window-placement setting. (#157025, Christian
Neumair)
Diffstat (limited to 'gtk/gtkscrolledwindow.c')
-rw-r--r-- | gtk/gtkscrolledwindow.c | 252 |
1 files changed, 230 insertions, 22 deletions
diff --git a/gtk/gtkscrolledwindow.c b/gtk/gtkscrolledwindow.c index 7eafb767a6..2baa45621e 100644 --- a/gtk/gtkscrolledwindow.c +++ b/gtk/gtkscrolledwindow.c @@ -30,6 +30,7 @@ #include "gtkbindings.h" #include "gtkmarshalers.h" #include "gtkscrolledwindow.h" +#include "gtkwindow.h" #include "gtkprivate.h" #include "gtkintl.h" #include "gtkalias.h" @@ -72,6 +73,13 @@ #define DEFAULT_SCROLLBAR_SPACING 3 +typedef struct { + gboolean window_placement_set; + GtkCornerType real_window_placement; +} GtkScrolledWindowPrivate; + +#define GTK_SCROLLED_WINDOW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_SCROLLED_WINDOW, GtkScrolledWindowPrivate)) + enum { PROP_0, PROP_HADJUSTMENT, @@ -79,6 +87,7 @@ enum { PROP_HSCROLLBAR_POLICY, PROP_VSCROLLBAR_POLICY, PROP_WINDOW_PLACEMENT, + PROP_WINDOW_PLACEMENT_SET, PROP_SHADOW_TYPE, PROP_LAST }; @@ -104,6 +113,8 @@ static void gtk_scrolled_window_get_property (GObject *obje GValue *value, GParamSpec *pspec); +static void gtk_scrolled_window_screen_changed (GtkWidget *widget, + GdkScreen *previous_screen); static gint gtk_scrolled_window_expose (GtkWidget *widget, GdkEventExpose *event); static void gtk_scrolled_window_size_request (GtkWidget *widget, @@ -133,6 +144,8 @@ static void gtk_scrolled_window_relative_allocation(GtkWidget *widg static void gtk_scrolled_window_adjustment_changed (GtkAdjustment *adjustment, gpointer data); +static void gtk_scrolled_window_update_real_placement (GtkScrolledWindow *scrolled_window); + static GtkContainerClass *parent_class = NULL; static guint signals[LAST_SIGNAL] = {0}; @@ -218,6 +231,7 @@ gtk_scrolled_window_class_init (GtkScrolledWindowClass *class) object_class->destroy = gtk_scrolled_window_destroy; + widget_class->screen_changed = gtk_scrolled_window_screen_changed; 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; @@ -268,10 +282,27 @@ gtk_scrolled_window_class_init (GtkScrolledWindowClass *class) PROP_WINDOW_PLACEMENT, g_param_spec_enum ("window-placement", P_("Window Placement"), - P_("Where the contents are located with respect to the scrollbars"), + P_("Where the contents are located with respect to the scrollbars. This property only takes effect if \"window-placement-set\" is TRUE."), GTK_TYPE_CORNER_TYPE, GTK_CORNER_TOP_LEFT, GTK_PARAM_READABLE | GTK_PARAM_WRITABLE)); + + /** + * GtkScrolledWindow::window-placement-set: + * + * Whether "window-placement" should be used to determine the location + * of the contents with respect to the scrollbars. Otherwise, the + * "gtk-scrolled-window-placement" setting is used. + * + * Since: 2.10 + */ + g_object_class_install_property (gobject_class, + PROP_WINDOW_PLACEMENT_SET, + g_param_spec_boolean ("window-placement-set", + P_("Window Placement Set"), + P_("Whether \"window-placement\" should be used to determine the location of the contents with respect to the scrollbars."), + FALSE, + GTK_PARAM_READABLE | GTK_PARAM_WRITABLE)); g_object_class_install_property (gobject_class, PROP_SHADOW_TYPE, g_param_spec_enum ("shadow-type", @@ -290,6 +321,22 @@ gtk_scrolled_window_class_init (GtkScrolledWindowClass *class) DEFAULT_SCROLLBAR_SPACING, GTK_PARAM_READABLE)); + /** + * GtkSettings::gtk-scrolled-window-placement: + * + * Where the contents of scrolled windows are located with respect to the + * scrollbars, if not overridden by the scrolled window's own placement. + * + * Since: 2.10 + */ + gtk_settings_install_property (g_param_spec_enum ("gtk-scrolled-window-placement", + P_("Scrolled Window Placement"), + P_("Where the contents of scrolled windows are located with respect to the scrollbars, if not overridden by the scrolled window's own placement."), + GTK_TYPE_CORNER_TYPE, + GTK_CORNER_TOP_LEFT, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + + signals[SCROLL_CHILD] = g_signal_new (I_("scroll_child"), G_TYPE_FROM_CLASS (object_class), @@ -329,6 +376,8 @@ gtk_scrolled_window_class_init (GtkScrolledWindowClass *class) 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); + + g_type_class_add_private (class, sizeof (GtkScrolledWindowPrivate)); } static void @@ -344,7 +393,7 @@ gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window) scrolled_window->vscrollbar_visible = FALSE; scrolled_window->focus_out = FALSE; scrolled_window->window_placement = GTK_CORNER_TOP_LEFT; - + gtk_scrolled_window_update_real_placement (scrolled_window); } GtkWidget* @@ -579,30 +628,88 @@ gtk_scrolled_window_get_policy (GtkScrolledWindow *scrolled_window, *vscrollbar_policy = scrolled_window->vscrollbar_policy; } -void -gtk_scrolled_window_set_placement (GtkScrolledWindow *scrolled_window, - GtkCornerType window_placement) +static void +gtk_scrolled_window_update_real_placement (GtkScrolledWindow *scrolled_window) { - g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window)); + GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window); + GtkSettings *settings; + + settings = gtk_widget_get_settings (GTK_WIDGET (scrolled_window)); + if (priv->window_placement_set || settings == NULL) + priv->real_window_placement = scrolled_window->window_placement; + else + g_object_get (settings, + "gtk-scrolled-window-placement", + &priv->real_window_placement, + NULL); +} + +static void +gtk_scrolled_window_set_placement_internal (GtkScrolledWindow *scrolled_window, + GtkCornerType window_placement) +{ if (scrolled_window->window_placement != window_placement) { scrolled_window->window_placement = window_placement; + gtk_scrolled_window_update_real_placement (scrolled_window); gtk_widget_queue_resize (GTK_WIDGET (scrolled_window)); g_object_notify (G_OBJECT (scrolled_window), "window-placement"); } } +static void +gtk_scrolled_window_set_placement_set (GtkScrolledWindow *scrolled_window, + gboolean placement_set, + gboolean emit_resize) +{ + GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window); + + if (priv->window_placement_set != placement_set) + { + priv->window_placement_set = placement_set; + + gtk_scrolled_window_update_real_placement (scrolled_window); + if (emit_resize) + gtk_widget_queue_resize (GTK_WIDGET (scrolled_window)); + + g_object_notify (G_OBJECT (scrolled_window), "window-placement-set"); + } +} + +/** + * gtk_scrolled_window_set_placement: + * @scrolled_window: a #GtkScrolledWindow + * + * Sets the placement of the contents with respect to the scrollbars + * for the scrolled window. + * + * See also gtk_scrolled_window_get_placement() and + * gtk_scrolled_window_unset_placement(). + **/ +void +gtk_scrolled_window_set_placement (GtkScrolledWindow *scrolled_window, + GtkCornerType window_placement) +{ + g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window)); + + gtk_scrolled_window_set_placement_set (scrolled_window, TRUE, FALSE); + gtk_scrolled_window_set_placement_internal (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(). + * Gets the placement of the contents with respect to the scrollbars + * for the scrolled window. See gtk_scrolled_window_set_placement(). * * Return value: the current placement value. + * + * See also gtk_scrolled_window_set_placement() and + * gtk_scrolled_window_unset_placement(). **/ GtkCornerType gtk_scrolled_window_get_placement (GtkScrolledWindow *scrolled_window) @@ -613,6 +720,36 @@ gtk_scrolled_window_get_placement (GtkScrolledWindow *scrolled_window) } /** + * gtk_scrolled_window_unset_placement: + * @scrolled_window: a #GtkScrolledWindow + * + * Unsets the placement of the contents with respect to the scrollbars + * for the scrolled window. If no window placement is set for a scrolled + * window, it obeys the "gtk-scrolled-window-placement" XSETTING. + * + * See also gtk_scrolled_window_set_placement() and + * gtk_scrolled_window_get_placement(). + * + * Since: 2.10 + **/ +void +gtk_scrolled_window_unset_placement (GtkScrolledWindow *scrolled_window) +{ + GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window); + + g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window)); + + if (priv->window_placement_set) + { + priv->window_placement_set = FALSE; + + gtk_widget_queue_resize (GTK_WIDGET (scrolled_window)); + + g_object_notify (G_OBJECT (scrolled_window), "window-placement-set"); + } +} + +/** * gtk_scrolled_window_set_shadow_type: * @scrolled_window: a #GtkScrolledWindow * @type: kind of shadow to draw around scrolled window contents @@ -715,8 +852,13 @@ gtk_scrolled_window_set_property (GObject *object, g_value_get_enum (value)); break; case PROP_WINDOW_PLACEMENT: - gtk_scrolled_window_set_placement (scrolled_window, - g_value_get_enum (value)); + gtk_scrolled_window_set_placement_internal (scrolled_window, + g_value_get_enum (value)); + break; + case PROP_WINDOW_PLACEMENT_SET: + gtk_scrolled_window_set_placement_set (scrolled_window, + g_value_get_enum (value), + TRUE); break; case PROP_SHADOW_TYPE: gtk_scrolled_window_set_shadow_type (scrolled_window, @@ -735,6 +877,7 @@ gtk_scrolled_window_get_property (GObject *object, GParamSpec *pspec) { GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (object); + GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window); switch (prop_id) { @@ -755,6 +898,9 @@ gtk_scrolled_window_get_property (GObject *object, case PROP_WINDOW_PLACEMENT: g_value_set_enum (value, scrolled_window->window_placement); break; + case PROP_WINDOW_PLACEMENT_SET: + g_value_set_boolean (value, priv->window_placement_set); + break; case PROP_SHADOW_TYPE: g_value_set_enum (value, scrolled_window->shadow_type); break; @@ -765,6 +911,62 @@ gtk_scrolled_window_get_property (GObject *object, } static void +traverse_container (GtkWidget *widget, + gpointer data) +{ + if (GTK_IS_SCROLLED_WINDOW (widget)) + { + gtk_scrolled_window_update_real_placement (GTK_SCROLLED_WINDOW (widget)); + gtk_widget_queue_draw (widget); + } + else if (GTK_IS_CONTAINER (widget)) + gtk_container_forall (GTK_CONTAINER (widget), traverse_container, NULL); +} + +static void +gtk_scrolled_window_settings_changed (GtkSettings *settings) +{ + GList *list, *l; + + list = gtk_window_list_toplevels (); + + for (l = list; l; l = l->next) + gtk_container_forall (GTK_CONTAINER (l->data), + traverse_container, NULL); + + g_list_free (list); +} + +static void +gtk_scrolled_window_screen_changed (GtkWidget *widget, + GdkScreen *previous_screen) +{ + GtkSettings *settings; + guint window_placement_connection; + + gtk_scrolled_window_update_real_placement (GTK_SCROLLED_WINDOW (widget)); + + if (!gtk_widget_has_screen (widget)) + return; + + settings = gtk_widget_get_settings (widget); + + window_placement_connection = + GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (settings), + "gtk-scrolled-window-connection")); + + if (window_placement_connection) + return; + + window_placement_connection = + g_signal_connect (settings, "notify::gtk-scrolled-window-placement", + G_CALLBACK (gtk_scrolled_window_settings_changed), 0); + g_object_set_data (G_OBJECT (settings), + I_("gtk-scrolled-window-connection"), + GUINT_TO_POINTER (window_placement_connection)); +} + +static void gtk_scrolled_window_paint (GtkWidget *widget, GdkRectangle *area) { @@ -1048,6 +1250,7 @@ gtk_scrolled_window_relative_allocation (GtkWidget *widget, GtkAllocation *allocation) { GtkScrolledWindow *scrolled_window; + GtkScrolledWindowPrivate *priv; gint scrollbar_spacing; g_return_if_fail (widget != NULL); @@ -1056,6 +1259,8 @@ gtk_scrolled_window_relative_allocation (GtkWidget *widget, scrolled_window = GTK_SCROLLED_WINDOW (widget); scrollbar_spacing = _gtk_scrolled_window_get_scrollbar_spacing (scrolled_window); + priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window); + allocation->x = GTK_CONTAINER (widget)->border_width; allocation->y = GTK_CONTAINER (widget)->border_width; @@ -1078,11 +1283,11 @@ gtk_scrolled_window_relative_allocation (GtkWidget *widget, is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL; if ((!is_rtl && - (scrolled_window->window_placement == GTK_CORNER_TOP_RIGHT || - scrolled_window->window_placement == GTK_CORNER_BOTTOM_RIGHT)) || + (priv->real_window_placement == GTK_CORNER_TOP_RIGHT || + priv->real_window_placement == GTK_CORNER_BOTTOM_RIGHT)) || (is_rtl && - (scrolled_window->window_placement == GTK_CORNER_TOP_LEFT || - scrolled_window->window_placement == GTK_CORNER_BOTTOM_LEFT))) + (priv->real_window_placement == GTK_CORNER_TOP_LEFT || + priv->real_window_placement == GTK_CORNER_BOTTOM_LEFT))) allocation->x += (vscrollbar_requisition.width + scrollbar_spacing); allocation->width = MAX (1, allocation->width - (vscrollbar_requisition.width + scrollbar_spacing)); @@ -1093,8 +1298,8 @@ gtk_scrolled_window_relative_allocation (GtkWidget *widget, gtk_widget_get_child_requisition (scrolled_window->hscrollbar, &hscrollbar_requisition); - if (scrolled_window->window_placement == GTK_CORNER_BOTTOM_LEFT || - scrolled_window->window_placement == GTK_CORNER_BOTTOM_RIGHT) + if (priv->real_window_placement == GTK_CORNER_BOTTOM_LEFT || + priv->real_window_placement == GTK_CORNER_BOTTOM_RIGHT) allocation->y += (hscrollbar_requisition.height + scrollbar_spacing); allocation->height = MAX (1, allocation->height - (hscrollbar_requisition.height + scrollbar_spacing)); @@ -1106,6 +1311,7 @@ gtk_scrolled_window_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { GtkScrolledWindow *scrolled_window; + GtkScrolledWindowPrivate *priv; GtkBin *bin; GtkAllocation relative_allocation; GtkAllocation child_allocation; @@ -1119,6 +1325,8 @@ gtk_scrolled_window_size_allocate (GtkWidget *widget, scrollbar_spacing = _gtk_scrolled_window_get_scrollbar_spacing (scrolled_window); + priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window); + widget->allocation = *allocation; if (scrolled_window->hscrollbar_policy == GTK_POLICY_ALWAYS) @@ -1184,8 +1392,8 @@ gtk_scrolled_window_size_allocate (GtkWidget *widget, gtk_widget_show (scrolled_window->hscrollbar); child_allocation.x = relative_allocation.x; - if (scrolled_window->window_placement == GTK_CORNER_TOP_LEFT || - scrolled_window->window_placement == GTK_CORNER_TOP_RIGHT) + if (priv->real_window_placement == GTK_CORNER_TOP_LEFT || + priv->real_window_placement == GTK_CORNER_TOP_RIGHT) child_allocation.y = (relative_allocation.y + relative_allocation.height + scrollbar_spacing + @@ -1220,11 +1428,11 @@ gtk_scrolled_window_size_allocate (GtkWidget *widget, &vscrollbar_requisition); 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)) || + (priv->real_window_placement == GTK_CORNER_TOP_RIGHT || + priv->real_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))) + (priv->real_window_placement == GTK_CORNER_TOP_LEFT || + priv->real_window_placement == GTK_CORNER_BOTTOM_LEFT))) child_allocation.x = (relative_allocation.x + relative_allocation.width + scrollbar_spacing + |