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/branches/WX_3_0_BRANCH@76183 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2014-03-23 00:51:27 +00:00
parent 37024c991c
commit 78c7a11877
2 changed files with 41 additions and 46 deletions

View File

@@ -645,6 +645,7 @@ wxMSW:
- Fix handling of controls in the vertical toolbars (Artur Wieczorek).
- Fix loading of top to bottom BMP files in wxBitmap (Artur Wieczorek).
- Fix resource leak in wxStaticBitmap with RGBA icons (Artur Wieczorek).
- Fix toolbar repainting after deleting a tool from it (Artur Wieczorek).
- Fix handling of deleting directories in wxFileSystemWatcher (Eric Raijmakers).
- Disable the use of new style wxDirDialog under Vista to work around a bug in
its implementation under this system (jtrauntvein).

View File

@@ -150,6 +150,7 @@ public:
{
m_nSepCount = 0;
m_staticText = NULL;
m_toBeDeleted = false;
}
wxToolBarTool(wxToolBar *tbar, wxControl *control, const wxString& label)
@@ -174,6 +175,7 @@ public:
}
m_nSepCount = 1;
m_toBeDeleted = false;
}
virtual ~wxToolBarTool()
@@ -233,9 +235,13 @@ public:
}
}
void ToBeDeleted() { m_toBeDeleted = true; }
bool IsToBeDeleted() const { return m_toBeDeleted; }
private:
size_t m_nSepCount;
wxStaticText *m_staticText;
bool m_toBeDeleted;
wxDECLARE_NO_COPY_CLASS(wxToolBarTool);
};
@@ -617,48 +623,11 @@ bool wxToolBar::DoDeleteTool(size_t pos, wxToolBarToolBase *tool)
return false;
}
}
static_cast<wxToolBarTool*>(tool)->ToBeDeleted();
// and finally rearrange the tools
// search for any stretch spacers before the removed tool
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
// by recalculating stretchable spacers, if there are any
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();
@@ -1293,9 +1262,13 @@ void wxToolBar::UpdateStretchableSpacersSize()
unsigned numSpaces = 0;
wxToolBarToolsList::compatibility_iterator node;
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();
if ( tool->IsToBeDeleted() )
continue;
if ( tool->IsStretchableSpace() )
{
// Count only enabled items
@@ -1303,6 +1276,8 @@ void wxToolBar::UpdateStretchableSpacersSize()
if ( !::IsRectEmpty(&rcItem) )
numSpaces++;
}
toolIndex++;
}
if ( !numSpaces )
@@ -1326,19 +1301,25 @@ void wxToolBar::UpdateStretchableSpacersSize()
// correct place
int offset = 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();
if ( tool->IsToBeDeleted() )
continue;
if ( tool->IsControl() && offset )
{
tool->MoveBy(offset);
toolIndex++;
continue;
}
if ( !tool->IsStretchableSpace() )
{
toolIndex++;
continue;
}
const RECT rcOld = wxGetTBItemRect(GetHwnd(), toolIndex);
@@ -1357,6 +1338,8 @@ void wxToolBar::UpdateStretchableSpacersSize()
// by the corresponding amount (may be positive or negative)
offset += tbbi.cx - (rcOld.right - rcOld.left);
}
toolIndex++;
}
#endif // TB_SETBUTTONINFO
}
@@ -1791,12 +1774,20 @@ bool wxToolBar::HandleSize(WXWPARAM WXUNUSED(wParam), WXLPARAM lParam)
int rowPosX = INT_MIN;
wxToolBarToolsList::compatibility_iterator node;
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
const RECT rcItem = wxGetTBItemRect(GetHwnd(), i);
if ( ::IsRectEmpty(&rcItem) )
{
i++;
continue;
}
if ( rcItem.top > rowPosX )
{
@@ -1813,8 +1804,6 @@ bool wxToolBar::HandleSize(WXWPARAM WXUNUSED(wParam), WXLPARAM lParam)
::SetRectEmpty(&rcRow);
}
wxToolBarTool * const tool = (wxToolBarTool*)node->GetData();
// Separators shouldn't be taken into account as they are sometimes
// 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
@@ -1824,6 +1813,8 @@ bool wxToolBar::HandleSize(WXWPARAM WXUNUSED(wParam), WXLPARAM lParam)
// Update bounding box of current row
::UnionRect(&rcRow, &rcRow, &rcItem);
}
i++;
}
// Take into account the last row rectangle too.
@@ -1888,6 +1879,9 @@ bool wxToolBar::HandlePaint(WXWPARAM wParam, WXLPARAM lParam)
wxToolBarTool * const
tool = static_cast<wxToolBarTool *>(node->GetData());
if ( tool->IsToBeDeleted() )
continue;
if ( tool->IsControl() || tool->IsStretchableSpace() )
{
const size_t numSeps = tool->GetSeparatorsCount();