Merge branch 'spinctrl-gettextvalue'

Add wxSpinCtrl::GetTextValue() and allow clearing the text value in
wxGTK version for compatibility with MSW.

See https://github.com/wxWidgets/wxWidgets/pull/2334
This commit is contained in:
Vadim Zeitlin
2021-04-22 23:55:30 +02:00
15 changed files with 467 additions and 167 deletions

View File

@@ -60,6 +60,7 @@ public:
virtual ~wxSpinCtrlGenericBase();
// accessors
virtual wxString GetTextValue() const wxOVERRIDE;
// T GetValue() const
// T GetMin() const
// T GetMax() const

View File

@@ -35,6 +35,7 @@ public:
// wxSpinCtrl(Double) methods call DoXXX functions of the same name
// accessors
virtual wxString GetTextValue() const wxOVERRIDE;
// T GetValue() const
// T GetMin() const
// T GetMax() const
@@ -57,7 +58,26 @@ public:
// implementation
void OnChar( wxKeyEvent &event );
// These values map to the possible return values of "input" GTK signal but
// are more readable and type-safe.
enum GTKInputResult
{
GTKInput_Error = -1,
GTKInput_Default,
GTKInput_Converted
};
virtual GTKInputResult GTKInput(double* value) const = 0;
virtual bool GTKOutput(wxString* text) const = 0;
virtual void GTKValueChanged() = 0;
void GTKTextChanged();
protected:
wxSpinCtrlGTKBase();
~wxSpinCtrlGTKBase();
double DoGetValue() const;
double DoGetMin() const;
double DoGetMax() const;
@@ -82,6 +102,26 @@ protected:
// override this and return true.
virtual bool UseGTKStyleBase() const wxOVERRIDE { return true; }
// Set m_textOverride to use the given text instead of the numeric value.
void GTKSetTextOverride(const wxString& text);
// Reset the override and changing the value to correspond to the
// previously overridden numeric value.
void GTKResetTextOverride();
// Just reset the override, without touching the value, returning true if
// we did it. In most cases, the function above should be used instead.
bool GTKResetTextOverrideOnly();
private:
// This function does _not_ take into account m_textOverride, so it is
// private and normally shouldn't be used -- use DoGetValue() instead.
double GTKGetValue() const;
// Non-null when the text value is different from the numeric value.
class wxSpinCtrlGTKTextOverride* m_textOverride;
friend class wxSpinCtrlEventDisabler;
wxDECLARE_EVENT_TABLE();
@@ -137,6 +177,10 @@ public:
virtual int GetBase() const wxOVERRIDE { return m_base; }
virtual bool SetBase(int base) wxOVERRIDE;
virtual GTKInputResult GTKInput(double* value) const wxOVERRIDE;
virtual bool GTKOutput(wxString* text) const wxOVERRIDE;
virtual void GTKValueChanged() wxOVERRIDE;
protected:
virtual void GtkSetEntryWidth() wxOVERRIDE;
@@ -205,6 +249,10 @@ public:
virtual int GetBase() const wxOVERRIDE { return 10; }
virtual bool SetBase(int WXUNUSED(base)) wxOVERRIDE { return false; }
virtual GTKInputResult GTKInput(double* value) const wxOVERRIDE;
virtual bool GTKOutput(wxString* text) const wxOVERRIDE;
virtual void GTKValueChanged() wxOVERRIDE;
protected:
virtual void GtkSetEntryWidth() wxOVERRIDE;

View File

@@ -48,6 +48,7 @@ public:
void SetValue(const wxString& text);
void SetSelection(long from, long to);
virtual wxString GetTextValue() const;
virtual int GetValue() const;
virtual void SetValue( int value );
virtual void SetRange( int minVal, int maxVal );

View File

@@ -62,6 +62,7 @@ public:
void SetSelection(long from, long to);
// wxSpinCtrlBase methods
virtual wxString GetTextValue() const;
virtual int GetBase() const;
virtual bool SetBase(int base);

View File

@@ -29,6 +29,7 @@ public:
T min, T max, T initial, T inc,
const wxString& name );
virtual wxString GetTextValue() const wxOVERRIDE;
virtual void SetValue(const wxString&) wxOVERRIDE {}
virtual void SetSnapToTicks(bool snap_to_ticks) wxOVERRIDE;

View File

@@ -35,6 +35,7 @@ public:
wxSpinCtrlBase() {}
// accessor functions that derived classes are expected to have
virtual wxString GetTextValue() const = 0;
// T GetValue() const
// T GetMin() const
// T GetMax() const

