diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index cdf344574..14386f381 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -136,6 +136,8 @@ bool Field::is_matched(const std::string& string, const std::string& pattern) return std::regex_match(string, regex_pattern); } +static wxString na_value() { return _(L("N/A")); } + void Field::get_value_by_opt_type(wxString& str) { switch (m_opt.type) { @@ -165,7 +167,9 @@ void Field::get_value_by_opt_type(wxString& str) val = 0.0; else { - if (!str.ToCDouble(&val)) + if (m_opt.nullable && str == na_value()) + val = ConfigOptionFloatsNullable::nil_value(); + else if (!str.ToCDouble(&val)) { show_error(m_parent, _(L("Invalid numeric input."))); set_value(double_to_string(val), true); @@ -346,6 +350,19 @@ void TextCtrl::propagate_value() on_kill_focus(); } +void TextCtrl::set_value(const boost::any& value, bool change_event/* = false*/) { + m_disable_change_event = !change_event; + if (m_opt.nullable) { + const bool m_is_na_val = boost::any_cast(value) == na_value(); + if (!m_is_na_val) + m_last_meaningful_value = value; + dynamic_cast(window)->SetValue(m_is_na_val ? na_value() : boost::any_cast(value)); + } + else + dynamic_cast(window)->SetValue(boost::any_cast(value)); + m_disable_change_event = false; +} + void TextCtrl::set_last_meaningful_value() { dynamic_cast(window)->SetValue(boost::any_cast(m_last_meaningful_value)); @@ -354,7 +371,7 @@ void TextCtrl::set_last_meaningful_value() void TextCtrl::set_na_value() { - dynamic_cast(window)->SetValue("nan"); + dynamic_cast(window)->SetValue(na_value()); propagate_value(); } diff --git a/src/slic3r/GUI/Field.hpp b/src/slic3r/GUI/Field.hpp index 6dbf4af06..49ff55d03 100644 --- a/src/slic3r/GUI/Field.hpp +++ b/src/slic3r/GUI/Field.hpp @@ -290,14 +290,7 @@ public: dynamic_cast(window)->SetValue(wxString(value)); m_disable_change_event = false; } - virtual void set_value(const boost::any& value, bool change_event = false) { - m_disable_change_event = !change_event; - dynamic_cast(window)->SetValue(boost::any_cast(value)); - if (boost::any_cast(value) != "nan") - m_last_meaningful_value = value; - m_disable_change_event = false; - } - + virtual void set_value(const boost::any& value, bool change_event = false) override; virtual void set_last_meaningful_value() override; virtual void set_na_value() override; diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index 2aca87d87..656e07a0e 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -565,10 +565,13 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config { case coPercents: case coFloats: { - double val = opt->type == coFloats ? - config.option(opt_key)->get_at(idx) : - config.option(opt_key)->get_at(idx); - ret = double_to_string(val); + if (config.option(opt_key)->is_nil()) + ret = _(L("N/A")); + else { + double val = opt->type == coFloats ? + config.option(opt_key)->get_at(idx) : + config.option(opt_key)->get_at(idx); + ret = double_to_string(val); } } break; case coBools: diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 4ff64de36..7bdaa0f2e 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1497,33 +1497,35 @@ void TabPrint::OnActivate() Tab::OnActivate(); } -static void check_line(const bool is_checked, ConfigOptionsGroupShp optgroup, const std::string& opt_key, int opt_index) -{ - Field* field = optgroup->get_fieldc(opt_key, opt_index); - if (field != nullptr) { - field->toggle(is_checked); - if (is_checked) - field->set_last_meaningful_value(); - else - field->set_na_value(); - } -}; - void TabFilament::add_filament_overrides_page() { PageShp page = add_options_page(_(L("Filament Overrides")), "wrench"); - ConfigOptionsGroupShp optgroup = page->new_optgroup(_(L("Retraction"))); auto append_single_option_line = [optgroup, this](const std::string& opt_key, int opt_index) { - Line line = optgroup->create_single_option_line(optgroup->get_option(opt_key)); + Line line {"",""}; + if (opt_key == "filament_retract_lift_above" || opt_key == "filament_retract_lift_below") { + Option opt = optgroup->get_option(opt_key); + opt.opt.label = opt.opt.full_label; + line = optgroup->create_single_option_line(opt); + } + else + line = optgroup->create_single_option_line(optgroup->get_option(opt_key)); line.near_label_widget = [this, optgroup, opt_key, opt_index](wxWindow* parent) { wxCheckBox* check_box = new wxCheckBox(parent, wxID_ANY, ""); check_box->Bind(wxEVT_CHECKBOX, [this, optgroup, opt_key, opt_index](wxCommandEvent& evt) { - check_line(evt.IsChecked(), optgroup, opt_key, opt_index); + const bool is_checked = evt.IsChecked(); + Field* field = optgroup->get_fieldc(opt_key, opt_index); + if (field != nullptr) { + field->toggle(is_checked); + if (is_checked) + field->set_last_meaningful_value(); + else + field->set_na_value(); + } }, check_box->GetId()); m_overrides_options[opt_key] = check_box; @@ -1533,41 +1535,21 @@ void TabFilament::add_filament_overrides_page() optgroup->append_line(line); }; - int extruder_idx = 0; // #ys_FIXME + const int extruder_idx = 0; // #ys_FIXME - append_single_option_line("filament_retract_length", extruder_idx); - append_single_option_line("filament_retract_lift", extruder_idx); - - Line line = { _(L("Only lift Z")), "" }; - - std::vector opt_keys = { "filament_retract_lift_above", "filament_retract_lift_below" }; - for (const std::string& opt_key : opt_keys) - line.append_option(optgroup->get_option(opt_key)); - - line.near_label_widget = [this, optgroup, opt_keys, extruder_idx](wxWindow* parent) { - wxCheckBox* check_box = new wxCheckBox(parent, wxID_ANY, ""); - - check_box->Bind(wxEVT_CHECKBOX, [optgroup, opt_keys, extruder_idx](wxCommandEvent& evt) { - const bool is_checked = evt.IsChecked(); - for (const std::string& opt_key : opt_keys) - check_line(is_checked, optgroup, opt_key, extruder_idx); - }, check_box->GetId()); - - for (const std::string& opt_key : opt_keys) - m_overrides_options[opt_key] = check_box; - - return check_box; - }; - - optgroup->append_line(line); - - append_single_option_line("filament_retract_speed", extruder_idx); - append_single_option_line("filament_deretract_speed", extruder_idx); - append_single_option_line("filament_retract_restart_extra", extruder_idx); - append_single_option_line("filament_retract_before_travel", extruder_idx); - append_single_option_line("filament_retract_layer_change", extruder_idx); - append_single_option_line("filament_wipe", extruder_idx); - append_single_option_line("filament_retract_before_wipe", extruder_idx); + for (const std::string opt_key : { "filament_retract_length", + "filament_retract_lift", + "filament_retract_lift_above", + "filament_retract_lift_below", + "filament_retract_speed", + "filament_deretract_speed", + "filament_retract_restart_extra", + "filament_retract_before_travel", + "filament_retract_layer_change", + "filament_wipe", + "filament_retract_before_wipe" + }) + append_single_option_line(opt_key, extruder_idx); } void TabFilament::update_filament_overrides_page() @@ -1584,7 +1566,8 @@ void TabFilament::update_filament_overrides_page() std::vector opt_keys = { "filament_retract_length", "filament_retract_lift", - "filament_retract_lift_above", "filament_retract_lift_below", + "filament_retract_lift_above", + "filament_retract_lift_below", "filament_retract_speed", "filament_deretract_speed", "filament_retract_restart_extra", @@ -1594,13 +1577,17 @@ void TabFilament::update_filament_overrides_page() "filament_retract_before_wipe" }; - int extruder_idx = 0; // #ys_FIXME + const int extruder_idx = 0; // #ys_FIXME + + const bool have_retract_length = m_config->option("filament_retract_length")->is_nil() ? false : + m_config->opt_float("filament_retract_length", extruder_idx) > 0; for (const std::string& opt_key : opt_keys) { + bool is_checked = opt_key=="filament_retract_length" ? true : have_retract_length; Field* field = optgroup->get_fieldc(opt_key, extruder_idx); if (field != nullptr) { - const bool is_checked = !m_config->option(opt_key)->is_nil(); + is_checked &= !m_config->option(opt_key)->is_nil(); m_overrides_options[opt_key]->SetValue(is_checked); field->toggle(is_checked); }