I am in the process of writing a new library interface for
logdiag, inspired by
Microsoft Visio. The idea is that there will be a pane on the side of the main
window showing various electronic symbols in several categories.
When displaying a category of symbols, what I am trying to do is to fit as many
of them as possible into the horizontal space the widget is given by its parent.
The result of the algorithm that accomplishes this task is the required height
to show them all without clipping.
This doesn’t go well with the size negotiation model used in GTK+ 2, though, as
it constitutes from only two steps: first you request a minimum size, and then
you simply receive the dimensions of the area your parent widget was able to
provide you. This problem is solved in the next major revision of GTK+, but as
I haven’t yet rewritten my code for it because I’m still waiting for a proper
Win32 bundle release, I was rather searching for any simple hack that would give
satisfying results.
While original GTK+ widgets use all sorts of sorcery involving private variables
in order to solve this, I’ve eventually found an easier way around. And it’s
kind of trivial indeed.
struct MyWidgetPrivate {
guint height_negotiation : 1;
};
static void on_size_request (MyWidget *self, GtkRequisition *requisition) {
requisition->width = MY_WIDGET_HORIZONTAL_MINIMUM;
if (self->priv->height_negotiation) {
GtkAllocation alloc;
gtk_widget_get_allocation (GTK_WIDGET (self), &alloc);
requisition->height = compute_height_for_width (self, alloc.width);
} else
requisition->height = MY_WIDGET_VERTICAL_MINIMUM;
}
static void on_size_allocate (MyWidget *self, GdkRectangle *allocation) {
if (self->priv->height_negotiation)
self->priv->height_negotiation = FALSE;
else {
self->priv->height_negotiation = TRUE;
gtk_widget_queue_resize (GTK_WIDGET (self));
}
}
Basically it just adds another stage to the negotiation. When asked first, it
returns what it’s supposed to (the minimum size of a single symbol in my case),
but when it receives the actual allocation, it goes one step back and says
‘Well, forget that, while I do want to have that width, I can’t allow myself
to be any shorter than this new value’. It assumes that it’s going to get the
same width as before, and it most probably is. If you put the actual width into
the second request, the widget would stop having its size renegotiated when the
containing widget becomes narrower than that.
Comments
Use e-mail, webchat, or the form below. I'll also pick up on new HN, Lobsters, and Reddit posts.