mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-14 18:55:59 +08:00
Added NumericChoice implementation along with tests.
Also added get_double() to interface.
This commit is contained in:
parent
dea6896c8e
commit
e8bb3f7e37
@ -180,6 +180,7 @@ set(UI_TEST_SOURCES
|
|||||||
${GUI_TESTDIR}/test_field_spinctrl.cpp
|
${GUI_TESTDIR}/test_field_spinctrl.cpp
|
||||||
${GUI_TESTDIR}/test_field_textbox.cpp
|
${GUI_TESTDIR}/test_field_textbox.cpp
|
||||||
${GUI_TESTDIR}/test_field_choice.cpp
|
${GUI_TESTDIR}/test_field_choice.cpp
|
||||||
|
${GUI_TESTDIR}/test_field_numchoice.cpp
|
||||||
)
|
)
|
||||||
set(SLIC3R_TEST_SOURCES
|
set(SLIC3R_TEST_SOURCES
|
||||||
${TESTDIR}/test_harness.cpp
|
${TESTDIR}/test_harness.cpp
|
||||||
@ -258,6 +259,7 @@ IF(wxWidgets_FOUND)
|
|||||||
${GUI_LIBDIR}/ProgressStatusBar.cpp
|
${GUI_LIBDIR}/ProgressStatusBar.cpp
|
||||||
${GUI_LIBDIR}/Settings.cpp
|
${GUI_LIBDIR}/Settings.cpp
|
||||||
${GUI_LIBDIR}/misc_ui.cpp
|
${GUI_LIBDIR}/misc_ui.cpp
|
||||||
|
${GUI_LIBDIR}/OptionsGroup/UI_NumChoice.cpp
|
||||||
)
|
)
|
||||||
target_compile_features(slic3r_gui PUBLIC cxx_std_14)
|
target_compile_features(slic3r_gui PUBLIC cxx_std_14)
|
||||||
#only build GUI lib if building with wx
|
#only build GUI lib if building with wx
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
#include <boost/any.hpp>
|
#include <boost/any.hpp>
|
||||||
#include "ConfigBase.hpp"
|
#include "ConfigBase.hpp"
|
||||||
#include "Log.hpp"
|
#include "Log.hpp"
|
||||||
@ -40,6 +42,7 @@ public:
|
|||||||
|
|
||||||
/// Getter functions for UI_Window items.
|
/// 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 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 double get_double() { Slic3r::Log::warn(this->LogChannel(), "get_double does not exist"s); return 0.0; } //< return 0.0 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.
|
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.
|
||||||
virtual std::string get_string() { Slic3r::Log::warn(this->LogChannel(), "get_string does not exist"s); return 0; } //< return 0 all the time if this is not implemented.
|
virtual std::string get_string() { Slic3r::Log::warn(this->LogChannel(), "get_string does not exist"s); return 0; } //< return 0 all the time if this is not implemented.
|
||||||
|
|
||||||
@ -247,6 +250,50 @@ private:
|
|||||||
wxComboBox* _choice {nullptr};
|
wxComboBox* _choice {nullptr};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class UI_NumChoice : public UI_Window {
|
||||||
|
public:
|
||||||
|
UI_NumChoice(wxWindow* parent, Slic3r::ConfigOptionDef _opt, wxWindowID id = wxID_ANY);
|
||||||
|
~UI_NumChoice() { _choice->Destroy(); }
|
||||||
|
|
||||||
|
/// Returns the underlying value for the selected value (defined by enum_values). If there are labels, this may not
|
||||||
|
/// match the underlying combobox->GetValue().
|
||||||
|
std::string get_string() override;
|
||||||
|
|
||||||
|
/// Returns the item in the value field of the associated option as an integer.
|
||||||
|
int get_int() override { return std::stoi(this->get_string()); }
|
||||||
|
|
||||||
|
/// Returns the item in the value field of the associated option as a double.
|
||||||
|
double get_double() override { return std::stod(this->get_string()); }
|
||||||
|
|
||||||
|
|
||||||
|
/// Returns a bare pointer to the underlying combobox, usually for test interface
|
||||||
|
wxComboBox* choice() { return this->_choice; }
|
||||||
|
|
||||||
|
/// For NumChoice, value can be the actual input value or an index into the value.
|
||||||
|
void set_value(boost::any value) override;
|
||||||
|
|
||||||
|
/// Function to call when the contents of this change.
|
||||||
|
std::function<void (const std::string&, std::string value)> on_change {nullptr};
|
||||||
|
protected:
|
||||||
|
virtual std::string LogChannel() override { return "UI_NumChoice"s; }
|
||||||
|
|
||||||
|
void _set_value(int value, bool show_value = false);
|
||||||
|
void _set_value(double value, bool show_value = false);
|
||||||
|
void _set_value(std::string value);
|
||||||
|
|
||||||
|
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_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
wxComboBox* _choice {nullptr};
|
||||||
|
std::regex show_value_flag {"\bshow_value\b"};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} } // Namespace Slic3r::GUI
|
} } // Namespace Slic3r::GUI
|
||||||
|
|
||||||
#endif // SLIC3R_FIELD_HPP
|
#endif // SLIC3R_FIELD_HPP
|
||||||
|
135
src/GUI/OptionsGroup/UI_NumChoice.cpp
Normal file
135
src/GUI/OptionsGroup/UI_NumChoice.cpp
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
#include "OptionsGroup/Field.hpp"
|
||||||
|
#include "misc_ui.hpp"
|
||||||
|
#include <typeinfo>
|
||||||
|
|
||||||
|
namespace Slic3r { namespace GUI {
|
||||||
|
|
||||||
|
void UI_NumChoice::set_value(boost::any value) {
|
||||||
|
const bool show_value { std::regex_search(this->opt.gui_flags, show_value_flag) };
|
||||||
|
|
||||||
|
if (value.type() == typeid(int)) {
|
||||||
|
this->_set_value(boost::any_cast<int>(value), show_value); return;
|
||||||
|
} else if (value.type() == typeid(double)) {
|
||||||
|
this->_set_value(boost::any_cast<double>(value), show_value); return;
|
||||||
|
} else if (value.type() == typeid(float)) {
|
||||||
|
this->_set_value(boost::any_cast<float>(value), show_value); return;
|
||||||
|
} else if (value.type() == typeid(std::string)) {
|
||||||
|
this->_set_value(boost::any_cast<std::string>(value)); return;
|
||||||
|
} else if (value.type() == typeid(wxString)) {
|
||||||
|
this->_set_value(boost::any_cast<wxString>(value).ToStdString()); return;
|
||||||
|
} else {
|
||||||
|
Slic3r::Log::warn(this->LogChannel(), LOG_WSTRING(wxString("Unsupported type ") + value.type().name() + wxString(" for set_value") ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Specialized set_value function for an input that is either a direct input or
|
||||||
|
// an index to the label vector.
|
||||||
|
void UI_NumChoice::_set_value(int value, bool show_value) {
|
||||||
|
auto& vlist {this->opt.enum_values}; // alias the vector to type less
|
||||||
|
auto& llist {this->opt.enum_labels};
|
||||||
|
if (show_value) {
|
||||||
|
Slic3r::Log::info(this->LogChannel(), "Using show_value branch");
|
||||||
|
this->_choice->ChangeValue(std::to_string(value));
|
||||||
|
} else {
|
||||||
|
if (vlist.size() > 0) {
|
||||||
|
Slic3r::Log::info(this->LogChannel(), LOG_WSTRING(wxString("Searching values vector for ") + wxString(std::to_string(value))));
|
||||||
|
// search the values vector for our input
|
||||||
|
auto result {std::find(vlist.cbegin(), vlist.cend(), std::to_string(value))};
|
||||||
|
if (result != vlist.cend()) {
|
||||||
|
auto value_idx {std::distance(vlist.cbegin(), result)};
|
||||||
|
Slic3r::Log::info(this->LogChannel(), LOG_WSTRING(wxString("Found. Setting selection to ") + wxString(std::to_string(value_idx))));
|
||||||
|
this->_choice->SetSelection(value_idx);
|
||||||
|
this->disable_change_event = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (llist.size() > 0 && static_cast<size_t>(value) < llist.size()) {
|
||||||
|
Slic3r::Log::info(this->LogChannel(), LOG_WSTRING(wxString("Setting label value to ") + wxString(llist.at(value))));
|
||||||
|
/// if there isn't a value list but there is a label list, this is an index to that list.
|
||||||
|
this->_choice->SetValue(wxString(llist.at(value)));
|
||||||
|
this->disable_change_event = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->_choice->SetValue(wxString(std::to_string(value)));
|
||||||
|
}
|
||||||
|
this->disable_change_event = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// In this case, can't be a numeric index.
|
||||||
|
void UI_NumChoice::_set_value(double value, bool show_value) {
|
||||||
|
if (show_value) {
|
||||||
|
this->_choice->ChangeValue(std::to_string(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// In this case, can't be a numeric index.
|
||||||
|
void UI_NumChoice::_set_value(std::string value) {
|
||||||
|
this->_choice->ChangeValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string UI_NumChoice::get_string() {
|
||||||
|
if (opt.enum_values.size() > 0) {
|
||||||
|
auto idx = this->_choice->GetSelection();
|
||||||
|
Slic3r::Log::debug(this->LogChannel(), LOG_WSTRING(this->_choice->GetString(idx) + " <-- label"));
|
||||||
|
Slic3r::Log::debug(this->LogChannel(), LOG_WSTRING(wxString("Selection for ") + this->_choice->GetValue() + wxString(": ") + wxString(std::to_string(idx))));
|
||||||
|
if (idx != wxNOT_FOUND) return this->opt.enum_values.at(idx);
|
||||||
|
}
|
||||||
|
Slic3r::Log::debug(this->LogChannel(), "Returning label as value");
|
||||||
|
return this->_choice->GetValue().ToStdString();
|
||||||
|
}
|
||||||
|
|
||||||
|
UI_NumChoice::UI_NumChoice(wxWindow* parent, Slic3r::ConfigOptionDef _opt, wxWindowID id) : UI_Window(parent, _opt) {
|
||||||
|
int style {0};
|
||||||
|
style |= wxTE_PROCESS_ENTER;
|
||||||
|
if (opt.gui_type.size() > 0 && opt.gui_type.compare("select_open"s)) style |= wxCB_READONLY;
|
||||||
|
|
||||||
|
/// Load the values
|
||||||
|
auto values {wxArrayString()};
|
||||||
|
if (opt.enum_labels.size() > 0) // if we have labels, use those instead.
|
||||||
|
for (auto v : opt.enum_labels) values.Add(wxString(v));
|
||||||
|
else
|
||||||
|
for (auto v : opt.enum_values) values.Add(wxString(v));
|
||||||
|
|
||||||
|
|
||||||
|
_choice = new wxComboBox(parent, id,
|
||||||
|
(opt.default_value != nullptr ? opt.default_value->getString() : ""),
|
||||||
|
wxDefaultPosition, _default_size(), values, style);
|
||||||
|
window = _choice;
|
||||||
|
|
||||||
|
this->set_value(opt.default_value != nullptr ? opt.default_value->getString() : "");
|
||||||
|
|
||||||
|
|
||||||
|
// Event handler for data entry and changing the combobox
|
||||||
|
auto pickup = [this](wxCommandEvent& e)
|
||||||
|
{
|
||||||
|
auto disable_change {this->disable_change_event};
|
||||||
|
this->disable_change_event = true;
|
||||||
|
|
||||||
|
auto idx {this->_choice->GetSelection()};
|
||||||
|
wxString lbl {""};
|
||||||
|
|
||||||
|
if (this->opt.enum_labels.size() > 0 && (unsigned)idx <= this->opt.enum_labels.size()) {
|
||||||
|
lbl << this->opt.enum_labels.at(idx);
|
||||||
|
} else if (this->opt.enum_values.size() > 0 && (unsigned)idx <= this->opt.enum_values.size()) {
|
||||||
|
lbl << this->opt.enum_values.at(idx);
|
||||||
|
} else {
|
||||||
|
lbl << idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// avoid leaving field blank on wxMSW
|
||||||
|
this->_choice->CallAfter([this,lbl]() {
|
||||||
|
auto dce {this->disable_change_event};
|
||||||
|
this->disable_change_event = true;
|
||||||
|
this->_choice->SetValue(lbl);
|
||||||
|
this->disable_change_event = dce;
|
||||||
|
});
|
||||||
|
|
||||||
|
this->disable_change_event = disable_change;
|
||||||
|
this->_on_change("");
|
||||||
|
};
|
||||||
|
_choice->Bind(wxEVT_COMBOBOX, pickup);
|
||||||
|
_choice->Bind(wxEVT_TEXT_ENTER, [this](wxCommandEvent& e) { this->set_value(this->_choice->GetValue()); this->_on_change(""); } );
|
||||||
|
_choice->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
|
312
src/test/GUI/test_field_numchoice.cpp
Normal file
312
src/test/GUI/test_field_numchoice.cpp
Normal file
@ -0,0 +1,312 @@
|
|||||||
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#ifndef WX_PRECOMP
|
||||||
|
#include "wx/app.h"
|
||||||
|
#include "wx/uiaction.h"
|
||||||
|
#endif // WX_PRECOMP
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "testableframe.h"
|
||||||
|
#include "OptionsGroup/Field.hpp"
|
||||||
|
#include "ConfigBase.hpp"
|
||||||
|
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
|
SCENARIO( "UI_NumChoice: default values from options") {
|
||||||
|
wxTestableFrame* old = dynamic_cast<wxTestableFrame*>(wxTheApp->GetTopWindow());
|
||||||
|
old->Destroy();
|
||||||
|
wxTheApp->SetTopWindow(new wxTestableFrame());
|
||||||
|
wxUIActionSimulator sim;
|
||||||
|
wxMilliSleep(500);
|
||||||
|
|
||||||
|
GIVEN( "I have a UI NumChoice with 3 options from ConfigOptionDef that has only values and a default_value that is not in the enumeration.") {
|
||||||
|
auto simple_option {ConfigOptionDef()};
|
||||||
|
auto* default_string {new ConfigOptionString("1")};
|
||||||
|
|
||||||
|
simple_option.default_value = default_string; // owned by ConfigOptionDef
|
||||||
|
simple_option.enum_values.push_back("2");
|
||||||
|
simple_option.enum_values.push_back("3");
|
||||||
|
simple_option.enum_values.push_back("4");
|
||||||
|
|
||||||
|
auto test_field {Slic3r::GUI::UI_NumChoice(wxTheApp->GetTopWindow(), simple_option)};
|
||||||
|
|
||||||
|
wxTheApp->GetTopWindow()->Show();
|
||||||
|
wxTheApp->GetTopWindow()->Fit();
|
||||||
|
|
||||||
|
WHEN( "I don't explicitly select any option in the drop-down") {
|
||||||
|
THEN( "get_value() returns the the value associated with the listed default option in the related ConfigOptionDef") {
|
||||||
|
REQUIRE(test_field.get_string() == simple_option.default_value->getString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN( "I select the first option in the drop-down") {
|
||||||
|
test_field.choice()->SetSelection(0);
|
||||||
|
THEN( "get_value() returns the the value associated with the first option in the related ConfigOptionDef") {
|
||||||
|
REQUIRE(test_field.get_string() == simple_option.enum_values[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN( "I select the second option in the drop-down") {
|
||||||
|
test_field.choice()->SetSelection(1);
|
||||||
|
THEN( "get_value() returns the the value associated with the second option in the related ConfigOptionDef") {
|
||||||
|
REQUIRE(test_field.get_string() == simple_option.enum_values[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN( "I select the third option in the drop-down") {
|
||||||
|
test_field.choice()->SetSelection(2);
|
||||||
|
THEN( "get_value() returns the the value associated with the third option in the related ConfigOptionDef") {
|
||||||
|
REQUIRE(test_field.get_string() == simple_option.enum_values[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GIVEN( "I have a UI NumChoice with 3 options from ConfigOptionDef that has only values and a default_value that is in the enumeration.") {
|
||||||
|
auto simple_option {ConfigOptionDef()};
|
||||||
|
auto* default_string {new ConfigOptionString("2"s)};
|
||||||
|
|
||||||
|
simple_option.default_value = default_string; // owned by ConfigOptionDef
|
||||||
|
simple_option.enum_values.push_back("2");
|
||||||
|
simple_option.enum_values.push_back("3");
|
||||||
|
simple_option.enum_values.push_back("4");
|
||||||
|
|
||||||
|
auto test_field {Slic3r::GUI::UI_NumChoice(wxTheApp->GetTopWindow(), simple_option)};
|
||||||
|
wxTheApp->GetTopWindow()->Show();
|
||||||
|
wxTheApp->GetTopWindow()->Fit();
|
||||||
|
|
||||||
|
WHEN( "I don't explicitly select any option in the drop-down") {
|
||||||
|
THEN( "get_value() returns the first value in the related ConfigOptionDef") {
|
||||||
|
REQUIRE(simple_option.enum_values[0] == test_field.get_string());
|
||||||
|
REQUIRE(test_field.choice()->FindString(simple_option.enum_values[0]) == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN( "I set the string value to another item in the enumeration") {
|
||||||
|
test_field.choice()->SetValue("3"s);
|
||||||
|
THEN( "get_string() returns the matching item in ConfigOptionDef") {
|
||||||
|
REQUIRE(test_field.get_string() == "3"s);
|
||||||
|
}
|
||||||
|
THEN( "get_int() returns the matching item in ConfigOptionDef as an integer") {
|
||||||
|
REQUIRE(test_field.get_int() == 3);
|
||||||
|
}
|
||||||
|
THEN( "get_double() returns the matching item in ConfigOptionDef as a double") {
|
||||||
|
REQUIRE(test_field.get_double() == 3.0);
|
||||||
|
}
|
||||||
|
THEN( "Combobox string shows up as the first enumeration value.") {
|
||||||
|
REQUIRE(test_field.choice()->GetValue() == simple_option.enum_values[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN( "I set the string value to another item that is not in the enumeration") {
|
||||||
|
test_field.choice()->SetValue("7"s);
|
||||||
|
THEN( "get_string() returns the matching item in ConfigOptionDef") {
|
||||||
|
REQUIRE(test_field.get_string() == "7"s);
|
||||||
|
REQUIRE(test_field.get_int() == 7);
|
||||||
|
REQUIRE(test_field.get_double() == 7.0);
|
||||||
|
REQUIRE(test_field.choice()->GetSelection() == wxNOT_FOUND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GIVEN( "I have a UI NumChoice with 3 options from ConfigOptionDef that has values that are doubles and labels and a default_value that is not in the enumeration.") {
|
||||||
|
auto simple_option {ConfigOptionDef()};
|
||||||
|
auto* default_int {new ConfigOptionFloat(1.0)};
|
||||||
|
|
||||||
|
simple_option.default_value = default_int; // owned by ConfigOptionDef
|
||||||
|
simple_option.enum_values.push_back("2.2");
|
||||||
|
simple_option.enum_values.push_back("3.3");
|
||||||
|
simple_option.enum_values.push_back("4.4");
|
||||||
|
|
||||||
|
simple_option.enum_labels.push_back("B");
|
||||||
|
simple_option.enum_labels.push_back("C");
|
||||||
|
simple_option.enum_labels.push_back("D");
|
||||||
|
|
||||||
|
auto test_field {Slic3r::GUI::UI_NumChoice(wxTheApp->GetTopWindow(), simple_option)};
|
||||||
|
wxTheApp->GetTopWindow()->Show();
|
||||||
|
wxTheApp->GetTopWindow()->Fit();
|
||||||
|
|
||||||
|
WHEN( "I don't explicitly select any option in the drop-down") {
|
||||||
|
THEN( "get_value() returns the the value associated with the listed default option in the related ConfigOptionDef") {
|
||||||
|
REQUIRE(simple_option.default_value->getString() == test_field.get_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN( "I select the first option in the drop-down") {
|
||||||
|
test_field.choice()->SetSelection(0);
|
||||||
|
THEN( "get_value() returns the the value associated with the first option in the related ConfigOptionDef") {
|
||||||
|
REQUIRE(simple_option.enum_values[0] == test_field.get_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN( "I select the second option in the drop-down") {
|
||||||
|
test_field.choice()->SetSelection(1);
|
||||||
|
THEN( "get_value() returns the the value associated with the second option in the related ConfigOptionDef") {
|
||||||
|
REQUIRE(simple_option.enum_values[1] == test_field.get_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN( "I select the third option in the drop-down") {
|
||||||
|
test_field.choice()->SetSelection(2);
|
||||||
|
THEN( "get_value() returns the the value associated with the third option in the related ConfigOptionDef") {
|
||||||
|
REQUIRE(simple_option.enum_values[2] == test_field.get_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GIVEN( "I have a UI NumChoice with 3 options from ConfigOptionDef that has values and labels and a default_value that is not in the enumeration.") {
|
||||||
|
auto simple_option {ConfigOptionDef()};
|
||||||
|
auto* default_int {new ConfigOptionInt(1)};
|
||||||
|
|
||||||
|
simple_option.default_value = default_int; // owned by ConfigOptionDef
|
||||||
|
simple_option.enum_values.push_back("2");
|
||||||
|
simple_option.enum_values.push_back("3");
|
||||||
|
simple_option.enum_values.push_back("4");
|
||||||
|
|
||||||
|
simple_option.enum_labels.push_back("B");
|
||||||
|
simple_option.enum_labels.push_back("C");
|
||||||
|
simple_option.enum_labels.push_back("D");
|
||||||
|
|
||||||
|
auto test_field {Slic3r::GUI::UI_NumChoice(wxTheApp->GetTopWindow(), simple_option)};
|
||||||
|
wxTheApp->GetTopWindow()->Show();
|
||||||
|
wxTheApp->GetTopWindow()->Fit();
|
||||||
|
|
||||||
|
WHEN( "I don't explicitly select any option in the drop-down") {
|
||||||
|
THEN( "get_value() returns the the value associated with the listed default option in the related ConfigOptionDef") {
|
||||||
|
REQUIRE(simple_option.default_value->getString() == test_field.get_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN( "I select the first option in the drop-down") {
|
||||||
|
test_field.choice()->SetSelection(0);
|
||||||
|
THEN( "get_value() returns the the value associated with the first option in the related ConfigOptionDef") {
|
||||||
|
REQUIRE(simple_option.enum_values[0] == test_field.get_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN( "I select the second option in the drop-down") {
|
||||||
|
test_field.choice()->SetSelection(1);
|
||||||
|
THEN( "get_value() returns the the value associated with the second option in the related ConfigOptionDef") {
|
||||||
|
REQUIRE(simple_option.enum_values[1] == test_field.get_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN( "I select the third option in the drop-down") {
|
||||||
|
test_field.choice()->SetSelection(2);
|
||||||
|
THEN( "get_value() returns the the value associated with the third option in the related ConfigOptionDef") {
|
||||||
|
REQUIRE(simple_option.enum_values[2] == test_field.get_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GIVEN( "I have a UI NumChoice with 3 options from ConfigOptionDef that has values and labels and a default_value that is in the enumeration.") {
|
||||||
|
auto simple_option {ConfigOptionDef()};
|
||||||
|
auto* default_string {new ConfigOptionString("2"s)};
|
||||||
|
|
||||||
|
simple_option.default_value = default_string; // owned by ConfigOptionDef
|
||||||
|
simple_option.enum_values.push_back("2");
|
||||||
|
simple_option.enum_values.push_back("3");
|
||||||
|
simple_option.enum_values.push_back("4");
|
||||||
|
|
||||||
|
simple_option.enum_labels.push_back("B");
|
||||||
|
simple_option.enum_labels.push_back("C");
|
||||||
|
simple_option.enum_labels.push_back("D");
|
||||||
|
|
||||||
|
auto test_field {Slic3r::GUI::UI_NumChoice(wxTheApp->GetTopWindow(), simple_option)};
|
||||||
|
|
||||||
|
wxTheApp->GetTopWindow()->Show();
|
||||||
|
wxTheApp->GetTopWindow()->Fit();
|
||||||
|
|
||||||
|
WHEN( "I don't explicitly select any option in the drop-down") {
|
||||||
|
THEN( "get_value functions return the first value in the related ConfigOptionDef") {
|
||||||
|
REQUIRE(test_field.get_string() == simple_option.enum_values[0]);
|
||||||
|
}
|
||||||
|
THEN( "get_int() returns the matching item in ConfigOptionDef as an integer") {
|
||||||
|
REQUIRE(test_field.get_int() == 2);
|
||||||
|
}
|
||||||
|
THEN( "get_double() returns the matching item in ConfigOptionDef as a double") {
|
||||||
|
REQUIRE(test_field.get_double() == 2.0);
|
||||||
|
}
|
||||||
|
THEN( "choice.FindString returns the label matching the item") {
|
||||||
|
REQUIRE(test_field.choice()->FindString(simple_option.enum_labels[0]) == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN( "I set the string value to another item in the enumeration") {
|
||||||
|
test_field.set_value(3);
|
||||||
|
THEN( "get_string() returns the matching item in ConfigOptionDef") {
|
||||||
|
REQUIRE(test_field.get_string() == "3"s);
|
||||||
|
}
|
||||||
|
THEN( "get_int() returns the matching item in ConfigOptionDef as an integer") {
|
||||||
|
REQUIRE(test_field.get_int() == 3);
|
||||||
|
}
|
||||||
|
THEN( "get_double() returns the matching item in ConfigOptionDef as a double") {
|
||||||
|
REQUIRE(test_field.get_double() == 3.0);
|
||||||
|
}
|
||||||
|
THEN( "choice.GetValue() returns the label.") {
|
||||||
|
REQUIRE(test_field.choice()->GetValue() == "C"s);
|
||||||
|
REQUIRE(test_field.choice()->FindString(simple_option.enum_labels[1]) == 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN( "I set the string value to another item that is not in the enumeration") {
|
||||||
|
test_field.set_value(7);
|
||||||
|
THEN( "get_string() returns the entered value.") {
|
||||||
|
REQUIRE(test_field.get_string() == "7"s);
|
||||||
|
}
|
||||||
|
THEN( "get_int() returns the entered value as an integer.") {
|
||||||
|
REQUIRE(test_field.get_int() == 7);
|
||||||
|
}
|
||||||
|
THEN( "get_double() returns the entered value as a double.") {
|
||||||
|
REQUIRE(test_field.get_double() == 7.0);
|
||||||
|
}
|
||||||
|
THEN( "Underlying selection is wxNOT_FOUND") {
|
||||||
|
REQUIRE(test_field.choice()->GetSelection() == wxNOT_FOUND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SCENARIO( "UI_NumChoice: event handling for on_change and on_kill_focus") {
|
||||||
|
auto event_count {0};
|
||||||
|
auto killfunc {[&event_count](const std::string& opt_id) { event_count += 1; }};
|
||||||
|
auto changefunc {[&event_count](const std::string& opt_id, std::string value) { event_count += 1; }};
|
||||||
|
GIVEN( "I have a UI NumChoice with 2 options from ConfigOptionDef, no default value, and an on_change handler and on_kill_focus handler.") {
|
||||||
|
auto simple_option {ConfigOptionDef()};
|
||||||
|
auto* default_string {new ConfigOptionString("2")};
|
||||||
|
|
||||||
|
simple_option.default_value = default_string; // owned by ConfigOptionDef
|
||||||
|
simple_option.enum_values.push_back("2");
|
||||||
|
simple_option.enum_values.push_back("3");
|
||||||
|
|
||||||
|
auto test_field {Slic3r::GUI::UI_NumChoice(wxTheApp->GetTopWindow(), simple_option)};
|
||||||
|
|
||||||
|
wxTheApp->GetTopWindow()->Show();
|
||||||
|
wxTheApp->GetTopWindow()->Fit();
|
||||||
|
|
||||||
|
test_field.on_kill_focus = killfunc;
|
||||||
|
test_field.on_change = changefunc;
|
||||||
|
|
||||||
|
WHEN( "I receive a wxEVT_COMBOBOX event") {
|
||||||
|
event_count = 0;
|
||||||
|
wxMilliSleep(250);
|
||||||
|
|
||||||
|
auto ev {wxCommandEvent(wxEVT_COMBOBOX, test_field.choice()->GetId())};
|
||||||
|
ev.SetEventObject(test_field.choice());
|
||||||
|
test_field.choice()->ProcessWindowEvent(ev);
|
||||||
|
THEN( "on_change handler is executed.") {
|
||||||
|
REQUIRE(event_count == 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN( "I receive a wxEVT_TEXT_ENTER event") {
|
||||||
|
event_count = 0;
|
||||||
|
wxMilliSleep(250);
|
||||||
|
|
||||||
|
auto ev {wxCommandEvent(wxEVT_TEXT_ENTER, test_field.choice()->GetId())};
|
||||||
|
ev.SetEventObject(test_field.choice());
|
||||||
|
test_field.choice()->ProcessWindowEvent(ev);
|
||||||
|
THEN( "on_change handler is executed.") {
|
||||||
|
REQUIRE(event_count == 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WHEN( "My control loses focus.") {
|
||||||
|
event_count = 0;
|
||||||
|
test_field.choice()->SetFocus();
|
||||||
|
wxMilliSleep(250);
|
||||||
|
|
||||||
|
auto ev {wxFocusEvent(wxEVT_KILL_FOCUS, test_field.choice()->GetId())};
|
||||||
|
ev.SetEventObject(test_field.choice());
|
||||||
|
test_field.choice()->ProcessWindowEvent(ev);
|
||||||
|
|
||||||
|
THEN( "on_change handler is executed and on_kill_focus handler is executed.") {
|
||||||
|
REQUIRE(event_count == 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -42,6 +42,15 @@ public:
|
|||||||
std::cerr << message << std::endl;
|
std::cerr << message << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void debug(std::string topic, std::wstring message) {
|
||||||
|
std::cerr << topic << " DEBUG" << ": ";
|
||||||
|
std::wcerr << message << std::endl;
|
||||||
|
}
|
||||||
|
static void debug(std::string topic, std::string message) {
|
||||||
|
std::cerr << topic << " DEBUG" << ": ";
|
||||||
|
std::cerr << message << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Utility debug function to transform a std::vector of anything that
|
/// Utility debug function to transform a std::vector of anything that
|
||||||
|
Loading…
x
Reference in New Issue
Block a user