From 9f83da9519a6084639016286f2c0741ce1e46432 Mon Sep 17 00:00:00 2001 From: Joseph Lenox Date: Wed, 4 Jul 2018 16:35:04 -0500 Subject: [PATCH] Implemented UI_Point3, fixed tests. --- src/GUI/OptionsGroup/Field.hpp | 49 ++++++++++- src/GUI/OptionsGroup/UI_Point3.cpp | 131 +++++++++++++++++++++++++++++ src/test/GUI/test_field_point3.cpp | 12 +-- 3 files changed, 185 insertions(+), 7 deletions(-) create mode 100644 src/GUI/OptionsGroup/UI_Point3.cpp diff --git a/src/GUI/OptionsGroup/Field.hpp b/src/GUI/OptionsGroup/Field.hpp index ab37b5e34..ccfab0fdb 100644 --- a/src/GUI/OptionsGroup/Field.hpp +++ b/src/GUI/OptionsGroup/Field.hpp @@ -308,7 +308,6 @@ public: /// Function to call when the contents of this change. std::function value)> on_change {nullptr}; - void enable() override { _ctrl_x->Enable(); _ctrl_y->Enable(); } void disable() override { _ctrl_x->Disable(); _ctrl_y->Disable(); } @@ -342,9 +341,57 @@ private: void _set_value(Slic3r::Pointf3 value); void _set_value(std::string value); +}; + +class UI_Point3 : public UI_Sizer { +public: + UI_Point3(wxWindow* _parent, Slic3r::ConfigOptionDef _opt); + ~UI_Point3() { _lbl_x->Destroy(); _lbl_y->Destroy(); _ctrl_x->Destroy(); _ctrl_y->Destroy(); _lbl_z->Destroy(); _ctrl_z->Destroy(); } + std::string get_string(); + + void set_value(boost::any value) override; //< Implements set_value + + Slic3r::Pointf get_point() override; /// return a Slic3r::Pointf corresponding to the textctrl contents. + Slic3r::Pointf3 get_point3() override; /// return a Slic3r::Pointf3 corresponding to the textctrl contents. + + void enable() override { _ctrl_x->Enable(); _ctrl_y->Enable(); _ctrl_z->Enable(); } + void disable() override { _ctrl_x->Disable(); _ctrl_y->Disable(); _ctrl_z->Disable(); } + + std::function value)> on_change {nullptr}; + + /// Local-access items + wxTextCtrl* ctrl_x() { return _ctrl_x;} + wxTextCtrl* ctrl_y() { return _ctrl_y;} + wxTextCtrl* ctrl_z() { return _ctrl_z;} + + wxStaticText* lbl_x() { return _lbl_x;} + wxStaticText* lbl_y() { return _lbl_y;} + wxStaticText* lbl_z() { return _lbl_z;} + +protected: + virtual std::string LogChannel() override { return "UI_Point3"s; } + + void _on_change(std::string opt_id) override { + if (!this->disable_change_event && this->_ctrl_x->IsEnabled() && this->on_change != nullptr) { + this->on_change(opt_id, std::make_tuple(_ctrl_x->GetValue().ToStdString(), _ctrl_y->GetValue().ToStdString(), _ctrl_z->GetValue().ToStdString())); + } } +private: + wxSize field_size {40, 1}; + wxStaticText* _lbl_x {nullptr}; + wxStaticText* _lbl_y {nullptr}; + wxStaticText* _lbl_z {nullptr}; + wxTextCtrl* _ctrl_x {nullptr}; + wxTextCtrl* _ctrl_y {nullptr}; + wxTextCtrl* _ctrl_z {nullptr}; + + wxBoxSizer* _sizer {nullptr}; + + void _set_value(Slic3r::Pointf value); + void _set_value(Slic3r::Pointf3 value); + void _set_value(std::string value); }; diff --git a/src/GUI/OptionsGroup/UI_Point3.cpp b/src/GUI/OptionsGroup/UI_Point3.cpp new file mode 100644 index 000000000..6164a1c9f --- /dev/null +++ b/src/GUI/OptionsGroup/UI_Point3.cpp @@ -0,0 +1,131 @@ +#include "OptionsGroup/Field.hpp" +#include "misc_ui.hpp" +#include "Log.hpp" + +#include + +namespace Slic3r { namespace GUI { + +using namespace std::string_literals; + +std::string UI_Point3::get_string() { + std::string result {""}; + if (_ctrl_x->GetValue().ToStdString() == "") { + result.append("0.0"); + } else { + result.append(trim_zeroes(_ctrl_x->GetValue().ToStdString())); + } + result.append(";"s); + if (_ctrl_y->GetValue().ToStdString() == "") { + result.append("0.0"); + } else { + result.append(trim_zeroes(_ctrl_y->GetValue().ToStdString())); + } + result.append(";"s); + if (_ctrl_z->GetValue().ToStdString() == "") { + result.append("0.0"); + } else { + result.append(trim_zeroes(_ctrl_z->GetValue().ToStdString())); + } + return result; +} + +Slic3r::Pointf3 UI_Point3::get_point3() { + return Pointf3( + this->_ctrl_x->GetValue().ToStdString() != ""s ? std::stod(this->_ctrl_x->GetValue().ToStdString()) : 0.0, + this->_ctrl_y->GetValue().ToStdString() != ""s ? std::stod(this->_ctrl_y->GetValue().ToStdString()) : 0.0, + this->_ctrl_z->GetValue().ToStdString() != ""s ? std::stod(this->_ctrl_z->GetValue().ToStdString()) : 0.0 + ); +} +Slic3r::Pointf UI_Point3::get_point() { + return Pointf( + this->_ctrl_x->GetValue().ToStdString() != ""s ? std::stod(this->_ctrl_x->GetValue().ToStdString()) : 0.0, + this->_ctrl_y->GetValue().ToStdString() != ""s ? std::stod(this->_ctrl_y->GetValue().ToStdString()) : 0.0 + ); +} +void UI_Point3::set_value(boost::any value) { + // type detection and handing off to children + if (value.type() == typeid(Slic3r::Pointf)) { + this->_set_value(boost::any_cast(value)); + } else if (value.type() == typeid(Slic3r::Pointf3)) { + this->_set_value(boost::any_cast(value)); + } else if (value.type() == typeid(std::string)) { + this->_set_value(boost::any_cast(value)); + } else if (value.type() == typeid(wxString)) { + this->_set_value(boost::any_cast(value).ToStdString()); + } else { + Slic3r::Log::warn(this->LogChannel(), LOG_WSTRING("Type " << value.type().name() << " is not handled in set_value.")); + } +} + +void UI_Point3::_set_value(Slic3r::Pointf value) { + /// load the controls directly from the value + this->_ctrl_x->SetValue(trim_zeroes(std::to_string(value.x))); + this->_ctrl_y->SetValue(trim_zeroes(std::to_string(value.y))); + this->_ctrl_z->SetValue("0.0"); +} + +void UI_Point3::_set_value(Slic3r::Pointf3 value) { + /// load the controls directly from the value + this->_ctrl_x->SetValue(trim_zeroes(std::to_string(value.x))); + this->_ctrl_y->SetValue(trim_zeroes(std::to_string(value.y))); + this->_ctrl_z->SetValue(trim_zeroes(std::to_string(value.z))); +} + +void UI_Point3::_set_value(std::string value) { + /// parse the string into the two parts. + std::regex format_regex(";"); + auto f_begin { std::sregex_token_iterator(value.begin(), value.end(), format_regex, -1) }; + auto f_end { std::sregex_token_iterator() }; + + if (f_begin != f_end) { + auto iter = f_begin; + this->_ctrl_x->SetValue(trim_zeroes(iter->str())); + iter++; + if (iter != f_end) + this->_ctrl_y->SetValue(trim_zeroes(iter->str())); + iter++; + if (iter != f_end) + this->_ctrl_z->SetValue(trim_zeroes(iter->str())); + } + + +} + +UI_Point3::UI_Point3(wxWindow* _parent, Slic3r::ConfigOptionDef _opt) : UI_Sizer(_parent, _opt) { + Slic3r::Pointf3 def_val {_opt.default_value == nullptr ? Pointf3() : Pointf3(*(dynamic_cast(_opt.default_value))) }; + + this->_ctrl_x = new wxTextCtrl(parent, wxID_ANY, trim_zeroes(wxString::FromDouble(def_val.x)), wxDefaultPosition, this->field_size, wxTE_PROCESS_ENTER); + this->_ctrl_y = new wxTextCtrl(parent, wxID_ANY, trim_zeroes(wxString::FromDouble(def_val.y)), wxDefaultPosition, this->field_size, wxTE_PROCESS_ENTER); + this->_ctrl_z = new wxTextCtrl(parent, wxID_ANY, trim_zeroes(wxString::FromDouble(def_val.z)), wxDefaultPosition, this->field_size, wxTE_PROCESS_ENTER); + + this->_lbl_x = new wxStaticText(parent, wxID_ANY, wxString("x:")); + this->_lbl_y = new wxStaticText(parent, wxID_ANY, wxString("y:")); + this->_lbl_z = new wxStaticText(parent, wxID_ANY, wxString("z:")); + + this->_sizer = new wxBoxSizer(wxHORIZONTAL); + this->sizer = _sizer; + + this->_sizer->Add(_lbl_x, 0, wxALIGN_CENTER_VERTICAL, 0); + this->_sizer->Add(_ctrl_x, 0, wxALIGN_CENTER_VERTICAL, 0); + this->_sizer->Add(_lbl_y, 0, wxALIGN_CENTER_VERTICAL, 0); + this->_sizer->Add(_ctrl_y, 0, wxALIGN_CENTER_VERTICAL, 0); + this->_sizer->Add(_lbl_z, 0, wxALIGN_CENTER_VERTICAL, 0); + this->_sizer->Add(_ctrl_z, 0, wxALIGN_CENTER_VERTICAL, 0); + + if (this->opt.tooltip != ""s) { + this->_ctrl_x->SetToolTip(this->opt.tooltip); + this->_ctrl_y->SetToolTip(this->opt.tooltip); + this->_ctrl_z->SetToolTip(this->opt.tooltip); + } + + // events + _ctrl_x->Bind(wxEVT_TEXT_ENTER, [this](wxCommandEvent& e) { this->_on_change(""); e.Skip(); }); + _ctrl_y->Bind(wxEVT_TEXT_ENTER, [this](wxCommandEvent& e) { this->_on_change(""); e.Skip(); }); + _ctrl_z->Bind(wxEVT_TEXT_ENTER, [this](wxCommandEvent& e) { this->_on_change(""); e.Skip(); }); + _ctrl_x->Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent& e) { if (this->on_kill_focus != nullptr) {this->on_kill_focus(""); this->_on_change("");} e.Skip(); }); + _ctrl_y->Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent& e) { if (this->on_kill_focus != nullptr) {this->on_kill_focus(""); this->_on_change("");} e.Skip(); }); + _ctrl_z->Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent& e) { if (this->on_kill_focus != nullptr) {this->on_kill_focus(""); this->_on_change("");} e.Skip(); }); +} + +} } // Namespace Slic3r::GUI diff --git a/src/test/GUI/test_field_point3.cpp b/src/test/GUI/test_field_point3.cpp index aaeedfd15..8cf6f3951 100644 --- a/src/test/GUI/test_field_point3.cpp +++ b/src/test/GUI/test_field_point3.cpp @@ -23,9 +23,9 @@ SCENARIO( "UI_Point3: default values from options and basic accessor methods") { wxUIActionSimulator sim; wxMilliSleep(500); - GIVEN( "A UI point method and a X,Y coordinate (3.2, 10.2) as the default_value") { + GIVEN( "A UI point method and a X,Y coordinate (3.2, 10.2, 0.0) as the default_value") { auto simple_option {ConfigOptionDef()}; - auto* default_point {new ConfigOptionPoint(Pointf(3.2, 10.2))}; + auto* default_point {new ConfigOptionPoint3(Pointf3(3.2, 10.2, 0.0))}; simple_option.default_value = default_point; auto test_field {Slic3r::GUI::UI_Point3(wxTheApp->GetTopWindow(), simple_option)}; @@ -44,7 +44,7 @@ SCENARIO( "UI_Point3: default values from options and basic accessor methods") { } GIVEN( "A UI point, coordinate in X/Y/Z and a tooltip in simple_option") { auto simple_option {ConfigOptionDef()}; - auto* default_point {new ConfigOptionPoint(Pointf3(3.2, 10.2, 0.2))}; + auto* default_point {new ConfigOptionPoint3(Pointf3(3.2, 10.2, 0.2))}; simple_option.default_value = default_point; auto test_field {Slic3r::GUI::UI_Point3(wxTheApp->GetTopWindow(), simple_option)}; @@ -122,7 +122,7 @@ SCENARIO( "UI_Point3: set_value works with several types of inputs") { WHEN( "set_value is called with a string of the form '30.9;211.2;411.0'") { test_field.set_value("30.9;211.2;411.0"s); THEN( "get_point3() returns a Pointf3(30.9, 211.2, 411.0)") { - REQUIRE(test_field.get_point3() == Pointf(30.9, 211.2, 411.0)); + REQUIRE(test_field.get_point3() == Pointf3(30.9, 211.2, 411.0)); } THEN( "get_point() returns a Pointf(30.9, 211.2)") { REQUIRE(test_field.get_point() == Pointf(30.9, 211.2)); @@ -173,7 +173,7 @@ SCENARIO( "UI_Point3: Event responses") { auto simple_option {ConfigOptionDef()}; auto test_field {Slic3r::GUI::UI_Point3(wxTheApp->GetTopWindow(), simple_option)}; auto event_count {0}; - auto changefunc {[&event_count] (const std::string& opt_id, std::tuple value) { event_count++; }}; + auto changefunc {[&event_count] (const std::string& opt_id, std::tuple value) { event_count++; }}; auto killfunc {[&event_count](const std::string& opt_id) { event_count++; }}; test_field.on_change = changefunc; @@ -240,7 +240,7 @@ SCENARIO( "UI_Point3: Event responses") { auto simple_option {ConfigOptionDef()}; auto test_field {Slic3r::GUI::UI_Point3(wxTheApp->GetTopWindow(), simple_option)}; auto event_count {0}; - auto changefunc {[&event_count] (const std::string& opt_id, std::tuple value) { event_count++; }}; + auto changefunc {[&event_count] (const std::string& opt_id, std::tuple value) { event_count++; }}; auto killfunc {[&event_count](const std::string& opt_id) { event_count += 1; }}; test_field.on_change = changefunc;