I was trying to write some simple code for a "flow layout" manager and what I came up with initially was something like the following (semi-pseudocode):
int rowHeight = 0;
RECT rect = parent.getClientRect();
POINT pos = rect.position; // Start at top-left corner, row by row
foreach (Window child in parent.children)
{
// POINT is a tuple of: (x, y)
// SIZE is a tuple of: (width, height)
// RECT is a tuple of: (left, top, right, bottom)
RECT proposed1 = RECT(rect.left + pos.x, rect.top + pos.y, rect.right, rect.bottom),
proposed2 = RECT(rect.left, rect.top + pos.y + rowHeight, rect.right, rect.bottom);
SIZE size1 = child.getPreferredSize(proposed1),
size2 = child.getPreferredSize(proposed2);
if (size1.width <= proposed1.width)
{
child.put(proposed1); // same row
pos.x += size1.width;
rowHeight = max(rowHeight, size1.height);
}
else
{
child.put(proposed2); // new row
pos.x = rect.left;
pos.y += rowHeight;
rowHeight = size2.height;
}
}
In other words, the algorithm is very simple:
The layout manager asks every component, "is the remaining portion of the row enough for you?" and, if the component says "no, my width is too long", it places the component on the next row instead.
There are two major problems with this approach:
This algorithm results in very long, thin components, because it is essentially greedy with the width of each component -- if a component wants the whole row, it will use the whole row (ugly), even if it could use a smaller width (but larger height).
It only works if you already know what the parent's size is -- but you might not! Instead, you might simply have a restriction, "the parent's size must be between these two dimensions", but the rest might be open-ended.
I am, however, at a loss of how to come up with a better algorithm -- how do I figure out what would be a good size to to 'propose' to the component? And even when I figure that out, what should I try to optimize, exactly? (The area, the width, the aspect ratio, the number of components on the screen, or something else?)
Any ideas on how I should approach this problem?