View File

@@ -133,6 +133,13 @@ public:
*/
int GetMin() const;
/**
Returns the text in the text entry part of the control.
@since 3.1.6
*/
wxString GetTextValue() const;
/**
Gets the value of the spin control.
*/
@@ -190,6 +197,10 @@ public:
Sets the value of the spin control.
It is recommended to use the overload taking an integer value instead.
The behaviour of this function when @a text doesn't represent a valid
number currently differs between the platforms, however passing an
empty string does clear the text part contents, without affecting the
value returned by GetValue(), under all of them.
Notice that, unlike wxTextCtrl::SetValue(), but like most of the other
setter methods in wxWidgets, calling this method does not generate any
@@ -243,6 +254,14 @@ public:
/**
Constructor, creating and showing a spin control.
If @a value is non-empty, it will be shown in the text entry part of
the control and if it has numeric value, the initial numeric value of
the control, as returned by GetValue() will also be determined by it
instead of by @a initial. Hence, it only makes sense to specify @a
initial if @a value is an empty string or is not convertible to a
number, otherwise @a initial is simply ignored and the number specified
by @a value is used.
@param parent
Parent window. Must not be @NULL.
@param value
@@ -315,6 +334,13 @@ public:
*/
double GetMin() const;
/**
Returns the text in the text entry part of the control.
@since 3.1.6
*/
wxString GetTextValue() const;
/**
Gets the value of the spin control.
*/
@@ -342,6 +368,10 @@ public:
Sets the value of the spin control.
It is recommended to use the overload taking a double value instead.
The behaviour of this function when @a text doesn't represent a valid
number currently differs between the platforms, however
passing an empty string does clear the text part contents, without
affecting the value returned by GetValue(), under all of them.
Notice that, unlike wxTextCtrl::SetValue(), but like most of the other
setter methods in wxWidgets, calling this method does not generate any

View File

