Improve validation of wxCheckBox styles.
Detect when incompatible styles are used (this required changing the value of wxCHK_2STATE to be non-null) and sanitize the styles (after asserting) in this case. Put the validation code in wxCheckBoxBase instead of having slightly different versions of it in port-specific wxCheckBox implementations. Add a unit test checking that the expected asserts are indeed generated. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@65824 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
a9df18b4e4
commit
f254e2424a
@ -25,8 +25,12 @@
|
||||
* Determine whether to use a 3-state or 2-state
|
||||
* checkbox. 3-state enables to differentiate
|
||||
* between 'unchecked', 'checked' and 'undetermined'.
|
||||
*
|
||||
* In addition to the styles here it is also possible to specify just 0 which
|
||||
* is treated the same as wxCHK_2STATE for compatibility (but using explicit
|
||||
* flag is preferred).
|
||||
*/
|
||||
#define wxCHK_2STATE 0x0000
|
||||
#define wxCHK_2STATE 0x4000
|
||||
#define wxCHK_3STATE 0x1000
|
||||
|
||||
/*
|
||||
@ -129,6 +133,47 @@ protected:
|
||||
return wxCHK_UNCHECKED;
|
||||
}
|
||||
|
||||
// Helper function to be called from derived classes Create()
|
||||
// implementations: it checks that the style doesn't contain any
|
||||
// incompatible bits and modifies it to be sane if it does.
|
||||
static void WXValidateStyle(long *stylePtr)
|
||||
{
|
||||
long& style = *stylePtr;
|
||||
|
||||
if ( style == 0 )
|
||||
{
|
||||
// For compatibility we use absence of style flags as wxCHK_2STATE
|
||||
// because wxCHK_2STATE used to have the value of 0 and some
|
||||
// existing code may use 0 instead of it.
|
||||
style = wxCHK_2STATE;
|
||||
}
|
||||
else if ( style & wxCHK_3STATE )
|
||||
{
|
||||
if ( style & wxCHK_2STATE )
|
||||
{
|
||||
wxFAIL_MSG( "wxCHK_2STATE and wxCHK_3STATE can't be used "
|
||||
"together" );
|
||||
style &= ~wxCHK_3STATE;
|
||||
}
|
||||
}
|
||||
else // No wxCHK_3STATE
|
||||
{
|
||||
if ( !(style & wxCHK_2STATE) )
|
||||
{
|
||||
wxFAIL_MSG( "Either wxCHK_2STATE or wxCHK_3STATE must be "
|
||||
"specified" );
|
||||
style |= wxCHK_2STATE;
|
||||
}
|
||||
|
||||
if ( style & wxCHK_ALLOW_3RD_STATE_FOR_USER )
|
||||
{
|
||||
wxFAIL_MSG( "wxCHK_ALLOW_3RD_STATE_FOR_USER doesn't make sense "
|
||||
"without wxCHK_3STATE" );
|
||||
style &= ~wxCHK_ALLOW_3RD_STATE_FOR_USER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
wxDECLARE_NO_COPY_CLASS(wxCheckBoxBase);
|
||||
};
|
||||
|
@ -105,6 +105,7 @@ bool wxCheckBox::Create(wxWindow *parent,
|
||||
const wxValidator& validator,
|
||||
const wxString &name )
|
||||
{
|
||||
WXValidateStyle( &style );
|
||||
if (!PreCreation( parent, pos, size ) ||
|
||||
!CreateBase( parent, id, pos, size, style, validator, name ))
|
||||
{
|
||||
@ -112,11 +113,6 @@ bool wxCheckBox::Create(wxWindow *parent,
|
||||
return false;
|
||||
}
|
||||
|
||||
wxASSERT_MSG( (style & wxCHK_ALLOW_3RD_STATE_FOR_USER) == 0 ||
|
||||
(style & wxCHK_3STATE) != 0,
|
||||
wxT("Using wxCHK_ALLOW_3RD_STATE_FOR_USER")
|
||||
wxT(" style flag for a 2-state checkbox is useless") );
|
||||
|
||||
if ( style & wxALIGN_RIGHT )
|
||||
{
|
||||
// VZ: as I don't know a way to create a right aligned checkbox with
|
||||
|
@ -77,6 +77,7 @@ bool wxCheckBox::Create(wxWindow *parent,
|
||||
m_acceptsFocus = true;
|
||||
m_blockEvent = false;
|
||||
|
||||
WXValidateStyle(&style);
|
||||
if (!PreCreation( parent, pos, size ) ||
|
||||
!CreateBase( parent, id, pos, size, style, validator, name ))
|
||||
{
|
||||
@ -84,11 +85,6 @@ bool wxCheckBox::Create(wxWindow *parent,
|
||||
return false;
|
||||
}
|
||||
|
||||
wxASSERT_MSG( (style & wxCHK_ALLOW_3RD_STATE_FOR_USER) == 0 ||
|
||||
(style & wxCHK_3STATE) != 0,
|
||||
wxT("Using wxCHK_ALLOW_3RD_STATE_FOR_USER")
|
||||
wxT(" style flag for a 2-state checkbox is useless") );
|
||||
|
||||
if ( style & wxALIGN_RIGHT )
|
||||
{
|
||||
// VZ: as I don't know a way to create a right aligned checkbox with
|
||||
|
@ -153,22 +153,16 @@ bool wxCheckBox::Create(wxWindow *parent,
|
||||
{
|
||||
Init();
|
||||
|
||||
WXValidateStyle(&style);
|
||||
if ( !CreateControl(parent, id, pos, size, style, validator, name) )
|
||||
return false;
|
||||
|
||||
long msStyle = WS_TABSTOP;
|
||||
|
||||
if ( style & wxCHK_3STATE )
|
||||
{
|
||||
msStyle |= BS_3STATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
wxASSERT_MSG( !Is3rdStateAllowedForUser(),
|
||||
wxT("Using wxCH_ALLOW_3RD_STATE_FOR_USER")
|
||||
wxT(" style flag for a 2-state checkbox is useless") );
|
||||
msStyle |= BS_CHECKBOX;
|
||||
}
|
||||
|
||||
if ( style & wxALIGN_RIGHT )
|
||||
{
|
||||
|
@ -36,6 +36,7 @@ bool wxCheckBox::Create(wxWindow *parent,
|
||||
|
||||
m_labelOrig = m_label = label ;
|
||||
|
||||
WXValidateStyle( &style );
|
||||
m_peer = wxWidgetImpl::CreateCheckBox( this, parent, id, label, pos, size, style, GetExtraStyle() ) ;
|
||||
|
||||
MacPostControlCreate(pos, size) ;
|
||||
|
@ -80,6 +80,7 @@ bool wxCheckBox::Create(wxWindow *parent,
|
||||
const wxValidator& validator,
|
||||
const wxString &name)
|
||||
{
|
||||
WXValidateStyle( &style );
|
||||
if ( !wxControl::Create(parent, id, pos, size, style, validator, name) )
|
||||
return false;
|
||||
|
||||
|
@ -35,11 +35,26 @@ private:
|
||||
CPPUNIT_TEST( Check );
|
||||
CPPUNIT_TEST( ThirdState );
|
||||
CPPUNIT_TEST( ThirdStateUser );
|
||||
CPPUNIT_TEST( InvalidStyles );
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
void Check();
|
||||
void ThirdState();
|
||||
void ThirdStateUser();
|
||||
void InvalidStyles();
|
||||
|
||||
// Initialize m_check with a new checkbox with the specified style
|
||||
//
|
||||
// This function always returns false just to make it more convenient to
|
||||
// use inside WX_ASSERT_FAILS_WITH_ASSERT(), its return value doesn't have
|
||||
// any meaning otherwise.
|
||||
bool CreateCheckBox(long style)
|
||||
{
|
||||
m_check = new wxCheckBox(wxTheApp->GetTopWindow(), wxID_ANY, "Check box",
|
||||
wxDefaultPosition, wxDefaultSize, style);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
wxCheckBox* m_check;
|
||||
|
||||
@ -96,8 +111,7 @@ void CheckBoxTestCase::ThirdState()
|
||||
{
|
||||
#if !defined(__WXMGL__) && !defined(__WXPM__) && !defined(__WXGTK12__)
|
||||
wxDELETE(m_check);
|
||||
m_check = new wxCheckBox(wxTheApp->GetTopWindow(), wxID_ANY, "Check box",
|
||||
wxDefaultPosition, wxDefaultSize, wxCHK_3STATE);
|
||||
CreateCheckBox(wxCHK_3STATE);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(wxCHK_UNCHECKED, m_check->Get3StateValue());
|
||||
CPPUNIT_ASSERT(m_check->Is3State());
|
||||
@ -117,9 +131,7 @@ void CheckBoxTestCase::ThirdStateUser()
|
||||
{
|
||||
#if !defined(__WXMGL__) && !defined(__WXPM__) && !defined(__WXGTK12__)
|
||||
wxDELETE(m_check);
|
||||
m_check = new wxCheckBox(wxTheApp->GetTopWindow(), wxID_ANY, "Check box",
|
||||
wxDefaultPosition, wxDefaultSize,
|
||||
wxCHK_3STATE | wxCHK_ALLOW_3RD_STATE_FOR_USER);
|
||||
CreateCheckBox(wxCHK_3STATE | wxCHK_ALLOW_3RD_STATE_FOR_USER);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(wxCHK_UNCHECKED, m_check->Get3StateValue());
|
||||
CPPUNIT_ASSERT(m_check->Is3State());
|
||||
@ -135,4 +147,27 @@ void CheckBoxTestCase::ThirdStateUser()
|
||||
#endif
|
||||
}
|
||||
|
||||
void CheckBoxTestCase::InvalidStyles()
|
||||
{
|
||||
// Check that using incompatible styles doesn't work.
|
||||
wxDELETE( m_check );
|
||||
WX_ASSERT_FAILS_WITH_ASSERT( CreateCheckBox(wxCHK_2STATE | wxCHK_3STATE) );
|
||||
#if !wxDEBUG_LEVEL
|
||||
CPPUNIT_ASSERT( !m_check->Is3State() );
|
||||
CPPUNIT_ASSERT( !m_check->Is3rdStateAllowedForUser() );
|
||||
#endif
|
||||
|
||||
wxDELETE( m_check );
|
||||
WX_ASSERT_FAILS_WITH_ASSERT(
|
||||
CreateCheckBox(wxCHK_2STATE | wxCHK_ALLOW_3RD_STATE_FOR_USER) );
|
||||
#if !wxDEBUG_LEVEL
|
||||
CPPUNIT_ASSERT( !m_check->Is3State() );
|
||||
CPPUNIT_ASSERT( !m_check->Is3rdStateAllowedForUser() );
|
||||
#endif
|
||||
|
||||
// wxCHK_ALLOW_3RD_STATE_FOR_USER without wxCHK_3STATE doesn't work.
|
||||
wxDELETE( m_check );
|
||||
WX_ASSERT_FAILS_WITH_ASSERT( CreateCheckBox(wxCHK_ALLOW_3RD_STATE_FOR_USER) );
|
||||
}
|
||||
|
||||
#endif //wxUSE_CHECKBOX
|
||||
|
Loading…
Reference in New Issue
Block a user