]> git.saurik.com Git - wxWidgets.git/commitdiff
Improve validation of wxCheckBox styles.
authorVadim Zeitlin <vadim@wxwidgets.org>
Sat, 16 Oct 2010 18:10:42 +0000 (18:10 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sat, 16 Oct 2010 18:10:42 +0000 (18:10 +0000)
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

include/wx/checkbox.h
src/gtk/checkbox.cpp
src/gtk1/checkbox.cpp
src/msw/checkbox.cpp
src/osx/checkbox_osx.cpp
src/univ/checkbox.cpp
tests/controls/checkboxtest.cpp

index 60a8189f24a2a272366f5d5b209bd9b9c2a2af80..342db830cf57130e9e286ec5f3575d8fcfa776a8 100644 (file)
  * 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);
 };
index 52d99fe5698201a1f86a43ed0cf8e3266a8f2d44..5faa27c19bf3850faaca00f232b4efd9109457fa 100644 (file)
@@ -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
index 4bd1fd35aff8c3d21ac3b2898831eef7f11ab68f..c895b7c82cea1e7f4e48fb8a2e3b8556d3051117 100644 (file)
@@ -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
index 3d2e8d80a9d575c23ccd13a14003e3ccbc4dceb2..2a9e8643ef0cf99636b1b8eaf7ea37ddffcd5588 100644 (file)
@@ -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 )
     {
index f248aff651193072420831c28b1dfee617f02049..93cbf2c7bb658c2205200e4a97863ac4309660f8 100644 (file)
@@ -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) ;
index b1f443903f83f4f2e26258fd3d56cc3a41fda5c0..d92d93808eb0804b07c6d0aabeda0ed721baa3ce 100644 (file)
@@ -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;
 
index 1e1ba92cc7d9da017597b498014d9dfb15289e76..359d544d1856f5e45ae7d7320eb6cc10635edf33 100644 (file)
@@ -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