@@ -483,6 +483,14 @@ void SpinBtnWidgetsPage::OnButtonSetBase(wxCommandEvent& WXUNUSED(event))
void SpinBtnWidgetsPage::OnButtonSetValue(wxCommandEvent& WXUNUSED(event))
{
if ( m_textValue->IsEmpty() )
{
m_spinctrl->SetValue( wxEmptyString );
m_spinctrldbl->SetValue( wxEmptyString );
return;
}
long val;
if ( !m_textValue->GetValue().ToLong(&val) || !IsValidValue(val) )
{
@@ -499,7 +507,8 @@ void SpinBtnWidgetsPage::OnButtonSetValue(wxCommandEvent& WXUNUSED(event))
void SpinBtnWidgetsPage::OnUpdateUIValueButton(wxUpdateUIEvent& event)
{
long val;
event.Enable( m_textValue->GetValue().ToLong(&val) && IsValidValue(val) );
event.Enable( m_textValue->IsEmpty() ||
( m_textValue->GetValue().ToLong(&val) && IsValidValue(val) ) );
}
void SpinBtnWidgetsPage::OnUpdateUIMinMaxButton(wxUpdateUIEvent& event)

View File

@@ -506,6 +506,11 @@ bool wxSpinCtrlGenericBase::SyncSpinToText(SendEvent sendEvent)
// changing value and range
// ----------------------------------------------------------------------------
wxString wxSpinCtrlGenericBase::GetTextValue() const
{
return m_textCtrl ? m_textCtrl->GetValue() : wxString();
}
void wxSpinCtrlGenericBase::SetValue(const wxString& text)
{
wxCHECK_RET( m_textCtrl, wxT("invalid call to wxSpinCtrl::SetValue") );

View File

@@ -37,27 +37,12 @@ extern bool g_blockEventsOnDrag;
extern "C" {
static void
gtk_value_changed(GtkSpinButton* spinbutton, wxSpinCtrlGTKBase* win)
gtk_value_changed(GtkSpinButton*, wxSpinCtrlGTKBase* win)
{
if (g_blockEventsOnDrag)
return;
if (wxIsKindOf(win, wxSpinCtrl))
{
wxSpinEvent event(wxEVT_SPINCTRL, win->GetId());
event.SetEventObject( win );
event.SetPosition(static_cast<wxSpinCtrl*>(win)->GetValue());
event.SetString(gtk_entry_get_text(GTK_ENTRY(spinbutton)));
win->HandleWindowEvent( event );
}
else // wxIsKindOf(win, wxSpinCtrlDouble)
{
wxSpinDoubleEvent event( wxEVT_SPINCTRLDOUBLE, win->GetId());
event.SetEventObject( win );
event.SetValue(static_cast<wxSpinCtrlDouble*>(win)->GetValue());
event.SetString(gtk_entry_get_text(GTK_ENTRY(spinbutton)));
win->HandleWindowEvent( event );
}
win->GTKValueChanged();
}
}
@@ -67,16 +52,53 @@ gtk_value_changed(GtkSpinButton* spinbutton, wxSpinCtrlGTKBase* win)
extern "C" {
static void
gtk_changed(GtkSpinButton* spinbutton, wxSpinCtrl* win)
gtk_changed(GtkSpinButton*, wxSpinCtrl* win)
{
wxCommandEvent event( wxEVT_TEXT, win->GetId() );
event.SetEventObject( win );
event.SetString(gtk_entry_get_text(GTK_ENTRY(spinbutton)));
event.SetInt(win->GetValue());
win->HandleWindowEvent( event );
win->GTKTextChanged();
}
}
//-----------------------------------------------------------------------------
// "input" and "output"
//-----------------------------------------------------------------------------
extern "C"
{
static gint
wx_gtk_spin_input(GtkSpinButton*, gdouble* val, wxSpinCtrlGTKBase* win)
{
switch ( win->GTKInput(val) )
{
case wxSpinCtrl::GTKInput_Error:
return GTK_INPUT_ERROR;
case wxSpinCtrl::GTKInput_Default:
return FALSE;
case wxSpinCtrl::GTKInput_Converted:
return TRUE;
}
wxFAIL_MSG("unreachable");
return FALSE;
}
static gboolean
wx_gtk_spin_output(GtkSpinButton* spin, wxSpinCtrlGTKBase* win)
{
wxString text;
if ( !win->GTKOutput(&text) )
return FALSE;
if ( text != win->GetTextValue() )
gtk_entry_set_text(GTK_ENTRY(spin), text.utf8_str());
return TRUE;
}
} // extern "C"
// ----------------------------------------------------------------------------
// wxSpinCtrlEventDisabler: helper to temporarily disable GTK+ events
// ----------------------------------------------------------------------------
@@ -101,6 +123,22 @@ private:
wxDECLARE_NO_COPY_CLASS(wxSpinCtrlEventDisabler);
};
// ----------------------------------------------------------------------------
// wxSpinCtrlGTKTextOverride: extra data for using a separate string value
// ----------------------------------------------------------------------------
class wxSpinCtrlGTKTextOverride
{
public:
wxSpinCtrlGTKTextOverride()
: m_value(0.0)
{
}
wxString m_text;
double m_value;
};
//-----------------------------------------------------------------------------
// wxSpinCtrlGTKBase
//-----------------------------------------------------------------------------
@@ -109,6 +147,62 @@ wxBEGIN_EVENT_TABLE(wxSpinCtrlGTKBase, wxSpinCtrlBase)
EVT_CHAR(wxSpinCtrlGTKBase::OnChar)
wxEND_EVENT_TABLE()
wxSpinCtrlGTKBase::wxSpinCtrlGTKBase()
: m_textOverride(NULL)
{
}
wxSpinCtrlGTKBase::~wxSpinCtrlGTKBase()
{
delete m_textOverride;
}
void wxSpinCtrlGTKBase::GTKSetTextOverride(const wxString& text)
{
if ( !m_textOverride )
{
// Remember the original numeric value, that we're going to keep using
// it while this override is valid, and do it before initializing
// m_textOverride as our own "input" handler called from GTKGetValue()
// would use it if it were non-null.
const double value = GTKGetValue();
m_textOverride = new wxSpinCtrlGTKTextOverride();
m_textOverride->m_value = value;
}
//else: No need to change the value, it stays the same anyhow.
// Update the text in any case.
m_textOverride->m_text = text;
}
bool wxSpinCtrlGTKBase::GTKResetTextOverrideOnly()
{
if ( !m_textOverride )
return false;
delete m_textOverride;
m_textOverride = NULL;
return true;
}
void wxSpinCtrlGTKBase::GTKResetTextOverride()
{
if ( !GTKResetTextOverrideOnly() )
return;
// Update the text part to reflect the numeric value now that we don't
// override it any longer, otherwise we'd keep showing the old one because
// the text is updated by GTK before "value" is generated.
wxSpinCtrlEventDisabler disable(this);
gtk_spin_button_set_value
(
GTK_SPIN_BUTTON(m_widget),
gtk_spin_button_get_value(GTK_SPIN_BUTTON(m_widget))
);
}
bool wxSpinCtrlGTKBase::Create(wxWindow *parent, wxWindowID id,
const wxString& value,
const wxPoint& pos, const wxSize& size,
@@ -146,6 +240,9 @@ bool wxSpinCtrlGTKBase::Create(wxWindow *parent, wxWindowID id,
g_signal_connect_after(m_widget, "value_changed", G_CALLBACK(gtk_value_changed), this);
g_signal_connect_after(m_widget, "changed", G_CALLBACK(gtk_changed), this);
g_signal_connect(m_widget, "input", G_CALLBACK(wx_gtk_spin_input), this);
g_signal_connect(m_widget, "output", G_CALLBACK(wx_gtk_spin_output), this);
m_parent->DoAddChild( this );
PostCreation(size);
@@ -159,6 +256,15 @@ bool wxSpinCtrlGTKBase::Create(wxWindow *parent, wxWindowID id,
}
double wxSpinCtrlGTKBase::DoGetValue() const
{
// While using a text override, the text value is fixed by the program and
// shouldn't be used, just return the numeric value we had had before, as
// the text override is reset whenever it changes, so it must not have
// changed yet.
return m_textOverride ? m_textOverride->m_value : GTKGetValue();
}
double wxSpinCtrlGTKBase::GTKGetValue() const
{
wxCHECK_MSG( (m_widget != NULL), 0, wxT("invalid spin button") );
@@ -214,6 +320,13 @@ double wxSpinCtrlGTKBase::DoGetIncrement() const
return inc;
}
wxString wxSpinCtrlGTKBase::GetTextValue() const
{
wxCHECK_MSG(m_widget, wxEmptyString, "invalid spin button");
return wxGTK_CONV_BACK(gtk_entry_get_text( GTK_ENTRY(m_widget) ));
}
bool wxSpinCtrlGTKBase::GetSnapToTicks() const
{
wxCHECK_MSG(m_widget, false, "invalid spin button");
@@ -233,7 +346,12 @@ void wxSpinCtrlGTKBase::SetValue( const wxString& value )
return;
}
// invalid number - set text as is (wxMSW compatible)
// invalid number - set text as is (wxMSW compatible) and remember that it
// is set to avoid overwriting it later, which is notably important when
// we're called before the window is realized as the default "realize"
// handler will call our "output" handler
GTKSetTextOverride(value);
wxSpinCtrlEventDisabler disable(this);
gtk_entry_set_text( GTK_ENTRY(m_widget), wxGTK_CONV( value ) );
}
@@ -242,6 +360,8 @@ void wxSpinCtrlGTKBase::DoSetValue( double value )
{
wxCHECK_RET( (m_widget != NULL), wxT("invalid spin button") );
GTKResetTextOverride();
wxSpinCtrlEventDisabler disable(this);
gtk_spin_button_set_value( GTK_SPIN_BUTTON(m_widget), value);
}
@@ -336,9 +456,7 @@ void wxSpinCtrlGTKBase::OnChar( wxKeyEvent &event )
{
wxCommandEvent evt( wxEVT_TEXT_ENTER, m_windowId );
evt.SetEventObject(this);
GtkSpinButton *gsb = GTK_SPIN_BUTTON(m_widget);
wxString val = wxGTK_CONV_BACK( gtk_entry_get_text( &gsb->entry ) );
evt.SetString( val );
evt.SetString(GetTextValue());
if (HandleWindowEvent(evt)) return;
}
@@ -390,46 +508,46 @@ wxSpinCtrlGTKBase::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
return GetDefaultAttributesFromGTKWidget(gtk_spin_button_new_with_range(0, 100, 1), true);
}
wxSpinCtrlGTKBase::GTKInputResult wxSpinCtrlGTKBase::GTKInput(double* value) const
{
if ( m_textOverride )
{
*value = m_textOverride->m_value;
return GTKInput_Converted;
}
return GTKInput_Default;
}
bool wxSpinCtrlGTKBase::GTKOutput(wxString* text) const
{
if ( m_textOverride )
{
*text = m_textOverride->m_text;
return true;
}
return false;
}
void wxSpinCtrlGTKBase::GTKTextChanged()
{
// We can't use GTKResetTextOverride() itself here because it would also
// reset the value and we do not want this to happen -- the value is being
// changed to correspond to the new text.
GTKResetTextOverrideOnly();
wxCommandEvent event( wxEVT_TEXT, GetId() );
event.SetEventObject( this );
event.SetString(GetTextValue());
event.SetInt(static_cast<int>(DoGetValue()));
HandleWindowEvent( event );
}
//-----------------------------------------------------------------------------
// wxSpinCtrl
//-----------------------------------------------------------------------------
extern "C"
{
static gboolean
wx_gtk_spin_input(GtkSpinButton* spin, gdouble* val, wxSpinCtrl* win)
{
// We might use g_ascii_strtoll() here but it's 2.12+ only, so use our own
// wxString function even if this requires an extra conversion.
const wxString
text(wxString::FromUTF8(gtk_entry_get_text(GTK_ENTRY(spin))));
long lval;
if ( !text.ToLong(&lval, win->GetBase()) )
return FALSE;
*val = lval;
return TRUE;
}
static gint
wx_gtk_spin_output(GtkSpinButton* spin, wxSpinCtrl* win)
{
const gint val = gtk_spin_button_get_value_as_int(spin);
gtk_entry_set_text
(
GTK_ENTRY(spin),
wxSpinCtrlImpl::FormatAsHex(val, win->GetMax()).utf8_str()
);
return TRUE;
}
} // extern "C"
void wxSpinCtrl::GtkSetEntryWidth()
{
const int minVal = static_cast<int>(DoGetMin());
@@ -462,23 +580,6 @@ bool wxSpinCtrl::SetBase(int base)
// We need to be able to enter letters for any base greater than 10.
gtk_spin_button_set_numeric( GTK_SPIN_BUTTON(m_widget), m_base <= 10 );
if ( m_base != 10 )
{
g_signal_connect( m_widget, "input",
G_CALLBACK(wx_gtk_spin_input), this);
g_signal_connect( m_widget, "output",
G_CALLBACK(wx_gtk_spin_output), this);
}
else
{
g_signal_handlers_disconnect_by_func(m_widget,
(gpointer)wx_gtk_spin_input,
this);
g_signal_handlers_disconnect_by_func(m_widget,
(gpointer)wx_gtk_spin_output,
this);
}
InvalidateBestSize();
GtkSetEntryWidth();
@@ -489,6 +590,61 @@ bool wxSpinCtrl::SetBase(int base)
return true;
}
wxSpinCtrl::GTKInputResult wxSpinCtrl::GTKInput(double* value) const
{
GTKInputResult res = wxSpinCtrlGTKBase::GTKInput(value);
if ( res != GTKInput_Default )
return res;
// Don't override the default logic unless really needed.
if ( GetBase() == 10 )
return GTKInput_Default;
long lval;
if ( !GetTextValue().ToLong(&lval, GetBase()) )
return GTKInput_Error;
*value = lval;
return GTKInput_Converted;
}
bool wxSpinCtrl::GTKOutput(wxString* text) const
{
if ( wxSpinCtrlGTKBase::GTKOutput(text) )
return true;
switch ( GetBase() )
{
default:
wxFAIL_MSG("unsupported base");
wxFALLTHROUGH;
case 10:
// Don't override the default output format unless really needed.
return false;
case 16:
const gint val = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(m_widget));
*text = wxSpinCtrlImpl::FormatAsHex(val, GetMax());
break;
}
return true;
}
void wxSpinCtrl::GTKValueChanged()
{
GTKResetTextOverride();
wxSpinEvent event(wxEVT_SPINCTRL, GetId());
event.SetEventObject( this );
event.SetPosition(GetValue());
event.SetString(GetTextValue());
HandleWindowEvent( event );
}
//-----------------------------------------------------------------------------
// wxSpinCtrlDouble
//-----------------------------------------------------------------------------
@@ -523,4 +679,28 @@ void wxSpinCtrlDouble::SetDigits(unsigned digits)
GtkSetEntryWidth();
}
wxSpinCtrl::GTKInputResult wxSpinCtrlDouble::GTKInput(double* value) const
{
return wxSpinCtrlGTKBase::GTKInput(value);
}
bool wxSpinCtrlDouble::GTKOutput(wxString* text) const
{
if ( wxSpinCtrlGTKBase::GTKOutput(text) )
return true;
return false;
}
void wxSpinCtrlDouble::GTKValueChanged()
{
GTKResetTextOverride();
wxSpinDoubleEvent event( wxEVT_SPINCTRLDOUBLE, GetId());
event.SetEventObject( this );
event.SetValue(GetValue());
event.SetString(GetTextValue());
HandleWindowEvent( event );
}
#endif // wxUSE_SPINCTRL

