+ // Since we passed available space along to the item, it should not
+ // take too much, so delta should not become negative.
+ delta -= deltaChange;
+ }
+ minMajorSize += GetSizeInMajorDir(item->GetMinSizeWithBorder());
+ }
+
+ // update our min size and delta which may have changed
+ SizeInMajorDir(m_minSize) = minMajorSize;
+ delta = totalMajorSize - minMajorSize;
+
+
+ // space and sum of proportions for the remaining items, both may change
+ // below
+ wxCoord remaining = totalMajorSize;
+ int totalProportion = m_totalProportion;
+
+ // size of the (visible) items in major direction, -1 means "not fixed yet"
+ wxVector<int> majorSizes(GetItemCount(), wxDefaultCoord);
+
+
+ // Check for the degenerated case when we don't have enough space for even
+ // the min sizes of all the items: in this case we really can't do much
+ // more than to allocate the min size to as many of fixed size items as
+ // possible (on the assumption that variable size items such as text zones
+ // or list boxes may use scrollbars to show their content even if their
+ // size is less than min size but that fixed size items such as buttons
+ // will suffer even more if we don't give them their min size)
+ if ( totalMajorSize < minMajorSize )
+ {
+ // Second degenerated case pass: allocate min size to all fixed size
+ // items.
+ for ( i = m_children.begin(), n = 0; i != m_children.end(); ++i, ++n )
+ {
+ wxSizerItem * const item = *i;
+
+ if ( !item->IsShown() )
+ continue;
+
+ // deal with fixed size items only during this pass
+ if ( item->GetProportion() )
+ continue;
+
+ majorSizes[n] = GetMinOrRemainingSize(m_orient, item, &remaining);
+ }
+
+
+ // Third degenerated case pass: allocate min size to all the remaining,
+ // i.e. non-fixed size, items.
+ for ( i = m_children.begin(), n = 0; i != m_children.end(); ++i, ++n )
+ {
+ wxSizerItem * const item = *i;
+
+ if ( !item->IsShown() )
+ continue;
+
+ // we've already dealt with fixed size items above
+ if ( !item->GetProportion() )
+ continue;
+
+ majorSizes[n] = GetMinOrRemainingSize(m_orient, item, &remaining);
+ }
+ }
+ else // we do have enough space to give at least min sizes to all items
+ {
+ // Second and maybe more passes in the non-degenerated case: deal with
+ // fixed size items and items whose min size is greater than what we
+ // would allocate to them taking their proportion into account. For
+ // both of them, we will just use their min size, but for the latter we
+ // also need to reexamine all the items as the items which fitted
+ // before we adjusted their size upwards might not fit any more. This
+ // does make for a quadratic algorithm but it's not obvious how to
+ // avoid it and hopefully it's not a huge problem in practice as the
+ // sizers don't have many items usually (and, of course, the algorithm
+ // still reduces into a linear one if there is enough space for all the
+ // min sizes).
+ bool nonFixedSpaceChanged = false;
+ for ( i = m_children.begin(), n = 0; ; ++i, ++n )
+ {
+ if ( nonFixedSpaceChanged )
+ {
+ i = m_children.begin();
+ n = 0;
+ nonFixedSpaceChanged = false;
+ }
+
+ // check for the end of the loop only after the check above as
+ // otherwise we wouldn't do another pass if the last child resulted
+ // in non fixed space reduction
+ if ( i == m_children.end() )
+ break;
+
+ wxSizerItem * const item = *i;
+
+ if ( !item->IsShown() )
+ continue;
+
+ // don't check the item which we had already dealt with during a
+ // previous pass (this is more than an optimization, the code
+ // wouldn't work correctly if we kept adjusting for the same item
+ // over and over again)
+ if ( majorSizes[n] != wxDefaultCoord )
+ continue;
+
+ wxCoord minMajor = GetSizeInMajorDir(item->GetMinSizeWithBorder());
+
+ // it doesn't make sense for min size to be negative but right now
+ // it's possible to create e.g. a spacer with (-1, 10) as size and
+ // people do it in their code apparently (see #11842) so ensure
+ // that we don't use this -1 as real min size as it conflicts with
+ // the meaning we use for it here and negative min sizes just don't
+ // make sense anyhow (which is why it might be a better idea to
+ // deal with them at wxSizerItem level in the future but for now
+ // this is the minimal fix for the bug)
+ if ( minMajor < 0 )
+ minMajor = 0;
+
+ const int propItem = item->GetProportion();
+ if ( propItem )
+ {
+ // is the desired size of this item big enough?
+ if ( (remaining*propItem)/totalProportion >= minMajor )
+ {
+ // yes, it is, we'll determine the real size of this
+ // item later, for now just leave it as wxDefaultCoord
+ continue;
+ }
+
+ // the proportion of this item won't count, it has
+ // effectively become fixed
+ totalProportion -= propItem;
+ }
+
+ // we can already allocate space for this item
+ majorSizes[n] = minMajor;
+
+ // change the amount of the space remaining to the other items,
+ // as this can result in not being able to satisfy their
+ // proportions any more we will need to redo another loop
+ // iteration
+ remaining -= minMajor;
+
+ nonFixedSpaceChanged = true;
+ }
+
+
+ // Last by one pass: distribute the remaining space among the non-fixed
+ // items whose size weren't fixed yet according to their proportions.
+ for ( i = m_children.begin(), n = 0; i != m_children.end(); ++i, ++n )
+ {
+ wxSizerItem * const item = *i;
+
+ if ( !item->IsShown() )
+ continue;
+
+ if ( majorSizes[n] == wxDefaultCoord )
+ {
+ const int propItem = item->GetProportion();
+ majorSizes[n] = (remaining*propItem)/totalProportion;
+
+ remaining -= majorSizes[n];
+ totalProportion -= propItem;
+ }