Re: locating a widget in a scrolled window
Hi Irtza, On Sun, Apr 10, 2005 at 09:48:24PM -0400, Irtza Sharif wrote: Thank you for your response. Let me clarify my situation. I have a Scrolled Window within which I add a vbox The widgets inside the vbox are held in a linked list that I have setup. New widgets can be created and added to this vbox within the scrolled window while the program is running. When these new widgets are created and added, I would like to shift the scrolled window to show this widget. If the new widgets are direct children of the vbox (which is a direct child of the scrolled window's viewport), you should be able to do something like this: void scroll_to(GtkWidget* scrolled_window, GtkWidget* widget) { gdouble page_inc, step_inc, upper, lower, pos; GtkAdjustment* vadj = gtk_scrolled_window_get_vadjustment( GTK_SCROLLED_WINDOW(scrolled_window)); page_inc = vadj-page_increment; step_inc = vadj-step_increment; lower = vadj-lower; /* Otherwise we sometimes scroll down into a page of black. */ upper = vadj-upper - page_inc - step_inc; /* Center on the widget. */ pos = (gdouble)widget-allocation.y - page_inc/2; gtk_adjustment_set_value(vadj, CLAMP(pos, lower, upper)); } This only takes into account the vertical, but I think the horizontal could be done similarly. If the new widgets aren't direct children of the vbox, you could still probably do this by recursing up through widget-parent until you get to the vbox, remapping the coordinates along the way. Hope this helps, Stephen ___ gtk-list mailing list gtk-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-list
GtkAdjustment smooth scrolling
Hello, I use a scrolled window in a program of mine, and I've noticed that if I set the value of its adjustment manually, the window is immediately scrolled to the given position. For example, with something like the following code (where vadj is the vertical adjustment of the window): gdouble current = gtk_adjustment_get_value(vadj); gtk_adjustment_set_value(vadj, CLAMP(current + vadj-page_increment, vadj-lower, vadj-upper)); The scrolled window appears at the given area instantly. If I just use the Page Down key, however, the scrolling is smooth, gradual. I have no real preference to either behaviour -- what I don't like is the inconsistency. I glanced through the source for GtkAdjustment and GtkScrolledWindow, but nothing jumped out at me as being the implementation of the smooth scrolling. Could someone here help me out or point me in the right direction? Thanks, Stephen ___ gtk-list mailing list gtk-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-list
Re: gtk_widget_queue_resize() forgetting allocation
On Mon, Sep 27, 2004 at 12:35:54PM -0400, Owen Taylor wrote: So, I'd actually appreciate it if you could file a bug in bugzilla with your test case as an attachment and a link to this analysis in the mail.gnome.org archives. Done. Two easy workarounds for your problem you might want to try: - Change the resize mode on the Viewport to PARENT after creating it. - Do your label_resize in a handler for 'size-allocate' on the toplevel rather than '::configure-event'. I went with a modified version of the second one, and all is well. Thanks -- your input was invaluable. Stephen ___ gtk-list mailing list [EMAIL PROTECTED] http://mail.gnome.org/mailman/listinfo/gtk-list
Re: gtk_widget_queue_resize() forgetting allocation
For posterity: I isolated the issue to the GtkViewport widget. I found that if I packed the label/vbox into a GtkLayout and packed that into the GtkScrolledWindow, the size negotiations worked the way they should. I don't know if the problem is caused by some function of the viewport that I don't understand, but I'm not going to spend any more time on it. Using a layout works, though it requires a little more massaging. The only problem I have now is that the step_increment field of the vertical GtkAdjustment in the scrolled window doesn't update itself upon resize, and indeed sits at zero. But I can deal with that. On Sun, Sep 19, 2004 at 12:02:48PM -0400, Stephen Bach wrote: stuff ___ gtk-list mailing list [EMAIL PROTECTED] http://mail.gnome.org/mailman/listinfo/gtk-list
GtkLayout and {h,v}adjustment-step_increment
Just a quick question. The gtk_layout_size_allocate() function seems to set the page_increment fields of its layout's GtkAdjustments, but not the step_increment fields. So in, say, gtk_set_hadjustment_values() and gtk_set_vadjustment_values() (called in gtk_viewport_size_allocate()) of gtkviewport.c: ... hadjustment-page_size = view_allocation.width; hadjustment-step_increment = view_allocation.width * 0.1; hadjustment-page_increment = view_allocation.width * 0.9; hadjustment-lower = 0; ... vadjustment-page_size = view_allocation.height; vadjustment-step_increment = view_allocation.height * 0.1; vadjustment-page_increment = view_allocation.height * 0.9; vadjustment-lower = 0; ... But in gtk_layout_size_allocate() of gtklayout.c: ... layout-hadjustment-page_size = allocation-width; layout-hadjustment-page_increment = allocation-width * 0.9; layout-hadjustment-lower = 0; ... layout-vadjustment-page_size = allocation-height; layout-vadjustment-page_increment = allocation-height * 0.9; layout-vadjustment-lower = 0; ... This means that clicking the steppers in the scrollbars for the layout do nothing. In my program I've set step_increment manually by connecting to the allocate signal of the layout, but I'm wondering what the reason is for the missing functionality. Thanks, Stephen ___ gtk-list mailing list [EMAIL PROTECTED] http://mail.gnome.org/mailman/listinfo/gtk-list
Re: gtk_widget_queue_resize() forgetting allocation
No one has any insight here? It seems to me that a call to gtk_widget_size_request() should be followed by a gtk_widget_size_allocate() when generated by a gtk_widget_queue_resize(), especially if the program goes idle. Is there something about the size negotiation process that I'm misunderstanding? Thanks On Sun, Sep 19, 2004 at 12:02:48PM -0400, Stephen Bach wrote: Hello, I've run into an issue in a program I'm writing where sometimes a call to gtk_widget_queue_resize() ends in a request rather than an allocate. I've put together a short test case (tested in GTK+ 2.4.4) which keeps the spirit of the program intact (see below). First, a little context -- connecting to the toplevel window's configure-event to queue a resize on one of its grandchildren probably seems unconventional and even redundant, but it's a requirement of my program (not this test case) because the request function of that grandchild optimizes itself to the window's width (i.e. the grandchild needs more information than just the size requests of its children). In the real program the change in the window's width is passed on and then the queue_resize is made. All of that is beside the point. Here is the problem: _sometimes_ when the window is resized, there is no allocation of the grandchild label after a request. If the window is resized again, _then_ the allocation happens (usually followed by another unfulfilled size request). One thing that's kind-of strange is that if the label is added directly to the scrolledwindow (without being added to the vbox, which then gets put into the scrolledwindow), everything works as it should -- every size request is followed by a size allocate. I also tried using a table instead of a vbox, but the result is the same. Insight welcome. Thanks, Stephen = #include gtk/gtk.h static void allocate_callback(GtkWidget *label, GtkAllocation *allocation, gpointer data) { g_print((allocate)); } static void request_callback(GtkWidget *label, GtkRequisition *requisition, gpointer data) { g_print((request)); } static gboolean configure_callback(GtkWidget* window, GdkEventConfigure* event, gpointer data) { GtkWidget* label = data; /* Only queue resize if the width is changed */ if (event-width != window-allocation.width) gtk_widget_queue_resize(label); return FALSE; } int main(int argc, char* argv[]) { GtkWidget* window; GtkWidget* scrolled_window; GtkWidget* vbox; GtkWidget* label; gtk_init (argc, argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); scrolled_window = gtk_scrolled_window_new(NULL, NULL); vbox = gtk_vbox_new(FALSE, 0); label = gtk_label_new(Testing); g_signal_connect(G_OBJECT(label), size-allocate, G_CALLBACK(allocate_callback), NULL); g_signal_connect(G_OBJECT(label), size-request, G_CALLBACK(request_callback), NULL); g_signal_connect(G_OBJECT(window), configure-event, G_CALLBACK(configure_callback), label); gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(scrolled_window), vbox); gtk_container_add(GTK_CONTAINER(window), scrolled_window); gtk_widget_show(label); gtk_widget_show(vbox); gtk_widget_show(scrolled_window); gtk_widget_show(window); gtk_main(); return 0; } ___ gtk-list mailing list [EMAIL PROTECTED] http://mail.gnome.org/mailman/listinfo/gtk-list ___ gtk-list mailing list [EMAIL PROTECTED] http://mail.gnome.org/mailman/listinfo/gtk-list
gtk_widget_queue_resize() forgetting allocation
Hello, I've run into an issue in a program I'm writing where sometimes a call to gtk_widget_queue_resize() ends in a request rather than an allocate. I've put together a short test case (tested in GTK+ 2.4.4) which keeps the spirit of the program intact (see below). First, a little context -- connecting to the toplevel window's configure-event to queue a resize on one of its grandchildren probably seems unconventional and even redundant, but it's a requirement of my program (not this test case) because the request function of that grandchild optimizes itself to the window's width (i.e. the grandchild needs more information than just the size requests of its children). In the real program the change in the window's width is passed on and then the queue_resize is made. All of that is beside the point. Here is the problem: _sometimes_ when the window is resized, there is no allocation of the grandchild label after a request. If the window is resized again, _then_ the allocation happens (usually followed by another unfulfilled size request). One thing that's kind-of strange is that if the label is added directly to the scrolledwindow (without being added to the vbox, which then gets put into the scrolledwindow), everything works as it should -- every size request is followed by a size allocate. I also tried using a table instead of a vbox, but the result is the same. Insight welcome. Thanks, Stephen = #include gtk/gtk.h static void allocate_callback(GtkWidget *label, GtkAllocation *allocation, gpointer data) { g_print((allocate)); } static void request_callback(GtkWidget *label, GtkRequisition *requisition, gpointer data) { g_print((request)); } static gboolean configure_callback(GtkWidget* window, GdkEventConfigure* event, gpointer data) { GtkWidget* label = data; /* Only queue resize if the width is changed */ if (event-width != window-allocation.width) gtk_widget_queue_resize(label); return FALSE; } int main(int argc, char* argv[]) { GtkWidget* window; GtkWidget* scrolled_window; GtkWidget* vbox; GtkWidget* label; gtk_init (argc, argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); scrolled_window = gtk_scrolled_window_new(NULL, NULL); vbox = gtk_vbox_new(FALSE, 0); label = gtk_label_new(Testing); g_signal_connect(G_OBJECT(label), size-allocate, G_CALLBACK(allocate_callback), NULL); g_signal_connect(G_OBJECT(label), size-request, G_CALLBACK(request_callback), NULL); g_signal_connect(G_OBJECT(window), configure-event, G_CALLBACK(configure_callback), label); gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(scrolled_window), vbox); gtk_container_add(GTK_CONTAINER(window), scrolled_window); gtk_widget_show(label); gtk_widget_show(vbox); gtk_widget_show(scrolled_window); gtk_widget_show(window); gtk_main(); return 0; } ___ gtk-list mailing list [EMAIL PROTECTED] http://mail.gnome.org/mailman/listinfo/gtk-list
Re: GtkTreeView with multicolumn mode
I don't know if there's a tree view for this (I don't think so), but there are a pair of widgets called GtkHWrapBox and GtkVWrapBox that may do what you want. They work on an arbitrary group of widgets, but in a project I'm working on I'm sort-of using them with labels to emulate a wrapping list. For some reason they're not in the official GTK+ package, but you can get them from the Gimp 2.0 sources (gimp-2.0.0/app/widgets/). I seem to remember that in order for them to work well you need to specify an aspect-ratio, which may or may not be an issue for you (if you decide they're useful). On Wed, Aug 25, 2004 at 04:45:47PM +0200, [EMAIL PROTECTED] wrote: Hi, can someone give me a hint if a GtkTreeView already exists where the list is shown in multicolumns. That means, if you have a list 1 bla 2 blu 3 foo 4 hey depending on the size or some parameter it is rendered like 1 bla 3 foo 2 blu 4 hey or 1 bla 2 blu 3 foo 4 hey or as original shown. Thanks for any help! Sebastian ___ gtk-list mailing list [EMAIL PROTECTED] http://mail.gnome.org/mailman/listinfo/gtk-list
Re: Muffling widget repaints
I've come up with an acceptable solution to my problem, which I'll post here for posterity. First my observations: - The expose signal for the container was emitted only once, and after all the widgets had been added/removed. This is good and means GTK is being smart, and that gdk_window_freeze_updates() wouldn't help me. - If I left the container showing, a changeover involving 2000 widgets took about 30 seconds, with X cpu usage hovering at about 85% and the program's cpu usage at about 15% (i.e. all of it). During the switchover, I could see widgets in the container shifting periodically, but the container never fully redrew itself during the switchover (and expose-event was not emitted). - If I hid the container immediately before the changeover and showed it directly afterwards, the changeover took only about 3 seconds, and X cpu usage only seemed to reach about 40% and the program's about the same. Eventually I found that most of the processing was because of (or related to) size negotiations. The container received size-request and size-allocate signals for each widget added/removed. Since only the final size-request/size-allocate pair was relevant, I took out the gtk_widget_queue_resize() calls from the pack and remove functions of the container. This worked great for the removal, but for the packing I'd still get the size negotiation thrashing as soon as I gtk_widget_show'd the new children (whether I did so before adding them or after they were all added). So I connected to the size-request signal of the container and added a condition to prevent signal propagation if it was during a switchover. This works okay -- it takes about 8 seconds for a changeover. Certainly there's a more complete solution, and hopefully something a little more elegant (insight welcome), but it'll do for now. ___ gtk-list mailing list [EMAIL PROTECTED] http://mail.gnome.org/mailman/listinfo/gtk-list
Re: Muffling widget repaints
Hi Todd, This sounds like a very similar problem I'm having. I'm curious if you have some test case code that you could post? My testing was all done within the context of my program, but I can try. The containers in question are WrapBox, which I've based on the GtkWrapBox class from Gimp 2.0, and its subclass FileBox. Here's most of the packing function, with the relevant changes commented. Both this and the removal function are called with do_resize == FALSE during the changeover. void wrap_box_pack_pos(WrapBox* wbox, GtkWidget* child, guint pos, gboolean do_resize) { /* This variable added. */ WrapBoxChild* child_info; g_return_if_fail(IS_WRAP_BOX (wbox)); g_return_if_fail(GTK_IS_WIDGET (child)); g_return_if_fail(child-parent == NULL); child_info = g_new(WrapBoxChild, 1); child_info-widget = child; /* snipping out irrelevant child insertion code */ gtk_widget_set_parent(child, GTK_WIDGET(wbox)); if (GTK_WIDGET_REALIZED(wbox)) gtk_widget_realize(child); if (GTK_WIDGET_VISIBLE(wbox) GTK_WIDGET_VISIBLE(child)) { if (GTK_WIDGET_MAPPED(wbox)) gtk_widget_map(child); if (do_resize) /* This conditional added. */ gtk_widget_queue_resize (child); } } And the removal function with a similar change: void wrap_box_remove(GtkContainer* container, GtkWidget* widget, gboolean do_resize) { /* This variable added. */ WrapBox* wbox = WRAP_BOX(container); WrapBoxChild *child, *last = NULL; child = wbox-children; while (child) { if (child-widget == widget) { gboolean was_visible; was_visible = GTK_WIDGET_VISIBLE(widget); gtk_widget_unparent(widget); if (last) last-next = child-next; else wbox-children = child-next; g_free(child); wbox-n_children--; if (was_visible do_resize) /* do_resize added here */ gtk_widget_queue_resize(GTK_WIDGET (container)); break; } last = child; child = last-next; } } In the initialization of the subclass object: static void file_box_init(FileBox *fbox) { GTK_WIDGET_SET_FLAGS (fbox, GTK_NO_WINDOW); fbox-optimal_width = 0; fbox-show_hidden_files = FALSE; fbox-n_files = 0; fbox-file_max = 32767; fbox-file_display_limit = DEFAULT_FILE_DISPLAY_LIMIT; fbox-fi_slist = NULL; /* This class variable and the next line added. */ fbox-eat_size_requests = FALSE; g_signal_connect(fbox, size-request, G_CALLBACK(size_request_kludge), NULL); } And the callback function: static gboolean size_request_kludge(GtkWidget* widget, GtkRequisition* requisition, gpointer data) { FileBox* fbox = FILE_BOX(widget); return fbox-eat_size_requests; } Then before entering the add/remove loop, this function is called with FALSE, and then with TRUE afterward: static void file_box_allow_size_requests(FileBox* fbox, gboolean allow) { if (fbox-eat_size_requests != allow) return; if (allow) { fbox-eat_size_requests = FALSE; gtk_widget_queue_resize(GTK_WIDGET(fbox)); /* ^^^ This is the final size request, and the only one to go through. */ } else fbox-eat_size_requests = TRUE; } Hopefully that's clear and of some use. ___ gtk-list mailing list [EMAIL PROTECTED] http://mail.gnome.org/mailman/listinfo/gtk-list
Muffling widget repaints
Hello, I have a container which periodically loses some of its widgets and gains others, sometimes on the order of hundreds. The changeover happens all at once (i.e. there's a big loop which does all the adding and destroying), but it's still pretty ugly and slow because sometimes many repaints are done. I only care about the final repaint. Is there some way that I can prevent the intervening repaints from happening? I've tested hiding and reshowing the container, and it is indeed much faster, but of course I don't want the user to see the container disappear. Ideally I'd have the before painting sit until the widget switch-over is done, and then display the after painting. I was hoping gdk_window_freeze_updates() and gdk_window_thaw_updates() would help, but they don't seem to do anything. As a test I even tried freezing the root gdk window right before calling gtk_main() (and after showing its widget), but the program proceeded normally. Maybe I'm not understanding what these functions are for. Any insight would be very welcome. Thanks ___ gtk-list mailing list [EMAIL PROTECTED] http://mail.gnome.org/mailman/listinfo/gtk-list
Re: Muffling widget repaints
BTW, I'm writing towards GTK+ 2.4. On Sat, Aug 21, 2004 at 02:16:52PM -0400, Stephen Bach wrote: Hello, I have a container which periodically loses some of its widgets and gains others, sometimes on the order of hundreds. The changeover happens all at once (i.e. there's a big loop which does all the adding and destroying), but it's still pretty ugly and slow because sometimes many repaints are done. I only care about the final repaint. Is there some way that I can prevent the intervening repaints from happening? I've tested hiding and reshowing the container, and it is indeed much faster, but of course I don't want the user to see the container disappear. Ideally I'd have the before painting sit until the widget switch-over is done, and then display the after painting. I was hoping gdk_window_freeze_updates() and gdk_window_thaw_updates() would help, but they don't seem to do anything. As a test I even tried freezing the root gdk window right before calling gtk_main() (and after showing its widget), but the program proceeded normally. Maybe I'm not understanding what these functions are for. Any insight would be very welcome. Thanks ___ gtk-list mailing list [EMAIL PROTECTED] http://mail.gnome.org/mailman/listinfo/gtk-list ___ gtk-list mailing list [EMAIL PROTECTED] http://mail.gnome.org/mailman/listinfo/gtk-list
Re: Muffling widget repaints
When I say repaint I just mean that the there is a visible change in the widget. I guess I'm not using the word in its conventional GTK sense. FWIW, I did connect to the expose signal of the container and found that it's only called once, after the widget switchover is finished. Which I guess is ideal. But the container still appears to be being updated (repainted in my incorrect terminology) many times during the switchover. For example, I can sometimes see the the container's children repositioning themselves. On Sat, Aug 21, 2004 at 02:22:56PM -0400, Paul Davis wrote: I have a container which periodically loses some of its widgets and gains others, sometimes on the order of hundreds. The changeover happens all at once (i.e. there's a big loop which does all the adding and destroying), but it's still pretty ugly and slow because sometimes many repaints are done. I only care about the final repaint. by repaint do you mean an expose signal? you should only be drawing within an expose handler (there is one exception: drawing into an off-screen drawable, typically a pixmap). drawing at any other time is just not the correct model. --p ___ gtk-list mailing list [EMAIL PROTECTED] http://mail.gnome.org/mailman/listinfo/gtk-list