Continued implementation for UI_Slider

Added enable/disable methods and set_range()
text control should update as well.
Added tests to build.
This commit is contained in:
Joseph Lenox 2018-07-23 09:45:25 -05:00
parent 2090fae11d
commit 17e588904b
4 changed files with 118 additions and 8 deletions

View File

@ -193,6 +193,7 @@ set(UI_TEST_SOURCES
${GUI_TESTDIR}/test_field_point.cpp ${GUI_TESTDIR}/test_field_point.cpp
${GUI_TESTDIR}/test_field_point3.cpp ${GUI_TESTDIR}/test_field_point3.cpp
${GUI_TESTDIR}/test_field_colorpicker.cpp ${GUI_TESTDIR}/test_field_colorpicker.cpp
${GUI_TESTDIR}/test_field_slider.cpp
${GUI_TESTDIR}/test_misc_ui.cpp ${GUI_TESTDIR}/test_misc_ui.cpp
) )

View File

@ -421,8 +421,7 @@ private:
class UI_Slider : public UI_Sizer { class UI_Slider : public UI_Sizer {
public: public:
UI_Slider(wxWindow* parent, Slic3r::ConfigOptionDef _opt); UI_Slider(wxWindow* parent, Slic3r::ConfigOptionDef _opt, size_t scale = 10);
UI_Slider(wxWindow* parent, Slic3r::ConfigOptionDef _opt, size_t scale);
~UI_Slider(); ~UI_Slider();
@ -431,11 +430,21 @@ public:
double get_double() override; double get_double() override;
int get_int() override; int get_int() override;
void enable() override;
void disable() override;
/// change the min/max of the built-in slider
template <typename T> void set_range(T min, T max);
/// Change the scale of the slider bar. Return value from get_X functions does not change. /// Change the scale of the slider bar. Return value from get_X functions does not change.
void set_scale(size_t new_scale); void set_scale(size_t new_scale);
/// Returns pointer to owned wxSlider.
wxSlider* slider() { return _slider;} wxSlider* slider() { return _slider;}
/// Returns pointer to owned wxTextCtrl.
wxTextCtrl* textctrl() { return _textctrl;} wxTextCtrl* textctrl() { return _textctrl;}
/// Registered on_change callback.
std::function<void (const std::string&, const double&)> on_change {nullptr}; std::function<void (const std::string&, const double&)> on_change {nullptr};
protected: protected:
virtual std::string LogChannel() override { return "UI_Slider"s; } virtual std::string LogChannel() override { return "UI_Slider"s; }
@ -445,6 +454,7 @@ private:
this->on_change(opt_id, _slider->GetValue() / _scale); this->on_change(opt_id, _slider->GetValue() / _scale);
} }
} }
void _update_textctrl();
wxTextCtrl* _textctrl {nullptr}; wxTextCtrl* _textctrl {nullptr};
wxSlider* _slider {nullptr}; wxSlider* _slider {nullptr};
size_t _scale {10}; size_t _scale {10};

View File

