Merge branch 'expose-radiogroup'
Add public functions for navigating in radio button groups. Also introduce wxRadioButtonBase defining wxRadioButton API for all ports. See https://github.com/wxWidgets/wxWidgets/pull/2052
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
// wxRadioButton
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class WXDLLIMPEXP_CORE wxRadioButton: public wxControl
|
||||
class WXDLLIMPEXP_CORE wxRadioButton: public wxRadioButtonBase
|
||||
{
|
||||
public:
|
||||
wxRadioButton() { }
|
||||
@@ -39,8 +39,8 @@ public:
|
||||
const wxString& name = wxASCII_STR(wxRadioButtonNameStr) );
|
||||
|
||||
virtual void SetLabel(const wxString& label) wxOVERRIDE;
|
||||
virtual void SetValue(bool val);
|
||||
virtual bool GetValue() const;
|
||||
virtual void SetValue(bool val) wxOVERRIDE;
|
||||
virtual bool GetValue() const wxOVERRIDE;
|
||||
|
||||
static wxVisualAttributes
|
||||
GetClassDefaultAttributes(wxWindowVariant variant = wxWINDOW_VARIANT_NORMAL);
|
||||
|
@@ -13,7 +13,7 @@
|
||||
// wxRadioButton
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class WXDLLIMPEXP_CORE wxRadioButton: public wxControl
|
||||
class WXDLLIMPEXP_CORE wxRadioButton: public wxRadioButtonBase
|
||||
{
|
||||
public:
|
||||
wxRadioButton() { }
|
||||
|
@@ -11,7 +11,7 @@
|
||||
#ifndef _WX_RADIOBUT_H_
|
||||
#define _WX_RADIOBUT_H_
|
||||
|
||||
class WXDLLIMPEXP_CORE wxRadioButton: public wxControl
|
||||
class WXDLLIMPEXP_CORE wxRadioButton: public wxRadioButtonBase
|
||||
{
|
||||
wxDECLARE_DYNAMIC_CLASS(wxRadioButton);
|
||||
public:
|
||||
|
@@ -13,7 +13,7 @@
|
||||
|
||||
#include "wx/msw/ownerdrawnbutton.h"
|
||||
|
||||
class WXDLLIMPEXP_CORE wxRadioButton : public wxMSWOwnerDrawnButton<wxControl>
|
||||
class WXDLLIMPEXP_CORE wxRadioButton : public wxMSWOwnerDrawnButton<wxRadioButtonBase>
|
||||
{
|
||||
public:
|
||||
// ctors and creation functions
|
||||
@@ -43,8 +43,8 @@ public:
|
||||
const wxString& name = wxASCII_STR(wxRadioButtonNameStr));
|
||||
|
||||
// implement the radio button interface
|
||||
virtual void SetValue(bool value);
|
||||
virtual bool GetValue() const;
|
||||
virtual void SetValue(bool value) wxOVERRIDE;
|
||||
virtual bool GetValue() const wxOVERRIDE;
|
||||
|
||||
// implementation only from now on
|
||||
virtual bool MSWCommand(WXUINT param, WXWORD id) wxOVERRIDE;
|
||||
|
@@ -11,7 +11,7 @@
|
||||
#ifndef _WX_RADIOBUT_H_
|
||||
#define _WX_RADIOBUT_H_
|
||||
|
||||
class WXDLLIMPEXP_CORE wxRadioButton: public wxControl
|
||||
class WXDLLIMPEXP_CORE wxRadioButton: public wxRadioButtonBase
|
||||
{
|
||||
wxDECLARE_DYNAMIC_CLASS(wxRadioButton);
|
||||
|
||||
@@ -35,8 +35,8 @@ public:
|
||||
const wxValidator& validator = wxDefaultValidator,
|
||||
const wxString& name = wxASCII_STR(wxRadioButtonNameStr));
|
||||
|
||||
virtual void SetValue(bool val);
|
||||
virtual bool GetValue() const ;
|
||||
virtual void SetValue(bool val) wxOVERRIDE;
|
||||
virtual bool GetValue() const wxOVERRIDE;
|
||||
|
||||
// implementation
|
||||
|
||||
|
@@ -10,7 +10,7 @@
|
||||
|
||||
class QRadioButton;
|
||||
|
||||
class WXDLLIMPEXP_CORE wxRadioButton : public wxControl
|
||||
class WXDLLIMPEXP_CORE wxRadioButton : public wxRadioButtonBase
|
||||
{
|
||||
public:
|
||||
wxRadioButton();
|
||||
@@ -32,8 +32,8 @@ public:
|
||||
const wxValidator& validator = wxDefaultValidator,
|
||||
const wxString& name = wxASCII_STR(wxRadioButtonNameStr) );
|
||||
|
||||
virtual void SetValue(bool value);
|
||||
virtual bool GetValue() const;
|
||||
virtual void SetValue(bool value) wxOVERRIDE;
|
||||
virtual bool GetValue() const wxOVERRIDE;
|
||||
|
||||
virtual QWidget *GetHandle() const wxOVERRIDE;
|
||||
|
||||
|
@@ -15,23 +15,42 @@
|
||||
|
||||
#if wxUSE_RADIOBTN
|
||||
|
||||
/*
|
||||
There is no wxRadioButtonBase class as wxRadioButton interface is the same
|
||||
as wxCheckBox(Base), but under some platforms wxRadioButton really
|
||||
derives from wxCheckBox and on the others it doesn't.
|
||||
|
||||
The pseudo-declaration of wxRadioButtonBase would look like this:
|
||||
|
||||
class wxRadioButtonBase : public ...
|
||||
{
|
||||
public:
|
||||
virtual void SetValue(bool value);
|
||||
virtual bool GetValue() const;
|
||||
};
|
||||
*/
|
||||
|
||||
#include "wx/control.h"
|
||||
|
||||
class WXDLLIMPEXP_FWD_CORE wxRadioButton;
|
||||
|
||||
// TODO: In wxUniv, wxRadioButton must derive from wxCheckBox as it reuses
|
||||
// much of its code. This should be fixed by refactoring wxCheckBox to allow
|
||||
// this class to reuse its functionality without inheriting from it, but for
|
||||
// now use this hack to allow the existing code to compile.
|
||||
#ifdef __WXUNIVERSAL__
|
||||
#include "wx/checkbox.h"
|
||||
|
||||
typedef wxCheckBox wxRadioButtonBaseBase;
|
||||
#else
|
||||
typedef wxControl wxRadioButtonBaseBase;
|
||||
#endif
|
||||
|
||||
class WXDLLIMPEXP_CORE wxRadioButtonBase : public wxRadioButtonBaseBase
|
||||
{
|
||||
public:
|
||||
wxRadioButtonBase() { }
|
||||
|
||||
// Methods to be implemented by the derived classes:
|
||||
virtual void SetValue(bool value) = 0;
|
||||
virtual bool GetValue() const = 0;
|
||||
|
||||
|
||||
// Methods implemented by this class itself.
|
||||
wxRadioButton* GetFirstInGroup() const;
|
||||
wxRadioButton* GetLastInGroup() const;
|
||||
wxRadioButton* GetPreviousInGroup() const;
|
||||
wxRadioButton* GetNextInGroup() const;
|
||||
|
||||
private:
|
||||
wxDECLARE_NO_COPY_CLASS(wxRadioButtonBase);
|
||||
};
|
||||
|
||||
extern WXDLLIMPEXP_DATA_CORE(const char) wxRadioButtonNameStr[];
|
||||
|
||||
#if defined(__WXUNIVERSAL__)
|
||||
|
@@ -11,13 +11,11 @@
|
||||
#ifndef _WX_UNIV_RADIOBUT_H_
|
||||
#define _WX_UNIV_RADIOBUT_H_
|
||||
|
||||
#include "wx/checkbox.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxRadioButton
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class WXDLLIMPEXP_CORE wxRadioButton : public wxCheckBox
|
||||
class WXDLLIMPEXP_CORE wxRadioButton : public wxRadioButtonBase
|
||||
{
|
||||
public:
|
||||
// constructors
|
||||
@@ -46,6 +44,10 @@ public:
|
||||
const wxValidator& validator = wxDefaultValidator,
|
||||
const wxString& name = wxASCII_STR(wxRadioButtonNameStr));
|
||||
|
||||
// (re)implement pure virtuals from wxRadioButtonBase
|
||||
virtual void SetValue(bool value) wxOVERRIDE { return wxCheckBox::SetValue(value); }
|
||||
virtual bool GetValue() const wxOVERRIDE { return wxCheckBox::GetValue(); }
|
||||
|
||||
// override some base class methods
|
||||
virtual void ChangeValue(bool value) wxOVERRIDE;
|
||||
|
||||
|
@@ -12,18 +12,28 @@
|
||||
mutually exclusive options. It has a text label next to a (usually) round
|
||||
button.
|
||||
|
||||
You can create a group of mutually-exclusive radio buttons by specifying
|
||||
@c wxRB_GROUP for the first in the group. The group ends when another
|
||||
radio button group is created, or there are no more radio buttons.
|
||||
Radio buttons are typically used in groups of mutually-exclusive buttons,
|
||||
i.e. exactly one of the buttons in the group is checked, and the other ones
|
||||
are unchecked automatically. Such groups are created implicitly, but can
|
||||
also be started explicitly by using @c wxRB_GROUP style: a button with this
|
||||
style starts a new group and will become the initial selection in this
|
||||
group. Alternatively, a radio button may be excluded from the group that it
|
||||
would otherwise belong to by using @c wxRB_SINGLE style.
|
||||
|
||||
To find the other elements of the same radio button group, you can use
|
||||
GetFirstInGroup(), GetPreviousInGroup(), GetNextInGroup() and
|
||||
GetLastInGroup() functions.
|
||||
|
||||
|
||||
@beginStyleTable
|
||||
@style{wxRB_GROUP}
|
||||
Marks the beginning of a new group of radio buttons.
|
||||
@style{wxRB_SINGLE}
|
||||
In some circumstances, radio buttons that are not consecutive
|
||||
siblings trigger a hang bug in Windows (only). If this happens, add
|
||||
this style to mark the button as not belonging to a group, and
|
||||
implement the mutually-exclusive group behaviour yourself.
|
||||
Creates a radio button which is not part of any radio button group.
|
||||
When this style is used, no other radio buttons will be turned off
|
||||
automatically when this button is turned on and such behaviour will
|
||||
need to be implemented manually, in the event handler for this
|
||||
button.
|
||||
@endStyleTable
|
||||
|
||||
@beginEventEmissionTable{wxCommandEvent}
|
||||
@@ -119,5 +129,64 @@ public:
|
||||
@true to check, @false to uncheck.
|
||||
*/
|
||||
virtual void SetValue(bool value);
|
||||
|
||||
/**
|
||||
Returns the first button of the radio button group this button belongs
|
||||
to.
|
||||
|
||||
For a radio button with @c wxRB_SINGLE style, this function returns this
|
||||
button itself, as it is the only member of its group. Otherwise, the
|
||||
function returns the closest previous radio button with @c wxRB_GROUP
|
||||
style (which could still be this button itself) or the first radio
|
||||
button in the same window.
|
||||
|
||||
The returned value is never @NULL.
|
||||
|
||||
@see GetPreviousInGroup(), GetNextInGroup(), GetLastInGroup()
|
||||
|
||||
@since 3.1.5
|
||||
*/
|
||||
wxRadioButton* GetFirstInGroup() const;
|
||||
|
||||
/**
|
||||
Returns the last button of the radio button group this button belongs
|
||||
to.
|
||||
|
||||
Similarly to GetFirstInGroup(), this function returns this button
|
||||
itself if it has @c wxRB_SINGLE style. Otherwise, the function returns
|
||||
the last button before the next button with @c wxRB_GROUP style or the
|
||||
last radio button in the same window.
|
||||
|
||||
The returned value is never @NULL.
|
||||
|
||||
@see GetPreviousInGroup(), GetNextInGroup()
|
||||
|
||||
@since 3.1.5
|
||||
*/
|
||||
wxRadioButton* GetLastInGroup() const;
|
||||
|
||||
/**
|
||||
Returns the previous radio button in the same group.
|
||||
|
||||
The return value is @NULL if there is no predecessor or if this button
|
||||
has @c wxRB_SINGLE style.
|
||||
|
||||
@see GetFirstInGroup(), GetNextInGroup(), GetLastInGroup()
|
||||
|
||||
@since 3.1.5
|
||||
*/
|
||||
wxRadioButton* GetPreviousInGroup() const;
|
||||
|
||||
/**
|
||||
Returns the next radio button in the same group.
|
||||
|
||||
The return value is @NULL if there is no successor or if this button
|
||||
has @c wxRB_SINGLE style.
|
||||
|
||||
@see GetFirstInGroup(), GetPreviousInGroup(), GetLastInGroup()
|
||||
|
||||
@since 3.1.5
|
||||
*/
|
||||
wxRadioButton* GetNextInGroup() const;
|
||||
};
|
||||
|
||||
|
@@ -234,101 +234,19 @@ void wxControlContainer::SetLastFocus(wxWindow *win)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// The following four functions are used to find other radio buttons
|
||||
// within the same group. Used by wxSetFocusToChild
|
||||
// The following functions is used by wxSetFocusToChild()
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#if wxUSE_RADIOBTN
|
||||
#if defined(USE_RADIOBTN_NAV)
|
||||
|
||||
wxRadioButton* wxGetPreviousButtonInGroup(wxRadioButton *btn)
|
||||
namespace
|
||||
{
|
||||
if ( btn->HasFlag(wxRB_GROUP) || btn->HasFlag(wxRB_SINGLE) )
|
||||
return NULL;
|
||||
|
||||
const wxWindowList& siblings = btn->GetParent()->GetChildren();
|
||||
wxWindowList::compatibility_iterator nodeThis = siblings.Find(btn);
|
||||
wxCHECK_MSG( nodeThis, NULL, wxT("radio button not a child of its parent?") );
|
||||
|
||||
// Iterate over all previous siblings until we find the next radio button
|
||||
wxWindowList::compatibility_iterator nodeBefore = nodeThis->GetPrevious();
|
||||
wxRadioButton *prevBtn = 0;
|
||||
while (nodeBefore)
|
||||
{
|
||||
prevBtn = wxDynamicCast(nodeBefore->GetData(), wxRadioButton);
|
||||
if (prevBtn)
|
||||
break;
|
||||
|
||||
nodeBefore = nodeBefore->GetPrevious();
|
||||
}
|
||||
|
||||
if (!prevBtn || prevBtn->HasFlag(wxRB_SINGLE))
|
||||
{
|
||||
// no more buttons in group
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return prevBtn;
|
||||
}
|
||||
|
||||
wxRadioButton* wxGetNextButtonInGroup(wxRadioButton *btn)
|
||||
{
|
||||
if (btn->HasFlag(wxRB_SINGLE))
|
||||
return NULL;
|
||||
|
||||
const wxWindowList& siblings = btn->GetParent()->GetChildren();
|
||||
wxWindowList::compatibility_iterator nodeThis = siblings.Find(btn);
|
||||
wxCHECK_MSG( nodeThis, NULL, wxT("radio button not a child of its parent?") );
|
||||
|
||||
// Iterate over all previous siblings until we find the next radio button
|
||||
wxWindowList::compatibility_iterator nodeNext = nodeThis->GetNext();
|
||||
wxRadioButton *nextBtn = 0;
|
||||
while (nodeNext)
|
||||
{
|
||||
nextBtn = wxDynamicCast(nodeNext->GetData(), wxRadioButton);
|
||||
if (nextBtn)
|
||||
break;
|
||||
|
||||
nodeNext = nodeNext->GetNext();
|
||||
}
|
||||
|
||||
if ( !nextBtn || nextBtn->HasFlag(wxRB_GROUP) || nextBtn->HasFlag(wxRB_SINGLE) )
|
||||
{
|
||||
// no more buttons or the first button of the next group
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return nextBtn;
|
||||
}
|
||||
|
||||
wxRadioButton* wxGetFirstButtonInGroup(wxRadioButton *btn)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
wxRadioButton* prevBtn = wxGetPreviousButtonInGroup(btn);
|
||||
if (!prevBtn)
|
||||
return btn;
|
||||
|
||||
btn = prevBtn;
|
||||
}
|
||||
}
|
||||
|
||||
wxRadioButton* wxGetLastButtonInGroup(wxRadioButton *btn)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
wxRadioButton* nextBtn = wxGetNextButtonInGroup(btn);
|
||||
if (!nextBtn)
|
||||
return btn;
|
||||
|
||||
btn = nextBtn;
|
||||
}
|
||||
}
|
||||
|
||||
wxRadioButton* wxGetSelectedButtonInGroup(wxRadioButton *btn)
|
||||
wxRadioButton* wxGetSelectedButtonInGroup(const wxRadioButton *btn)
|
||||
{
|
||||
// Find currently selected button
|
||||
if (btn->GetValue())
|
||||
return btn;
|
||||
return const_cast<wxRadioButton*>(btn);
|
||||
|
||||
if (btn->HasFlag(wxRB_SINGLE))
|
||||
return NULL;
|
||||
@@ -336,19 +254,21 @@ wxRadioButton* wxGetSelectedButtonInGroup(wxRadioButton *btn)
|
||||
wxRadioButton *selBtn;
|
||||
|
||||
// First check all previous buttons
|
||||
for (selBtn = wxGetPreviousButtonInGroup(btn); selBtn; selBtn = wxGetPreviousButtonInGroup(selBtn))
|
||||
for (selBtn = btn->GetPreviousInGroup(); selBtn; selBtn = selBtn->GetPreviousInGroup())
|
||||
if (selBtn->GetValue())
|
||||
return selBtn;
|
||||
|
||||
// Now all following buttons
|
||||
for (selBtn = wxGetNextButtonInGroup(btn); selBtn; selBtn = wxGetNextButtonInGroup(selBtn))
|
||||
for (selBtn = btn->GetNextInGroup(); selBtn; selBtn = selBtn->GetNextInGroup())
|
||||
if (selBtn->GetValue())
|
||||
return selBtn;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif // wxUSE_RADIOBTN
|
||||
} // anonymous namespace
|
||||
|
||||
#endif // USE_RADIOBTN_NAV
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Keyboard handling - this is the place where the TAB traversal logic is
|
||||
@@ -468,7 +388,7 @@ void wxControlContainer::HandleOnNavigationKey( wxNavigationKeyEvent& event )
|
||||
// If we are in a radio button group, start from the first item in the
|
||||
// group
|
||||
if ( event.IsFromTab() && wxIsKindOf(winFocus, wxRadioButton ) )
|
||||
winFocus = wxGetFirstButtonInGroup((wxRadioButton*)winFocus);
|
||||
winFocus = static_cast<wxRadioButton*>(winFocus)->GetFirstInGroup();
|
||||
#endif // USE_RADIOBTN_NAV
|
||||
// ok, we found the focus - now is it our child?
|
||||
start_node = children.Find( winFocus );
|
||||
@@ -586,20 +506,20 @@ void wxControlContainer::HandleOnNavigationKey( wxNavigationKeyEvent& event )
|
||||
// find the correct radio button to focus
|
||||
if ( forward )
|
||||
{
|
||||
child = wxGetNextButtonInGroup(lastBtn);
|
||||
child = lastBtn->GetNextInGroup();
|
||||
if ( !child )
|
||||
{
|
||||
// no next button in group, set it to the first button
|
||||
child = wxGetFirstButtonInGroup(lastBtn);
|
||||
child = lastBtn->GetFirstInGroup();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
child = wxGetPreviousButtonInGroup(lastBtn);
|
||||
child = lastBtn->GetPreviousInGroup();
|
||||
if ( !child )
|
||||
{
|
||||
// no previous button in group, set it to the last button
|
||||
child = wxGetLastButtonInGroup(lastBtn);
|
||||
child = lastBtn->GetLastInGroup();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -92,4 +92,96 @@ wxCONSTRUCTOR_6( wxRadioButton, wxWindow*, Parent, wxWindowID, Id, \
|
||||
wxString, Label, wxPoint, Position, wxSize, Size, long, WindowStyle )
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxRadioButton group navigation
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
wxRadioButton* wxRadioButtonBase::GetFirstInGroup() const
|
||||
{
|
||||
wxRadioButton*
|
||||
btn = static_cast<wxRadioButton*>(const_cast<wxRadioButtonBase*>(this));
|
||||
while (true)
|
||||
{
|
||||
wxRadioButton* prevBtn = btn->GetPreviousInGroup();
|
||||
if (!prevBtn)
|
||||
return btn;
|
||||
|
||||
btn = prevBtn;
|
||||
}
|
||||
}
|
||||
|
||||
wxRadioButton* wxRadioButtonBase::GetLastInGroup() const
|
||||
{
|
||||
wxRadioButton*
|
||||
btn = static_cast<wxRadioButton*>(const_cast<wxRadioButtonBase*>(this));
|
||||
while (true)
|
||||
{
|
||||
wxRadioButton* nextBtn = btn->GetNextInGroup();
|
||||
if (!nextBtn)
|
||||
return btn;
|
||||
|
||||
btn = nextBtn;
|
||||
}
|
||||
}
|
||||
|
||||
wxRadioButton* wxRadioButtonBase::GetPreviousInGroup() const
|
||||
{
|
||||
if ( HasFlag(wxRB_GROUP) || HasFlag(wxRB_SINGLE) )
|
||||
return NULL;
|
||||
|
||||
const wxWindowList& siblings = GetParent()->GetChildren();
|
||||
wxWindowList::compatibility_iterator nodeThis = siblings.Find(this);
|
||||
wxCHECK_MSG( nodeThis, NULL, wxT("radio button not a child of its parent?") );
|
||||
|
||||
// Iterate over all previous siblings until we find the next radio button
|
||||
wxWindowList::compatibility_iterator nodeBefore = nodeThis->GetPrevious();
|
||||
wxRadioButton *prevBtn = 0;
|
||||
while (nodeBefore)
|
||||
{
|
||||
prevBtn = wxDynamicCast(nodeBefore->GetData(), wxRadioButton);
|
||||
if (prevBtn)
|
||||
break;
|
||||
|
||||
nodeBefore = nodeBefore->GetPrevious();
|
||||
}
|
||||
|
||||
if (!prevBtn || prevBtn->HasFlag(wxRB_SINGLE))
|
||||
{
|
||||
// no more buttons in group
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return prevBtn;
|
||||
}
|
||||
|
||||
wxRadioButton* wxRadioButtonBase::GetNextInGroup() const
|
||||
{
|
||||
if ( HasFlag(wxRB_SINGLE) )
|
||||
return NULL;
|
||||
|
||||
const wxWindowList& siblings = GetParent()->GetChildren();
|
||||
wxWindowList::compatibility_iterator nodeThis = siblings.Find(this);
|
||||
wxCHECK_MSG( nodeThis, NULL, wxT("radio button not a child of its parent?") );
|
||||
|
||||
// Iterate over all previous siblings until we find the next radio button
|
||||
wxWindowList::compatibility_iterator nodeNext = nodeThis->GetNext();
|
||||
wxRadioButton *nextBtn = 0;
|
||||
while (nodeNext)
|
||||
{
|
||||
nextBtn = wxDynamicCast(nodeNext->GetData(), wxRadioButton);
|
||||
if (nextBtn)
|
||||
break;
|
||||
|
||||
nodeNext = nodeNext->GetNext();
|
||||
}
|
||||
|
||||
if ( !nextBtn || nextBtn->HasFlag(wxRB_GROUP) || nextBtn->HasFlag(wxRB_SINGLE) )
|
||||
{
|
||||
// no more buttons or the first button of the next group
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return nextBtn;
|
||||
}
|
||||
|
||||
#endif // wxUSE_RADIOBTN
|
||||
|
@@ -27,40 +27,19 @@
|
||||
#include "testableframe.h"
|
||||
#include "testwindow.h"
|
||||
|
||||
class RadioButtonTestCase : public CppUnit::TestCase
|
||||
class RadioButtonTestCase
|
||||
{
|
||||
public:
|
||||
RadioButtonTestCase() { }
|
||||
|
||||
void setUp() wxOVERRIDE;
|
||||
void tearDown() wxOVERRIDE;
|
||||
|
||||
private:
|
||||
CPPUNIT_TEST_SUITE( RadioButtonTestCase );
|
||||
WXUISIM_TEST( Click );
|
||||
CPPUNIT_TEST( Value );
|
||||
CPPUNIT_TEST( Group );
|
||||
CPPUNIT_TEST( Single );
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
void Click();
|
||||
void Value();
|
||||
void Group();
|
||||
void Single();
|
||||
RadioButtonTestCase();
|
||||
~RadioButtonTestCase();
|
||||
|
||||
protected:
|
||||
wxRadioButton* m_radio;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(RadioButtonTestCase);
|
||||
};
|
||||
|
||||
// register in the unnamed registry so that these tests are run by default
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION( RadioButtonTestCase );
|
||||
|
||||
// also include in its own registry so that these tests can be run alone
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( RadioButtonTestCase,
|
||||
"RadioButtonTestCase" );
|
||||
|
||||
void RadioButtonTestCase::setUp()
|
||||
RadioButtonTestCase::RadioButtonTestCase()
|
||||
{
|
||||
m_radio = new wxRadioButton(wxTheApp->GetTopWindow(), wxID_ANY,
|
||||
"wxRadioButton");
|
||||
@@ -68,12 +47,12 @@ void RadioButtonTestCase::setUp()
|
||||
m_radio->Refresh();
|
||||
}
|
||||
|
||||
void RadioButtonTestCase::tearDown()
|
||||
RadioButtonTestCase::~RadioButtonTestCase()
|
||||
{
|
||||
wxDELETE(m_radio);
|
||||
delete m_radio;
|
||||
}
|
||||
|
||||
void RadioButtonTestCase::Click()
|
||||
TEST_CASE_METHOD(RadioButtonTestCase, "RadioButton::Click", "[radiobutton]")
|
||||
{
|
||||
// OS X doesn't support selecting a single radio button
|
||||
#if wxUSE_UIACTIONSIMULATOR && !defined(__WXOSX__)
|
||||
@@ -87,87 +66,115 @@ void RadioButtonTestCase::Click()
|
||||
|
||||
wxYield();
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL( 1, selected.GetCount() );
|
||||
CHECK(selected.GetCount() == 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void RadioButtonTestCase::Value()
|
||||
TEST_CASE_METHOD(RadioButtonTestCase, "RadioButton::Value", "[radiobutton]")
|
||||
{
|
||||
#ifndef __WXGTK__
|
||||
EventCounter selected(m_radio, wxEVT_RADIOBUTTON);
|
||||
|
||||
m_radio->SetValue(true);
|
||||
|
||||
CPPUNIT_ASSERT(m_radio->GetValue());
|
||||
CHECK(m_radio->GetValue());
|
||||
|
||||
m_radio->SetValue(false);
|
||||
|
||||
CPPUNIT_ASSERT(!m_radio->GetValue());
|
||||
CHECK(!m_radio->GetValue());
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(0, selected.GetCount());
|
||||
CHECK(selected.GetCount() == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void RadioButtonTestCase::Group()
|
||||
TEST_CASE_METHOD(RadioButtonTestCase, "RadioButton::Group", "[radiobutton]")
|
||||
{
|
||||
wxWindow* const parent = wxTheApp->GetTopWindow();
|
||||
|
||||
// Create two different radio groups.
|
||||
wxRadioButton* g1radio0 = new wxRadioButton(parent, wxID_ANY, "radio 1.0",
|
||||
wxScopedPtr<wxRadioButton> g1radio0(new wxRadioButton(parent, wxID_ANY, "radio 1.0",
|
||||
wxDefaultPosition, wxDefaultSize,
|
||||
wxRB_GROUP);
|
||||
wxRB_GROUP));
|
||||
|
||||
wxRadioButton* g1radio1 = new wxRadioButton(parent, wxID_ANY, "radio 1.1");
|
||||
wxScopedPtr<wxRadioButton> g1radio1(new wxRadioButton(parent, wxID_ANY, "radio 1.1"));
|
||||
|
||||
wxRadioButton* g2radio0 = new wxRadioButton(parent, wxID_ANY, "radio 2.0",
|
||||
wxScopedPtr<wxRadioButton> g2radio0(new wxRadioButton(parent, wxID_ANY, "radio 2.0",
|
||||
wxDefaultPosition, wxDefaultSize,
|
||||
wxRB_GROUP);
|
||||
wxRB_GROUP));
|
||||
|
||||
wxRadioButton* g2radio1 = new wxRadioButton(parent, wxID_ANY, "radio 2.1");
|
||||
wxScopedPtr<wxRadioButton> g2radio1(new wxRadioButton(parent, wxID_ANY, "radio 2.1"));
|
||||
|
||||
// Check that having another control between radio buttons doesn't break
|
||||
// grouping.
|
||||
wxStaticText* text = new wxStaticText(parent, wxID_ANY, "Label");
|
||||
wxRadioButton* g2radio2 = new wxRadioButton(parent, wxID_ANY, "radio 2.1");
|
||||
wxScopedPtr<wxStaticText> text(new wxStaticText(parent, wxID_ANY, "Label"));
|
||||
wxScopedPtr<wxRadioButton> g2radio2(new wxRadioButton(parent, wxID_ANY, "radio 2.2"));
|
||||
|
||||
g1radio0->SetValue(true);
|
||||
g2radio0->SetValue(true);
|
||||
|
||||
CPPUNIT_ASSERT(g1radio0->GetValue());
|
||||
CPPUNIT_ASSERT(!g1radio1->GetValue());
|
||||
CPPUNIT_ASSERT(g2radio0->GetValue());
|
||||
CPPUNIT_ASSERT(!g2radio1->GetValue());
|
||||
CHECK(g1radio0->GetValue());
|
||||
CHECK(!g1radio1->GetValue());
|
||||
CHECK(g2radio0->GetValue());
|
||||
CHECK(!g2radio1->GetValue());
|
||||
|
||||
g1radio1->SetValue(true);
|
||||
g2radio1->SetValue(true);
|
||||
|
||||
CPPUNIT_ASSERT(!g1radio0->GetValue());
|
||||
CPPUNIT_ASSERT(g1radio1->GetValue());
|
||||
CPPUNIT_ASSERT(!g2radio0->GetValue());
|
||||
CPPUNIT_ASSERT(g2radio1->GetValue());
|
||||
CHECK(!g1radio0->GetValue());
|
||||
CHECK(g1radio1->GetValue());
|
||||
CHECK(!g2radio0->GetValue());
|
||||
CHECK(g2radio1->GetValue());
|
||||
|
||||
g2radio2->SetValue(true);
|
||||
CPPUNIT_ASSERT(!g2radio0->GetValue());
|
||||
CPPUNIT_ASSERT(!g2radio1->GetValue());
|
||||
CPPUNIT_ASSERT(g2radio2->GetValue());
|
||||
CHECK(!g2radio0->GetValue());
|
||||
CHECK(!g2radio1->GetValue());
|
||||
CHECK(g2radio2->GetValue());
|
||||
|
||||
g1radio0->SetValue(true);
|
||||
g2radio0->SetValue(true);
|
||||
|
||||
CPPUNIT_ASSERT(g1radio0->GetValue());
|
||||
CPPUNIT_ASSERT(!g1radio1->GetValue());
|
||||
CPPUNIT_ASSERT(g2radio0->GetValue());
|
||||
CPPUNIT_ASSERT(!g2radio1->GetValue());
|
||||
CHECK(g1radio0->GetValue());
|
||||
CHECK(!g1radio1->GetValue());
|
||||
CHECK(g2radio0->GetValue());
|
||||
CHECK(!g2radio1->GetValue());
|
||||
|
||||
wxDELETE(g1radio0);
|
||||
wxDELETE(g1radio1);
|
||||
wxDELETE(g2radio0);
|
||||
wxDELETE(g2radio1);
|
||||
wxDELETE(g2radio2);
|
||||
wxDELETE(text);
|
||||
|
||||
// Check that group navigation functions behave as expected.
|
||||
|
||||
// GetFirstInGroup()
|
||||
CHECK_SAME_WINDOW(g1radio0->GetFirstInGroup(), g1radio0);
|
||||
CHECK_SAME_WINDOW(g1radio1->GetFirstInGroup(), g1radio0);
|
||||
|
||||
CHECK_SAME_WINDOW(g2radio0->GetFirstInGroup(), g2radio0);
|
||||
CHECK_SAME_WINDOW(g2radio1->GetFirstInGroup(), g2radio0);
|
||||
CHECK_SAME_WINDOW(g2radio2->GetFirstInGroup(), g2radio0);
|
||||
|
||||
// GetLastInGroup()
|
||||
CHECK_SAME_WINDOW(g1radio0->GetLastInGroup(), g1radio1);
|
||||
CHECK_SAME_WINDOW(g1radio1->GetLastInGroup(), g1radio1);
|
||||
|
||||
CHECK_SAME_WINDOW(g2radio0->GetLastInGroup(), g2radio2);
|
||||
CHECK_SAME_WINDOW(g2radio1->GetLastInGroup(), g2radio2);
|
||||
CHECK_SAME_WINDOW(g2radio2->GetLastInGroup(), g2radio2);
|
||||
|
||||
// GetNextInGroup()
|
||||
CHECK_SAME_WINDOW(g1radio0->GetNextInGroup(), g1radio1);
|
||||
CHECK_SAME_WINDOW(g1radio1->GetNextInGroup(), NULL);
|
||||
|
||||
CHECK_SAME_WINDOW(g2radio0->GetNextInGroup(), g2radio1);
|
||||
CHECK_SAME_WINDOW(g2radio1->GetNextInGroup(), g2radio2);
|
||||
CHECK_SAME_WINDOW(g2radio2->GetNextInGroup(), NULL);
|
||||
|
||||
// GetPreviousInGroup()
|
||||
CHECK_SAME_WINDOW(g1radio0->GetPreviousInGroup(), NULL);
|
||||
CHECK_SAME_WINDOW(g1radio1->GetPreviousInGroup(), g1radio0);
|
||||
|
||||
CHECK_SAME_WINDOW(g2radio0->GetPreviousInGroup(), NULL);
|
||||
CHECK_SAME_WINDOW(g2radio1->GetPreviousInGroup(), g2radio0);
|
||||
CHECK_SAME_WINDOW(g2radio2->GetPreviousInGroup(), g2radio1);
|
||||
}
|
||||
|
||||
void RadioButtonTestCase::Single()
|
||||
TEST_CASE_METHOD(RadioButtonTestCase, "RadioButton::Single", "[radiobutton]")
|
||||
{
|
||||
//Create a group of 2 buttons, having second button selected
|
||||
wxScopedPtr<wxRadioButton> gradio0(new wxRadioButton(wxTheApp->GetTopWindow(),
|
||||
@@ -197,9 +204,15 @@ void RadioButtonTestCase::Single()
|
||||
|
||||
CHECK(gradio1->GetValue());
|
||||
CHECK(ngradio->GetValue());
|
||||
|
||||
// Also check that navigation works as expected with "single" buttons.
|
||||
CHECK_SAME_WINDOW(sradio->GetFirstInGroup(), sradio);
|
||||
CHECK_SAME_WINDOW(sradio->GetLastInGroup(), sradio);
|
||||
CHECK_SAME_WINDOW(sradio->GetPreviousInGroup(), NULL);
|
||||
CHECK_SAME_WINDOW(sradio->GetNextInGroup(), NULL);
|
||||
}
|
||||
|
||||
TEST_CASE("wxRadioButton::Focus", "[radiobutton][focus]")
|
||||
TEST_CASE("RadioButton::Focus", "[radiobutton][focus]")
|
||||
{
|
||||
// Create a container panel just to be able to destroy all the windows
|
||||
// created here at once by simply destroying it.
|
||||
|
@@ -9,6 +9,7 @@
|
||||
#ifndef _WX_TESTS_TESTWINDOW_H_
|
||||
#define _WX_TESTS_TESTWINDOW_H_
|
||||
|
||||
#include "wx/scopedptr.h"
|
||||
#include "wx/window.h"
|
||||
|
||||
// We need to wrap wxWindow* in a class as specializing StringMaker for
|
||||
@@ -17,6 +18,8 @@ class wxWindowPtr
|
||||
{
|
||||
public:
|
||||
explicit wxWindowPtr(wxWindow* win) : m_win(win) {}
|
||||
template <typename W>
|
||||
explicit wxWindowPtr(const wxScopedPtr<W>& win) : m_win(win.get()) {}
|
||||
|
||||
wxString Dump() const
|
||||
{
|
||||
@@ -44,7 +47,9 @@ private:
|
||||
|
||||
// Macro providing more information about the current focus if comparison
|
||||
// fails.
|
||||
#define CHECK_FOCUS_IS(w) CHECK(wxWindowPtr(wxWindow::FindFocus()) == wxWindowPtr(w))
|
||||
#define CHECK_SAME_WINDOW(w1, w2) CHECK(wxWindowPtr(w1) == wxWindowPtr(w2))
|
||||
|
||||
#define CHECK_FOCUS_IS(w) CHECK_SAME_WINDOW(wxWindow::FindFocus(), w)
|
||||
|
||||
namespace Catch
|
||||
{
|
||||
|
Reference in New Issue
Block a user