Re: Baseline alignment ideas

On Wed, Feb 27, 2013 at 8:44 PM, Alexander Larsson <alexl redhat com> wrote:
On ons, 2013-02-27 at 17:47 +0900, Tristan wrote:

Ah, I think I understand your question better now.

Use a natural allocation process similar to

Instead of looping over widget size requests, provide a normalized
value for the minimum and natural requests "above" and "below" the
children (after allocating the absolute minimum height).

 o Start by giving equal minimum "above" height to all children and
   equal minimum "below" height to all children

Well, this just means give each child their minimum height initially.

 o Distribute extra allocated space above and below equally until
   one of the sides ("above" or "below") reaches natural allocation

But, this is where I don't really follow. In practice all we have are
child widgets which we can ask for "what would the baseline be if you
had this height (and width, since its always fixed by now). From this
we want to decide the *total* height of each child.

How do we assign 5 pixels above the baseline based on this? All we can
do is give the child more total height (via gtk_widget_size_allocate),
we have in general no control of where that height will go. The child
might be expandable both above and below its baseline, but how can we
"tell" it to only grow above?

Interesting... taking your previous example of HBox with widgets
A, B, B, and D... let's consider that A & B is in VBox1 and B & D is
in VBox2

What you are asking (I think) is how can we determine that VBox2
can only grow /below/ and that VBox1 can only grow /above/.

Is this correct ?

I think this conversation needs a little bit more context (as to how
precisely you plan to layout the groundwork APIs for this), but
here's what I would envision:

I think that HBox has the responsibility to 'request and set the baseline'
of it's contents (being VBox1 & VBox2)

VBox1 reports a baseline which is close to the bottom of it's content,
while VBox2 requests a baseline which is near the top of it's content.

HBox then determines at allocation time, that the baseline of it's content
is an offset which agrees with VBox1 & VBox2, and then proceeds to
inform both VBoxes of the 'allocated baseline' and also distributes
the _full_ height of HBox to both children.

Determining what is a suitable baseline for the children of HBox is
problematic for HBox to solve, I would say let's _start_ by trying to
ignore natural height and use only minimum height, expand space
could either be distributed equally above and below both VBoxes,
allow this to be declarative (it will probably end up being needed)

Then, at this point HBox has determined a suitable baseline (either
by guessing and distributing equally above and below, or by using
some semantics)

Then, VBox1 and VBox2 allocate() routines kick in, and they have
a strict baseline rule to follow. This baseline is semantically linked
with widget "B" somehow (there must be some way that you determine
which of the children of either VBoxes 'own' the baseline for it's parent).

VBox1 (and VBox2) now have to satisfy the requirement that the
baseline offset request from it's widget B must be placed at the
same VBox1 relative position that it was assigned by it's parent
HBox directly before allocating.

Now note that we absolutely don't care about how much extra
space will be allocated to widgets A and D, they should align
themselves into whatever extra space which was given them
according to their own alignments.

I'm pretty sure this approach work's in theory, but there's a big
'gotcha' in play... which is the intrusive 'halign'/'valign' properties
and any properties which are implicitly calculated by the
->adjust_size_request() and ->adjust_size_allocate() vfuncs.

Which means the whole thing breaks down if either VBoxes
have a valign property that != GTK_ALIGN_FILL or that
margins or border_width are set... this is a hard problem to
figure out too... it might require that widgets retain access to
the full allocation given them by their parent, instead of the
final allocation stored after adjustments are made.

Finally, it's worth noting (I'm sure you're already aware) that
minimum & natural preferred_height_for_width() will hardly
ever differ (they will only differ for vertically rotated text, or
perhaps some GtkWrapBox which is oriented to wrap from
top to bottom).

Hope this helps,

The only way I can see is this iterative algorithm. Its based on the
fact that as we add height to each child it may appear above or below
the baseline, and in the worst case of two children growing on different
sides the container height will grow by double of what we add to the

So, we do something like:

1. allocate each child its own min height, calculate baseline and total
2. calculate the missing height to the allocated height
3. assign half the missing height to each child, this will at
   *most* grow you to the allocated height.
4. Recalc the missing height, if > 0, goto 3

This will take log2 (assigned_height - min_height) steps and will result
in a state where there is at least one child we can't give more height
as that would make the total height larger than the allocation.

However, there might still be some children that can safely expand. To
fill those we'd have to for each child try to grow it as much as
possible without affecting the total height. This can be done with a
similar loop, starting with adding MIN(space above widget, space below
widget) in a loop until this is 0. We then hit the top say, but then we
need another loop to see if giving more height means it extends towards
the bottom.

Each "try" here is a full size request, including w4h, h4w, children
with baselines, etc. This just strikes me as *way* too expensive.

A simpler approach would be to only ever look at the natural size
request for baseline aligned children, and always allocate size as per
this, never ever growing any children. Then we can top/bottom/center
align the whole group of baseline aligned children, but never FILL it.
This is trivial to calculate, but are there cases where this will not be

gtk-devel-list mailing list
gtk-devel-list gnome org

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