Implemented UI_SpinCtrl and refactored common components to UI_Window. Added tests.

Replaced click tests in UI_Checkbox with event pushes.
This commit is contained in:
Joseph Lenox 2018-06-26 20:20:27 -05:00 committed by Joseph Lenox
parent dbff12c4e0
commit e13eb18455
5 changed files with 317 additions and 174 deletions

View File

@ -177,6 +177,7 @@ set(UI_TEST_SOURCES
${GUI_TESTDIR}/testableframe.cpp
${GUI_TESTDIR}/test_harness_gui.cpp
${GUI_TESTDIR}/test_field_checkbox.cpp
${GUI_TESTDIR}/test_field_spinctrl.cpp
)
set(SLIC3R_TEST_SOURCES
${TESTDIR}/test_harness.cpp

View File

@ -2,16 +2,65 @@
#define SLIC3R_FIELD_HPP
#include <functional>
#include <string>
#include <limits>
#include <boost/any.hpp>
#include "ConfigBase.hpp"
#include "Log.hpp"
#include "wx/spinctrl.h"
namespace Slic3r { namespace GUI {
class UI_Checkbox {
using namespace std::string_literals;
class UI_Window {
public:
UI_Checkbox(wxWindow* parent, Slic3r::ConfigOptionDef _opt, wxWindowID checkid = wxID_ANY) : parent(parent), opt(_opt) {
ui_window = new wxCheckBox(parent, checkid, "");
_check = dynamic_cast<wxCheckBox*>(ui_window);
UI_Window(wxWindow* _parent, Slic3r::ConfigOptionDef _opt) : parent(_parent), opt(_opt) {};
virtual ~UI_Window() = default;
/// Don't trigger on_change when this is true.
bool disable_change_event {false};
/// Set the underlying control to the value (cast it and throw bad_any_cast if there are problems).
virtual void set_value(boost::any value) = 0;
/// Enables the underlying UI widget.
void enable() { this->window->Enable(); }
/// Disables the underlying UI widget.
void disable() { this->window->Disable(); }
/// Set the underlying widget to either enabled or disabled.
void toggle(bool enable = true) { enable ? this->enable() : this->disable(); }
/// Getter functions for UI_Window items.
virtual bool get_bool() { Slic3r::Log::warn(this->LogChannel(), "get_bool does not exist"s); return false; } //< return false all the time if this is not implemented.
virtual int get_int() { Slic3r::Log::warn(this->LogChannel(), "get_int does not exist"s); return 0; } //< return 0 all the time if this is not implemented.
/// Function to call when the contents of this change.
std::function<void (const std::string&, bool value)> on_change {nullptr};
std::function<void (const std::string&)> on_kill_focus {nullptr};
protected:
wxWindow* parent {nullptr};
wxWindow* window {nullptr}; //< Pointer copy of the derived classes
const Slic3r::ConfigOptionDef opt; //< Reference to the UI-specific bits of this option
virtual std::string LogChannel() { return "UI_Window"s; }
virtual void _on_change(std::string opt_id) = 0;
/// Define a default size for derived classes.
wxSize _default_size() { return wxSize((opt.width >= 0 ? opt.width : 60), (opt.height != -1 ? opt.height : -1)); }
};
class UI_Checkbox : public UI_Window {
public:
UI_Checkbox(wxWindow* parent, Slic3r::ConfigOptionDef _opt, wxWindowID checkid = wxID_ANY) : UI_Window(parent, _opt) {
_check = new wxCheckBox(parent, checkid, "");
this->window = _check;
// Set some defaults.
if (this->opt.readonly) { this->_check->Disable(); }
@ -21,43 +70,68 @@ public:
_check->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent& e) { this->_on_change(""); e.Skip(); });
_check->Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent& e) { if (this->on_kill_focus != nullptr) {this->on_kill_focus("");} e.Skip(); });
}
~UI_Checkbox() { wxDELETE(_check); ui_window = _check = nullptr; }
/// Function to call when the contents of this change.
std::function<void (const std::string&, bool value)> on_change {nullptr};
std::function<void (const std::string&)> on_kill_focus {nullptr};
/// Don't trigger on_change when this is true.
bool disable_change_event {false};
/// Enables the underlying UI widget.
void enable() { this->_check->Enable(); }
/// Disables the underlying UI widget.
void disable() { this->ui_window->Disable(); }
/// Set the underlying widget to either enabled or disabled.
void toggle(bool enable = true) { enable ? this->enable() : this->disable(); }
~UI_Checkbox() = default;
/// Returns a bare pointer to the underlying checkbox, usually for test interface
wxCheckBox* check() { return _check; }
/// Returns the value of the enclosed checkbox.
/// Implements get_bool
bool get_bool() { return _check->GetValue();}
virtual bool get_bool() override { return _check->GetValue();}
/// Casts the containing value to boolean and sets the built-in checkbox appropriately.
/// implements set_value
void set_value(boost::any value) { this->_check->SetValue(boost::any_cast<bool>(value)); }
private:
wxWindow* parent {nullptr};
wxWindow* ui_window {nullptr};
virtual void set_value(boost::any value) override { this->_check->SetValue(boost::any_cast<bool>(value)); }
protected:
wxCheckBox* _check {nullptr};
const Slic3r::ConfigOptionDef opt; //< Reference to the UI-specific bits of this option
virtual std::string LogChannel() override { return "UI_Checkbox"s; }
void _on_change(std::string opt_id) {
if (!this->disable_change_event && this->on_change != nullptr) {
if (!this->disable_change_event && this->window->IsEnabled() && this->on_change != nullptr) {
this->on_change(opt_id, this->get_bool());
}
}
};
class UI_SpinCtrl : public UI_Window {
public:
UI_SpinCtrl(wxWindow* parent, Slic3r::ConfigOptionDef _opt, wxWindowID spinid = wxID_ANY) : UI_Window(parent, _opt) {
/// Initialize and set defaults, if available.
_spin = new wxSpinCtrl(parent, spinid, "", wxDefaultPosition, _default_size(), 0,
(opt.min > 0 ? opt.min : 0),
(opt.max > 0 ? opt.max : std::numeric_limits<int>::max()),
(opt.default_value != NULL ? opt.default_value->getInt() : 0));
window = _spin;
// Set up event handlers
_spin->Bind(wxEVT_SPINCTRL, [this](wxCommandEvent& e) { this->_on_change(""); e.Skip(); });
_spin->Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent& e) { if (this->on_kill_focus != nullptr) {this->on_kill_focus("");} e.Skip(); });
}
~UI_SpinCtrl() = default;
int get_int() { return this->_spin->GetValue(); }
void set_value(boost::any value) { this->_spin->SetValue(boost::any_cast<int>(value)); }
/// Access method for the underlying SpinCtrl
wxSpinCtrl* spinctrl() { return _spin; }
protected:
virtual std::string LogChannel() { return "UI_SpinCtrl"s; }
void _on_change(std::string opt_id) {
if (!this->disable_change_event && this->window->IsEnabled() && this->on_change != nullptr) {
this->on_change(opt_id, this->get_int());
}
}
private:
wxSpinCtrl* _spin {nullptr};
int _tmp {0};
};
} } // Namespace Slic3r::GUI

