I hope you don't mind I am using GTK+ C API in the description, the sollution could be converted to the PyGTK easily and the principles remains the same.
Starting with the second question - if you know which widget to test, you can detect its visibility by calling gtk_widget_translate_coordinates(child, parent, 0, 0, &x, &y)
to get the position of the child relative to the parent. By gtk_widget_get_allocation()
you get the size of parent and child and you simply test if whole child rectangle is in the scrolled window.
gboolean is_visible_in (GtkWidget *child, GtkWidget *scrolled)
{
gint x, y;
GtkAllocation child_alloc, scroll_alloc;
gtk_widget_translate_coordinates (child, scrolled, 0, 0, &x, &y);
gtk_widget_get_allocation(child, &child_alloc);
gtk_widget_get_allocation(scrolled, &scroll_alloc);
return (x >= 0 && y >= 0)
&& x + child_alloc.width <= scroll_alloc.width
&& y + child_alloc.height <= scroll_alloc.height;
}
You can obtain the curently focused widget in window by gtk_window_get_focus ()
or you can detect it when focus is changed.
In the autoscroll problem you can handle "focus"
signal connected to the widget which can be focussed or the "set-focus-child"
event connected to the container containing the widgets. In the signal handler you should check, if the focused widget is visible. If not, determinate its position and scroll properly.
To do so you have to detect the position of the widget inside the whole scrolled area. If you are using some container which does not support scrolling (such GtkHBox
) iside GtkScrolledWindow
(adapted by viewport), you can get the coordinates of the focused widget relative to the container by gtk_widget_translate_coordinates()
again - now using the container instead of scrolled window. The value of the adjustment, if using GtkViewport
, the adjustment value correspond to the position in pixels in the scrolled area, so setting adjustment value to x relative coordinate will do scrolling. So the important part of the handler could be
GtkWidget *scrolled = /* The scrolled window */
GtkWidget *container = /* The container in the scrolled window */
GtkWidget *focused = /* The focused widget */
GtkAdjustment *hadj = gtk_scrolled_window_get_hadjustment(
GTK_SCROLLED_WINDOW(scrolled));
gint x, y;
gtk_widget_translate_coordinates (focused, container, 0, 0, &x, &y);
gtk_adjustment_set_value(hadj, min(x, maximal adjustment value allowed);
The maximal adjustment value allowed is adjustment.upper - adjustment.page_size. The focused widget is passed as signal handler argument for both signals, in the case of "set-focus-child"
signal you get also the container as argument.