diff options
author | YuSanka <yusanka@gmail.com> | 2019-07-31 14:05:47 +0300 |
---|---|---|
committer | YuSanka <yusanka@gmail.com> | 2019-07-31 14:05:47 +0300 |
commit | 3bade450b8a4d1189138bb3cbed325a479fe6b94 (patch) | |
tree | ce2cbe63accbf59226ec785790e83130b640504a /src/slic3r | |
parent | aeb29b11849e2e3e9a0282c289a9a7d165bfdbc8 (diff) | |
parent | 7c2e199472524c40bbd3f50650c2a0c7345bd4dd (diff) |
Merge remote-tracking branch 'origin/ys_overrides'
Diffstat (limited to 'src/slic3r')
-rw-r--r-- | src/slic3r/GUI/Field.cpp | 123 | ||||
-rw-r--r-- | src/slic3r/GUI/Field.hpp | 22 | ||||
-rw-r--r-- | src/slic3r/GUI/GUI.cpp | 7 | ||||
-rw-r--r-- | src/slic3r/GUI/OptionsGroup.cpp | 54 | ||||
-rw-r--r-- | src/slic3r/GUI/OptionsGroup.hpp | 3 | ||||
-rw-r--r-- | src/slic3r/GUI/Preset.cpp | 4 | ||||
-rw-r--r-- | src/slic3r/GUI/PresetBundle.cpp | 2 | ||||
-rw-r--r-- | src/slic3r/GUI/Tab.cpp | 111 | ||||
-rw-r--r-- | src/slic3r/GUI/Tab.hpp | 5 |
9 files changed, 274 insertions, 57 deletions
diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index db935cc05..39fa9c54b 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); @@ -256,6 +260,7 @@ void TextCtrl::BUILD() { m_opt.default_value->getFloat() : m_opt.get_default_value<ConfigOptionPercents>()->get_at(m_opt_idx); text_value = double_to_string(val); + m_last_meaningful_value = text_value; break; } case coString: @@ -325,24 +330,7 @@ void TextCtrl::BUILD() { } propagate_value(); }), temp->GetId()); - /* - temp->Bind(wxEVT_TEXT, ([this](wxCommandEvent& evt) - { -#ifdef __WXGTK__ - if (bChangedValueEvent) -#endif //__WXGTK__ - if(is_defined_input_value()) - on_change_field(); - }), temp->GetId()); -#ifdef __WXGTK__ - // to correct value updating on GTK we should: - // call on_change_field() on wxEVT_KEY_UP instead of wxEVT_TEXT - // and prevent value updating on wxEVT_KEY_DOWN - temp->Bind(wxEVT_KEY_DOWN, &TextCtrl::change_field_value, this); - temp->Bind(wxEVT_KEY_UP, &TextCtrl::change_field_value, this); -#endif //__WXGTK__ -*/ // select all text using Ctrl+A temp->Bind(wxEVT_CHAR, ([temp](wxKeyEvent& event) { @@ -355,14 +343,70 @@ void TextCtrl::BUILD() { window = dynamic_cast<wxWindow*>(temp); } +bool TextCtrl::value_was_changed() +{ + if (m_value.empty()) + return true; + + boost::any val = m_value; + wxString ret_str = static_cast<wxTextCtrl*>(window)->GetValue(); + // update m_value! + get_value_by_opt_type(ret_str); + + switch (m_opt.type) { + case coInt: + return boost::any_cast<int>(m_value) != boost::any_cast<int>(val); + case coPercent: + case coPercents: + case coFloats: + case coFloat: { + if (m_opt.nullable && std::isnan(boost::any_cast<double>(m_value)) && + std::isnan(boost::any_cast<double>(val))) + return false; + return boost::any_cast<double>(m_value) != boost::any_cast<double>(val); + } + case coString: + case coStrings: + case coFloatOrPercent: + return boost::any_cast<std::string>(m_value) != boost::any_cast<std::string>(val); + default: + return true; + } +} + void TextCtrl::propagate_value() { - if (is_defined_input_value<wxTextCtrl>(window, m_opt.type)) + if (is_defined_input_value<wxTextCtrl>(window, m_opt.type) && value_was_changed()) on_change_field(); else 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<wxString>(value) == na_value(); + if (!m_is_na_val) + m_last_meaningful_value = value; + dynamic_cast<wxTextCtrl*>(window)->SetValue(m_is_na_val ? na_value() : boost::any_cast<wxString>(value)); + } + else + dynamic_cast<wxTextCtrl*>(window)->SetValue(boost::any_cast<wxString>(value)); + m_disable_change_event = false; +} + +void TextCtrl::set_last_meaningful_value() +{ + dynamic_cast<wxTextCtrl*>(window)->SetValue(boost::any_cast<wxString>(m_last_meaningful_value)); + propagate_value(); +} + +void TextCtrl::set_na_value() +{ + dynamic_cast<wxTextCtrl*>(window)->SetValue(na_value()); + propagate_value(); +} + boost::any& TextCtrl::get_value() { wxString ret_str = static_cast<wxTextCtrl*>(window)->GetValue(); @@ -409,6 +453,8 @@ void CheckBox::BUILD() { m_opt.get_default_value<ConfigOptionBools>()->get_at(m_opt_idx) : false; + m_last_meaningful_value = static_cast<unsigned char>(check_value); + // Set Label as a string of at least one space simbol to correct system scaling of a CheckBox auto temp = new wxCheckBox(m_parent, wxID_ANY, wxString(" "), wxDefaultPosition, size); temp->SetFont(Slic3r::GUI::wxGetApp().normal_font()); @@ -416,7 +462,10 @@ void CheckBox::BUILD() { temp->SetValue(check_value); if (m_opt.readonly) temp->Disable(); - temp->Bind(wxEVT_CHECKBOX, ([this](wxCommandEvent e) { on_change_field(); }), temp->GetId()); + temp->Bind(wxEVT_CHECKBOX, ([this](wxCommandEvent e) { + m_is_na_val = false; + on_change_field(); + }), temp->GetId()); temp->SetToolTip(get_tooltip_text(check_value ? "true" : "false")); @@ -424,6 +473,38 @@ void CheckBox::BUILD() { window = dynamic_cast<wxWindow*>(temp); } +void CheckBox::set_value(const boost::any& value, bool change_event) +{ + m_disable_change_event = !change_event; + if (m_opt.nullable) { + m_is_na_val = boost::any_cast<unsigned char>(value) == ConfigOptionBoolsNullable::nil_value(); + if (!m_is_na_val) + m_last_meaningful_value = value; + dynamic_cast<wxCheckBox*>(window)->SetValue(m_is_na_val ? false : boost::any_cast<unsigned char>(value) != 0); + } + else + dynamic_cast<wxCheckBox*>(window)->SetValue(boost::any_cast<bool>(value)); + m_disable_change_event = false; +} + +void CheckBox::set_last_meaningful_value() +{ + if (m_opt.nullable) { + m_is_na_val = false; + dynamic_cast<wxCheckBox*>(window)->SetValue(boost::any_cast<unsigned char>(m_last_meaningful_value) != 0); + on_change_field(); + } +} + +void CheckBox::set_na_value() +{ + if (m_opt.nullable) { + m_is_na_val = true; + dynamic_cast<wxCheckBox*>(window)->SetValue(false); + on_change_field(); + } +} + boost::any& CheckBox::get_value() { // boost::any m_value; @@ -431,7 +512,7 @@ boost::any& CheckBox::get_value() if (m_opt.type == coBool) m_value = static_cast<bool>(value); else - m_value = static_cast<unsigned char>(value); + m_value = m_is_na_val ? ConfigOptionBoolsNullable::nil_value() : static_cast<unsigned char>(value); return m_value; } diff --git a/src/slic3r/GUI/Field.hpp b/src/slic3r/GUI/Field.hpp index 990c40e6f..6c16f90f2 100644 --- a/src/slic3r/GUI/Field.hpp +++ b/src/slic3r/GUI/Field.hpp @@ -123,6 +123,8 @@ public: /// subclasses should overload with a specific version /// Postcondition: Method does not fire the on_change event. virtual void set_value(const boost::any& value, bool change_event) = 0; + virtual void set_last_meaningful_value() {} + virtual void set_na_value() {} /// Gets a boost::any representing this control. /// subclasses should overload with a specific version @@ -247,6 +249,8 @@ protected: // current value boost::any m_value; + // last maeningful value + boost::any m_last_meaningful_value; int m_em_unit; @@ -277,6 +281,7 @@ public: ~TextCtrl() {} void BUILD(); + bool value_was_changed(); // Propagate value from field to the OptionGroupe and Config after kill_focus/ENTER void propagate_value(); wxWindow* window {nullptr}; @@ -286,11 +291,9 @@ public: dynamic_cast<wxTextCtrl*>(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<wxTextCtrl*>(window)->SetValue(boost::any_cast<wxString>(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; boost::any& get_value() override; @@ -303,6 +306,7 @@ public: class CheckBox : public Field { using Field::Field; + bool m_is_na_val {false}; public: CheckBox(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {} CheckBox(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {} @@ -316,11 +320,9 @@ public: dynamic_cast<wxCheckBox*>(window)->SetValue(value); m_disable_change_event = false; } - void set_value(const boost::any& value, bool change_event = false) { - m_disable_change_event = !change_event; - dynamic_cast<wxCheckBox*>(window)->SetValue(boost::any_cast<bool>(value)); - m_disable_change_event = false; - } + void set_value(const boost::any& value, bool change_event = false) override; + void set_last_meaningful_value() override; + void set_na_value() override; boost::any& get_value() override; void msw_rescale() override; diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index 8f41ed5a3..826f2d6fc 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -148,6 +148,13 @@ void config_wizard(int reason) void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt_key, const boost::any& value, int opt_index /*= 0*/) { try{ + + if (config.def()->get(opt_key)->type == coBools && config.def()->get(opt_key)->nullable) { + ConfigOptionBoolsNullable* vec_new = new ConfigOptionBoolsNullable{ boost::any_cast<unsigned char>(value) }; + config.option<ConfigOptionBoolsNullable>(opt_key)->set_at(vec_new, opt_index, 0); + return; + } + switch (config.def()->get(opt_key)->type) { case coFloatOrPercent:{ std::string str = boost::any_cast<std::string>(value); diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index 9feca2f3d..656e07a0e 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -202,7 +202,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** full_Label/* = n // so we need a horizontal sizer to arrange these things auto sizer = new wxBoxSizer(wxHORIZONTAL); grid_sizer->Add(sizer, 0, wxEXPAND | (staticbox ? wxALL : wxBOTTOM | wxTOP | wxLEFT), staticbox ? 0 : 1); - sizer->Add(m_near_label_widget_ptrs.back(), 0, wxRIGHT, 7); + sizer->Add(m_near_label_widget_ptrs.back(), 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 7); sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | wxALIGN_CENTER_VERTICAL, 5); } } @@ -372,30 +372,10 @@ void ConfigOptionsGroup::on_change_OG(const t_config_option_key& opt_id, const b auto option = m_options.at(opt_id).opt; - // get value -//! auto field_value = get_value(opt_id); - if (option.gui_flags.compare("serialized")==0) { - if (opt_index != -1) { - // die "Can't set serialized option indexed value" ; - } - change_opt_value(*m_config, opt_key, value); - } - else { - if (opt_index == -1) { - // change_opt_value(*m_config, opt_key, field_value); - //!? why field_value?? in this case changed value will be lose! No? - change_opt_value(*m_config, opt_key, value); - } - else { - change_opt_value(*m_config, opt_key, value, opt_index); -// auto value = m_config->get($opt_key); -// $value->[$opt_index] = $field_value; -// $self->config->set($opt_key, $value); - } - } + change_opt_value(*m_config, opt_key, value, opt_index == -1 ? 0 : opt_index); } - OptionsGroup::on_change_OG(opt_id, value); //!? Why doing this + OptionsGroup::on_change_OG(opt_id, value); } void ConfigOptionsGroup::back_to_initial_value(const std::string& opt_key) @@ -578,6 +558,34 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config boost::any ret; wxString text_value = wxString(""); const ConfigOptionDef* opt = config.def()->get(opt_key); + + if (opt->nullable) + { + switch (opt->type) + { + case coPercents: + case coFloats: { + if (config.option(opt_key)->is_nil()) + ret = _(L("N/A")); + else { + double val = opt->type == coFloats ? + config.option<ConfigOptionFloatsNullable>(opt_key)->get_at(idx) : + config.option<ConfigOptionPercentsNullable>(opt_key)->get_at(idx); + ret = double_to_string(val); } + } + break; + case coBools: + ret = config.option<ConfigOptionBoolsNullable>(opt_key)->values[idx]; + break; + case coInts: + ret = config.option<ConfigOptionIntsNullable>(opt_key)->get_at(idx); + break; + default: + break; + } + return ret; + } + switch (opt->type) { case coFloatOrPercent:{ const auto &value = *config.option<ConfigOptionFloatOrPercent>(opt_key); diff --git a/src/slic3r/GUI/OptionsGroup.hpp b/src/slic3r/GUI/OptionsGroup.hpp index d720787b6..cc3d89b1f 100644 --- a/src/slic3r/GUI/OptionsGroup.hpp +++ b/src/slic3r/GUI/OptionsGroup.hpp @@ -252,6 +252,9 @@ public: Option option = get_option(title, idx); return OptionsGroup::create_single_option_line(option); } + Line create_single_option_line(const Option& option) const { + return OptionsGroup::create_single_option_line(option); + } void append_single_option_line(const Option& option) { OptionsGroup::append_single_option_line(option); } diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index e34c9be28..fa8b5baee 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -400,6 +400,10 @@ const std::vector<std::string>& Preset::filament_options() "temperature", "first_layer_temperature", "bed_temperature", "first_layer_bed_temperature", "fan_always_on", "cooling", "min_fan_speed", "max_fan_speed", "bridge_fan_speed", "disable_fan_first_layers", "fan_below_layer_time", "slowdown_below_layer_time", "min_print_speed", "start_filament_gcode", "end_filament_gcode", + // Retract overrides + "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", + // Profile compatibility "compatible_prints", "compatible_prints_condition", "compatible_printers", "compatible_printers_condition", "inherits" }; return s_opts; diff --git a/src/slic3r/GUI/PresetBundle.cpp b/src/slic3r/GUI/PresetBundle.cpp index 00c1f8168..7c9f7af4e 100644 --- a/src/slic3r/GUI/PresetBundle.cpp +++ b/src/slic3r/GUI/PresetBundle.cpp @@ -72,6 +72,8 @@ PresetBundle::PresetBundle() : this->filaments.default_preset().config.option<ConfigOptionStrings>("filament_settings_id", true)->values = { "" }; this->filaments.default_preset().compatible_printers_condition(); this->filaments.default_preset().inherits(); + // Set all the nullable values to nils. + this->filaments.default_preset().config.null_nullables(); this->sla_materials.default_preset().config.optptr("sla_material_settings_id", true); this->sla_materials.default_preset().compatible_printers_condition(); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index a00f7902f..9d7fc20a3 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1497,6 +1497,105 @@ void TabPrint::OnActivate() Tab::OnActivate(); } +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 {"",""}; + 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) { + 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; + return check_box; + }; + + optgroup->append_line(line); + }; + + const int extruder_idx = 0; // #ys_FIXME + + 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() +{ + const auto page_it = std::find_if(m_pages.begin(), m_pages.end(), [](const PageShp page) {return page->title() == _(L("Filament Overrides")); }); + if (page_it == m_pages.end()) + return; + PageShp page = *page_it; + + const auto og_it = std::find_if(page->m_optgroups.begin(), page->m_optgroups.end(), [](const ConfigOptionsGroupShp og) {return og->title == _(L("Retraction")); }); + if (og_it == page->m_optgroups.end()) + return; + ConfigOptionsGroupShp optgroup = *og_it; + + std::vector<std::string> opt_keys = { "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" + }; + + const int extruder_idx = 0; // #ys_FIXME + + const bool have_retract_length = m_config->option("filament_retract_length")->is_nil() || + 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; + m_overrides_options[opt_key]->Enable(is_checked); + + is_checked &= !m_config->option(opt_key)->is_nil(); + m_overrides_options[opt_key]->SetValue(is_checked); + + Field* field = optgroup->get_fieldc(opt_key, extruder_idx); + if (field != nullptr) + field->toggle(is_checked); + } +} + void TabFilament::build() { m_presets = &m_preset_bundle->filaments; @@ -1594,10 +1693,14 @@ void TabFilament::build() }; optgroup->append_line(line); + + add_filament_overrides_page(); + + const int gcode_field_height = 15; // 150 const int notes_field_height = 25; // 250 - page = add_options_page(_(L("Custom G-code")), "cog"); + page = add_options_page(_(L("Custom G-code")), "cog"); optgroup = page->new_optgroup(_(L("Start G-code")), 0); Option option = optgroup->get_option("start_filament_gcode"); option.opt.full_width = true; @@ -1661,7 +1764,7 @@ void TabFilament::update() return; // ys_FIXME m_update_cnt++; -// Freeze(); + wxString text = from_u8(PresetHints::cooling_description(m_presets->get_edited_preset())); m_cooling_description_line->SetText(text); text = from_u8(PresetHints::maximum_volumetric_flow_description(*m_preset_bundle)); @@ -1676,7 +1779,9 @@ void TabFilament::update() for (auto el : { "min_fan_speed", "disable_fan_first_layers" }) get_field(el)->toggle(fan_always_on); -// Thaw(); + + update_filament_overrides_page(); + m_update_cnt--; if (m_update_cnt == 0) diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index 73b6bb08d..6ff76f5c4 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -337,6 +337,11 @@ class TabFilament : public Tab { ogStaticText* m_volumetric_speed_description_line; ogStaticText* m_cooling_description_line; + + void add_filament_overrides_page(); + void update_filament_overrides_page(); + + std::map<std::string, wxCheckBox*> m_overrides_options; public: TabFilament(wxNotebook* parent) : // Tab(parent, _(L("Filament Settings")), L("filament")) {} |