Simplify wxMSW wxToolBar controls support implementation.

Rely on being able to set the separator size, which is supported since
comctl32.dll v4.71 (the version distributed with IE 4.0...).

This allows to remove big chunks of code dealing with multiple separators and
simplifies the rest.

Closes #16129.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@76215 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2014-03-29 16:53:34 +00:00
parent f8e96589d9
commit 68a483a340

View File

@@ -148,7 +148,6 @@ public:
: wxToolBarToolBase(tbar, id, label, bmpNormal, bmpDisabled, kind, : wxToolBarToolBase(tbar, id, label, bmpNormal, bmpDisabled, kind,
clientData, shortHelp, longHelp) clientData, shortHelp, longHelp)
{ {
m_nSepCount = 0;
m_staticText = NULL; m_staticText = NULL;
m_toBeDeleted = false; m_toBeDeleted = false;
} }
@@ -174,7 +173,6 @@ public:
m_staticText = NULL; m_staticText = NULL;
} }
m_nSepCount = 1;
m_toBeDeleted = false; m_toBeDeleted = false;
} }
@@ -207,11 +205,6 @@ public:
return m_staticText; return m_staticText;
} }
// set/get the number of separators which we use to cover the space used by
// a control in the toolbar
void SetSeparatorsCount(size_t count) { m_nSepCount = count; }
size_t GetSeparatorsCount() const { return m_nSepCount; }
// we need ids for the spacers which we want to modify later on, this // we need ids for the spacers which we want to modify later on, this
// function will allocate a valid/unique id for a spacer if not done yet // function will allocate a valid/unique id for a spacer if not done yet
void AllocSpacerId() void AllocSpacerId()
@@ -239,7 +232,6 @@ public:
bool IsToBeDeleted() const { return m_toBeDeleted; } bool IsToBeDeleted() const { return m_toBeDeleted; }
private: private:
size_t m_nSepCount;
wxStaticText *m_staticText; wxStaticText *m_staticText;
bool m_toBeDeleted; bool m_toBeDeleted;
@@ -571,58 +563,22 @@ bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos),
bool wxToolBar::DoDeleteTool(size_t pos, wxToolBarToolBase *tool) bool wxToolBar::DoDeleteTool(size_t pos, wxToolBarToolBase *tool)
{ {
// the main difficulty we have here is with the controls in the toolbars:
// as we (sometimes) use several separators to cover up the space used by
// them, the indices are not the same for us and the toolbar
// first determine the position of the first button to delete: it may be
// different from pos if we use several separators to cover the space used
// by a control
wxToolBarToolsList::compatibility_iterator node;
for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
{
wxToolBarToolBase *tool2 = node->GetData();
if ( tool2 == tool )
{
// let node point to the next node in the list
node = node->GetNext();
break;
}
if ( tool2->IsControl() )
pos += ((wxToolBarTool *)tool2)->GetSeparatorsCount() - 1;
}
// now determine the number of buttons to delete and the area taken by them
size_t nButtonsToDelete = 1;
// get the size of the button we're going to delete // get the size of the button we're going to delete
const RECT r = wxGetTBItemRect(GetHwnd(), pos); const RECT r = wxGetTBItemRect(GetHwnd(), pos);
int delta = IsVertical() ? r.bottom - r.top : r.right - r.left; int delta = IsVertical() ? r.bottom - r.top : r.right - r.left;
if ( tool->IsControl() )
{
nButtonsToDelete = ((wxToolBarTool *)tool)->GetSeparatorsCount();
if ( !IsVertical() )
delta *= nButtonsToDelete;
}
m_totalFixedSize -= delta; m_totalFixedSize -= delta;
// do delete all buttons // do delete the button
m_nButtons -= nButtonsToDelete; m_nButtons--;
while ( nButtonsToDelete-- > 0 ) if ( !::SendMessage(GetHwnd(), TB_DELETEBUTTON, pos, 0) )
{ {
if ( !::SendMessage(GetHwnd(), TB_DELETEBUTTON, pos, 0) ) wxLogLastError(wxT("TB_DELETEBUTTON"));
{
wxLogLastError(wxT("TB_DELETEBUTTON"));
return false; return false;
}
} }
static_cast<wxToolBarTool*>(tool)->ToBeDeleted(); static_cast<wxToolBarTool*>(tool)->ToBeDeleted();
// and finally rearrange the tools // and finally rearrange the tools
@@ -974,6 +930,14 @@ bool wxToolBar::Realize()
staticText-> staticText->
Show(HasFlag(wxTB_TEXT) && !HasFlag(wxTB_NOICONS)); Show(HasFlag(wxTB_TEXT) && !HasFlag(wxTB_NOICONS));
} }
// Set separator width/height to fit the control width/height
// (height is not used but it is set for the sake of consistency).
{
const wxSize sizeControl = tool->GetControl()->GetSize();
button.iBitmap = IsVertical() ? sizeControl.y : sizeControl.x;
}
// Fall through // Fall through
case wxTOOL_STYLE_SEPARATOR: case wxTOOL_STYLE_SEPARATOR:
@@ -983,10 +947,6 @@ bool wxToolBar::Realize()
// so we need a valid id for it and not wxID_SEPARATOR // so we need a valid id for it and not wxID_SEPARATOR
// which is used by spacers by default // which is used by spacers by default
tool->AllocSpacerId(); tool->AllocSpacerId();
// also set the number of separators so that the logic in
// HandlePaint() works correctly
tool->SetSeparatorsCount(1);
} }
button.idCommand = tool->GetId(); button.idCommand = tool->GetId();
@@ -1144,59 +1104,6 @@ bool wxToolBar::Realize()
staticTextSize.y += 3; // margin between control and its label staticTextSize.y += 3; // margin between control and its label
} }
// TB_SETBUTTONINFO message is only supported by comctl32.dll 4.71+
#ifdef TB_SETBUTTONINFO
// available in headers, now check whether it is available now
// (during run-time)
if ( wxApp::GetComCtl32Version() >= 471 )
{
// set the (underlying) separators width to be that of the
// control
TBBUTTONINFO tbbi;
tbbi.cbSize = sizeof(tbbi);
tbbi.dwMask = TBIF_SIZE;
tbbi.cx = (WORD)size.x;
if ( !::SendMessage(GetHwnd(), TB_SETBUTTONINFO,
tool->GetId(), (LPARAM)&tbbi) )
{
// the id is probably invalid?
wxLogLastError(wxT("TB_SETBUTTONINFO"));
}
}
else
#endif // comctl32.dll 4.71
// TB_SETBUTTONINFO unavailable
{
// try adding several separators to fit the controls width
int widthSep = r.right - r.left;
TBBUTTON tbb;
wxZeroMemory(tbb);
tbb.idCommand = 0;
tbb.fsState = TBSTATE_ENABLED;
tbb.fsStyle = TBSTYLE_SEP;
size_t nSeparators = size.x / widthSep;
for ( size_t nSep = 0; nSep < nSeparators; nSep++ )
{
if ( !::SendMessage(GetHwnd(), TB_INSERTBUTTON,
toolIndex, (LPARAM)&tbb) )
{
wxLogLastError(wxT("TB_INSERTBUTTON"));
}
toolIndex++;
}
// remember the number of separators we used - we'd have to
// delete all of them later
tool->SetSeparatorsCount(nSeparators);
// adjust the controls width to exactly cover the separators
size.x = (nSeparators + 1)*widthSep;
control->SetSize(size.x, wxDefaultCoord);
}
// position the control itself correctly vertically centering it on the // position the control itself correctly vertically centering it on the
// icon area of the toolbar // icon area of the toolbar
int height = r.bottom - r.top - staticTextSize.y; int height = r.bottom - r.top - staticTextSize.y;
@@ -1597,29 +1504,6 @@ wxSize wxToolBar::GetToolSize() const
} }
} }
static
wxToolBarToolBase *GetItemSkippingDummySpacers(const wxToolBarToolsList& tools,
size_t index )
{
wxToolBarToolsList::compatibility_iterator current = tools.GetFirst();
for ( ; current ; current = current->GetNext() )
{
if ( index == 0 )
return current->GetData();
wxToolBarTool *tool = (wxToolBarTool *)current->GetData();
size_t separators = tool->GetSeparatorsCount();
// if it is a normal button, sepcount == 0, so skip 1 item (the button)
// otherwise, skip as many items as the separator count, plus the
// control itself
index -= separators ? separators + 1 : 1;
}
return 0;
}
wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const
{ {
POINT pt; POINT pt;
@@ -1633,18 +1517,7 @@ wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const
// it's a separator or there is no tool at all there // it's a separator or there is no tool at all there
return NULL; return NULL;
// when TB_SETBUTTONINFO is available (both during compile- and run-time),
// we don't use the dummy separators hack
#ifdef TB_SETBUTTONINFO
if ( wxApp::GetComCtl32Version() >= 471 )
{
return m_tools.Item((size_t)index)->GetData(); return m_tools.Item((size_t)index)->GetData();
}
else
#endif // TB_SETBUTTONINFO
{
return GetItemSkippingDummySpacers( m_tools, (size_t) index );
}
} }
void wxToolBar::UpdateSize() void wxToolBar::UpdateSize()
@@ -1920,7 +1793,7 @@ bool wxToolBar::HandlePaint(WXWPARAM wParam, WXLPARAM lParam)
int toolIndex = 0; int toolIndex = 0;
for ( wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst(); for ( wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
node; node;
node = node->GetNext() ) node = node->GetNext(), toolIndex++ )
{ {
wxToolBarTool * const wxToolBarTool * const
tool = static_cast<wxToolBarTool *>(node->GetData()); tool = static_cast<wxToolBarTool *>(node->GetData());
@@ -1930,40 +1803,31 @@ bool wxToolBar::HandlePaint(WXWPARAM wParam, WXLPARAM lParam)
if ( tool->IsControl() || tool->IsStretchableSpace() ) if ( tool->IsControl() || tool->IsStretchableSpace() )
{ {
const size_t numSeps = tool->GetSeparatorsCount(); // for some reason TB_GETITEMRECT returns a rectangle 1 pixel
for ( size_t n = 0; n < numSeps; n++, toolIndex++ ) // shorter than the full window size (at least under Windows 7)
// but we need to erase the full width/height below
RECT rcItem = wxGetTBItemRect(GetHwnd(), toolIndex);
// Skip hidden buttons
if ( ::IsRectEmpty(&rcItem) )
continue;
if ( IsVertical() )
{ {
// for some reason TB_GETITEMRECT returns a rectangle 1 pixel rcItem.left = 0;
// shorter than the full window size (at least under Windows 7) rcItem.right = rectTotal.width;
// but we need to erase the full width/height below
RECT rcItem = wxGetTBItemRect(GetHwnd(), toolIndex);
// Skip hidden buttons
if ( ::IsRectEmpty(&rcItem) )
continue;
if ( IsVertical() )
{
rcItem.left = 0;
rcItem.right = rectTotal.width;
}
else
{
rcItem.bottom = rcItem.top + rectTotal.height / m_maxRows;
}
// Apparently, regions of height < 3 are not taken into account
// in clipping so we need to extend them for this purpose.
if ( rcItem.bottom - rcItem.top > 0 && rcItem.bottom - rcItem.top < 3 )
rcItem.bottom = rcItem.top + 3;
rgnDummySeps.Union(wxRectFromRECT(rcItem));
} }
} else
else {
{ rcItem.bottom = rcItem.top + rectTotal.height / m_maxRows;
// normal tools never correspond to more than one native button }
toolIndex++;
// Apparently, regions of height < 3 are not taken into account
// in clipping so we need to extend them for this purpose.
if ( rcItem.bottom - rcItem.top > 0 && rcItem.bottom - rcItem.top < 3 )
rcItem.bottom = rcItem.top + 3;
rgnDummySeps.Union(wxRectFromRECT(rcItem));
} }
} }