Please help with patch to gbsizer.cpp

Frank Millman frank at chagford.com
Wed Sep 5 05:58:54 PDT 2007


Hi all

Some of you may have noticed an anomaly when using column or row 'spanning'
with GridBagSizer. The layout algorithm sometimes allocates unnecessary
extra space to the column or row.

I have looked at gbsizer.cpp, and I think I can see the problem. I have
mentioned this on the wxPython-users list, and Robin Dunn has indicated that
he would be happy to look at a patch. Unfortunately I am a Python
programmer, not C++, so I am asking for some assistance in creating the
appropriate patch.

I have attached gbsizer_patch.txt, which contains the following -

1. The relevant lines from gbsizer.cpp - lines 449-477
2. The equivalent piece of code translated into Python
3. The changes necessary to apply to 2 above, to effect the required change
in Python

If someone can help me to convert 3 above into a valid C++ patch to
gbsizer.cpp, I will be most grateful.

For those not familiar with Python, it reads more or less like pseudo code,
so it should be mostly self-explanatory, but the following may need some
explanation -

rowHeights = []
    [] represents a Python list, which is an array of arbitrary objects

for idx in range(row, endrow+1):
    this is equivalent to 'for (idx=row; idx <= endrow; idx++)'

rowSpans.append( (row,endrow,size.Height) )
    this appends a Python 'tuple' (a C++ 'struct'?) containing three
integers to the array rowSpans

for row,endrow,height in rowSpans:
    this loops through the array rowSpans, and unpacks each tuple into local
variables for each iteration

You will note that Python does not use braces to indicate code blocks, it
uses indentation. An indent to the right indicates the start of a new code
block. A return to a previous level of indentation indicates continuation
from the last line of code at the same indentation level.

Feel free to ask any other questions.

I am not subscribed to the list, but I will monitor the archive - it usually
seems to be pretty up-to-date.

TIA for any assistance
	
Frank Millman
-------------- next part --------------
# lines 449-477 from gbsizer.cpp Rev 1.16 (current cvs)

    m_rowHeights.Empty();
    m_colWidths.Empty();

    wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
    while (node)
    {
        wxGBSizerItem* item = (wxGBSizerItem*)node->GetData();
        if ( item->IsShown() )
        {
            int row, col, endrow, endcol;

            item->GetPos(row, col);
            item->GetEndPos(endrow, endcol);

            // fill heights and widths upto this item if needed
            while ( m_rowHeights.GetCount() <= (size_t)endrow )
                m_rowHeights.Add(m_emptyCellSize.GetHeight());
            while ( m_colWidths.GetCount() <= (size_t)endcol )
                m_colWidths.Add(m_emptyCellSize.GetWidth());

            // See if this item increases the size of its row(s) or col(s)
            wxSize size(item->CalcMin());
            for (idx=row; idx <= endrow; idx++)
                m_rowHeights[idx] = wxMax(m_rowHeights[idx], size.GetHeight() / (endrow-row+1));
            for (idx=col; idx <= endcol; idx++)
                m_colWidths[idx] = wxMax(m_colWidths[idx], size.GetWidth() / (endcol-col+1));
        }
        node = node->GetNext();
    }

#-----------------------------------------------------------------------------

# python equivalent of the above -

    rowHeights = []
    colWidths = []

    for item in SizerItemList:
        if item.IsShown():

            row, col = item.Pos
            endrow, endcol = item.EndPos

            if endrow >= len(rowHeights):
                rowHeights.extend([emptyCellSize.Height] * (endrow-len(rowHeights)+1))
            if endcol >= len(colWidths):
                colWidths.extend([emptyCellSize.Width] * (endcol-len(colWidths)+1))

            size = item.CalcMin()

            for idx in range(row, endrow+1):
                rowHeights[idx] = max( rowHeights[idx], size.Height / (endrow-row+1 )
            for idx in range(col, endcol+1):
                colWidths[idx] = max( colWidths[idx], size.Width / (endcol-col+1 )

#-----------------------------------------------------------------------------

# new python equivalent required -
#   lines marked - are deleted from the original
#   lines marked + are added to the original


    rowHeights = []
    colWidths = []
+   rowSpans = []
+   colSpans = []

    for item in SizerItemList:
        if item.IsShown():

            row, col = item.Pos
            endrow, endcol = item.EndPos

            if endrow >= len(rowHeights):
                rowHeights.extend([emptyCellSize.Height] * (endrow-len(rowHeights)+1))
            if endcol >= len(colWidths):
                colWidths.extend([emptyCellSize.Width] * (endcol-len(colWidths)+1))

            size = item.CalcMin()

-           for idx in range(row, endrow+1):
-               rowHeights[idx] = max( rowHeights[idx], size.Height / (endrow-row+1 )
-           for idx in range(col, endcol+1):
-               colWidths[idx] = max( colWidths[idx], size.Width / (endcol-col+1 )

+           if row == endrow:
+               rowHeights[row] = max( rowHeights[row], size.Height)
+           else:
+               rowSpans.append( (row,endrow,size.Height) )

+           if col == endcol:
+               colWidths[col] = max( colWidths[col], size.Width)
+           else:
+               colSpans.append( (col,endcol,size.Width) )

+   for row,endrow,height in rowSpans:
+       availableHeight = 0
+       for idx in range(row, endrow+1):
+           availableHeight += rowHeights[idx]
+       if height > availableHeight:
+           amountToAdd = int((height-availableHeight) / (endrow-row+1))
+           for idx in range(row, endrow+1):
+               rowHeights[idx] += amountToAdd

+   for col,endcol,width in colSpans:
+       availableWidth = 0
+       for idx in range(col, endcol+1):
+           availableWidth += colWidths[idx]
+       if width > availableWidth:
+           amountToAdd = int((width-availableWidth) / (endcol-col+1))
+           for idx in range(row, endcol+1):
+               colWidths[idx] += amountToAdd

#-----------------------------------------------------------------------------


More information about the wx-users mailing list