Fix incorrect code sorting pages by their widths in wxRibbon.
The "sneaky obj array trickery" wasn't very sneaky but was just plain wrong and misused object array of pages in a way that was invalid and didn't crash just because of sheer luck. Rewrite this code to use a temporary wxVector of pages that can be sorted independently of the main m_pages array. This is 100% safe and also more clear. Closes #14625. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@72516 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -21,6 +21,7 @@
|
|||||||
#include "wx/ribbon/art.h"
|
#include "wx/ribbon/art.h"
|
||||||
#include "wx/dcbuffer.h"
|
#include "wx/dcbuffer.h"
|
||||||
#include "wx/app.h"
|
#include "wx/app.h"
|
||||||
|
#include "wx/vector.h"
|
||||||
|
|
||||||
#ifndef WX_PRECOMP
|
#ifndef WX_PRECOMP
|
||||||
#endif
|
#endif
|
||||||
@@ -465,10 +466,21 @@ void wxRibbonBar::SetTabCtrlMargins(int left, int right)
|
|||||||
RecalculateTabSizes();
|
RecalculateTabSizes();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int OrderPageTabInfoBySmallWidthAsc(wxRibbonPageTabInfo **first, wxRibbonPageTabInfo **second)
|
struct PageComparedBySmallWidthAsc
|
||||||
{
|
{
|
||||||
return (**first).small_must_have_separator_width - (**second).small_must_have_separator_width;
|
wxEXPLICIT PageComparedBySmallWidthAsc(wxRibbonPageTabInfo* page)
|
||||||
}
|
: m_page(page)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const PageComparedBySmallWidthAsc& other) const
|
||||||
|
{
|
||||||
|
return m_page->small_must_have_separator_width
|
||||||
|
< other.m_page->small_must_have_separator_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxRibbonPageTabInfo *m_page;
|
||||||
|
};
|
||||||
|
|
||||||
void wxRibbonBar::RecalculateTabSizes()
|
void wxRibbonBar::RecalculateTabSizes()
|
||||||
{
|
{
|
||||||
@@ -624,30 +636,27 @@ void wxRibbonBar::RecalculateTabSizes()
|
|||||||
if(width >= total_small_width)
|
if(width >= total_small_width)
|
||||||
{
|
{
|
||||||
// Do (2)
|
// Do (2)
|
||||||
wxRibbonPageTabInfoArray sorted_pages;
|
wxVector<PageComparedBySmallWidthAsc> sorted_pages;
|
||||||
for(i = 0; i < numtabs; ++i)
|
sorted_pages.reserve(numtabs);
|
||||||
{
|
for ( i = 0; i < numtabs; ++i )
|
||||||
// Sneaky obj array trickery to not copy the tab descriptors
|
sorted_pages.push_back(PageComparedBySmallWidthAsc(&m_pages.Item(i)));
|
||||||
if (!m_pages.Item(i).shown)
|
|
||||||
continue;
|
wxVectorSort(sorted_pages);
|
||||||
sorted_pages.Add(&m_pages.Item(i));
|
|
||||||
}
|
|
||||||
sorted_pages.Sort(OrderPageTabInfoBySmallWidthAsc);
|
|
||||||
width -= tabsep * (numtabs - 1);
|
width -= tabsep * (numtabs - 1);
|
||||||
for(i = 0; i < numtabs; ++i)
|
for(i = 0; i < numtabs; ++i)
|
||||||
{
|
{
|
||||||
wxRibbonPageTabInfo& info = sorted_pages.Item(i);
|
wxRibbonPageTabInfo* info = sorted_pages[i].m_page;
|
||||||
if (!info.shown)
|
if (!info->shown)
|
||||||
continue;
|
continue;
|
||||||
if(info.small_must_have_separator_width * (int)(numtabs - i) <= width)
|
if(info->small_must_have_separator_width * (int)(numtabs - i) <= width)
|
||||||
{
|
{
|
||||||
info.rect.width = info.small_must_have_separator_width;;
|
info->rect.width = info->small_must_have_separator_width;;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
info.rect.width = width / (numtabs - i);
|
info->rect.width = width / (numtabs - i);
|
||||||
}
|
}
|
||||||
width -= info.rect.width;
|
width -= info->rect.width;
|
||||||
}
|
}
|
||||||
for(i = 0; i < numtabs; ++i)
|
for(i = 0; i < numtabs; ++i)
|
||||||
{
|
{
|
||||||
@@ -658,7 +667,6 @@ void wxRibbonBar::RecalculateTabSizes()
|
|||||||
info.rect.y = y;
|
info.rect.y = y;
|
||||||
info.rect.height = m_tab_height;
|
info.rect.height = m_tab_height;
|
||||||
x += info.rect.width + tabsep;
|
x += info.rect.width + tabsep;
|
||||||
sorted_pages.Detach(numtabs - (i + 1));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
Reference in New Issue
Block a user