[RFC] supporting an alternative layout management algorithm



Hi everybody,

I am trying to bring "stack-flow layout" (see
http://code.whytheluckystiff.net/shoes/wiki/StacksAndFlows for more
info) to GTK+.  If you do not want to read the linked page, the idea is
to have a UI made of standard GTK+ widgets, but organized in a
document-like way with vertical scrolling capability.

The system is different from what GTK+ uses for its geometry management.
Stacks and flows are similar to GtkVBox and GtkHBox respectively, but
they do not match well with the GTK+ concept that widgets have to
provide their final size before you lay them down in the window. For
example, a flow is basically a GtkHBox, but its content can wrap: see
this picture:

  http://smalltalk.gnu.org/files/gtk+/layout.png

There are then two main differences: 1) the four buttons are in the same
flow, but they wrap to the following line; 2) if an element of the UI
causes a flow to have more width than it requested, the flow can benefit
of the extra width and use it to avoid wrapping.  Avoiding the wrapping
may mean, in turn, being able to use less vertical space than it had
requested.

The last point is particularly important, because a stack knows that,
and indeed only allocates to a flow the space that it needs.  This maps
in my implementation to different semantics for the requisition and
allocation phases:

1) while the requisition phase uses the same GtkRequisition struct,
right now only the width information is used, to place an horizontal
scrollbar if needed;

2) the allocation phase is given substantially more freedom.  The
widget/container can modify the GtkAllocation struct to tell the parent
how much horizontal space it has actually occupied (it must be less than
what the parent puts in allocation->width), and how much vertical space
it has needed (which can be any amount >= 0px).

My implementation uses a new interface, GtkLayoutable, that is
implemented by all widgets (my system does not require right now
modifications to Gtk+, though I'd be happy to see it integrated; and in
that case, with only two available slots in GtkWidgetClass, I guess an
interface is anyway a better match for Gtk+ 2.x?).  There is also a new
scrollable container widget, GtkManagedLayout.

The new interface, GtkLayoutable, is implemented by all widgets, and
provides an additional pair of size_request/size_allocate methods with
the semantics I gave a couple of paragraphs above.

GtkManagedLayout is a GtkBin that is similar to GtkViewport and, like
most other GtkBins, implements a decorator pattern; it lays out the
wrapped widget using the GtkLayoutable pair of methods and exposes the
result of the layout process through the scrollbar GtkAdjustments.  If
the wrapped widget is a container, and is stack/flow-enabled, it will
use the GtkLayoutable methods also for its the subwidgets.  If a widget
(or even a container) is reached that does not support the new system,
that can be either because it does not matter, as for GtkButtons, or
because GtkLayoutable has not been implemented yet; but in any case, no
change is needed to these widgets because GtkWidget provides a default
implementation of the two methods that delegates to the old system.

Since existing containers can be modified to support the new layout
manager, stacks are just GtkVBoxes and flows are just GtkHBoxes.
GtkLabel also provides its own GtkLayoutable implementation, because if
it is placed inside a GtkManagedLayout becomes the equivalent of an HTML
"display: block" or "inline-block" element.  (Here actually comes a side
question: why isn't a GtkLabel allowed to take all the horizontal space
that is available to it?)  I also plan to implement the interface on
GtkExpander, so that the expanded content can be laid out as
stacks/flows too, and possibly on GtkEventBox.

The code is available at
http://www.inf.unisi.ch/phd/bonzini/webdav/gtk-widgets.git/ (together
with a couple of demos and two other widgets that I use in the demos).

So, here are my questions.  Bear with me because, believe it or not,
this is hardly my first project using GTK+.

1) Does the above make sense? :-)

2) Does the implementation seem sound?  (I'm not asking anyone to look
at the code, though reviews are very appreciated -- I'm just asking for
comments on the design I explained above).

3) What would the cost be when using it for relatively large interfaces?
 For example, what is the cost of having a UI with ~300-400 GtkExpanders
at the same time?  Should I modify GtkManagedLayout to map children
lazily as they become visible for the first time?  Does it work to
create a GtkExpander with no child, and add it only when the GtkExpander
is activated?

4) Would there be any interest to integrate this into GTK+?  (I am a
volunteer so I doubt I will have enough free time to do so -- but you
never know.)

Paolo



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]