From e62c17bddfbedc4ccc97ff7a49d28ceb454435c2 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Fri, 5 Jan 2018 15:11:33 +0100 Subject: [PATCH] "on_change" function call correctly work now. Start adding of Tab::update(). It's need to think about config->set_key_value(...): at cpp side it's non-trivial. --- lib/Slic3r/GUI/OptionsGroup.pm | 3 + xs/src/slic3r/GUI/Field.cpp | 176 +++++++-------- xs/src/slic3r/GUI/Field.hpp | 40 ++-- xs/src/slic3r/GUI/GUI.cpp | 56 ++++- xs/src/slic3r/GUI/GUI.hpp | 5 +- xs/src/slic3r/GUI/OptionsGroup.cpp | 76 +++++-- xs/src/slic3r/GUI/OptionsGroup.hpp | 117 +++++----- xs/src/slic3r/GUI/Tab.cpp | 343 +++++++++++++++++++++++++---- xs/src/slic3r/GUI/Tab.h | 63 +++--- 9 files changed, 617 insertions(+), 262 deletions(-) diff --git a/lib/Slic3r/GUI/OptionsGroup.pm b/lib/Slic3r/GUI/OptionsGroup.pm index 7ffb2067b3..a537d62150 100644 --- a/lib/Slic3r/GUI/OptionsGroup.pm +++ b/lib/Slic3r/GUI/OptionsGroup.pm @@ -158,7 +158,9 @@ sub _build_field { my $opt_id = $opt->opt_id; my $on_change = sub { + #! This function will be called from Field. my ($opt_id, $value) = @_; + #! Call OptionGroup._on_change(...) $self->_on_change($opt_id, $value) unless $self->_disabled; }; @@ -213,6 +215,7 @@ sub _build_field { } return undef if !$field; + #! setting up a function that will be triggered when the field changes $field->on_change($on_change); $field->on_kill_focus($on_kill_focus); $self->_fields->{$opt_id} = $field; diff --git a/xs/src/slic3r/GUI/Field.cpp b/xs/src/slic3r/GUI/Field.cpp index dd9d7f70bd..a4c1fdf966 100644 --- a/xs/src/slic3r/GUI/Field.cpp +++ b/xs/src/slic3r/GUI/Field.cpp @@ -15,13 +15,13 @@ namespace Slic3r { namespace GUI { event.Skip(1); // call the registered function if it is available -//! if (on_kill_focus) -//! on_kill_focus(opt_id); + if (on_kill_focus) + on_kill_focus(m_opt_id); } - void Field::_on_change(wxCommandEvent& event) { - std::cerr << "calling Field::_on_change \n"; -//! if (on_change != nullptr && !disable_change_event) -//! on_change(opt_id, "A"); + void Field::on_change_field(wxCommandEvent& event) { +// std::cerr << "calling Field::_on_change \n"; + if (m_on_change != nullptr && !m_disable_change_event) + m_on_change(m_opt_id, get_value()); } @@ -33,32 +33,32 @@ namespace Slic3r { namespace GUI { void TextCtrl::BUILD() { auto size = wxSize(wxDefaultSize); - if (opt.height >= 0) size.SetHeight(opt.height); - if (opt.width >= 0) size.SetWidth(opt.width); + if (m_opt.height >= 0) size.SetHeight(m_opt.height); + if (m_opt.width >= 0) size.SetWidth(m_opt.width); wxString text_value = wxString(""); - switch (opt.type) { + switch (m_opt.type) { case coFloatOrPercent: { - if (static_cast(opt.default_value)->percent) + if (static_cast(m_opt.default_value)->percent) { - text_value = wxString::Format(_T("%i"), int(opt.default_value->getFloat())); + text_value = wxString::Format(_T("%i"), int(m_opt.default_value->getFloat())); text_value += "%"; } else - wxNumberFormatter::ToString(opt.default_value->getFloat(), 2); + wxNumberFormatter::ToString(m_opt.default_value->getFloat(), 2); break; } case coPercent: { - text_value = wxString::Format(_T("%i"), int(opt.default_value->getFloat())); + text_value = wxString::Format(_T("%i"), int(m_opt.default_value->getFloat())); text_value += "%"; break; } case coPercents: { - const ConfigOptionPercents *vec = static_cast(opt.default_value); + const ConfigOptionPercents *vec = static_cast(m_opt.default_value); if (vec == nullptr || vec->empty()) break; if (vec->size() > 1) break; @@ -68,13 +68,13 @@ namespace Slic3r { namespace GUI { } case coFloat: { - double val = opt.default_value->getFloat(); + double val = m_opt.default_value->getFloat(); text_value = (val - int(val)) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2); break; } case coFloats: { - const ConfigOptionFloats *vec = static_cast(opt.default_value); + const ConfigOptionFloats *vec = static_cast(m_opt.default_value); if (vec == nullptr || vec->empty()) break; if (vec->size() > 1) break; @@ -83,11 +83,11 @@ namespace Slic3r { namespace GUI { break; } case coString: - text_value = static_cast(opt.default_value)->value; + text_value = static_cast(m_opt.default_value)->value; break; case coStrings: { - const ConfigOptionStrings *vec = static_cast(opt.default_value); + const ConfigOptionStrings *vec = static_cast(m_opt.default_value); if (vec == nullptr || vec->empty()) break; if (vec->size() > 1) break; @@ -98,11 +98,11 @@ namespace Slic3r { namespace GUI { break; } - auto temp = new wxTextCtrl(parent, wxID_ANY, text_value, wxDefaultPosition, size, (opt.multiline ? wxTE_MULTILINE : 0)); + auto temp = new wxTextCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, (m_opt.multiline ? wxTE_MULTILINE : 0)); - if (opt.tooltip.length() > 0) { temp->SetToolTip(opt.tooltip); } + if (m_opt.tooltip.length() > 0) { temp->SetToolTip(m_opt.tooltip); } - temp->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { _on_change(e); }), temp->GetId()); + temp->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { on_change_field(e); }), temp->GetId()); temp->Bind(wxEVT_KILL_FOCUS, ([this](wxFocusEvent e) { _on_kill_focus(e); }), temp->GetId()); // recast as a wxWindow to fit the calling convention @@ -116,21 +116,21 @@ namespace Slic3r { namespace GUI { void CheckBox::BUILD() { auto size = wxSize(wxDefaultSize); - if (opt.height >= 0) size.SetHeight(opt.height); - if (opt.width >= 0) size.SetWidth(opt.width); + if (m_opt.height >= 0) size.SetHeight(m_opt.height); + if (m_opt.width >= 0) size.SetWidth(m_opt.width); - bool check_value = opt.type == coBool ? - opt.default_value->getBool() : opt.type == coBools ? - static_cast(opt.default_value)->values.at(0) : + bool check_value = m_opt.type == coBool ? + m_opt.default_value->getBool() : m_opt.type == coBools ? + static_cast(m_opt.default_value)->values.at(0) : false; - auto temp = new wxCheckBox(parent, wxID_ANY, wxString(""), wxDefaultPosition, size); + auto temp = new wxCheckBox(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, size); temp->SetValue(check_value); - if (opt.readonly) temp->Disable(); + if (m_opt.readonly) temp->Disable(); - temp->Bind(wxEVT_CHECKBOX, ([this](wxCommandEvent e) { _on_change(e); }), temp->GetId()); + temp->Bind(wxEVT_CHECKBOX, ([this](wxCommandEvent e) { on_change_field(e); }), temp->GetId()); - if (opt.tooltip.length() > 0) { temp->SetToolTip(opt.tooltip); } + if (m_opt.tooltip.length() > 0) { temp->SetToolTip(m_opt.tooltip); } // recast as a wxWindow to fit the calling convention window = dynamic_cast(temp); @@ -140,20 +140,20 @@ int undef_spin_val = -9999; //! Probably, It's not necessary void SpinCtrl::BUILD() { auto size = wxSize(wxDefaultSize); - if (opt.height >= 0) size.SetHeight(opt.height); - if (opt.width >= 0) size.SetWidth(opt.width); + if (m_opt.height >= 0) size.SetHeight(m_opt.height); + if (m_opt.width >= 0) size.SetWidth(m_opt.width); wxString text_value = wxString(""); int default_value = 0; - switch (opt.type) { + switch (m_opt.type) { case coInt: - default_value = opt.default_value->getInt(); + default_value = m_opt.default_value->getInt(); text_value = wxString::Format(_T("%i"), default_value); break; case coInts: { - const ConfigOptionInts *vec = static_cast(opt.default_value); + const ConfigOptionInts *vec = static_cast(m_opt.default_value); if (vec == nullptr || vec->empty()) break; for (size_t id = 0; id < vec->size(); ++id) { @@ -166,10 +166,10 @@ void SpinCtrl::BUILD() { break; } - auto temp = new wxSpinCtrl(parent, wxID_ANY, text_value, wxDefaultPosition, size, - 0, opt.min >0 ? opt.min : 0, opt.max < 2147483647 ? opt.max : 2147483647, default_value); + auto temp = new wxSpinCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, + 0, m_opt.min >0 ? m_opt.min : 0, m_opt.max < 2147483647 ? m_opt.max : 2147483647, default_value); - temp->Bind(wxEVT_SPINCTRL, ([=](wxCommandEvent e) { tmp_value = undef_spin_val; _on_change(e); }), temp->GetId()); + temp->Bind(wxEVT_SPINCTRL, ([=](wxCommandEvent e) { tmp_value = undef_spin_val; on_change_field(e); }), temp->GetId()); temp->Bind(wxEVT_KILL_FOCUS, ([this](wxFocusEvent e) { tmp_value = undef_spin_val; _on_kill_focus(e); }), temp->GetId()); temp->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { @@ -181,14 +181,14 @@ void SpinCtrl::BUILD() { std::string value = e.GetString(); if (is_matched(value, "^\d+$")) tmp_value = std::stoi(value); - _on_change(e); + on_change_field(e); // # We don't reset tmp_value here because _on_change might put callbacks // # in the CallAfter queue, and we want the tmp value to be available from // # them as well. }), temp->GetId()); - if (opt.tooltip.length() > 0) { temp->SetToolTip(opt.tooltip); } + if (m_opt.tooltip.length() > 0) { temp->SetToolTip(m_opt.tooltip); } // recast as a wxWindow to fit the calling convention window = dynamic_cast(temp); @@ -196,66 +196,66 @@ void SpinCtrl::BUILD() { void Choice::BUILD() { auto size = wxSize(wxDefaultSize); - if (opt.height >= 0) size.SetHeight(opt.height); - if (opt.width >= 0) size.SetWidth(opt.width); + if (m_opt.height >= 0) size.SetHeight(m_opt.height); + if (m_opt.width >= 0) size.SetWidth(m_opt.width); - auto temp = new wxComboBox(parent, wxID_ANY, wxString(""), wxDefaultPosition, size); - if (opt.gui_type.compare("select_open") != 0) + auto temp = new wxComboBox(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, size); + if (m_opt.gui_type.compare("select_open") != 0) temp->SetExtraStyle(wxCB_READONLY); // recast as a wxWindow to fit the calling convention window = dynamic_cast(temp); - if (opt.enum_labels.empty() && opt.enum_values.empty()){ + if (m_opt.enum_labels.empty() && m_opt.enum_values.empty()){ } else{ - for (auto el : opt.enum_labels.empty() ? opt.enum_values : opt.enum_labels) + for (auto el : m_opt.enum_labels.empty() ? m_opt.enum_values : m_opt.enum_labels) temp->Append(wxString(el)); set_selection(); } - temp->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { _on_change(e); }), temp->GetId()); - temp->Bind(wxEVT_COMBOBOX, ([this](wxCommandEvent e) { _on_change(e); }), temp->GetId()); + temp->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { on_change_field(e); }), temp->GetId()); + temp->Bind(wxEVT_COMBOBOX, ([this](wxCommandEvent e) { on_change_field(e); }), temp->GetId()); - if (opt.tooltip.length() > 0) temp->SetToolTip(opt.tooltip); + if (m_opt.tooltip.length() > 0) temp->SetToolTip(m_opt.tooltip); } void Choice::set_selection() { wxString text_value = wxString(""); - switch (opt.type){ + switch (m_opt.type){ case coFloat: case coPercent: { - double val = opt.default_value->getFloat(); + double val = m_opt.default_value->getFloat(); text_value = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 1); auto idx = 0; - for (auto el : opt.enum_values) + for (auto el : m_opt.enum_values) { if (el.compare(text_value) == 0) break; ++idx; } - if (opt.type == coPercent) text_value += "%"; - idx == opt.enum_values.size() ? + if (m_opt.type == coPercent) text_value += "%"; + idx == m_opt.enum_values.size() ? dynamic_cast(window)->SetValue(text_value) : dynamic_cast(window)->SetSelection(idx); break; } case coEnum:{ - int id_value = static_cast*>(opt.default_value)->value; //!! + int id_value = static_cast*>(m_opt.default_value)->value; //!! dynamic_cast(window)->SetSelection(id_value); break; } case coInt:{ - int val = opt.default_value->getInt(); //!! + int val = m_opt.default_value->getInt(); //!! text_value = wxString::Format(_T("%i"), int(val)); auto idx = 0; - for (auto el : opt.enum_values) + for (auto el : m_opt.enum_values) { if (el.compare(text_value) == 0) break; ++idx; } - idx == opt.enum_values.size() ? + idx == m_opt.enum_values.size() ? dynamic_cast(window)->SetValue(text_value) : dynamic_cast(window)->SetSelection(idx); break; @@ -276,16 +276,16 @@ void Choice::set_selection() // break; // } case coStrings:{ - text_value = static_cast(opt.default_value)->values.at(0); + text_value = static_cast(m_opt.default_value)->values.at(0); auto idx = 0; - for (auto el : opt.enum_values) + for (auto el : m_opt.enum_values) { if (el.compare(text_value) == 0) break; ++idx; } - idx == opt.enum_values.size() ? + idx == m_opt.enum_values.size() ? dynamic_cast(window)->SetValue(text_value) : dynamic_cast(window)->SetSelection(idx); break; @@ -295,27 +295,29 @@ void Choice::set_selection() void Choice::set_value(const std::string value) //! Redundant? { - disable_change_event = true; + m_disable_change_event = true; auto idx=0; - for (auto el : opt.enum_values) + for (auto el : m_opt.enum_values) { if (el.compare(value) == 0) break; ++idx; } - idx == opt.enum_values.size() ? + idx == m_opt.enum_values.size() ? dynamic_cast(window)->SetValue(value) : dynamic_cast(window)->SetSelection(idx); - disable_change_event = false; + m_disable_change_event = false; } //! it's needed for _update_serial_ports() void Choice::set_values(const std::vector values) { - disable_change_event = true; + if (values.empty()) + return; + m_disable_change_event = true; // # it looks that Clear() also clears the text field in recent wxWidgets versions, // # but we want to preserve it @@ -326,75 +328,75 @@ void Choice::set_values(const std::vector values) ww->Append(wxString(el)); ww->SetValue(value); - disable_change_event = false; + m_disable_change_event = false; } void ColourPicker::BUILD() { auto size = wxSize(wxDefaultSize); - if (opt.height >= 0) size.SetHeight(opt.height); - if (opt.width >= 0) size.SetWidth(opt.width); + if (m_opt.height >= 0) size.SetHeight(m_opt.height); + if (m_opt.width >= 0) size.SetWidth(m_opt.width); - wxString clr(static_cast(opt.default_value)->values.at(0)); - auto temp = new wxColourPickerCtrl(parent, wxID_ANY, clr, wxDefaultPosition, size); + wxString clr(static_cast(m_opt.default_value)->values.at(0)); + auto temp = new wxColourPickerCtrl(m_parent, wxID_ANY, clr, wxDefaultPosition, size); // // recast as a wxWindow to fit the calling convention window = dynamic_cast(temp); - temp->Bind(wxEVT_COLOURPICKER_CHANGED, ([=](wxCommandEvent e) { _on_change(e); }), temp->GetId()); + temp->Bind(wxEVT_COLOURPICKER_CHANGED, ([=](wxCommandEvent e) { on_change_field(e); }), temp->GetId()); - if (opt.tooltip.length() > 0) temp->SetToolTip(opt.tooltip); + if (m_opt.tooltip.length() > 0) temp->SetToolTip(m_opt.tooltip); } void Point::BUILD() { auto size = wxSize(wxDefaultSize); - if (opt.height >= 0) size.SetHeight(opt.height); - if (opt.width >= 0) size.SetWidth(opt.width); + if (m_opt.height >= 0) size.SetHeight(m_opt.height); + if (m_opt.width >= 0) size.SetWidth(m_opt.width); auto temp = new wxBoxSizer(wxHORIZONTAL); // $self->wxSizer($sizer); // wxSize field_size(40, -1); - auto default_pt = static_cast(opt.default_value)->values.at(0); + auto default_pt = static_cast(m_opt.default_value)->values.at(0); double val = default_pt.x; wxString X = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2); val = default_pt.y; wxString Y = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2); - x_textctrl = new wxTextCtrl(parent, wxID_ANY, X, wxDefaultPosition, field_size); - y_textctrl = new wxTextCtrl(parent, wxID_ANY, Y, wxDefaultPosition, field_size); + x_textctrl = new wxTextCtrl(m_parent, wxID_ANY, X, wxDefaultPosition, field_size); + y_textctrl = new wxTextCtrl(m_parent, wxID_ANY, Y, wxDefaultPosition, field_size); - temp->Add(new wxStaticText(parent, wxID_ANY, "x:")/*, 0, wxALIGN_CENTER_VERTICAL, 0*/); + temp->Add(new wxStaticText(m_parent, wxID_ANY, "x:")/*, 0, wxALIGN_CENTER_VERTICAL, 0*/); temp->Add(x_textctrl); - temp->Add(new wxStaticText(parent, wxID_ANY, "y:")/*, 0, wxALIGN_CENTER_VERTICAL, 0*/); + temp->Add(new wxStaticText(m_parent, wxID_ANY, "y:")/*, 0, wxALIGN_CENTER_VERTICAL, 0*/); temp->Add(y_textctrl); - x_textctrl->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { _on_change(e/*$self->option->opt_id*/); }), x_textctrl->GetId()); - y_textctrl->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { _on_change(e/*$self->option->opt_id*/); }), x_textctrl->GetId()); + x_textctrl->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { on_change_field(e/*$self->option->opt_id*/); }), x_textctrl->GetId()); + y_textctrl->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { on_change_field(e/*$self->option->opt_id*/); }), x_textctrl->GetId()); // // recast as a wxWindow to fit the calling convention sizer = dynamic_cast(temp); - if (opt.tooltip.length() > 0) + if (m_opt.tooltip.length() > 0) { - x_textctrl->SetToolTip(opt.tooltip); - y_textctrl->SetToolTip(opt.tooltip); + x_textctrl->SetToolTip(m_opt.tooltip); + y_textctrl->SetToolTip(m_opt.tooltip); } } void Point::set_value(const Pointf value) { - disable_change_event = true; + m_disable_change_event = true; double val = value.x; x_textctrl->SetValue(val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2)); val = value.y; y_textctrl->SetValue(val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2)); - disable_change_event = false; + m_disable_change_event = false; } boost::any Point::get_value() diff --git a/xs/src/slic3r/GUI/Field.hpp b/xs/src/slic3r/GUI/Field.hpp index ae1de6bf54..b36e2fe159 100644 --- a/xs/src/slic3r/GUI/Field.hpp +++ b/xs/src/slic3r/GUI/Field.hpp @@ -23,6 +23,8 @@ namespace Slic3r { namespace GUI { class Field; using t_field = std::unique_ptr; +using t_kill_focus = std::function; +using t_change = std::function; class Field { protected: @@ -35,47 +37,47 @@ protected: /// Call the attached on_kill_focus method. void _on_kill_focus(wxFocusEvent& event); /// Call the attached on_change method. - void _on_change(wxCommandEvent& event); + void on_change_field(wxCommandEvent& event); public: /// parent wx item, opportunity to refactor (probably not necessary - data duplication) - wxWindow* parent {nullptr}; + wxWindow* m_parent {nullptr}; /// Function object to store callback passed in from owning object. -//! t_kill_focus on_kill_focus {nullptr}; + t_kill_focus on_kill_focus {nullptr}; /// Function object to store callback passed in from owning object. -//! t_change on_change {nullptr}; + t_change m_on_change {nullptr}; - bool disable_change_event {false}; + bool m_disable_change_event {false}; /// Copy of ConfigOption for deduction purposes - const ConfigOptionDef opt {ConfigOptionDef()}; - const t_config_option_key opt_id;//! {""}; + const ConfigOptionDef m_opt {ConfigOptionDef()}; + const t_config_option_key m_opt_id;//! {""}; /// Sets a value for this control. /// subclasses should overload with a specific version /// Postcondition: Method does not fire the on_change event. - virtual void set_value(boost::any value) = 0; + virtual void set_value(boost::any value) = 0; /// Gets a boost::any representing this control. /// subclasses should overload with a specific version - virtual boost::any get_value() = 0; + virtual boost::any get_value() = 0; - virtual void enable() = 0; - virtual void disable() = 0; + virtual void enable() = 0; + virtual void disable() = 0; /// Fires the enable or disable function, based on the input. - inline void toggle(bool en) { en ? enable() : disable(); } + inline void toggle(bool en) { en ? enable() : disable(); } - virtual void set_tooltip(const wxString& tip) = 0; + virtual void set_tooltip(const wxString& tip) = 0; - Field(const ConfigOptionDef& opt, const t_config_option_key& id) : opt(opt), opt_id(id) {}; - Field(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : parent(parent), opt(opt), opt_id(id) {}; + Field(const ConfigOptionDef& opt, const t_config_option_key& id) : m_opt(opt), m_opt_id(id) {}; + Field(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : m_parent(parent), m_opt(opt), m_opt_id(id) {}; /// If you don't know what you are getting back, check both methods for nullptr. - virtual wxSizer* getSizer() { return nullptr; } - virtual wxWindow* getWindow() { return nullptr; } + virtual wxSizer* getSizer() { return nullptr; } + virtual wxWindow* getWindow() { return nullptr; } bool is_matched(std::string string, std::string pattern); @@ -210,14 +212,14 @@ public: wxWindow* window{ nullptr }; void BUILD() override; - void set_selection(); +// void set_selection(); void set_value(const std::string value) { dynamic_cast(window)->SetColour(value); } void set_value(boost::any value) { dynamic_cast(window)->SetColour(boost::any_cast(value)); } - void set_values(const std::vector values); +// void set_values(const std::vector values); boost::any get_value() override { return boost::any(dynamic_cast(window)->GetColour()); } diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp index 57f40df4cd..24b11e2a87 100644 --- a/xs/src/slic3r/GUI/GUI.cpp +++ b/xs/src/slic3r/GUI/GUI.cpp @@ -32,11 +32,7 @@ #include #include "Tab.h" - -//#include -//#include -//#include -//#include +#include "AppConfig.hpp" namespace Slic3r { namespace GUI { @@ -189,15 +185,53 @@ void add_debug_menu(wxMenuBar *menu) } void create_preset_tabs(PresetBundle *preset_bundle, AppConfig *app_config) -{ - add_created_tab(new CTabPrint (g_wxTabPanel, "Print"), preset_bundle, app_config); - add_created_tab(new CTabFilament(g_wxTabPanel, "Filament"), preset_bundle, app_config); - add_created_tab(new CTabPrinter (g_wxTabPanel, "Printer"), preset_bundle, app_config); +{ + add_created_tab(new TabPrint (g_wxTabPanel, "Print"), preset_bundle, app_config); + add_created_tab(new TabFilament(g_wxTabPanel, "Filament"), preset_bundle, app_config); + add_created_tab(new TabPrinter (g_wxTabPanel, "Printer"), preset_bundle, app_config); } -void add_created_tab(CTab* panel, PresetBundle *preset_bundle, AppConfig *app_config) +void add_created_tab(Tab* panel, PresetBundle *preset_bundle, AppConfig *app_config) { - panel->create_preset_tab(preset_bundle, app_config); + panel->m_no_controller = app_config->get("no_controller").empty(); + panel->create_preset_tab(preset_bundle); + // Callback to be executed after any of the configuration fields(Perl class Slic3r::GUI::OptionsGroup::Field) change their value. + panel->m_on_value_change = [/*this*/](std::string opt_key, boost::any value){ + //! plater & loaded - variables of MainFrame +// if (plater) { +// plater->on_config_change(m_config); //# propagate config change events to the plater +// if (opt_key.compare("extruders_count") plater->on_extruders_change(value); +// } + // don't save while loading for the first time +// if (loaded && Slic3r::GUI::autosave) m_config->save(Slic3r::GUI::autosave) ; + }; + +// # Install a callback for the tab to update the platter and print controller presets, when +// # a preset changes at Slic3r::GUI::Tab. +// $tab->on_presets_changed(sub{ +// if ($self->{plater}) { +// # Update preset combo boxes(Print settings, Filament, Printer) from their respective tabs. +// $self->{plater}->update_presets($tab_name, @_); +// if ($tab_name eq 'printer') { +// # Printer selected at the Printer tab, update "compatible" marks at the print and filament selectors. +// my($presets, $reload_dependent_tabs) = @_; +// for my $tab_name_other(qw(print filament)) { +// # If the printer tells us that the print or filament preset has been switched or invalidated, +// # refresh the print or filament tab page.Otherwise just refresh the combo box. +// my $update_action = ($reload_dependent_tabs && (first{ $_ eq $tab_name_other } (@{$reload_dependent_tabs}))) +// ? 'load_current_preset' : 'update_tab_ui'; +// $self->{options_tabs}{$tab_name_other}->$update_action; +// } +// # Update the controller printers. +// $self->{controller}->update_presets(@_) if $self->{controller}; +// } +// $self->{plater}->on_config_change($tab->{presets}->get_current_preset->config); +// } +// }); + + //# Load the currently selected preset into the GUI, update the preset selection box. +// panel->load_current_preset; + g_wxTabPanel->AddPage(panel, panel->title()); } diff --git a/xs/src/slic3r/GUI/GUI.hpp b/xs/src/slic3r/GUI/GUI.hpp index 3f94f0c917..4f9e45aef6 100644 --- a/xs/src/slic3r/GUI/GUI.hpp +++ b/xs/src/slic3r/GUI/GUI.hpp @@ -13,11 +13,12 @@ class wxNotebook; namespace Slic3r { class PresetBundle; +class PresetCollection; class AppConfig; namespace GUI { -class CTab; +class Tab; void disable_screensaver(); void enable_screensaver(); @@ -34,7 +35,7 @@ void add_debug_menu(wxMenuBar *menu); // Create a new preset tab (print, filament and printer), void create_preset_tabs(PresetBundle *preset_bundle, AppConfig *app_config); // add it at the end of the tab panel. -void add_created_tab(CTab* panel, PresetBundle *preset_bundle, AppConfig *app_config); +void add_created_tab(Tab* panel, PresetBundle *preset_bundle, AppConfig *app_config); void show_error(wxWindow* parent, std::string message); void show_info(wxWindow* parent, std::string message, std::string title); diff --git a/xs/src/slic3r/GUI/OptionsGroup.cpp b/xs/src/slic3r/GUI/OptionsGroup.cpp index 981d2a36b3..438dc284c4 100644 --- a/xs/src/slic3r/GUI/OptionsGroup.cpp +++ b/xs/src/slic3r/GUI/OptionsGroup.cpp @@ -10,7 +10,7 @@ const t_field& OptionsGroup::build_field(const Option& opt) { return build_field(opt.opt_id, opt.opt); } const t_field& OptionsGroup::build_field(const t_config_option_key& id) { - const ConfigOptionDef& opt = options.at(id); + const ConfigOptionDef& opt = m_options_map.at(id); return build_field(id, opt); } @@ -19,13 +19,13 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co // is the normal type. if (opt.gui_type.compare("select") == 0) { } else if (opt.gui_type.compare("select_open") == 0) { - fields.emplace(id, STDMOVE(Choice::Create(_parent, opt, id))); + m_fields.emplace(id, STDMOVE(Choice::Create(m_parent, opt, id))); } else if (opt.gui_type.compare("color") == 0) { - fields.emplace(id, STDMOVE(ColourPicker::Create(_parent, opt, id))); + m_fields.emplace(id, STDMOVE(ColourPicker::Create(m_parent, opt, id))); } else if (opt.gui_type.compare("f_enum_open") == 0 || opt.gui_type.compare("i_enum_open") == 0 || opt.gui_type.compare("i_enum_closed") == 0) { - fields.emplace(id, STDMOVE(Choice::Create(_parent, opt, id))); + m_fields.emplace(id, STDMOVE(Choice::Create(m_parent, opt, id))); } else if (opt.gui_type.compare("slider") == 0) { } else if (opt.gui_type.compare("i_spin") == 0) { // Spinctrl } else { @@ -37,21 +37,21 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co case coPercents: case coString: case coStrings: - fields.emplace(id, STDMOVE(TextCtrl::Create(_parent, opt, id))); + m_fields.emplace(id, STDMOVE(TextCtrl::Create(m_parent, opt, id))); break; case coBool: case coBools: - fields.emplace(id, STDMOVE(CheckBox::Create(_parent, opt, id))); + m_fields.emplace(id, STDMOVE(CheckBox::Create(m_parent, opt, id))); break; case coInt: case coInts: - fields.emplace(id, STDMOVE(SpinCtrl::Create(_parent, opt, id))); + m_fields.emplace(id, STDMOVE(SpinCtrl::Create(m_parent, opt, id))); break; case coEnum: - fields.emplace(id, STDMOVE(Choice::Create(_parent, opt, id))); + m_fields.emplace(id, STDMOVE(Choice::Create(m_parent, opt, id))); break; case coPoints: - fields.emplace(id, STDMOVE(Point::Create(_parent, opt, id))); + m_fields.emplace(id, STDMOVE(Point::Create(m_parent, opt, id))); break; case coNone: break; default: @@ -59,9 +59,14 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co } } // Grab a reference to fields for convenience - const t_field& field = fields[id]; -//! field->on_change = [this](std::string id, boost::any val) { }; - field->parent = parent(); + const t_field& field = m_fields[id]; + field->m_on_change = [this](std::string opt_id, boost::any value){ + //! This function will be called from Field. + //! Call OptionGroup._on_change(...) + if (!this->m_disabled) + this->on_change_OG(opt_id, value); + }; + field->m_parent = parent(); // assign function objects for callbacks, etc. return field; } @@ -74,7 +79,7 @@ void OptionsGroup::append_line(const Line& line) { return; } if (line.widget != nullptr) { - sizer->Add(line.widget(_parent), 0, wxEXPAND | wxALL, wxOSX ? 0 : 15); + sizer->Add(line.widget(m_parent), 0, wxEXPAND | wxALL, wxOSX ? 0 : 15); return; } } @@ -95,7 +100,7 @@ void OptionsGroup::append_line(const Line& line) { return; } - auto grid_sizer = _grid_sizer; + auto grid_sizer = m_grid_sizer; // Build a label if we have it if (label_width != 0) { @@ -146,8 +151,6 @@ void OptionsGroup::append_line(const Line& line) { // add field const Option& opt_ref = opt; -//! auto field = build_field(opt_ref)->getWindow(); -//! sizer->Add(field, 0, wxALIGN_CENTER_VERTICAL, 0); auto& field = build_field(opt_ref); is_sizer_field(field) ? sizer->Add(field->getSizer(), 0, wxALIGN_CENTER_VERTICAL, 0) : @@ -184,14 +187,45 @@ Line OptionsGroup::create_single_option_line(const Option& option) const { return retval; } -//! void OptionsGroup::_on_change(t_config_option_key id, config_value value) { -//! if (on_change != nullptr) -//! on_change(id, value); -//! } +void OptionsGroup::on_change_OG(t_config_option_key id, /*config_value*/boost::any value) { + if (m_on_change != nullptr) + m_on_change(id, value); +} void OptionsGroup::_on_kill_focus (t_config_option_key id) { // do nothing. } +void ConfigOptionsGroup::on_change_OG(t_config_option_key opt_id, boost::any value) +{ +// if (m_options_map.at(opt_id)/*exists $self->_opt_map->{$opt_id}*/) { +// my($opt_key, $opt_index) = @{ $self->_opt_map->{$opt_id} }; +// auto option = m_options->{$opt_id}; -}} + // get value + auto field_value = get_value(opt_id); +// if ($option->gui_flags = ~/ \bserialized\b / ) { +// die "Can't set serialized option indexed value" if $opt_index != -1; +// # Split a string to multiple strings by a semi - colon.This is the old way of storing multi - string values. +// # Currently used for the post_process config value only. +// my @values = split / ; / , $field_value; +// $self->config->set($opt_key, \@values); +// } +// else { +// if ($opt_index == -1) { +// $self->config->set($opt_key, $field_value); +//! m_config->set_key_value(opt_id, new ConfigOption(value)); +// } +// else { +// my $value = $self->config->get($opt_key); +// $value->[$opt_index] = $field_value; +// $self->config->set($opt_key, $value); +// } +// } +// } + + OptionsGroup::on_change_OG(opt_id, value); +} + +} // GUI +} // Slic3r diff --git a/xs/src/slic3r/GUI/OptionsGroup.hpp b/xs/src/slic3r/GUI/OptionsGroup.hpp index ce6a147e69..00bb55c613 100644 --- a/xs/src/slic3r/GUI/OptionsGroup.hpp +++ b/xs/src/slic3r/GUI/OptionsGroup.hpp @@ -33,118 +33,119 @@ class StaticText; /// Wraps a ConfigOptionDef and adds function object for creating a side_widget. struct Option { - ConfigOptionDef opt { ConfigOptionDef() }; - t_config_option_key opt_id;//! {""}; - widget_t side_widget {nullptr}; - bool readonly {false}; + ConfigOptionDef opt { ConfigOptionDef() }; + t_config_option_key opt_id;//! {""}; + widget_t side_widget {nullptr}; + bool readonly {false}; - Option(const ConfigOptionDef& _opt, t_config_option_key id) : opt(_opt), opt_id(id) {}; + Option(const ConfigOptionDef& _opt, t_config_option_key id) : + opt(_opt), opt_id(id) {} }; using t_option = std::unique_ptr