Fix toolbar repainting after deleting a tool in wxMSW.
The toolbar was in an inconsistent state when recalculating the sizes of the separators used as placeholders for the controls and stretch spacers as the tool was already deleted from the native toolbar but still present in wx internal toolbar data and this resulted in discrepancies between the indices in the native and wx toolbars. Fix this by specially marking the already deleted but not yet removed tool and ignoring it during the recalculations. This makes the old, and only partially successful, attempt to work around this bug in DoDeleteTool() unnecessary and so the code is actually simplified by this change. Closes #16095. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@76189 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -150,6 +150,7 @@ public:
|
|||||||
{
|
{
|
||||||
m_nSepCount = 0;
|
m_nSepCount = 0;
|
||||||
m_staticText = NULL;
|
m_staticText = NULL;
|
||||||
|
m_toBeDeleted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxToolBarTool(wxToolBar *tbar, wxControl *control, const wxString& label)
|
wxToolBarTool(wxToolBar *tbar, wxControl *control, const wxString& label)
|
||||||
@@ -174,6 +175,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_nSepCount = 1;
|
m_nSepCount = 1;
|
||||||
|
m_toBeDeleted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~wxToolBarTool()
|
virtual ~wxToolBarTool()
|
||||||
@@ -233,9 +235,13 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ToBeDeleted() { m_toBeDeleted = true; }
|
||||||
|
bool IsToBeDeleted() const { return m_toBeDeleted; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t m_nSepCount;
|
size_t m_nSepCount;
|
||||||
wxStaticText *m_staticText;
|
wxStaticText *m_staticText;
|
||||||
|
bool m_toBeDeleted;
|
||||||
|
|
||||||
wxDECLARE_NO_COPY_CLASS(wxToolBarTool);
|
wxDECLARE_NO_COPY_CLASS(wxToolBarTool);
|
||||||
};
|
};
|
||||||
@@ -617,48 +623,11 @@ bool wxToolBar::DoDeleteTool(size_t pos, wxToolBarToolBase *tool)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static_cast<wxToolBarTool*>(tool)->ToBeDeleted();
|
||||||
|
|
||||||
// and finally rearrange the tools
|
// and finally rearrange the tools
|
||||||
|
// by recalculating stretchable spacers, if there are any
|
||||||
// search for any stretch spacers before the removed tool
|
UpdateStretchableSpacersSize();
|
||||||
bool hasPrecedingStrechables = false;
|
|
||||||
for ( wxToolBarToolsList::compatibility_iterator nodeStch = m_tools.GetFirst();
|
|
||||||
nodeStch != node; nodeStch = nodeStch->GetNext() )
|
|
||||||
{
|
|
||||||
if ( ((wxToolBarTool*)nodeStch->GetData())->IsStretchable() )
|
|
||||||
{
|
|
||||||
hasPrecedingStrechables = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( hasPrecedingStrechables )
|
|
||||||
{
|
|
||||||
// if the removed tool is preceded by stretch spacers
|
|
||||||
// just redistribute the space
|
|
||||||
UpdateStretchableSpacersSize();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// reposition all the controls after this button but before any
|
|
||||||
// stretch spacer (the toolbar takes care of all normal items)
|
|
||||||
for ( /* node -> first after deleted */ ; node; node = node->GetNext() )
|
|
||||||
{
|
|
||||||
wxToolBarTool *tool2 = (wxToolBarTool*)node->GetData();
|
|
||||||
|
|
||||||
if ( tool2->IsControl() )
|
|
||||||
{
|
|
||||||
tool2->MoveBy(-delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if a stretch spacer is found just redistribute the available space
|
|
||||||
else if ( tool2->IsStretchable() )
|
|
||||||
{
|
|
||||||
UpdateStretchableSpacersSize();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
InvalidateBestSize();
|
InvalidateBestSize();
|
||||||
|
|
||||||
@@ -1318,9 +1287,13 @@ void wxToolBar::UpdateStretchableSpacersSize()
|
|||||||
unsigned numSpaces = 0;
|
unsigned numSpaces = 0;
|
||||||
wxToolBarToolsList::compatibility_iterator node;
|
wxToolBarToolsList::compatibility_iterator node;
|
||||||
int toolIndex = 0;
|
int toolIndex = 0;
|
||||||
for ( node = m_tools.GetFirst(); node; node = node->GetNext(), toolIndex++ )
|
for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
|
||||||
{
|
{
|
||||||
wxToolBarTool * const tool = (wxToolBarTool*)node->GetData();
|
wxToolBarTool * const tool = (wxToolBarTool*)node->GetData();
|
||||||
|
|
||||||
|
if ( tool->IsToBeDeleted() )
|
||||||
|
continue;
|
||||||
|
|
||||||
if ( tool->IsStretchableSpace() )
|
if ( tool->IsStretchableSpace() )
|
||||||
{
|
{
|
||||||
// Count only enabled items
|
// Count only enabled items
|
||||||
@@ -1328,6 +1301,8 @@ void wxToolBar::UpdateStretchableSpacersSize()
|
|||||||
if ( !::IsRectEmpty(&rcItem) )
|
if ( !::IsRectEmpty(&rcItem) )
|
||||||
numSpaces++;
|
numSpaces++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toolIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !numSpaces )
|
if ( !numSpaces )
|
||||||
@@ -1351,19 +1326,25 @@ void wxToolBar::UpdateStretchableSpacersSize()
|
|||||||
// correct place
|
// correct place
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
toolIndex = 0;
|
toolIndex = 0;
|
||||||
for ( node = m_tools.GetFirst(); node; node = node->GetNext(), toolIndex++ )
|
for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
|
||||||
{
|
{
|
||||||
wxToolBarTool * const tool = (wxToolBarTool*)node->GetData();
|
wxToolBarTool * const tool = (wxToolBarTool*)node->GetData();
|
||||||
|
|
||||||
|
if ( tool->IsToBeDeleted() )
|
||||||
|
continue;
|
||||||
|
|
||||||
if ( tool->IsControl() && offset )
|
if ( tool->IsControl() && offset )
|
||||||
{
|
{
|
||||||
tool->MoveBy(offset);
|
tool->MoveBy(offset);
|
||||||
|
toolIndex++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !tool->IsStretchableSpace() )
|
if ( !tool->IsStretchableSpace() )
|
||||||
|
{
|
||||||
|
toolIndex++;
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const RECT rcOld = wxGetTBItemRect(GetHwnd(), toolIndex);
|
const RECT rcOld = wxGetTBItemRect(GetHwnd(), toolIndex);
|
||||||
|
|
||||||
@@ -1398,6 +1379,8 @@ void wxToolBar::UpdateStretchableSpacersSize()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toolIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1837,12 +1820,20 @@ bool wxToolBar::HandleSize(WXWPARAM WXUNUSED(wParam), WXLPARAM lParam)
|
|||||||
int rowPosX = INT_MIN;
|
int rowPosX = INT_MIN;
|
||||||
wxToolBarToolsList::compatibility_iterator node;
|
wxToolBarToolsList::compatibility_iterator node;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for ( node = m_tools.GetFirst(); node; node = node->GetNext(), i++)
|
for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
|
||||||
{
|
{
|
||||||
|
wxToolBarTool * const
|
||||||
|
tool = static_cast<wxToolBarTool *>(node->GetData());
|
||||||
|
if ( tool->IsToBeDeleted() )
|
||||||
|
continue;
|
||||||
|
|
||||||
// Skip hidden buttons
|
// Skip hidden buttons
|
||||||
const RECT rcItem = wxGetTBItemRect(GetHwnd(), i);
|
const RECT rcItem = wxGetTBItemRect(GetHwnd(), i);
|
||||||
if ( ::IsRectEmpty(&rcItem) )
|
if ( ::IsRectEmpty(&rcItem) )
|
||||||
|
{
|
||||||
|
i++;
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if ( rcItem.top > rowPosX )
|
if ( rcItem.top > rowPosX )
|
||||||
{
|
{
|
||||||
@@ -1859,8 +1850,6 @@ bool wxToolBar::HandleSize(WXWPARAM WXUNUSED(wParam), WXLPARAM lParam)
|
|||||||
::SetRectEmpty(&rcRow);
|
::SetRectEmpty(&rcRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
wxToolBarTool * const tool = (wxToolBarTool*)node->GetData();
|
|
||||||
|
|
||||||
// Separators shouldn't be taken into account as they are sometimes
|
// Separators shouldn't be taken into account as they are sometimes
|
||||||
// reported to have the width of the entire client area by the toolbar.
|
// reported to have the width of the entire client area by the toolbar.
|
||||||
// And we know that they are not the biggest items in the toolbar in
|
// And we know that they are not the biggest items in the toolbar in
|
||||||
@@ -1870,6 +1859,8 @@ bool wxToolBar::HandleSize(WXWPARAM WXUNUSED(wParam), WXLPARAM lParam)
|
|||||||
// Update bounding box of current row
|
// Update bounding box of current row
|
||||||
::UnionRect(&rcRow, &rcRow, &rcItem);
|
::UnionRect(&rcRow, &rcRow, &rcItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Take into account the last row rectangle too.
|
// Take into account the last row rectangle too.
|
||||||
@@ -1934,6 +1925,9 @@ bool wxToolBar::HandlePaint(WXWPARAM wParam, WXLPARAM lParam)
|
|||||||
wxToolBarTool * const
|
wxToolBarTool * const
|
||||||
tool = static_cast<wxToolBarTool *>(node->GetData());
|
tool = static_cast<wxToolBarTool *>(node->GetData());
|
||||||
|
|
||||||
|
if ( tool->IsToBeDeleted() )
|
||||||
|
continue;
|
||||||
|
|
||||||
if ( tool->IsControl() || tool->IsStretchableSpace() )
|
if ( tool->IsControl() || tool->IsStretchableSpace() )
|
||||||
{
|
{
|
||||||
const size_t numSeps = tool->GetSeparatorsCount();
|
const size_t numSeps = tool->GetSeparatorsCount();
|
||||||
|
Reference in New Issue
Block a user