diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 5836b8a2c..53cd71f8e 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -27,9 +27,7 @@ void ConfigManipulation::toggle_field(const std::string& opt_key, const bool tog if (local_config->option(opt_key) == nullptr) return; } - Field* field = get_field(opt_key, opt_index); - if (field==nullptr) return; - field->toggle(toggle); + cb_toggle_field(opt_key, toggle, opt_index); } void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, const bool is_global_config) diff --git a/src/slic3r/GUI/ConfigManipulation.hpp b/src/slic3r/GUI/ConfigManipulation.hpp index 7344f758b..82aa53310 100644 --- a/src/slic3r/GUI/ConfigManipulation.hpp +++ b/src/slic3r/GUI/ConfigManipulation.hpp @@ -21,25 +21,25 @@ class ConfigManipulation // function to loading of changed configuration std::function load_config = nullptr; - std::function get_field = nullptr; + std::function cb_toggle_field = nullptr; // callback to propagation of changed value, if needed std::function cb_value_change = nullptr; DynamicPrintConfig* local_config = nullptr; public: ConfigManipulation(std::function load_config, - std::function get_field, + std::function cb_toggle_field, std::function cb_value_change, DynamicPrintConfig* local_config = nullptr) : load_config(load_config), - get_field(get_field), + cb_toggle_field(cb_toggle_field), cb_value_change(cb_value_change), local_config(local_config) {} ConfigManipulation() {} ~ConfigManipulation() { load_config = nullptr; - get_field = nullptr; + cb_toggle_field = nullptr; cb_value_change = nullptr; } diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index a21826205..e075c7709 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -51,6 +51,20 @@ wxString double_to_string(double const value, const int max_precision /*= 4*/) return s; } +Field::~Field() +{ + if (m_on_kill_focus) + m_on_kill_focus = nullptr; + if (m_on_set_focus) + m_on_set_focus = nullptr; + if (m_on_change) + m_on_change = nullptr; + if (m_back_to_initial_value) + m_back_to_initial_value = nullptr; + if (m_back_to_sys_value) + m_back_to_sys_value = nullptr; +} + void Field::PostInitialize() { auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); @@ -318,7 +332,7 @@ void Field::sys_color_changed() template bool is_defined_input_value(wxWindow* win, const ConfigOptionType& type) { - if (static_cast(win)->GetValue().empty() && type != coString && type != coStrings) + if (!win || (static_cast(win)->GetValue().empty() && type != coString && type != coStrings)) return false; return true; } diff --git a/src/slic3r/GUI/Field.hpp b/src/slic3r/GUI/Field.hpp index 1a4997756..d919304a9 100644 --- a/src/slic3r/GUI/Field.hpp +++ b/src/slic3r/GUI/Field.hpp @@ -145,7 +145,7 @@ public: 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) {}; - virtual ~Field() {} + virtual ~Field(); /// If you don't know what you are getting back, check both methods for nullptr. virtual wxSizer* getSizer() { return nullptr; } diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index d59a83e87..26f19d0c1 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -68,6 +68,8 @@ #include #endif // __WXMSW__ +#include + #if ENABLE_THUMBNAIL_GENERATOR_DEBUG #include #include @@ -78,6 +80,25 @@ namespace GUI { class MainFrame; +class InitTimer +{ + std::chrono::milliseconds start_timer; +public: + InitTimer() + { + start_timer = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()); + } + + ~InitTimer() + { + std::chrono::milliseconds stop_timer = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()); + auto process_duration = std::chrono::milliseconds(stop_timer - start_timer).count(); + printf("on_init duration = %lld ms \n", process_duration); + } +}; + class SplashScreen : public wxSplashScreen { public: @@ -596,6 +617,7 @@ bool GUI_App::OnInit() bool GUI_App::on_init_inner() { + InitTimer local_timer; // Verify resources path const wxString resources_dir = from_u8(Slic3r::resources_dir()); wxCHECK_MSG(wxDirExists(resources_dir), false, diff --git a/src/slic3r/GUI/GUI_ObjectSettings.cpp b/src/slic3r/GUI/GUI_ObjectSettings.cpp index 398cd51d4..e157cb385 100644 --- a/src/slic3r/GUI/GUI_ObjectSettings.cpp +++ b/src/slic3r/GUI/GUI_ObjectSettings.cpp @@ -148,14 +148,15 @@ bool ObjectSettings::update_settings_list() if (is_extruders_cat) option.opt.max = wxGetApp().extruders_edited_cnt(); optgroup->append_single_option_line(option); - + } + optgroup->activate(); + for (auto& opt : cat.second) optgroup->get_field(opt)->m_on_change = [optgroup](const std::string& opt_id, const boost::any& value) { // first of all take a snapshot and then change value in configuration wxGetApp().plater()->take_snapshot(from_u8((boost::format(_utf8(L("Change Option %s"))) % opt_id).str())); optgroup->on_change_OG(opt_id, value); }; - } optgroup->reload_config(); m_settings_list_sizer->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 0); @@ -233,18 +234,19 @@ void ObjectSettings::update_config_values(DynamicPrintConfig* config) } }; - auto get_field = [this](const t_config_option_key & opt_key, int opt_index) + auto toggle_field = [this](const t_config_option_key & opt_key, bool toggle, int opt_index) { Field* field = nullptr; for (auto og : m_og_settings) { field = og->get_fieldc(opt_key, opt_index); if (field != nullptr) - return field; + break; } - return field; + if (field) + field->toggle(toggle); }; - ConfigManipulation config_manipulation(load_config, get_field, nullptr, config); + ConfigManipulation config_manipulation(load_config, toggle_field, nullptr, config); if (!is_object_settings) { diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index dd00b3d68..a5e896fa3 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -116,23 +116,9 @@ OptionsGroup::OptionsGroup( wxWindow* _parent, const wxString& title, } else stb = nullptr; sizer = (staticbox ? new wxStaticBoxSizer(stb, wxVERTICAL) : new wxBoxSizer(wxVERTICAL)); - auto num_columns = 1U; - if (label_width != 0) num_columns++; - if (extra_column != nullptr) num_columns++; - m_grid_sizer = new wxFlexGridSizer(0, num_columns, 1,0); - static_cast(m_grid_sizer)->SetFlexibleDirection(wxBOTH/*wxHORIZONTAL*/); - static_cast(m_grid_sizer)->AddGrowableCol(label_width == 0 ? 0 : !extra_column ? 1 : 2 ); -#if 0//#ifdef __WXGTK__ - m_panel = new wxPanel( _parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - sizer->Fit(m_panel); - sizer->Add(m_panel, 0, wxEXPAND | wxALL, wxOSX||!staticbox ? 0: 5); -#else - sizer->Add(m_grid_sizer, 0, wxEXPAND | wxALL, wxOSX||!staticbox ? 0: 5); -#endif /* __WXGTK__ */ - } -void OptionsGroup::add_undo_buttuns_to_sizer(wxSizer* sizer, const t_field& field) +void OptionsGroup::add_undo_buttons_to_sizer(wxSizer* sizer, const t_field& field) { if (!m_show_modified_btns) { field->m_Undo_btn->set_as_hidden(); @@ -146,11 +132,32 @@ void OptionsGroup::add_undo_buttuns_to_sizer(wxSizer* sizer, const t_field& fiel sizer->Add(field->m_Undo_btn, 0, wxALIGN_CENTER_VERTICAL); } -void OptionsGroup::append_line(const Line& line, wxStaticText** full_Label/* = nullptr*/) { - if ( line.full_width && ( - line.sizer != nullptr || - line.widget != nullptr || - !line.get_extra_widgets().empty() ) +void OptionsGroup::append_line(const Line& line) +{ + m_lines.emplace_back(line); + + if (line.full_width && ( + line.sizer != nullptr || + line.widget != nullptr || + !line.get_extra_widgets().empty()) + ) + return; + + auto option_set = line.get_options(); + for (auto opt : option_set) + m_options.emplace(opt.opt_id, opt); + + // add mode value for current line to m_options_mode + if (!option_set.empty()) + m_options_mode.push_back(option_set[0].opt.mode); +} + +void OptionsGroup::activate_line(Line& line) +{ + if (line.full_width && ( + line.sizer != nullptr || + line.widget != nullptr || + !line.get_extra_widgets().empty()) ) { if (line.sizer != nullptr) { sizer->Add(line.sizer, 0, wxEXPAND | wxALL, wxOSX ? 0 : 15); @@ -174,23 +181,13 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** full_Label/* = n } auto option_set = line.get_options(); - for (auto opt : option_set) - m_options.emplace(opt.opt_id, opt); // Set sidetext width for a better alignment of options in line // "m_show_modified_btns==true" means that options groups are in tabs if (option_set.size() > 1 && m_show_modified_btns) { sidetext_width = Field::def_width_thinner(); - /* Temporary commented till UI-review will be completed - if (m_show_modified_btns) // means that options groups are in tabs - sublabel_width = Field::def_width(); - */ } - // add mode value for current line to m_options_mode - if (!option_set.empty()) - m_options_mode.push_back(option_set[0].opt.mode); - // if we have a single option with no label, no sidetext just add it directly to sizer if (option_set.size() == 1 && label_width == 0 && option_set.front().opt.full_width && option_set.front().opt.label.empty() && @@ -209,7 +206,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** full_Label/* = n const auto& field = build_field(option); auto btn_sizer = new wxBoxSizer(wxHORIZONTAL); - add_undo_buttuns_to_sizer(btn_sizer, field); + add_undo_buttons_to_sizer(btn_sizer, field); tmp_sizer->Add(btn_sizer, 0, wxEXPAND | wxALL, 0); if (is_window_field(field)) tmp_sizer->Add(field->getWindow(), 0, wxEXPAND | wxALL, wxOSX ? 0 : 5); @@ -220,16 +217,16 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** full_Label/* = n auto grid_sizer = m_grid_sizer; #if 0//#ifdef __WXGTK__ - m_panel->SetSizer(m_grid_sizer); - m_panel->Layout(); + m_panel->SetSizer(m_grid_sizer); + m_panel->Layout(); #endif /* __WXGTK__ */ // if we have an extra column, build it - if (extra_column) - { - m_extra_column_item_ptrs.push_back(extra_column(this->ctrl_parent(), line)); - grid_sizer->Add(m_extra_column_item_ptrs.back(), 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 3); - } + if (extra_column) + { + m_extra_column_item_ptrs.push_back(extra_column(this->ctrl_parent(), line)); + grid_sizer->Add(m_extra_column_item_ptrs.back(), 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 3); + } // Build a label if we have it wxStaticText* label=nullptr; @@ -243,8 +240,8 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** full_Label/* = n // Text is properly aligned only when Ellipsize is checked. label_style |= staticbox ? 0 : wxST_ELLIPSIZE_END; #endif /* __WXGTK__ */ - label = new wxStaticText(this->ctrl_parent(), wxID_ANY, line.label + (line.label.IsEmpty() ? "" : ": "), - wxDefaultPosition, wxSize(label_width*wxGetApp().em_unit(), -1), label_style); + label = new wxStaticText(this->ctrl_parent(), wxID_ANY, line.label + (line.label.IsEmpty() ? "" : ": "), + wxDefaultPosition, wxSize(label_width * wxGetApp().em_unit(), -1), label_style); label->SetBackgroundStyle(wxBG_STYLE_PAINT); label->SetFont(wxGetApp().normal_font()); label->Wrap(label_width*wxGetApp().em_unit()); // avoid a Linux/GTK bug @@ -269,16 +266,16 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** full_Label/* = n label->SetToolTip(line.label_tooltip); } - if (full_Label != nullptr) - *full_Label = label; // Initiate the pointer to the control of the full label, if we need this one. - // If there's a widget, build it and add the result to the sizer. + if (line.full_Label != nullptr) + *line.full_Label = label; // Initiate the pointer to the control of the full label, if we need this one. + // If there's a widget, build it and add the result to the sizer. if (line.widget != nullptr) { auto wgt = line.widget(this->ctrl_parent()); // If widget doesn't have label, don't use border grid_sizer->Add(wgt, 0, wxEXPAND | wxBOTTOM | wxTOP, (wxOSX || line.label.IsEmpty()) ? 0 : 5); return; } - + // If we're here, we have more than one option or a single option with sidetext // so we need a horizontal sizer to arrange these things auto sizer = new wxBoxSizer(wxHORIZONTAL); @@ -290,11 +287,11 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** full_Label/* = n const auto& option = option_set.front(); const auto& field = build_field(option, label); - add_undo_buttuns_to_sizer(sizer, field); - if (is_window_field(field)) - sizer->Add(field->getWindow(), option.opt.full_width ? 1 : 0, //(option.opt.full_width ? wxEXPAND : 0) | - wxBOTTOM | wxTOP | (option.opt.full_width ? wxEXPAND : wxALIGN_CENTER_VERTICAL), (wxOSX || !staticbox) ? 0 : 2); - if (is_sizer_field(field)) + add_undo_buttons_to_sizer(sizer, field); + if (is_window_field(field)) + sizer->Add(field->getWindow(), option.opt.full_width ? 1 : 0, //(option.opt.full_width ? wxEXPAND : 0) | + wxBOTTOM | wxTOP | (option.opt.full_width ? wxEXPAND : wxALIGN_CENTER_VERTICAL), (wxOSX || !staticbox) ? 0 : 2); + if (is_sizer_field(field)) sizer->Add(field->getSizer(), 1, /*(*/option.opt.full_width ? wxEXPAND : /*0) |*/ wxALIGN_CENTER_VERTICAL, 0); return; } @@ -306,8 +303,8 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** full_Label/* = n if (!option.label.empty()) { //! To correct translation by context have to use wxGETTEXT_IN_CONTEXT macro from wxWidget 3.1.1 wxString str_label = (option.label == L_CONTEXT("Top", "Layers") || option.label == L_CONTEXT("Bottom", "Layers")) ? - _CTX(option.label, "Layers") : - _(option.label); + _CTX(option.label, "Layers") : + _(option.label); label = new wxStaticText(this->ctrl_parent(), wxID_ANY, str_label + ": ", wxDefaultPosition, //wxDefaultSize); wxSize(sublabel_width != -1 ? sublabel_width * wxGetApp().em_unit() : -1, -1), wxALIGN_RIGHT); label->SetBackgroundStyle(wxBG_STYLE_PAINT); @@ -318,7 +315,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** full_Label/* = n // add field const Option& opt_ref = opt; auto& field = build_field(opt_ref, label); - add_undo_buttuns_to_sizer(sizer_tmp, field); + add_undo_buttons_to_sizer(sizer_tmp, field); if (option_set.size() == 1 && option_set.front().opt.full_width) { const auto v_sizer = new wxBoxSizer(wxVERTICAL); @@ -329,10 +326,10 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** full_Label/* = n break;//return; } - is_sizer_field(field) ? + is_sizer_field(field) ? sizer_tmp->Add(field->getSizer(), 0, wxALIGN_CENTER_VERTICAL, 0) : sizer_tmp->Add(field->getWindow(), 0, wxALIGN_CENTER_VERTICAL, 0); - + // add sidetext if any if (!option.sidetext.empty() || sidetext_width > 0) { auto sidetext = new wxStaticText( this->ctrl_parent(), wxID_ANY, _(option.sidetext), wxDefaultPosition, @@ -369,6 +366,56 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** full_Label/* = n } } +// create all controls for the option group from the m_lines +void OptionsGroup::activate() +{ + if (!sizer->IsEmpty()) + return; + + auto num_columns = 1U; + size_t grow_col = 1; + + if (label_width == 0) + grow_col = 0; + else + num_columns++; + + if (extra_column) { + num_columns++; + grow_col++; + } + + m_grid_sizer = new wxFlexGridSizer(0, num_columns, 1, 0); + static_cast(m_grid_sizer)->SetFlexibleDirection(wxBOTH); + static_cast(m_grid_sizer)->AddGrowableCol(grow_col); + + sizer->Add(m_grid_sizer, 0, wxEXPAND | wxALL, wxOSX || !staticbox ? 0 : 5); + + // activate lines + for (Line& line: m_lines) + activate_line(line); +} +// delete all controls from the option group +void OptionsGroup::clear() +{ + if (sizer->IsEmpty()) + return; + + m_grid_sizer->Clear(true); + sizer->Clear(true); + + for (Line& line : m_lines) + if(line.full_Label) + *line.full_Label = nullptr; + + //for (auto extra_col_win : m_extra_column_item_ptrs) + // destroy(extra_col_win); + m_extra_column_item_ptrs.clear(); + + m_near_label_widget_ptrs.clear(); + m_fields.clear(); +} + Line OptionsGroup::create_single_option_line(const Option& option) const { // Line retval{ _(option.opt.label), _(option.opt.tooltip) }; wxString tooltip = _(option.opt.tooltip); @@ -520,15 +567,31 @@ void ConfigOptionsGroup::Show(const bool show) #endif /* __WXGTK__ */ } -bool ConfigOptionsGroup::update_visibility(ConfigOptionMode mode) { +bool ConfigOptionsGroup::is_visible(ConfigOptionMode mode) +{ if (m_options_mode.empty()) return true; - int opt_mode_size = m_options_mode.size(); - if (m_grid_sizer->GetEffectiveRowsCount() != opt_mode_size && - opt_mode_size == 1) + if (m_options_mode.size() == 1) return m_options_mode[0] <= mode; - Show(true); + int hidden_row_cnt = 0; + for (auto opt_mode : m_options_mode) + if (opt_mode > mode) + hidden_row_cnt++; + + return hidden_row_cnt != m_options_mode.size(); +} + +bool ConfigOptionsGroup::update_visibility(ConfigOptionMode mode) +{ + if (m_options_mode.empty()) + return true; + int opt_mode_size = m_options_mode.size(); + if (m_grid_sizer->GetEffectiveRowsCount() != opt_mode_size && + opt_mode_size == 1) + return m_options_mode[0] <= mode; + + Show(true); int coef = 0; int hidden_row_cnt = 0; diff --git a/src/slic3r/GUI/OptionsGroup.hpp b/src/slic3r/GUI/OptionsGroup.hpp index edd4a15bc..2a4c2cdb6 100644 --- a/src/slic3r/GUI/OptionsGroup.hpp +++ b/src/slic3r/GUI/OptionsGroup.hpp @@ -48,6 +48,7 @@ public: wxString label {wxString("")}; wxString label_tooltip {wxString("")}; size_t full_width {0}; + wxStaticText** full_Label {nullptr}; wxSizer* sizer {nullptr}; widget_t widget {nullptr}; std::function near_label_widget{ nullptr }; @@ -119,7 +120,15 @@ public: return this->stb ? (wxWindow*)this->stb : this->parent(); } - void append_line(const Line& line, wxStaticText** full_Label = nullptr); + void append_line(const Line& line); + // create controls for the option group + void activate_line(Line& line); + + // create all controls for the option group from the m_lines + void activate(); + // delete all controls from the option group + void clear(); + Line create_single_option_line(const Option& option) const; void append_single_option_line(const Option& option) { append_line(create_single_option_line(option)); } @@ -170,11 +179,7 @@ public: void clear_fields_except_of(const std::vector left_fields); - void hide_labels() { - label_width = 0; - m_grid_sizer->SetCols(m_grid_sizer->GetEffectiveColsCount()-1); - static_cast(m_grid_sizer)->AddGrowableCol(!extra_column ? 0 : 1); - } + void hide_labels() { label_width = 0; } OptionsGroup( wxWindow* _parent, const wxString& title, bool is_tab_opt = false, column_t extra_clmn = nullptr); @@ -188,6 +193,8 @@ protected: std::vector m_extra_column_item_ptrs; std::vector m_near_label_widget_ptrs; + std::vector m_lines; + /// Field list, contains unique_ptrs of the derived type. /// using types that need to know what it is beyond the public interface /// need to cast based on the related ConfigOptionDef. @@ -210,7 +217,7 @@ protected: const t_field& build_field(const t_config_option_key& id, const ConfigOptionDef& opt, wxStaticText* label = nullptr); const t_field& build_field(const t_config_option_key& id, wxStaticText* label = nullptr); const t_field& build_field(const Option& opt, wxStaticText* label = nullptr); - void add_undo_buttuns_to_sizer(wxSizer* sizer, const t_field& field); + void add_undo_buttons_to_sizer(wxSizer* sizer, const t_field& field); virtual void on_kill_focus(const std::string& opt_key) {}; virtual void on_set_focus(const std::string& opt_key); @@ -259,6 +266,7 @@ public: // return value shows visibility : false => all options are hidden void Hide(); void Show(const bool show); + bool is_visible(ConfigOptionMode mode); bool update_visibility(ConfigOptionMode mode); void msw_rescale(); void sys_color_changed(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index f7fd608ba..7d6823b97 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -439,9 +439,9 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent) : return sizer; }; line.append_widget(wiping_dialog_btn); - m_og->append_line(line); + m_og->activate(); // Frequently changed parameters for SLA_technology m_og_sla = std::make_shared(parent, ""); @@ -513,6 +513,8 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent) : m_og_sla->append_line(line); + m_og_sla->activate(); + m_sizer = new wxBoxSizer(wxVERTICAL); m_sizer->Add(m_og->sizer, 0, wxEXPAND); m_sizer->Add(m_og_sla->sizer, 0, wxEXPAND); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 29c9e3302..e8519cc0f 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -107,9 +107,9 @@ Tab::Tab(wxNotebook* parent, const wxString& title, Preset::Type type) : m_config_manipulation = get_config_manipulation(); Bind(wxEVT_SIZE, ([this](wxSizeEvent &evt) { - for (auto page : m_pages) - if (! page.get()->IsShown()) - page->layout_valid = false; + //for (auto page : m_pages) + // if (! page.get()->IsShown()) + // page->layout_valid = false; evt.Skip(); })); @@ -290,7 +290,6 @@ void Tab::create_preset_tab() m_treectrl->AssignImageList(m_icons); m_treectrl->AddRoot("root"); m_treectrl->SetIndent(0); - m_disable_tree_sel_changed_event = 0; m_treectrl->Bind(wxEVT_TREE_SEL_CHANGED, &Tab::OnTreeSelChange, this); m_treectrl->Bind(wxEVT_KEY_DOWN, &Tab::OnKeyDown, this); @@ -316,7 +315,7 @@ void Tab::create_preset_tab() // Initialize the DynamicPrintConfig by default keys/values. build(); - rebuild_page_tree(); +// rebuild_page_tree(); m_completed = true; } @@ -450,6 +449,67 @@ void Tab::update_labels_colour() } } +void Tab::decorate() +{ + for (const auto opt : m_options_list) + { + wxStaticText* label = nullptr; + Field* field = nullptr; + + if (opt.first == "bed_shape" || opt.first == "filament_ramming_parameters" || + opt.first == "compatible_prints" || opt.first == "compatible_printers") + label = (m_colored_Labels.find(opt.first) == m_colored_Labels.end()) ? nullptr : m_colored_Labels.at(opt.first); + + if (!label) + field = get_field(opt.first); + if (!label && !field) + continue; + + bool is_nonsys_value = false; + bool is_modified_value = true; + const ScalableBitmap* sys_icon = &m_bmp_value_lock; + const ScalableBitmap* icon = &m_bmp_value_revert; + + const wxColour* color = m_is_default_preset ? &m_default_text_clr : &m_sys_label_clr; + + const wxString* sys_tt = &m_tt_value_lock; + const wxString* tt = &m_tt_value_revert; + + // value isn't equal to system value + if ((opt.second & osSystemValue) == 0) { + is_nonsys_value = true; + sys_icon = m_bmp_non_system; + sys_tt = m_tt_non_system; + // value is equal to last saved + if ((opt.second & osInitValue) != 0) + color = &m_default_text_clr; + // value is modified + else + color = &m_modified_label_clr; + } + if ((opt.second & osInitValue) != 0) + { + is_modified_value = false; + icon = &m_bmp_white_bullet; + tt = &m_tt_white_bullet; + } + + if (label) { + label->SetForegroundColour(*color); + label->Refresh(true); + continue; + } + + field->m_is_nonsys_value = is_nonsys_value; + field->m_is_modified_value = is_modified_value; + field->set_undo_bitmap(icon); + field->set_undo_to_sys_bitmap(sys_icon); + field->set_undo_tooltip(tt); + field->set_undo_to_sys_tooltip(sys_tt); + field->set_label_colour(color); + } +} + // Update UI according to changes void Tab::update_changed_ui() { @@ -473,59 +533,7 @@ void Tab::update_changed_ui() for (auto opt_key : dirty_options) m_options_list[opt_key] &= ~osInitValue; for (auto opt_key : nonsys_options) m_options_list[opt_key] &= ~osSystemValue; -// Freeze(); - //update options "decoration" - for (const auto opt : m_options_list) - { - bool is_nonsys_value = false; - bool is_modified_value = true; - const ScalableBitmap *sys_icon = &m_bmp_value_lock; - const ScalableBitmap *icon = &m_bmp_value_revert; - - const wxColour *color = m_is_default_preset ? &m_default_text_clr : &m_sys_label_clr; - - const wxString *sys_tt = &m_tt_value_lock; - const wxString *tt = &m_tt_value_revert; - - // value isn't equal to system value - if ((opt.second & osSystemValue) == 0) { - is_nonsys_value = true; - sys_icon = m_bmp_non_system; - sys_tt = m_tt_non_system; - // value is equal to last saved - if ((opt.second & osInitValue) != 0) - color = &m_default_text_clr; - // value is modified - else - color = &m_modified_label_clr; - } - if ((opt.second & osInitValue) != 0) - { - is_modified_value = false; - icon = &m_bmp_white_bullet; - tt = &m_tt_white_bullet; - } - if (opt.first == "bed_shape" || opt.first == "filament_ramming_parameters" || - opt.first == "compatible_prints" || opt.first == "compatible_printers") { - wxStaticText* label = (m_colored_Labels.find(opt.first) == m_colored_Labels.end()) ? nullptr : m_colored_Labels.at(opt.first); - if (label) { - label->SetForegroundColour(*color); - label->Refresh(true); - } - continue; - } - - Field* field = get_field(opt.first); - if (field == nullptr) continue; - field->m_is_nonsys_value = is_nonsys_value; - field->m_is_modified_value = is_modified_value; - field->set_undo_bitmap(icon); - field->set_undo_to_sys_bitmap(sys_icon); - field->set_undo_tooltip(tt); - field->set_undo_to_sys_tooltip(sys_tt); - field->set_label_colour(color); - } -// Thaw(); + decorate(); wxTheApp->CallAfter([this]() { if (parent()) //To avoid a crash, parent should be exist for a moment of a tree updating @@ -833,16 +841,12 @@ void Tab::update_visibility() { Freeze(); // There is needed Freeze/Thaw to avoid a flashing after Show/Layout - // m_detach_preset_btn will be shown always after call page->update_visibility() - // So let save a "show state" of m_detach_preset_btn before update_visibility - bool was_shown = m_detach_preset_btn->IsShown(); - for (auto page : m_pages) - page->update_visibility(m_mode); - update_page_tree_visibility(); + page->update_visibility(m_mode, page.get() == m_active_page); + rebuild_page_tree(); - // update visibility for detach_preset_btn - m_detach_preset_btn->Show(was_shown); + if (this->m_type == Preset::TYPE_SLA_PRINT) + update_description_lines(); Layout(); Thaw(); @@ -942,6 +946,15 @@ Field* Tab::get_field(const t_config_option_key& opt_key, Page** selected_page, return field; } +void Tab::toggle_option(const std::string& opt_key, bool toggle, int opt_index/* = -1*/) +{ + if (!m_active_page) + return; + Field* field = m_active_page->get_field(opt_key, opt_index); + if (field) + field->toggle(toggle); +}; + // Set a key/value pair on this page. Return true if the value has been modified. // Currently used for distributing extruders_count over preset pages of Slic3r::GUI::Tab::Printer // after a preset is loaded. @@ -1132,7 +1145,7 @@ void Tab::on_presets_changed() // Instead of PostEvent (EVT_TAB_PRESETS_CHANGED) just call update_presets wxGetApp().plater()->sidebar().update_presets(m_type); - update_preset_description_line(); +// update_preset_description_line(); // Printer selected at the Printer tab, update "compatible" marks at the print and filament selectors. for (auto t: m_dependent_tabs) @@ -1540,27 +1553,46 @@ void TabPrint::reload_config() Tab::reload_config(); } +void TabPrint::update_description_lines() +{ + Tab::update_description_lines(); + + if (m_preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA) + return; + + if (m_active_page && m_active_page->title() == "Layers and perimeters" && + m_recommended_thin_wall_thickness_description_line && m_top_bottom_shell_thickness_explanation) + { + m_recommended_thin_wall_thickness_description_line->SetText( + from_u8(PresetHints::recommended_thin_wall_thickness(*m_preset_bundle))); + m_top_bottom_shell_thickness_explanation->SetText( + from_u8(PresetHints::top_bottom_shell_thickness_explanation(*m_preset_bundle))); + } +} + +void TabPrint::toggle_options() +{ + if (!m_active_page) return; + + m_config_manipulation.toggle_print_fff_options(m_config); +} + void TabPrint::update() { if (m_preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA) return; // ys_FIXME m_update_cnt++; -// Freeze(); m_config_manipulation.update_print_fff_config(m_config, true); - m_recommended_thin_wall_thickness_description_line->SetText( - from_u8(PresetHints::recommended_thin_wall_thickness(*m_preset_bundle))); - m_top_bottom_shell_thickness_explanation->SetText( - from_u8(PresetHints::top_bottom_shell_thickness_explanation(*m_preset_bundle))); + update_description_lines(); Layout(); -// Thaw(); m_update_cnt--; if (m_update_cnt==0) { - m_config_manipulation.toggle_print_fff_options(m_config); + toggle_options(); // update() could be called during undo/redo execution // Update of objectList can cause a crash in this case (because m_objects doesn't match ObjectList) @@ -1571,13 +1603,18 @@ void TabPrint::update() } } -void TabPrint::OnActivate() +//void TabPrint::OnActivate() +//{ +// update_description_lines(); +// Tab::OnActivate(); +//} + +void TabPrint::clear_pages() { - m_recommended_thin_wall_thickness_description_line->SetText( - from_u8(PresetHints::recommended_thin_wall_thickness(*m_preset_bundle))); - m_top_bottom_shell_thickness_explanation->SetText( - from_u8(PresetHints::top_bottom_shell_thickness_explanation(*m_preset_bundle))); - Tab::OnActivate(); + Tab::clear_pages(); + + m_recommended_thin_wall_thickness_description_line = nullptr; + m_top_bottom_shell_thickness_explanation = nullptr; } void TabFilament::add_filament_overrides_page() @@ -1637,10 +1674,13 @@ void TabFilament::add_filament_overrides_page() 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() == "Filament Overrides"; }); - if (page_it == m_pages.end()) + if (!m_active_page || m_active_page->title() != "Filament Overrides") return; - PageShp page = *page_it; + //const auto page_it = std::find_if(m_pages.begin(), m_pages.end(), [](const PageShp page) { return page->title() == "Filament Overrides"; }); + //if (page_it == m_pages.end()) + // return; + //PageShp page = *page_it; + Page* page = m_active_page; const auto og_it = std::find_if(page->m_optgroups.begin(), page->m_optgroups.end(), [](const ConfigOptionsGroupShp og) { return og->title == "Retraction"; }); if (og_it == page->m_optgroups.end()) @@ -1847,6 +1887,40 @@ void TabFilament::update_volumetric_flow_preset_hints() m_volumetric_speed_description_line->SetText(text); } +void TabFilament::update_description_lines() +{ + Tab::update_description_lines(); + + if (!m_active_page) + return; + + if (m_active_page->title() == "Cooling" && m_cooling_description_line) + m_cooling_description_line->SetText(from_u8(PresetHints::cooling_description(m_presets->get_edited_preset()))); + if (m_active_page->title() == "Advanced" && m_volumetric_speed_description_line) + this->update_volumetric_flow_preset_hints(); +} + +void TabFilament::toggle_options() +{ + if (!m_active_page) + return; + + if (m_active_page->title() == "Cooling") + { + bool cooling = m_config->opt_bool("cooling", 0); + bool fan_always_on = cooling || m_config->opt_bool("fan_always_on", 0); + + for (auto el : { "max_fan_speed", "fan_below_layer_time", "slowdown_below_layer_time", "min_print_speed" }) + toggle_option(el, cooling); + + for (auto el : { "min_fan_speed", "disable_fan_first_layers" }) + toggle_option(el, fan_always_on); + } + + if (m_active_page->title() == "Filament Overrides") + update_filament_overrides_page(); +} + void TabFilament::update() { if (m_preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA) @@ -1854,21 +1928,10 @@ void TabFilament::update() m_update_cnt++; - wxString text = from_u8(PresetHints::cooling_description(m_presets->get_edited_preset())); - m_cooling_description_line->SetText(text); - this->update_volumetric_flow_preset_hints(); + update_description_lines(); Layout(); - bool cooling = m_config->opt_bool("cooling", 0); - bool fan_always_on = cooling || m_config->opt_bool("fan_always_on", 0); - - for (auto el : { "max_fan_speed", "fan_below_layer_time", "slowdown_below_layer_time", "min_print_speed" }) - get_field(el)->toggle(cooling); - - for (auto el : { "min_fan_speed", "disable_fan_first_layers" }) - get_field(el)->toggle(fan_always_on); - - update_filament_overrides_page(); + toggle_options(); m_update_cnt--; @@ -1876,10 +1939,18 @@ void TabFilament::update() wxGetApp().mainframe->on_config_changed(m_config); } -void TabFilament::OnActivate() +//void TabFilament::OnActivate() +//{ +// update_description_lines(); +// Tab::OnActivate(); +//} + +void TabFilament::clear_pages() { - this->update_volumetric_flow_preset_hints(); - Tab::OnActivate(); + Tab::clear_pages(); + + m_volumetric_speed_description_line = nullptr; + m_cooling_description_line = nullptr; } wxSizer* Tab::description_line_widget(wxWindow* parent, ogStaticText* *StaticText) @@ -2695,97 +2766,73 @@ void TabPrinter::update_pages() rebuild_page_tree(); } -void TabPrinter::update() +void TabPrinter::active_selected_page() { - m_update_cnt++; - m_presets->get_edited_preset().printer_technology() == ptFFF ? update_fff() : update_sla(); - m_update_cnt--; + Tab::active_selected_page(); - if (m_update_cnt == 0) - wxGetApp().mainframe->on_config_changed(m_config); + // "extruders_count" doesn't update from the update_config(), + // so update it implicitly + if (m_active_page->title() == "General") + m_active_page->set_value("extruders_count", int(m_extruders_count)); } -void TabPrinter::update_fff() +void TabPrinter::toggle_options() { -// Freeze(); - - bool en; - auto serial_speed = get_field("serial_speed"); - if (serial_speed != nullptr) { - en = !m_config->opt_string("serial_port").empty(); - get_field("serial_speed")->toggle(en); - if (m_config->opt_int("serial_speed") != 0 && en) - m_serial_test_btn->Enable(); - else - m_serial_test_btn->Disable(); - } - - /* - { - std::unique_ptr host(PrintHost::get_print_host(m_config)); - m_print_host_test_btn->Enable(!m_config->opt_string("print_host").empty() && host->can_test()); - m_printhost_browse_btn->Enable(host->has_auto_discovery()); - } - */ + if (!m_active_page || m_presets->get_edited_preset().printer_technology() == ptSLA) + return; bool have_multiple_extruders = m_extruders_count > 1; - get_field("toolchange_gcode")->toggle(have_multiple_extruders); - get_field("single_extruder_multi_material")->toggle(have_multiple_extruders); + if (m_active_page->title() == "Custom G-code") + toggle_option("toolchange_gcode", have_multiple_extruders); + if (m_active_page->title() == "General") { + toggle_option("single_extruder_multi_material", have_multiple_extruders); - bool is_marlin_flavor = m_config->option>("gcode_flavor")->value == gcfMarlin; + bool is_marlin_flavor = m_config->option>("gcode_flavor")->value == gcfMarlin; + // Disable silent mode for non-marlin firmwares. + toggle_option("silent_mode", is_marlin_flavor); + } + wxString extruder_number; + long val; + if (m_active_page->title().StartsWith("Extruder ", &extruder_number) && extruder_number.ToLong(&val) && + val > 0 && val <= m_extruders_count) { - Field *sm = get_field("silent_mode"); - if (! is_marlin_flavor) - // Disable silent mode for non-marlin firmwares. - get_field("silent_mode")->toggle(false); - if (is_marlin_flavor) - sm->enable(); - else - sm->disable(); - } - - if (m_use_silent_mode != m_config->opt_bool("silent_mode")) { - m_rebuild_kinematics_page = true; - m_use_silent_mode = m_config->opt_bool("silent_mode"); - } - - for (size_t i = 0; i < m_extruders_count; ++i) { + size_t i = size_t(val - 1); bool have_retract_length = m_config->opt_float("retract_length", i) > 0; // when using firmware retraction, firmware decides retraction length bool use_firmware_retraction = m_config->opt_bool("use_firmware_retraction"); - get_field("retract_length", i)->toggle(!use_firmware_retraction); + toggle_option("retract_length", !use_firmware_retraction, i); // user can customize travel length if we have retraction length or we"re using // firmware retraction - get_field("retract_before_travel", i)->toggle(have_retract_length || use_firmware_retraction); + toggle_option("retract_before_travel", have_retract_length || use_firmware_retraction, i); // user can customize other retraction options if retraction is enabled bool retraction = (have_retract_length || use_firmware_retraction); std::vector vec = { "retract_lift", "retract_layer_change" }; for (auto el : vec) - get_field(el, i)->toggle(retraction); + toggle_option(el, retraction, i); // retract lift above / below only applies if using retract lift vec.resize(0); vec = { "retract_lift_above", "retract_lift_below" }; for (auto el : vec) - get_field(el, i)->toggle(retraction && m_config->opt_float("retract_lift", i) > 0); + toggle_option(el, retraction && (m_config->opt_float("retract_lift", i) > 0), i); // some options only apply when not using firmware retraction vec.resize(0); vec = { "retract_speed", "deretract_speed", "retract_before_wipe", "retract_restart_extra", "wipe" }; for (auto el : vec) - get_field(el, i)->toggle(retraction && !use_firmware_retraction); + toggle_option(el, retraction && !use_firmware_retraction, i); bool wipe = m_config->opt_bool("wipe", i); - get_field("retract_before_wipe", i)->toggle(wipe); + toggle_option("retract_before_wipe", wipe, i); if (use_firmware_retraction && wipe) { wxMessageDialog dialog(parent(), _(L("The Wipe option is not available when using the Firmware Retraction mode.\n" - "\nShall I disable it in order to enable Firmware Retraction?")), + "\nShall I disable it in order to enable Firmware Retraction?")), _(L("Firmware Retraction")), wxICON_WARNING | wxYES | wxNO); DynamicPrintConfig new_conf = *m_config; @@ -2801,14 +2848,32 @@ void TabPrinter::update_fff() load_config(new_conf); } - get_field("retract_length_toolchange", i)->toggle(have_multiple_extruders); + toggle_option("retract_length_toolchange", have_multiple_extruders, i); bool toolchange_retraction = m_config->opt_float("retract_length_toolchange", i) > 0; - get_field("retract_restart_extra_toolchange", i)->toggle - (have_multiple_extruders && toolchange_retraction); + toggle_option("retract_restart_extra_toolchange", have_multiple_extruders && toolchange_retraction, i); } -// Thaw(); +} + +void TabPrinter::update() +{ + m_update_cnt++; + m_presets->get_edited_preset().printer_technology() == ptFFF ? update_fff() : update_sla(); + m_update_cnt--; + + if (m_update_cnt == 0) + wxGetApp().mainframe->on_config_changed(m_config); +} + +void TabPrinter::update_fff() +{ + if (m_use_silent_mode != m_config->opt_bool("silent_mode")) { + m_rebuild_kinematics_page = true; + m_use_silent_mode = m_config->opt_bool("silent_mode"); + } + + toggle_options(); } void TabPrinter::update_sla() @@ -2914,55 +2979,32 @@ void Tab::rebuild_page_tree() const auto selected = sel_item ? m_treectrl->GetItemText(sel_item) : ""; const auto rootItem = m_treectrl->GetRootItem(); - auto have_selection = 0; + wxTreeItemId item; + + // Delete/Append events invoke wxEVT_TREE_SEL_CHANGED event. + // To avoid redundant clear/activate functions call + // suppress activate page before page_tree rebuilding + m_disable_tree_sel_changed_event = true; m_treectrl->DeleteChildren(rootItem); - for (auto p : m_pages) - { - auto itemId = m_treectrl->AppendItem(rootItem, _(p->title()), p->iconID()); - m_treectrl->SetItemTextColour(itemId, p->get_item_colour()); - if (p->title() == selected) { - m_treectrl->SelectItem(itemId); - have_selection = 1; - } - } - if (!have_selection) { - // this is triggered on first load, so we don't disable the sel change event - auto item = m_treectrl->GetFirstVisibleItem(); - if (item) { - m_treectrl->SelectItem(item); - } - } -} - -void Tab::update_page_tree_visibility() -{ - const auto sel_item = m_treectrl->GetSelection(); - const auto selected = sel_item ? m_treectrl->GetItemText(sel_item) : ""; - const auto rootItem = m_treectrl->GetRootItem(); - - auto have_selection = 0; - m_treectrl->DeleteChildren(rootItem); for (auto p : m_pages) { if (!p->get_show()) continue; auto itemId = m_treectrl->AppendItem(rootItem, _(p->title()), p->iconID()); m_treectrl->SetItemTextColour(itemId, p->get_item_colour()); - if (p->title() == selected) { - m_treectrl->SelectItem(itemId); - have_selection = 1; - } + if (p->title() == selected) + item = itemId; } - - if (!have_selection) { + if (!item) { // this is triggered on first load, so we don't disable the sel change event - auto item = m_treectrl->GetFirstVisibleItem(); - if (item) { - m_treectrl->SelectItem(item); - } + item = m_treectrl->GetFirstVisibleItem(); } + // allow activate page before selection of a page_tree item + m_disable_tree_sel_changed_event = false; + if (item) + m_treectrl->SelectItem(item); } void Tab::update_btns_enabling() @@ -3241,6 +3283,34 @@ bool Tab::may_switch_to_SLA_preset() return true; } +void Tab::clear_pages() +{ + // clear pages from the controlls + for (auto p : m_pages) + p->clear(); + + // nulling description lines pointers + m_parent_preset_description_line = nullptr; + m_detach_preset_btn = nullptr; +} + +void Tab::update_description_lines() +{ + if (m_active_page && m_active_page->title() == "Dependencies") + update_preset_description_line(); +} + +void Tab::active_selected_page() +{ + if (!m_active_page) + return; + + m_active_page->activate(m_mode); + update_changed_ui(); + update_description_lines(); + toggle_options(); +} + void Tab::OnTreeSelChange(wxTreeEvent& event) { if (m_disable_tree_sel_changed_event) @@ -3256,9 +3326,9 @@ void Tab::OnTreeSelChange(wxTreeEvent& event) * so on Window is no needed to call a Freeze/Thaw functions. * But under OSX (builds compiled with MacOSX10.14.sdk) wxStaticBitmap rendering is broken without Freeze/Thaw call. */ -#ifdef __WXOSX__ +//#ifdef __WXOSX__ // Use Freeze/Thaw to avoid flickering during cleare/activate new page wxWindowUpdateLocker noUpdates(this); -#endif +//#endif #endif if (m_pages.empty()) @@ -3275,25 +3345,26 @@ void Tab::OnTreeSelChange(wxTreeEvent& event) m_is_modified_values = page->m_is_modified_values; break; } - if (page == nullptr) return; + if (page == nullptr || m_active_page == page) return; + + // clear pages from the controls + m_active_page = page; + clear_pages(); for (auto& el : m_pages) -// if (el.get()->IsShown()) { - el.get()->Hide(); -// break; -// } + el.get()->Hide(); + + active_selected_page(); #ifdef __linux__ no_updates.reset(nullptr); #endif update_undo_buttons(); - page->Show(); -// if (! page->layout_valid) { - page->layout_valid = true; - m_hsizer->Layout(); - Refresh(); -// } + + m_active_page->Show(); + m_hsizer->Layout(); + Refresh(); } void Tab::OnKeyDown(wxKeyEvent& event) @@ -3308,7 +3379,7 @@ void Tab::OnKeyDown(wxKeyEvent& event) // This removes the "dirty" flag of the preset, possibly creates a new preset under a new name, // and activates the new preset. // Wizard calls save_preset with a name "My Settings", otherwise no name is provided and this method -// opens a Slic3r::GUI::SavePresetWindow dialog. +// opens a Slic3r::GUI::SavePresetDialog dialog. void Tab::save_preset(std::string name /*= ""*/, bool detach) { // since buttons(and choices too) don't get focus on Mac, we set focus manually @@ -3494,7 +3565,8 @@ void Tab::create_line_with_widget(ConfigOptionsGroup* optgroup, const std::strin line.widget = widget; m_colored_Labels[opt_key] = nullptr; - optgroup->append_line(line, &m_colored_Labels[opt_key]); + line.full_Label = &m_colored_Labels[opt_key]; + optgroup->append_line(line); } // Return a callback to create a Tab widget to mark the preferences as compatible / incompatible to the current printer. @@ -3649,10 +3721,15 @@ void TabPrinter::apply_extruder_cnt_from_cache() void Tab::compatible_widget_reload(PresetDependencies &deps) { + Field* field = this->get_field(deps.key_condition); + if (!field) + return; + bool has_any = ! m_config->option(deps.key_list)->values.empty(); has_any ? deps.btn->Enable() : deps.btn->Disable(); deps.checkbox->SetValue(! has_any); - this->get_field(deps.key_condition)->toggle(! has_any); + + field->toggle(! has_any); } void Tab::fill_icon_descriptions() @@ -3731,15 +3808,34 @@ void Page::reload_config() group->reload_config(); } -void Page::update_visibility(ConfigOptionMode mode) +void Page::update_visibility(ConfigOptionMode mode, bool update_contolls_visibility) { bool ret_val = false; - for (auto group : m_optgroups) - ret_val = group->update_visibility(mode) || ret_val; + for (auto group : m_optgroups) { + ret_val = (update_contolls_visibility ? + group->update_visibility(mode) : // update visibility for all controlls in group + group->is_visible(mode) // just detect visibility for the group + ) || ret_val; + } m_show = ret_val; } +void Page::activate(ConfigOptionMode mode) +{ + for (auto group : m_optgroups) { + group->activate(); + group->update_visibility(mode); + group->reload_config(); + } +} + +void Page::clear() +{ + for (auto group : m_optgroups) + group->clear(); +} + void Page::msw_rescale() { for (auto group : m_optgroups) @@ -3838,65 +3934,6 @@ ConfigOptionsGroupShp Page::new_optgroup(const wxString& title, int noncommon_la return optgroup; } -void SavePresetWindow::build(const wxString& title, const std::string& default_name, std::vector &values) -{ - // TRN Preset - auto text = new wxStaticText(this, wxID_ANY, from_u8((boost::format(_utf8(L("Save %s as:"))) % into_u8(title)).str()), - wxDefaultPosition, wxDefaultSize); - m_combo = new wxComboBox(this, wxID_ANY, from_u8(default_name), - wxDefaultPosition, wxDefaultSize, 0, 0, wxTE_PROCESS_ENTER); - for (auto value : values) - m_combo->Append(from_u8(value)); - auto buttons = CreateStdDialogButtonSizer(wxOK | wxCANCEL); - - auto sizer = new wxBoxSizer(wxVERTICAL); - sizer->Add(text, 0, wxEXPAND | wxALL, 10); - sizer->Add(m_combo, 0, wxEXPAND | wxLEFT | wxRIGHT, 10); - sizer->Add(buttons, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 10); - - wxButton* btn = static_cast(FindWindowById(wxID_OK, this)); - btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { accept(); }); - m_combo->Bind(wxEVT_TEXT_ENTER, [this](wxCommandEvent&) { accept(); }); - - SetSizer(sizer); - sizer->SetSizeHints(this); -} - -void SavePresetWindow::accept() -{ - m_chosen_name = normalize_utf8_nfc(m_combo->GetValue().ToUTF8()); - if (!m_chosen_name.empty()) { - const char* unusable_symbols = "<>[]:/\\|?*\""; - bool is_unusable_symbol = false; - bool is_unusable_suffix = false; - const std::string unusable_suffix = PresetCollection::get_suffix_modified();//"(modified)"; - for (size_t i = 0; i < std::strlen(unusable_symbols); i++) { - if (m_chosen_name.find_first_of(unusable_symbols[i]) != std::string::npos) { - is_unusable_symbol = true; - break; - } - } - if (m_chosen_name.find(unusable_suffix) != std::string::npos) - is_unusable_suffix = true; - - if (is_unusable_symbol) { - show_error(this,_(L("The supplied name is not valid;")) + "\n" + - _(L("the following characters are not allowed:")) + " " + unusable_symbols); - } - else if (is_unusable_suffix) { - show_error(this,_(L("The supplied name is not valid;")) + "\n" + - _(L("the following suffix is not allowed:")) + "\n\t" + - wxString::FromUTF8(unusable_suffix.c_str())); - } - else if (m_chosen_name == "- default -") { - show_error(this, _(L("The supplied name is not available."))); - } - else { - EndModal(wxID_OK); - } - } -} - void TabSLAMaterial::build() { m_presets = &m_preset_bundle->sla_materials; @@ -4120,6 +4157,34 @@ void TabSLAPrint::reload_config() Tab::reload_config(); } +void TabSLAPrint::update_description_lines() +{ + Tab::update_description_lines(); + + if (m_active_page && m_active_page->title() == "Supports") + { + bool is_visible = m_config->def()->get("support_object_elevation")->mode <= m_mode; + if (m_support_object_elevation_description_line) + { + m_support_object_elevation_description_line->Show(is_visible); + if (is_visible) + { + bool elev = !m_config->opt_bool("pad_enable") || !m_config->opt_bool("pad_around_object"); + m_support_object_elevation_description_line->SetText(elev ? "" : + from_u8((boost::format(_u8L("\"%1%\" is disabled because \"%2%\" is on in \"%3%\" category.\n" + "To enable \"%1%\", please switch off \"%2%\"")) + % _L("Object elevation") % _L("Pad around object") % _L("Pad")).str())); + } + } + } +} + +void TabSLAPrint::toggle_options() +{ + if (m_active_page) + m_config_manipulation.toggle_print_sla_options(m_config); +} + void TabSLAPrint::update() { if (m_preset_bundle->printers.get_selected_preset().printer_technology() == ptFFF) @@ -4129,17 +4194,13 @@ void TabSLAPrint::update() m_config_manipulation.update_print_sla_config(m_config, true); - bool elev = !m_config->opt_bool("pad_enable") || !m_config->opt_bool("pad_around_object"); - m_support_object_elevation_description_line->SetText(elev ? "" : - from_u8((boost::format(_u8L("\"%1%\" is disabled because \"%2%\" is on in \"%3%\" category.\n" - "To enable \"%1%\", please switch off \"%2%\"")) - % _L("Object elevation") % _L("Pad around object") % _L("Pad")).str())); + update_description_lines(); Layout(); m_update_cnt--; if (m_update_cnt == 0) { - m_config_manipulation.toggle_print_sla_options(m_config); + toggle_options(); // update() could be called during undo/redo execution // Update of objectList can cause a crash in this case (because m_objects doesn't match ObjectList) @@ -4150,6 +4211,13 @@ void TabSLAPrint::update() } } +void TabSLAPrint::clear_pages() +{ + Tab::clear_pages(); + + m_support_object_elevation_description_line = nullptr; +} + ConfigManipulation Tab::get_config_manipulation() { auto load_config = [this]() @@ -4160,15 +4228,15 @@ ConfigManipulation Tab::get_config_manipulation() update(); }; - auto get_field_ = [this](const t_config_option_key& opt_key, int opt_index) { - return get_field(opt_key, opt_index); + auto cb_toggle_field = [this](const t_config_option_key& opt_key, bool toggle, int opt_index) { + return toggle_option(opt_key, toggle, opt_index); }; auto cb_value_change = [this](const std::string& opt_key, const boost::any& value) { return on_value_change(opt_key, value); }; - return ConfigManipulation(load_config, get_field_, cb_value_change); + return ConfigManipulation(load_config, cb_toggle_field, cb_value_change); } diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index f0b2e97b3..e8bc2dbb5 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -60,7 +60,6 @@ public: bool m_is_nonsys_values{ true }; // Delayed layout after resizing the main window. - bool layout_valid = false; const std::vector& m_mode_bitmap_cache; public: @@ -73,7 +72,9 @@ public: size_t iconID() const { return m_iconID; } void set_config(DynamicPrintConfig* config_in) { m_config = config_in; } void reload_config(); - void update_visibility(ConfigOptionMode mode); + void update_visibility(ConfigOptionMode mode, bool update_contolls_visibility); + void activate(ConfigOptionMode mode); + void clear(); void msw_rescale(); void sys_color_changed(); Field* get_field(const t_config_option_key& opt_key, int opt_index = -1) const; @@ -195,7 +196,8 @@ protected: int m_icon_count; std::map m_icon_index; // Map from an icon file name to its index std::vector m_pages; - bool m_disable_tree_sel_changed_event; + Page* m_active_page {nullptr}; + bool m_disable_tree_sel_changed_event {false}; bool m_show_incompatible_presets; std::vector m_dependent_tabs; @@ -238,7 +240,7 @@ public: bool m_show_btn_incompatible_presets = false; PresetCollection* m_presets; DynamicPrintConfig* m_config; - ogStaticText* m_parent_preset_description_line; + ogStaticText* m_parent_preset_description_line = nullptr; ScalableButton* m_detach_preset_btn = nullptr; // map of option name -> wxStaticText (colored label, associated with option) @@ -277,7 +279,6 @@ public: void update_ui_items_related_on_parent_preset(const Preset* selected_preset_parent); void load_current_preset(); void rebuild_page_tree(); - void update_page_tree_visibility(); void update_btns_enabling(); void update_preset_choice(); // Select a new preset, possibly delete the current one. @@ -285,6 +286,10 @@ public: bool may_discard_current_dirty_preset(PresetCollection* presets = nullptr, const std::string& new_printer_name = ""); bool may_switch_to_SLA_preset(); + virtual void clear_pages(); + virtual void update_description_lines(); + virtual void active_selected_page(); + void OnTreeSelChange(wxTreeEvent& event); void OnKeyDown(wxKeyEvent& event); @@ -294,6 +299,7 @@ public: void update_show_hide_incompatible_button(); void update_ui_from_settings(); void update_labels_colour(); + void decorate(); void update_changed_ui(); void get_sys_and_mod_flags(const std::string& opt_key, bool& sys_page, bool& modified_page); void update_changed_tree_ui(); @@ -307,6 +313,7 @@ public: virtual void on_preset_loaded() {} virtual void build() = 0; virtual void update() = 0; + virtual void toggle_options() = 0; virtual void init_options_list(); void load_initial_data(); void update_dirty(); @@ -319,6 +326,7 @@ public: virtual void sys_color_changed(); Field* get_field(const t_config_option_key& opt_key, int opt_index = -1) const; Field* get_field(const t_config_option_key &opt_key, Page** selected_page, int opt_index = -1); + void toggle_option(const std::string& opt_key, bool toggle, int opt_index = -1); bool set_value(const t_config_option_key& opt_key, const boost::any& value); wxSizer* description_line_widget(wxWindow* parent, ogStaticText** StaticText); bool current_preset_is_dirty(); @@ -365,15 +373,18 @@ public: void build() override; void reload_config() override; + void update_description_lines() override; + void toggle_options() override; void update() override; - void OnActivate() override; +// void OnActivate() override; + void clear_pages() override; bool supports_printer_technology(const PrinterTechnology tech) override { return tech == ptFFF; } }; class TabFilament : public Tab { - ogStaticText* m_volumetric_speed_description_line; - ogStaticText* m_cooling_description_line; + ogStaticText* m_volumetric_speed_description_line {nullptr}; + ogStaticText* m_cooling_description_line {nullptr}; void add_filament_overrides_page(); void update_filament_overrides_page(); @@ -388,8 +399,11 @@ public: void build() override; void reload_config() override; + void update_description_lines() override; + void toggle_options() override; void update() override; - void OnActivate() override; +// void OnActivate() override; + void clear_pages() override; bool supports_printer_technology(const PrinterTechnology tech) override { return tech == ptFFF; } }; @@ -426,6 +440,8 @@ public: void build() override; void build_fff(); void build_sla(); + void active_selected_page() override; + void toggle_options() override; void update() override; void update_fff(); void update_sla(); @@ -455,6 +471,7 @@ public: void build() override; void reload_config() override; + void toggle_options() override {}; void update() override; void init_options_list() override; bool supports_printer_technology(const PrinterTechnology tech) override { return tech == ptSLA; } @@ -472,25 +489,13 @@ public: void build() override; void reload_config() override; + void update_description_lines() override; + void toggle_options() override; void update() override; -// void init_options_list() override; + void clear_pages() override; bool supports_printer_technology(const PrinterTechnology tech) override { return tech == ptSLA; } }; -class SavePresetWindow :public wxDialog -{ -public: - SavePresetWindow(wxWindow* parent) :wxDialog(parent, wxID_ANY, _(L("Save preset"))) {} - ~SavePresetWindow() {} - - std::string m_chosen_name; - wxComboBox* m_combo; - - void build(const wxString& title, const std::string& default_name, std::vector &values); - void accept(); - std::string get_name() { return m_chosen_name; } -}; - } // GUI } // Slic3r