View File

@@ -203,6 +203,13 @@ int wxSpinCtrl::GetMax() const
return (int)ceil(m_adjust->upper);
}
wxString wxSpinCtrl::GetTextValue() const
{
wxCHECK_MSG(m_widget, wxEmptyString, "invalid spin button");
return gtk_entry_get_text( GTK_ENTRY(m_widget) );
}
int wxSpinCtrl::GetValue() const
{
wxCHECK_MSG( (m_widget != NULL), 0, wxT("invalid spin button") );

View File

@@ -442,6 +442,11 @@ bool wxSpinCtrl::SetBase(int base)
// wxTextCtrl-like methods
// ----------------------------------------------------------------------------
wxString wxSpinCtrl::GetTextValue() const
{
return wxGetWindowText(m_hwndBuddy);
}
void wxSpinCtrl::SetValue(const wxString& text)
{
if ( !::SetWindowText(GetBuddyHwnd(), text.c_str()) )

View File

@@ -58,6 +58,12 @@ bool wxSpinCtrlQt< T, Widget >::Create( wxWindow *parent, wxWindowID id,
return QtCreateControl( parent, id, pos, size, style, wxDefaultValidator, name );
}
template< typename T, typename Widget >
wxString wxSpinCtrlQt< T, Widget >::GetTextValue() const
{
return wxQtConvertString(m_qtSpinBox->text());
}
template< typename T, typename Widget >
void wxSpinCtrlQt< T, Widget >::SetValue( T val )
{

View File

@@ -19,76 +19,59 @@
#include "wx/uiaction.h"
#include "wx/spinctrl.h"
class SpinCtrlDoubleTestCase : public CppUnit::TestCase
class SpinCtrlDoubleTestCase
{
public:
SpinCtrlDoubleTestCase() { }
SpinCtrlDoubleTestCase(int style = wxSP_ARROW_KEYS)
: m_spin(new wxSpinCtrlDouble(wxTheApp->GetTopWindow(), wxID_ANY, "",
wxDefaultPosition, wxDefaultSize,
style))
{
}
void setUp() wxOVERRIDE;
void tearDown() wxOVERRIDE;
~SpinCtrlDoubleTestCase()
{
delete m_spin;
}
private:
CPPUNIT_TEST_SUITE( SpinCtrlDoubleTestCase );
CPPUNIT_TEST( NoEventsInCtor );
WXUISIM_TEST( Arrows );
WXUISIM_TEST( Wrap );
CPPUNIT_TEST( Range );
CPPUNIT_TEST( Value );
WXUISIM_TEST( Increment );
CPPUNIT_TEST( Digits );
CPPUNIT_TEST_SUITE_END();
void NoEventsInCtor();
void Arrows();
void Wrap();
void Range();
void Value();
void Increment();
void Digits();
wxSpinCtrlDouble* m_spin;
protected:
wxSpinCtrlDouble* const m_spin;
wxDECLARE_NO_COPY_CLASS(SpinCtrlDoubleTestCase);
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( SpinCtrlDoubleTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( SpinCtrlDoubleTestCase, "SpinCtrlDoubleTestCase" );
void SpinCtrlDoubleTestCase::setUp()
class SpinCtrlDoubleTestCaseWrap : public SpinCtrlDoubleTestCase
{
m_spin = new wxSpinCtrlDouble(wxTheApp->GetTopWindow());
}
public:
SpinCtrlDoubleTestCaseWrap()
: SpinCtrlDoubleTestCase(wxSP_ARROW_KEYS | wxSP_WRAP)
{
}
};
void SpinCtrlDoubleTestCase::tearDown()
{
wxDELETE(m_spin);
}
void SpinCtrlDoubleTestCase::NoEventsInCtor()
TEST_CASE("SpinCtrlDouble::NoEventsInCtor", "[spinctrl][spinctrldouble]")
{
// Verify that creating the control does not generate any events. This is
// unexpected and shouldn't happen.
wxWindow* const parent = m_spin->GetParent();
delete m_spin;
m_spin = new wxSpinCtrlDouble;
wxSpinCtrlDouble *m_spin = new wxSpinCtrlDouble;
EventCounter updatedSpin(m_spin, wxEVT_SPINCTRLDOUBLE);
EventCounter updatedText(m_spin, wxEVT_TEXT);
m_spin->Create(parent, wxID_ANY, "",
m_spin->Create(wxTheApp->GetTopWindow(), wxID_ANY, "",
wxDefaultPosition, wxDefaultSize, 0,
0., 100., 17.);
CPPUNIT_ASSERT_EQUAL(0, updatedSpin.GetCount());
CPPUNIT_ASSERT_EQUAL(0, updatedText.GetCount());
CHECK( updatedSpin.GetCount() == 0 );
CHECK( updatedText.GetCount() == 0 );
}
void SpinCtrlDoubleTestCase::Arrows()
{
#if wxUSE_UIACTIONSIMULATOR
TEST_CASE_METHOD(SpinCtrlDoubleTestCase,
"SpinCtrlDouble::Arrows", "[spinctrl][spinctrldouble]")
{
EventCounter updated(m_spin, wxEVT_SPINCTRLDOUBLE);
wxUIActionSimulator sim;
@@ -99,26 +82,20 @@ void SpinCtrlDoubleTestCase::Arrows()
sim.Char(WXK_UP);
wxYield();
CPPUNIT_ASSERT_EQUAL(1, updated.GetCount());
CPPUNIT_ASSERT_EQUAL(1.0, m_spin->GetValue());
CHECK( updated.GetCount() == 1 );
CHECK( m_spin->GetValue() == 1.0 );
updated.Clear();
sim.Char(WXK_DOWN);
wxYield();
CPPUNIT_ASSERT_EQUAL(1, updated.GetCount());
CPPUNIT_ASSERT_EQUAL(0.0, m_spin->GetValue());
#endif
CHECK( updated.GetCount() == 1 );
CHECK( m_spin->GetValue() == 0.0 );
}
void SpinCtrlDoubleTestCase::Wrap()
TEST_CASE_METHOD(SpinCtrlDoubleTestCaseWrap,
"SpinCtrlDouble::Wrap", "[spinctrl][spinctrldouble]")
{
#if wxUSE_UIACTIONSIMULATOR
wxDELETE(m_spin);
m_spin = new wxSpinCtrlDouble(wxTheApp->GetTopWindow(), wxID_ANY, "",
wxDefaultPosition, wxDefaultSize,
wxSP_ARROW_KEYS | wxSP_WRAP);
wxUIActionSimulator sim;
m_spin->SetFocus();
@@ -128,20 +105,21 @@ void SpinCtrlDoubleTestCase::Wrap()
wxYield();
CPPUNIT_ASSERT_EQUAL(100.0, m_spin->GetValue());
CHECK( m_spin->GetValue() == 100.0 );
sim.Char(WXK_UP);
wxYield();
CPPUNIT_ASSERT_EQUAL(0.0, m_spin->GetValue());
#endif
CHECK( m_spin->GetValue() == 0.0 );
}
#endif // wxUSE_UIACTIONSIMULATOR
void SpinCtrlDoubleTestCase::Range()
TEST_CASE_METHOD(SpinCtrlDoubleTestCase,
"SpinCtrlDouble::Range", "[spinctrl][spinctrldouble]")
{
CPPUNIT_ASSERT_EQUAL(0.0, m_spin->GetMin());
CPPUNIT_ASSERT_EQUAL(100.0, m_spin->GetMax());
CHECK( m_spin->GetMin() == 0.0 );
CHECK( m_spin->GetMax() == 100.0 );
// Test that the value is adjusted to be inside the new valid range but
// that this doesn't result in any events (as this is not something done by
@@ -151,26 +129,27 @@ void SpinCtrlDoubleTestCase::Range()
EventCounter updatedText(m_spin, wxEVT_TEXT);
m_spin->SetRange(1., 10.);
CPPUNIT_ASSERT_EQUAL(1., m_spin->GetValue());
CHECK( m_spin->GetValue() == 1. );
CPPUNIT_ASSERT_EQUAL(0, updatedSpin.GetCount());
CPPUNIT_ASSERT_EQUAL(0, updatedText.GetCount());
CHECK( updatedSpin.GetCount() == 0 );
CHECK( updatedText.GetCount() == 0 );
}
//Test negative ranges
m_spin->SetRange(-10.0, 10.0);
CPPUNIT_ASSERT_EQUAL(-10.0, m_spin->GetMin());
CPPUNIT_ASSERT_EQUAL(10.0, m_spin->GetMax());
CHECK( m_spin->GetMin() == -10.0 );
CHECK( m_spin->GetMax() == 10.0 );
//Test backwards ranges
m_spin->SetRange(75.0, 50.0);
CPPUNIT_ASSERT_EQUAL(75.0, m_spin->GetMin());
CPPUNIT_ASSERT_EQUAL(50.0, m_spin->GetMax());
CHECK( m_spin->GetMin() == 75.0 );
CHECK( m_spin->GetMax() == 50.0 );
}
void SpinCtrlDoubleTestCase::Value()
TEST_CASE_METHOD(SpinCtrlDoubleTestCase,
"SpinCtrlDouble::Value", "[spinctrl][spinctrldouble]")
{
EventCounter updatedSpin(m_spin, wxEVT_SPINCTRLDOUBLE);
EventCounter updatedText(m_spin, wxEVT_TEXT);
@@ -178,28 +157,41 @@ void SpinCtrlDoubleTestCase::Value()
m_spin->SetDigits(2);
m_spin->SetIncrement(0.1);
CPPUNIT_ASSERT_EQUAL(0.0, m_spin->GetValue());
CHECK( m_spin->GetValue() == 0.0 );
m_spin->SetValue(50.0);
CPPUNIT_ASSERT_EQUAL(50.0, m_spin->GetValue());
CHECK( m_spin->GetValue() == 50.0 );
m_spin->SetValue(49.1);
CPPUNIT_ASSERT_EQUAL(49.1, m_spin->GetValue());
CHECK( m_spin->GetValue() == 49.1 );
// Calling SetValue() shouldn't have generated any events.
CPPUNIT_ASSERT_EQUAL(0, updatedSpin.GetCount());
CPPUNIT_ASSERT_EQUAL(0, updatedText.GetCount());
CHECK( updatedSpin.GetCount() == 0 );
CHECK( updatedText.GetCount() == 0 );
// Also test that setting the text value works.
CHECK( m_spin->GetTextValue() == "49.10" );
m_spin->SetValue("57.30");
CHECK( m_spin->GetTextValue() == "57.30" );
CHECK( m_spin->GetValue() == 57.3 );
m_spin->SetValue("");
CHECK( m_spin->GetTextValue() == "" );
CHECK( m_spin->GetValue() == 57.3 );
}
void SpinCtrlDoubleTestCase::Increment()
{
#if wxUSE_UIACTIONSIMULATOR
CPPUNIT_ASSERT_EQUAL(1.0, m_spin->GetIncrement());
TEST_CASE_METHOD(SpinCtrlDoubleTestCase,
"SpinCtrlDouble::Increment", "[spinctrl][spinctrldouble]")
{
CHECK( m_spin->GetIncrement() == 1.0 );
m_spin->SetDigits(1);
m_spin->SetIncrement(0.1);
CPPUNIT_ASSERT_EQUAL(0.1, m_spin->GetIncrement());
CHECK( m_spin->GetIncrement() == 0.1 );
wxUIActionSimulator sim;
@@ -210,15 +202,17 @@ void SpinCtrlDoubleTestCase::Increment()
wxYield();
CPPUNIT_ASSERT_EQUAL(0.1, m_spin->GetValue());
#endif
CHECK( m_spin->GetValue() == 0.1 );
}
void SpinCtrlDoubleTestCase::Digits()
#endif // wxUSE_UIACTIONSIMULATOR
TEST_CASE_METHOD(SpinCtrlDoubleTestCase,
"SpinCtrlDouble::Digits", "[spinctrl][spinctrldouble]")
{
m_spin->SetDigits(5);
CPPUNIT_ASSERT_EQUAL(5, m_spin->GetDigits());
CHECK( m_spin->GetDigits() == 5 );
}
static inline unsigned int GetInitialDigits(double inc)
@@ -230,7 +224,7 @@ static inline unsigned int GetInitialDigits(double inc)
return digits;
}
TEST_CASE("SpinCtrlDoubleTestCase::InitialDigits", "[spinctrldouble][initialdigits]")
TEST_CASE("SpinCtrlDouble::InitialDigits", "[spinctrldouble][initialdigits]")
{
REQUIRE(GetInitialDigits(15) == 0);
REQUIRE(GetInitialDigits(10) == 0);

View File

@@ -268,6 +268,17 @@ TEST_CASE_METHOD(SpinCtrlTestCase2, "SpinCtrl::Value", "[spinctrl]")
// Calling SetValue() shouldn't have generated any events.
CHECK(updatedSpin.GetCount() == 0);
CHECK(updatedText.GetCount() == 0);
// Also test that setting the text value works.
CHECK( m_spin->GetTextValue() == "100" );
m_spin->SetValue("57");
CHECK( m_spin->GetTextValue() == "57" );
CHECK( m_spin->GetValue() == 57 );
m_spin->SetValue("");
CHECK( m_spin->GetTextValue() == "" );
CHECK( m_spin->GetValue() == 57 );
}
TEST_CASE_METHOD(SpinCtrlTestCase2, "SpinCtrl::Base", "[spinctrl]")