Reputation: 1048
I'm trying to implement an image viewer using GTK+3, and it's supposed to have two modes:
Now, in both modes, I need the image are to be scrollable, and in fit-to-X, I need to know the actual size of the "displayed image area" which is actually the directly visible window region. Also, since the window could be resized, I need to scale the image dynamically.
In Qt, it is just a breeze. No 3rd party libraries (gdkpixbuf), no need to create a custom widget, no worries.
I can set the image for a QLabel, and on resize, I can smoothly scale the image (without relying on any 3rd party libraries such as gdkpixbuf) to the new size (it seems it's not possible to get the current size with GTK+ due to some convoluted reasons which clearly don't apply to Qt; in order to get the size of the "image arena", Comix gets the total window dimensions, subtracts dimensions of menubar, scrollbar, toolbar and scrollbars in get_visible_area_size if they are visible!) . With correct parameters, this plays well both with expanding and shrinking, and the parent scroll area can do the scrolling depending on the size of QLabel.
But to my surprise, such an elementary thing, if I'm not missing something, is not possible using out-of-the box widgets with GTK+.
Here's what I have tried so far:
Using a Layout directly, moving Image object around manually, and adding & handling horizontal and vertical scrollbars manually (and of course, handle signals and move()ing of the image inside Layout manually). This is what Comix does! This is terrible, so I stopped doing this in the mid-way.
Placed an image object inside ScrolledWindow + Viewport: scrolls nice and neat, but the problem is, I don't know the visible size of the "directly visible" part of the ScrolledWindow (nor the encapsulating window or Viewport); get_allocation returns the size of the total image area, that is, the visible part plus the non-visible part (that user can see by scrolling). The allocation for Viewport reports the correct size after "ordinary" resize events, but it reports the previous size after maximize/minimize (I'm listening at both window-state-event and configure-event). A behavior which I think is a long standing GTK+ bug.
Other things I have exhausted:
The problem would be basically solved if GTK+ provided:
My question is, am I missing something obvious here? It's hard to believe such an elementary thing cannot be done directly using out-of-the-box widgets with such an established library. What is the most straightforward way of implementing an image viewer that can do scrolling as well as responsive scaling of the image?
Upvotes: 4
Views: 2459
Reputation: 1048
I found that I'm listening for the wrong event: I've listening to "configure-event" of the window which doesn't fire during minimize/maximize. Listening to "size-allocate" solved the problem.
Thanks everyone for their answers!
Upvotes: 2
Reputation: 3134
I'm creating an image viewer too! And I can tell you this is actually fairly easy to implement. All you need to do is get the child widget of the GtkScrolledWindow
.
The solution I used on my image viewer used a custom widget which implemented the GtkScrollable
interface and rendered the images. If you used one, then that custom widget allocation is the dimensions of of the "visible area".
If you are using a GtkViewport
instead(through gtk_scrolled_window_add_with_viewport
maybe?), then that GtkViewport
allocation is the visible area of the GtkScrolledWindow
. A GtkViewport
child widget is always at its requested size, which might be bigger than the GtkScrolledWindow
visible area.
Either way, you use gtk_bin_get_child
to get the child widget of a GtkScrolledWindow
and then use gtk_widget_get_allocation
on that GtkWidget to get its allocation. That allocation is the "visible area" of the scrolled window without the scrollbars.
Upvotes: 4
Reputation: 400029
I think your main point:
A way of obtaining the actual size of the visible area in the ScrolledWindow.
is easily handled by quering the GtkAdjustments
that the scrollbars visualize. The "page_size" of the adjustments should correspond to the currently visible area.
Upvotes: -1