@ -3,28 +3,98 @@
namespace Slic3r { namespace GUI { namespace Slic3r { namespace GUI {
UI_Slider::UI_Slider(wxWindow* parent, Slic3r::ConfigOptionDef _opt) : UI_Sizer(parent, _opt), _scale(10) { UI_Slider::UI_Slider(wxWindow* parent, Slic3r::ConfigOptionDef _opt, size_t scale) : UI_Sizer(parent, _opt), _scale(scale) {
} double default_value {0.0};
UI_Slider::UI_Slider(wxWindow* parent, Slic3r::ConfigOptionDef _opt, size_t scale ) : UI_Sizer(parent, _opt), _scale(scale) {
sizer = new wxBoxSizer(wxHORIZONTAL);
_slider = new wxSlider(parent, wxID_ANY,
(default_value < _opt.min ? _opt.min : default_value) * this->_scale,
(_opt.min > _opt.max || _opt.min == INT_MIN ? 0 : _opt.min) * this->_scale,
(_opt.max <= _opt.min || _opt.max == INT_MAX ? 100 : _opt.max) * this->_scale,
wxDefaultPosition,
wxSize(_opt.width, _opt.height));
_textctrl = new wxTextCtrl(parent, wxID_ANY,
static_cast<double>(_slider->GetValue()) / this->_scale,
wxDefaultPosition,
wxSize(50, -1));
sizer->Add(_slider, 1, wxALIGN_CENTER_VERTICAL, 0);
sizer->Add(_textctrl, 0, wxALIGN_CENTER_VERTICAL, 0);
_textctrl->Bind(wxEVT_TEXT_ENTER, [this](wxCommandEvent& e) { this->_on_change(""); e.Skip(); });
_textctrl->Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent& e) { if (this->on_kill_focus != nullptr) {this->on_kill_focus(""); this->_on_change("");} e.Skip(); });
_slider->Bind(wxEVT_SLIDER, [this](wxCommandEvent& e) { this->_on_change(""); e.Skip(); });
} }
UI_Slider::~UI_Slider() { _slider->Destroy(); _textctrl->Destroy(); } UI_Slider::~UI_Slider() { _slider->Destroy(); _textctrl->Destroy(); }
void UI_Slider::set_value(boost::any value) { void UI_Slider::set_value(boost::any value) {
this->disable_change_event = true;
if (value.type() == typeid(int)) {
this->_slider->SetValue(boost::any_cast<int>(value) * this->_scale);
} else if (value.type() == typeid(double)) {
this->_slider->SetValue(boost::any_cast<double>(value) * this->_scale);
} else if (value.type() == typeid(float)) {
this->_slider->SetValue(boost::any_cast<float>(value) * this->_scale);
} else if (value.type() == typeid(std::string)) {
std::string _val = boost::any_cast<std::string>(value);
try {
this->_slider->SetValue(std::stod(_val) * this->_scale);
} catch (std::invalid_argument &e) {
Slic3r::Log::error(this->LogChannel()) << "Conversion to numeric from string failed.\n";
}
} else if (value.type() == typeid(wxString)) {
std::string _val = boost::any_cast<wxString>(value).ToStdString();
try {
this->_slider->SetValue(std::stod(_val) * this->_scale);
} catch (std::invalid_argument &e) {
Slic3r::Log::error(this->LogChannel()) << "Conversion to numeric from string failed.\n";
}
} else {
Slic3r::Log::warn(this->LogChannel(), LOG_WSTRING("Type " << value.type().name() << " is not handled in set_value."));
}
this->_update_textctrl();
this->disable_change_event = false;
} }
double UI_Slider::get_double() { double UI_Slider::get_double() {
return 0.0; return static_cast<double>(this->_slider->GetValue()) / this->_scale;
} }
int UI_Slider::get_int() { int UI_Slider::get_int() {
return 0; return static_cast<int>(this->_slider->GetValue()) / this->_scale;
} }
std::string UI_Slider::get_string() { std::string UI_Slider::get_string() {
return std::string(); return trim_zeroes(std::to_string(static_cast<double>(this->_slider->GetValue()) / this->_scale));
} }
void UI_Slider::set_scale(size_t new_scale) { void UI_Slider::set_scale(size_t new_scale) {
this->disable_change_event = true;
auto current_value {this->get_double()};
this->_slider->SetRange(
this->_slider->GetMin() / this->_scale * new_scale,
this->_slider->GetMax() / this->_scale * new_scale);
this->_scale = new_scale;
this->set_value(current_value);
this->disable_change_event = false;
} }
void UI_Slider::_update_textctrl() {
this->_textctrl->ChangeValue(this->get_string());
this->_textctrl->SetInsertionPointEnd();
}
template <typename T>
void UI_Slider::set_range(T min, T max) {
this->_slider->SetRange(static_cast<int>(min * static_cast<int>(self->_scale)), static_cast<int>(max * static_cast<int>(self->_scale)));
}
} } // Namespace Slic3r::GUI } } // Namespace Slic3r::GUI

View File

@ -77,6 +77,34 @@ SCENARIO( "UI_Slider: Defaults, Min/max handling, accessors.") {
REQUIRE(test_field.textctrl()->GetValue() == "0.0"); REQUIRE(test_field.textctrl()->GetValue() == "0.0");
} }
} }
WHEN("disable() is called") {
test_field.slider()->Enable();
test_field.textctrl()->Enable();
test_field.textctrl()->SetEditable(true);
test_field.disable();
THEN("Internal slider is disabled.") {
REQUIRE(test_field.slider()->IsEnabled() == false);
}
THEN("Internal textctrl is disabled.") {
REQUIRE(test_field.textctrl()->IsEnabled() == false);
REQUIRE(test_field.textctrl()->IsEditable() == false);
}
}
WHEN("enable() is called") {
test_field.slider()->Disable();
test_field.textctrl()->Disable();
test_field.textctrl()->SetEditable(false);
test_field.enable();
THEN("Internal slider is enabled.") {
REQUIRE(test_field.slider()->IsEnabled() == true);
}
THEN("Internal textctrl is enabled.") {
REQUIRE(test_field.textctrl()->IsEnabled() == true);
REQUIRE(test_field.textctrl()->IsEditable() == true);
}
}
} }
GIVEN("A UI Slider with scale of 1") { GIVEN("A UI Slider with scale of 1") {
@ -98,6 +126,7 @@ SCENARIO( "UI_Slider: Defaults, Min/max handling, accessors.") {
} }
} }
} }
SCENARIO( "UI_Slider: Event handlers") { SCENARIO( "UI_Slider: Event handlers") {
wxTestableFrame* old = dynamic_cast<wxTestableFrame*>(wxTheApp->GetTopWindow()); wxTestableFrame* old = dynamic_cast<wxTestableFrame*>(wxTheApp->GetTopWindow());
old->Destroy(); old->Destroy();