View File

@ -22,23 +22,23 @@ SCENARIO( "GUI Checkbox option items fire their on_kill_focus when focus leaves
wxMilliSleep(500);
GIVEN( "A checkbox field item exists on a window") {
auto exec_counter {0};
auto* test_field {new Slic3r::GUI::UI_Checkbox(wxTheApp->GetTopWindow(), Slic3r::ConfigOptionDef())};
auto test_field {Slic3r::GUI::UI_Checkbox(wxTheApp->GetTopWindow(), Slic3r::ConfigOptionDef())};
auto killfunc {[&exec_counter](const std::string& opt_id) { exec_counter += 1; }};
test_field->on_kill_focus = killfunc;
test_field.on_kill_focus = killfunc;
wxTheApp->GetTopWindow()->Show();
wxTheApp->GetTopWindow()->Fit();
WHEN ( "focus leaves the checkbox") {
exec_counter = 0;
test_field->check()->SetFocus();
test_field.check()->SetFocus();
wxMilliSleep(500);
auto ev {wxFocusEvent(wxEVT_KILL_FOCUS, test_field->check()->GetId())};
ev.SetEventObject(test_field->check());
test_field->check()->ProcessWindowEvent(ev);
auto ev {wxFocusEvent(wxEVT_KILL_FOCUS, test_field.check()->GetId())};
ev.SetEventObject(test_field.check());
test_field.check()->ProcessWindowEvent(ev);
wxYield();
wxMilliSleep(500);
THEN( "on_focus_kill is executed.") {
@ -47,15 +47,15 @@ SCENARIO( "GUI Checkbox option items fire their on_kill_focus when focus leaves
}
WHEN ( "focus leaves the checkbox and no callback is assigned") {
test_field->on_kill_focus = nullptr;
test_field.on_kill_focus = nullptr;
exec_counter = 0;
test_field->check()->SetFocus();
test_field.check()->SetFocus();
wxMilliSleep(500);
auto ev {wxFocusEvent(wxEVT_KILL_FOCUS, test_field->check()->GetId())};
ev.SetEventObject(test_field->check());
test_field->check()->ProcessWindowEvent(ev);
auto ev {wxFocusEvent(wxEVT_KILL_FOCUS, test_field.check()->GetId())};
ev.SetEventObject(test_field.check());
test_field.check()->ProcessWindowEvent(ev);
wxYield();
wxMilliSleep(500);
THEN( "on_focus_kill doesn't try to execute nullptr") {
@ -63,7 +63,6 @@ SCENARIO( "GUI Checkbox option items fire their on_kill_focus when focus leaves
REQUIRE(exec_counter == 0);
}
}
delete test_field;
}
}
SCENARIO( "GUI Checkbox set_value and get_bool work as expected." ) {
@ -72,41 +71,38 @@ SCENARIO( "GUI Checkbox set_value and get_bool work as expected." ) {
wxTheApp->SetTopWindow(new wxTestableFrame());
wxMilliSleep(500);
auto* test_field {new Slic3r::GUI::UI_Checkbox(wxTheApp->GetTopWindow(), Slic3r::ConfigOptionDef())};
auto test_field {Slic3r::GUI::UI_Checkbox(wxTheApp->GetTopWindow(), Slic3r::ConfigOptionDef())};
GIVEN( "A checkbox field item exists on a window") {
WHEN ( "set_value is an bool and true") {
test_field->set_value(true);
test_field.set_value(true);
THEN( " Result is converted correctly.") {
REQUIRE( test_field->get_bool() == true);
REQUIRE( test_field.get_bool() == true);
}
}
WHEN ( "set_value is an bool and false") {
test_field->set_value(false);
test_field.set_value(false);
THEN( " Result is converted correctly.") {
REQUIRE( test_field->get_bool() == false);
REQUIRE( test_field.get_bool() == false);
}
}
WHEN ( "set_value is a floating point number > 0") {
test_field->set_value(true);
test_field.set_value(true);
try {
test_field->set_value(10.2);
test_field.set_value(10.2);
} catch (boost::bad_any_cast &e) {
THEN( " Nothing happens; exception was thrown (and caught).") {
REQUIRE(true);
}
}
THEN( " Value did not change.") {
REQUIRE( test_field->get_bool() == true);
REQUIRE( test_field.get_bool() == true);
}
}
}
}
delete test_field;
}
SCENARIO( "GUI Checkbox option items fire their on_change event when clicked and appropriate." ) {
SCENARIO( "GUI Checkbox option respond to EVT_CHECKBOX when appropriate." ) {
wxUIActionSimulator sim;
wxTestableFrame* old = dynamic_cast<wxTestableFrame*>(wxTheApp->GetTopWindow());
old->Destroy();
@ -118,82 +114,46 @@ SCENARIO( "GUI Checkbox option items fire their on_change event when clicked and
auto exec_counter {0};
auto changefunc {[&exec_counter](const std::string& opt_id, bool value) { exec_counter += 1; }};
auto* test_field {new Slic3r::GUI::UI_Checkbox(wxTheApp->GetTopWindow(), Slic3r::ConfigOptionDef())};
auto test_field {Slic3r::GUI::UI_Checkbox(wxTheApp->GetTopWindow(), Slic3r::ConfigOptionDef())};
test_field->disable_change_event = false;
test_field->on_change = changefunc;
test_field.disable_change_event = false;
test_field.on_change = changefunc;
wxTheApp->GetTopWindow()->Show();
wxTheApp->GetTopWindow()->Fit();
WHEN ( "the box is checked") {
WHEN ( "CHECKBOX event is received") {
exec_counter = 0;
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
wxYield();
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
wxYield();
sim.MouseClick(wxMOUSE_BTN_LEFT);
wxYield();
sim.MouseClick(wxMOUSE_BTN_LEFT);
auto ev {wxCommandEvent(wxEVT_CHECKBOX, test_field.check()->GetId())};
ev.SetEventObject(test_field.check());
test_field.check()->ProcessWindowEvent(ev);
wxYield();
wxMilliSleep(250);
THEN ( "on_change is executed.") {
REQUIRE(exec_counter == 1);
}
}
WHEN ( "the box is unchecked") {
exec_counter = 0;
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
wxYield();
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
wxYield();
sim.MouseClick(wxMOUSE_BTN_LEFT);
wxYield();
sim.MouseClick(wxMOUSE_BTN_LEFT);
wxYield();
THEN ( "on_change is executed.") {
REQUIRE(exec_counter == 1);
}
}
delete test_field;
}
GIVEN( "A checkbox field item and disable_change = true") {
auto exec_counter {0};
auto changefunc {[&exec_counter] (const std::string& opt_id, bool value) { exec_counter++; }};
auto* test_field {new Slic3r::GUI::UI_Checkbox(wxTheApp->GetTopWindow(), Slic3r::ConfigOptionDef())};
auto test_field {Slic3r::GUI::UI_Checkbox(wxTheApp->GetTopWindow(), Slic3r::ConfigOptionDef())};
wxTheApp->GetTopWindow()->Show();
wxTheApp->GetTopWindow()->Fit();
test_field->disable_change_event = true;
test_field->on_change = changefunc;
test_field.disable_change_event = true;
test_field.on_change = changefunc;
WHEN ( "the box is checked") {
WHEN ( "CHECKBOX event is received") {
exec_counter = 0;
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
wxYield();
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
wxYield();
sim.MouseClick(wxMOUSE_BTN_LEFT);
wxYield();
sim.MouseClick(wxMOUSE_BTN_LEFT);
auto ev {wxCommandEvent(wxEVT_CHECKBOX, test_field.check()->GetId())};
ev.SetEventObject(test_field.check());
test_field.check()->ProcessWindowEvent(ev);
wxYield();
wxMilliSleep(250);
THEN ( "on_change is not executed.") {
REQUIRE(exec_counter == 0);
}
}
WHEN ( "the box is unchecked") {
exec_counter = 0;
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
wxYield();
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
wxYield();
sim.MouseClick(wxMOUSE_BTN_LEFT);
wxYield();
sim.MouseClick(wxMOUSE_BTN_LEFT);
wxYield();
THEN ( "on_change is not executed.") {
REQUIRE(exec_counter == 0);
}
}
delete test_field;
}
GIVEN( "A checkbox field item and readonly") {
@ -209,77 +169,31 @@ SCENARIO( "GUI Checkbox option items fire their on_change event when clicked and
test_field->disable_change_event = false; // don't disable :D
test_field->on_change = changefunc;
WHEN ( "the box is clicked and readonly") {
WHEN ( "CHECKBOX event is received") {
exec_counter = 0;
test_field->set_value(false);
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
wxYield();
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
wxYield();
sim.MouseClick(wxMOUSE_BTN_LEFT);
wxYield();
sim.MouseClick(wxMOUSE_BTN_LEFT);
auto ev {wxCommandEvent(wxEVT_CHECKBOX, test_field->check()->GetId())};
ev.SetEventObject(test_field->check());
test_field->check()->ProcessWindowEvent(ev);
wxYield();
wxMilliSleep(250);
THEN ( "on_change is not executed.") {
REQUIRE(exec_counter == 0);
}
THEN ( "Box is not checked.") {
REQUIRE(test_field->get_bool() == false);
}
}
WHEN ( "the box is clicked and readonly") {
exec_counter = 0;
test_field->set_value(true);
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
wxYield();
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
wxYield();
sim.MouseClick(wxMOUSE_BTN_LEFT);
wxYield();
sim.MouseClick(wxMOUSE_BTN_LEFT);
wxYield();
THEN ( "on_change is not executed.") {
REQUIRE(exec_counter == 0);
}
THEN ( "Box is checked.") {
REQUIRE(test_field->get_bool() == true);
}
}
WHEN ( "the box is clicked and enabled") {
exec_counter = 0;
test_field->enable();
test_field->set_value(true);
wxMilliSleep(500);
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
wxYield();
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
wxYield();
sim.MouseClick(wxMOUSE_BTN_LEFT);
wxYield();
sim.MouseClick(wxMOUSE_BTN_LEFT);
auto ev {wxCommandEvent(wxEVT_CHECKBOX, test_field->check()->GetId())};
ev.SetEventObject(test_field->check());
test_field->check()->ProcessWindowEvent(ev);
wxYield();
wxMilliSleep(250);
THEN ( "on_change is executed.") {
REQUIRE(exec_counter == 1);
}
THEN ( "Box is not checked.") {
REQUIRE(test_field->get_bool() == false);
}
}
WHEN ( "the box is clicked and disabled") {
exec_counter = 0;
test_field->set_value(true);
test_field->disable();
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
wxYield();
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
wxYield();
sim.MouseClick(wxMOUSE_BTN_LEFT);
wxYield();
sim.MouseClick(wxMOUSE_BTN_LEFT);
wxYield();
THEN ( "on_change is not executed.") {
REQUIRE(exec_counter == 0);
}
THEN ( "Box is checked.") {
REQUIRE(test_field->get_bool() == true);
}
@ -288,33 +202,27 @@ SCENARIO( "GUI Checkbox option items fire their on_change event when clicked and
exec_counter = 0;
test_field->set_value(true);
test_field->toggle(true);
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
wxYield();
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
wxYield();
sim.MouseClick(wxMOUSE_BTN_LEFT);
wxYield();
sim.MouseClick(wxMOUSE_BTN_LEFT);
auto ev {wxCommandEvent(wxEVT_CHECKBOX, test_field->check()->GetId())};
ev.SetEventObject(test_field->check());
test_field->check()->ProcessWindowEvent(ev);
wxYield();
wxMilliSleep(250);
THEN ( "on_change is executed.") {
REQUIRE(exec_counter == 1);
}
THEN ( "Box is not checked.") {
REQUIRE(test_field->get_bool() == false);
THEN ( "Box is checked.") {
REQUIRE(test_field->get_bool() == true);
}
}
WHEN ( "the box is clicked and toggled false") {
exec_counter = 0;
test_field->set_value(true);
test_field->toggle(false);
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
wxYield();
sim.MouseMove(test_field->check()->GetScreenPosition() + wxPoint(10, 10));
wxYield();
sim.MouseClick(wxMOUSE_BTN_LEFT);
wxYield();
sim.MouseClick(wxMOUSE_BTN_LEFT);
auto ev {wxCommandEvent(wxEVT_CHECKBOX, test_field->check()->GetId())};
ev.SetEventObject(test_field->check());
test_field->check()->ProcessWindowEvent(ev);
wxYield();
wxMilliSleep(250);
THEN ( "on_change is not executed.") {
REQUIRE(exec_counter == 0);
}

View File

@ -0,0 +1,156 @@
#include <catch.hpp>
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/sizer.h"
#include "wx/checkbox.h"
#include "wx/uiaction.h"
#endif // WX_PRECOMP
#include <iostream>
#include "testableframe.h"
#include "OptionsGroup/Field.hpp"
#include "ConfigBase.hpp"
using namespace Slic3r::GUI;
SCENARIO( "Spinctrl initializes with default value if available.") {
wxTestableFrame* old = dynamic_cast<wxTestableFrame*>(wxTheApp->GetTopWindow());
old->Destroy();
wxTheApp->SetTopWindow(new wxTestableFrame());
wxMilliSleep(250);
Slic3r::ConfigOptionDef simple_option;
simple_option.type = coInt;
auto* intopt { new Slic3r::ConfigOptionInt(7) };
simple_option.default_value = intopt; // no delete, it's taken care of by ConfigOptionDef
GIVEN ( "A UI Spinctrl") {
auto test_field {Slic3r::GUI::UI_SpinCtrl(wxTheApp->GetTopWindow(), simple_option)};
wxTheApp->GetTopWindow()->Show();
wxTheApp->GetTopWindow()->Fit();
REQUIRE(test_field.get_int() == 7);
}
}
SCENARIO( "Receiving a Spinctrl event") {
wxTestableFrame* old = dynamic_cast<wxTestableFrame*>(wxTheApp->GetTopWindow());
old->Destroy();
wxTheApp->SetTopWindow(new wxTestableFrame());
wxMilliSleep(250);
GIVEN ( "A UI Spinctrl") {
auto exec_counter {0};
auto changefunc {[&exec_counter] (const std::string& opt_id, bool value) { exec_counter++; }};
auto test_field {Slic3r::GUI::UI_SpinCtrl(wxTheApp->GetTopWindow(), Slic3r::ConfigOptionDef())};
test_field.on_change = changefunc;
wxTheApp->GetTopWindow()->Show();
wxTheApp->GetTopWindow()->Fit();
WHEN( "A spin event occurs") {
exec_counter = 0;
auto ev {wxSpinEvent(wxEVT_SPINCTRL, test_field.spinctrl()->GetId())};
ev.SetEventObject(test_field.spinctrl());
test_field.spinctrl()->ProcessWindowEvent(ev);
wxYield();
wxMilliSleep(250);
THEN( "on_change is executed.") {
REQUIRE(exec_counter == 1);
}
}
WHEN( "A spin event occurs and change event is disabled") {
exec_counter = 0;
test_field.disable_change_event = false;
auto ev {wxSpinEvent(wxEVT_SPINCTRL, test_field.spinctrl()->GetId())};
ev.SetEventObject(test_field.spinctrl());
test_field.spinctrl()->ProcessWindowEvent(ev);
wxYield();
wxMilliSleep(250);
THEN( "on_change is not executed.") {
REQUIRE(exec_counter == 1);
}
}
}
}
SCENARIO( "Changing the text via entry works on pressing enter") {
wxTestableFrame* old = dynamic_cast<wxTestableFrame*>(wxTheApp->GetTopWindow());
old->Destroy();
wxTheApp->SetTopWindow(new wxTestableFrame());
wxUIActionSimulator sim;
wxMilliSleep(500);
GIVEN ( "A UI Spinctrl") {
auto exec_counter {0};
auto changefunc {[&exec_counter] (const std::string& opt_id, bool value) { exec_counter++; }};
auto test_field {Slic3r::GUI::UI_SpinCtrl(wxTheApp->GetTopWindow(), Slic3r::ConfigOptionDef())};
test_field.on_change = changefunc;
wxTheApp->GetTopWindow()->Show();
wxTheApp->GetTopWindow()->Fit();
WHEN( "A number is entered followed by enter key") {
exec_counter = 0;
test_field.spinctrl()->SetFocus();
wxYield();
wxMilliSleep(250);
sim.Char('3');
wxMilliSleep(250);
sim.Char(WXK_RETURN);
wxMilliSleep(250);
wxYield();
THEN( "on_change is executed.") {
REQUIRE(exec_counter == 1);
}
THEN( "get_int returns entered value.") {
REQUIRE(test_field.get_int() == 3);
}
}
WHEN( "A number is entered followed by enter key and change event is disabled") {
exec_counter = 0;
test_field.disable_change_event = true;
test_field.spinctrl()->SetFocus();
wxYield();
wxMilliSleep(250);
sim.Char('3');
wxMilliSleep(250);
sim.Char(WXK_RETURN);
wxMilliSleep(250);
wxYield();
THEN( "on_change is not executed.") {
REQUIRE(exec_counter == 0);
}
THEN( "get_int returns entered value.") {
REQUIRE(test_field.get_int() == 3);
}
}
WHEN( "A number is entered and focus is lost") {
auto killfunc {[&exec_counter](const std::string& opt_id) { exec_counter += 1; }};
test_field.on_kill_focus = killfunc;
auto ev {wxFocusEvent(wxEVT_KILL_FOCUS, test_field.spinctrl()->GetId())};
ev.SetEventObject(test_field.spinctrl());
exec_counter = 0;
test_field.spinctrl()->SetValue(3);
test_field.spinctrl()->SetFocus();
wxYield();
wxMilliSleep(250);
sim.Char('7');
wxYield();
wxMilliSleep(250);
test_field.spinctrl()->ProcessWindowEvent(ev);
wxMilliSleep(250);
wxYield();
THEN( "on_kill_focus is executed and on_change are both executed.") {
REQUIRE(exec_counter == 2);
}
THEN( "get_int returns updated value.") {
REQUIRE(test_field.get_int() == 7);
}
THEN( "get_bool returns 0.") {
REQUIRE(test_field.get_bool() == 0);
}
}
}
}

View File

@ -37,6 +37,10 @@ public:
std::cerr << topic << " WARN" << ": ";
std::wcerr << message << std::endl;
}
static void warn(std::string topic, std::string message) {
std::cerr << topic << " WARN" << ": ";
std::cerr << message << std::endl;
}
};