From 398ff9053d2218bde0b365503b5d39ec18d40fa8 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 22 Sep 2020 11:17:43 +0200 Subject: [PATCH 01/11] Code refactoring of the OptionsGroup class: Controls are created only for the active page now --- src/slic3r/GUI/ConfigManipulation.cpp | 4 +- src/slic3r/GUI/ConfigManipulation.hpp | 8 +- src/slic3r/GUI/Field.cpp | 16 +- src/slic3r/GUI/Field.hpp | 2 +- src/slic3r/GUI/GUI_App.cpp | 22 + src/slic3r/GUI/GUI_ObjectSettings.cpp | 14 +- src/slic3r/GUI/OptionsGroup.cpp | 181 +++++--- src/slic3r/GUI/OptionsGroup.hpp | 22 +- src/slic3r/GUI/Plater.cpp | 4 +- src/slic3r/GUI/Tab.cpp | 628 ++++++++++++++------------ src/slic3r/GUI/Tab.hpp | 53 ++- 11 files changed, 568 insertions(+), 386 deletions(-) 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 From 35d225d673de4a937db27aaf79080b1053c2a06a Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 22 Sep 2020 16:16:35 +0200 Subject: [PATCH 02/11] Fixed scaling on MSW for new OptionsGroup --- src/slic3r/GUI/BedShapeDialog.cpp | 3 ++ src/slic3r/GUI/GUI_App.cpp | 17 +++++++---- src/slic3r/GUI/MainFrame.cpp | 5 +-- src/slic3r/GUI/OptionsGroup.cpp | 2 +- src/slic3r/GUI/PhysicalPrinterDialog.cpp | 2 ++ src/slic3r/GUI/Preferences.cpp | 8 +++++ src/slic3r/GUI/Tab.cpp | 39 ++++++++++++++++++------ src/slic3r/GUI/Tab.hpp | 1 + 8 files changed, 59 insertions(+), 18 deletions(-) diff --git a/src/slic3r/GUI/BedShapeDialog.cpp b/src/slic3r/GUI/BedShapeDialog.cpp index 2fc7d1036..29acdff00 100644 --- a/src/slic3r/GUI/BedShapeDialog.cpp +++ b/src/slic3r/GUI/BedShapeDialog.cpp @@ -252,6 +252,7 @@ void BedShapePanel::build_panel(const ConfigOptionPoints& default_pt, const Conf return sizer; }; optgroup->append_line(line); + optgroup->activate(); wxPanel* texture_panel = init_texture_panel(); wxPanel* model_panel = init_model_panel(); @@ -373,6 +374,7 @@ wxPanel* BedShapePanel::init_texture_panel() return sizer; }; optgroup->append_line(line); + optgroup->activate(); panel->SetSizerAndFit(optgroup->sizer); @@ -452,6 +454,7 @@ wxPanel* BedShapePanel::init_model_panel() return sizer; }; optgroup->append_line(line); + optgroup->activate(); panel->SetSizerAndFit(optgroup->sizer); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 26f19d0c1..0e4e1c897 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -80,22 +80,27 @@ namespace GUI { class MainFrame; -class InitTimer +class TaskTimer { - std::chrono::milliseconds start_timer; + std::chrono::milliseconds start_timer; + std::string task_name; public: - InitTimer() + TaskTimer(std::string task_name): + task_name(task_name.empty() ? "task" : task_name) { start_timer = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()); } - ~InitTimer() + ~TaskTimer() { 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); + std::string out = (boost::format("\n!!! %1% duration = %2% ms \n\n") % task_name % process_duration).str(); + printf(out.c_str()); + std::wstring stemp = std::wstring(out.begin(), out.end()); + OutputDebugString(stemp.c_str()); } }; @@ -617,7 +622,7 @@ bool GUI_App::OnInit() bool GUI_App::on_init_inner() { - InitTimer local_timer; + TaskTimer timer("on_init"); // Verify resources path const wxString resources_dir = from_u8(Slic3r::resources_dir()); wxCHECK_MSG(wxDirExists(resources_dir), false, diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index fbb7a190f..941841f6f 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -345,8 +345,9 @@ void MainFrame::update_layout() fromDlg, toDlg }; - State update_scaling_state = m_layout == ESettingsLayout::Dlg ? State::fromDlg : - layout == ESettingsLayout::Dlg ? State::toDlg : State::noUpdate; + State update_scaling_state = m_layout == ESettingsLayout::Unknown ? State::noUpdate : // don't scale settings dialog from the application start + m_layout == ESettingsLayout::Dlg ? State::fromDlg : + layout == ESettingsLayout::Dlg ? State::toDlg : State::noUpdate; #endif //__WXMSW__ m_layout = layout; diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index a5e896fa3..6e653c2f8 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -632,7 +632,7 @@ void ConfigOptionsGroup::msw_rescale() const int em = em_unit(parent()); // rescale width of label column - if (!m_options_mode.empty() && label_width > 1) + if (m_grid_sizer && !m_options_mode.empty() && label_width > 1) { const int cols = m_grid_sizer->GetCols(); const int rows = m_grid_sizer->GetEffectiveRowsCount(); diff --git a/src/slic3r/GUI/PhysicalPrinterDialog.cpp b/src/slic3r/GUI/PhysicalPrinterDialog.cpp index 3d832ae56..aa8a3811a 100644 --- a/src/slic3r/GUI/PhysicalPrinterDialog.cpp +++ b/src/slic3r/GUI/PhysicalPrinterDialog.cpp @@ -374,6 +374,7 @@ void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgr m_optgroup->append_single_option_line(option); } + m_optgroup->activate(); update(); } @@ -434,6 +435,7 @@ void PhysicalPrinterDialog::on_dpi_changed(const wxRect& suggested_rect) { const int& em = em_unit(); + m_add_preset_btn->msw_rescale(); m_printhost_browse_btn->msw_rescale(); m_printhost_test_btn->msw_rescale(); if (m_printhost_cafile_browse_btn) diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index a3a23fd85..c5fb76637 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -140,6 +140,8 @@ void PreferencesDialog::build() option = Option(def, "show_splash_screen"); m_optgroup_general->append_single_option_line(option); + m_optgroup_general->activate(); + m_optgroup_camera = std::make_shared(this, _(L("Camera"))); m_optgroup_camera->label_width = 40; m_optgroup_camera->m_on_change = [this](t_config_option_key opt_key, boost::any value) { @@ -160,6 +162,8 @@ void PreferencesDialog::build() option = Option(def, "use_free_camera"); m_optgroup_camera->append_single_option_line(option); + m_optgroup_camera->activate(); + m_optgroup_gui = std::make_shared(this, _(L("GUI"))); m_optgroup_gui->label_width = 40; m_optgroup_gui->m_on_change = [this](t_config_option_key opt_key, boost::any value) { @@ -184,6 +188,8 @@ void PreferencesDialog::build() option = Option(def, "use_custom_toolbar_size"); m_optgroup_gui->append_single_option_line(option); + m_optgroup_gui->activate(); + create_icon_size_slider(); m_icon_size_sizer->ShowItems(app_config->get("use_custom_toolbar_size") == "1"); @@ -202,6 +208,8 @@ void PreferencesDialog::build() def.set_default_value(new ConfigOptionBool{ app_config->get("use_environment_map") == "1" }); option = Option(def, "use_environment_map"); m_optgroup_render->append_single_option_line(option); + + m_optgroup_render->activate(); #endif // ENABLE_ENVIRONMENT_MAP auto sizer = new wxBoxSizer(wxVERTICAL); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index e8519cc0f..47c4cf8f9 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -882,8 +882,10 @@ void Tab::msw_rescale() m_treectrl->AssignImageList(m_icons); // rescale options_groups - for (auto page : m_pages) - page->msw_rescale(); + if (m_active_page) + m_active_page->msw_rescale(); + //for (auto page : m_pages) + // page->msw_rescale(); Layout(); } @@ -1169,7 +1171,9 @@ void Tab::build_preset_description_line(ConfigOptionsGroup* optgroup) }; auto detach_preset_btn = [this](wxWindow* parent) { - add_scaled_button(parent, &m_detach_preset_btn, "lock_open_sys", _(L("Detach from system preset")), wxBU_LEFT | wxBU_EXACTFIT); + //add_scaled_button(parent, &m_detach_preset_btn, "lock_open_sys", _(L("Detach from system preset")), wxBU_LEFT | wxBU_EXACTFIT); + m_detach_preset_btn = new ScalableButton(parent, wxID_ANY, "lock_open_sys", _L("Detach from system preset"), + wxDefaultSize, wxDefaultPosition, wxBU_LEFT | wxBU_EXACTFIT, true); ScalableButton* btn = m_detach_preset_btn; btn->SetFont(Slic3r::GUI::wxGetApp().normal_font()); @@ -2668,8 +2672,10 @@ void TabPrinter::build_unregular_pages() optgroup = page->new_optgroup(L("Preview")); auto reset_to_filament_color = [this, extruder_idx](wxWindow* parent) { - add_scaled_button(parent, &m_reset_to_filament_color, "undo", - _(L("Reset to Filament Color")), wxBU_LEFT | wxBU_EXACTFIT); + //add_scaled_button(parent, &m_reset_to_filament_color, "undo", + // _(L("Reset to Filament Color")), wxBU_LEFT | wxBU_EXACTFIT); + m_reset_to_filament_color = new ScalableButton(parent, wxID_ANY, "undo", _L("Reset to Filament Color"), + wxDefaultSize, wxDefaultPosition, wxBU_LEFT | wxBU_EXACTFIT, true); ScalableButton* btn = m_reset_to_filament_color; btn->SetFont(Slic3r::GUI::wxGetApp().normal_font()); auto sizer = new wxBoxSizer(wxHORIZONTAL); @@ -2776,6 +2782,12 @@ void TabPrinter::active_selected_page() m_active_page->set_value("extruders_count", int(m_extruders_count)); } +void TabPrinter::clear_pages() +{ + Tab::clear_pages(); + m_reset_to_filament_color = nullptr; +} + void TabPrinter::toggle_options() { if (!m_active_page || m_presets->get_edited_preset().printer_technology() == ptSLA) @@ -3289,9 +3301,15 @@ void Tab::clear_pages() for (auto p : m_pages) p->clear(); - // nulling description lines pointers + // nulling pointers m_parent_preset_description_line = nullptr; m_detach_preset_btn = nullptr; + + m_compatible_printers.checkbox = nullptr; + m_compatible_printers.btn = nullptr; + + m_compatible_prints.checkbox = nullptr; + m_compatible_prints.btn = nullptr; } void Tab::update_description_lines() @@ -3574,7 +3592,9 @@ wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &dep { deps.checkbox = new wxCheckBox(parent, wxID_ANY, _(L("All"))); deps.checkbox->SetFont(Slic3r::GUI::wxGetApp().normal_font()); - add_scaled_button(parent, &deps.btn, "printer_white", from_u8((boost::format(" %s %s") % _utf8(L("Set")) % std::string(dots.ToUTF8())).str()), wxBU_LEFT | wxBU_EXACTFIT); +// add_scaled_button(parent, &deps.btn, "printer_white", from_u8((boost::format(" %s %s") % _utf8(L("Set")) % std::string(dots.ToUTF8())).str()), wxBU_LEFT | wxBU_EXACTFIT); + deps.btn = new ScalableButton(parent, wxID_ANY, "printer_white", from_u8((boost::format(" %s %s") % _utf8(L("Set")) % std::string(dots.ToUTF8())).str()), + wxDefaultSize, wxDefaultPosition, wxBU_LEFT | wxBU_EXACTFIT, true); deps.btn->SetFont(Slic3r::GUI::wxGetApp().normal_font()); BlinkingBitmap* bbmp = new BlinkingBitmap(parent); @@ -3652,8 +3672,9 @@ wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &dep // Return a callback to create a TabPrinter widget to edit bed shape wxSizer* TabPrinter::create_bed_shape_widget(wxWindow* parent) { - ScalableButton* btn; - add_scaled_button(parent, &btn, "printer_white", " " + _(L("Set")) + " " + dots, wxBU_LEFT | wxBU_EXACTFIT); + ScalableButton* btn = new ScalableButton(parent, wxID_ANY, "printer_white", " " + _(L("Set")) + " " + dots, + wxDefaultSize, wxDefaultPosition, wxBU_LEFT | wxBU_EXACTFIT, true); +// add_scaled_button(parent, &btn, "printer_white", " " + _(L("Set")) + " " + dots, wxBU_LEFT | wxBU_EXACTFIT); btn->SetFont(wxGetApp().normal_font()); BlinkingBitmap* bbmp = new BlinkingBitmap(parent); diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index e8bc2dbb5..89dc2d131 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -441,6 +441,7 @@ public: void build_fff(); void build_sla(); void active_selected_page() override; + void clear_pages() override; void toggle_options() override; void update() override; void update_fff(); From 9377013824e900d3344b3db057ff330ed95d82aa Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 23 Sep 2020 08:33:16 +0200 Subject: [PATCH 03/11] Fixed non-MSW builds --- src/slic3r/GUI/GUI_App.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 0e4e1c897..14fabc3ed 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -99,8 +99,10 @@ public: auto process_duration = std::chrono::milliseconds(stop_timer - start_timer).count(); std::string out = (boost::format("\n!!! %1% duration = %2% ms \n\n") % task_name % process_duration).str(); printf(out.c_str()); +#ifdef __WXMSW__ std::wstring stemp = std::wstring(out.begin(), out.end()); OutputDebugString(stemp.c_str()); +#endif } }; From 52e605069844c02113c93d30f2306c4fb6e2970c Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 23 Sep 2020 09:35:30 +0200 Subject: [PATCH 04/11] Fixed msw_scale() for Infill field --- src/slic3r/GUI/Field.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index e075c7709..09e29caf9 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -1118,8 +1118,7 @@ void Choice::msw_rescale(bool rescale_sidetext/* = false*/) Field::msw_rescale(); wxBitmapComboBox* field = dynamic_cast(window); - - const wxString selection = field->GetString(field->GetSelection()); + const wxString selection = field->GetValue();// field->GetString(index); /* To correct scaling (set new controll size) of a wxBitmapCombobox * we need to refill control with new bitmaps. So, in our case : From 8fb3a44a4e293ca01eb897a5706ef8283c8c9770 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 24 Sep 2020 15:41:48 +0200 Subject: [PATCH 05/11] Fixed highlighting of the searched option + Create controls only on the shown and active tab + Line class : deleted unused sizer + In GUI_Utils added TaskTimer class for the print a time of some task duration + BedShapeDialog:: activated options_groups + commented some unused code --- src/slic3r/GUI/BedShapeDialog.cpp | 2 + src/slic3r/GUI/GUI_App.cpp | 36 ++------- src/slic3r/GUI/GUI_Utils.hpp | 28 +++++++ src/slic3r/GUI/MainFrame.cpp | 75 +++++++++++++++--- src/slic3r/GUI/MainFrame.hpp | 2 + src/slic3r/GUI/OptionsGroup.cpp | 8 +- src/slic3r/GUI/OptionsGroup.hpp | 1 - src/slic3r/GUI/Plater.cpp | 11 ++- src/slic3r/GUI/Tab.cpp | 121 ++++++++++++++++++------------ src/slic3r/GUI/Tab.hpp | 8 +- 10 files changed, 186 insertions(+), 106 deletions(-) diff --git a/src/slic3r/GUI/BedShapeDialog.cpp b/src/slic3r/GUI/BedShapeDialog.cpp index 29acdff00..3caf168b5 100644 --- a/src/slic3r/GUI/BedShapeDialog.cpp +++ b/src/slic3r/GUI/BedShapeDialog.cpp @@ -229,9 +229,11 @@ void BedShapePanel::build_panel(const ConfigOptionPoints& default_pt, const Conf auto optgroup = init_shape_options_page(BedShape::get_name(BedShape::Type::Rectangular)); BedShape::append_option_line(optgroup, BedShape::Parameter::RectSize); BedShape::append_option_line(optgroup, BedShape::Parameter::RectOrigin); + optgroup->activate(); optgroup = init_shape_options_page(BedShape::get_name(BedShape::Type::Circular)); BedShape::append_option_line(optgroup, BedShape::Parameter::Diameter); + optgroup->activate(); optgroup = init_shape_options_page(BedShape::get_name(BedShape::Type::Custom)); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index a9d75e5df..f99e87caf 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -68,8 +68,6 @@ #include #endif // __WXMSW__ -#include - #if ENABLE_THUMBNAIL_GENERATOR_DEBUG #include #include @@ -80,32 +78,6 @@ namespace GUI { class MainFrame; -class TaskTimer -{ - std::chrono::milliseconds start_timer; - std::string task_name; -public: - TaskTimer(std::string task_name): - task_name(task_name.empty() ? "task" : task_name) - { - start_timer = std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()); - } - - ~TaskTimer() - { - 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(); - std::string out = (boost::format("\n!!! %1% duration = %2% ms \n\n") % task_name % process_duration).str(); - printf(out.c_str()); -#ifdef __WXMSW__ - std::wstring stemp = std::wstring(out.begin(), out.end()); - OutputDebugString(stemp.c_str()); -#endif - } -}; - class SplashScreen : public wxSplashScreen { public: @@ -753,9 +725,11 @@ bool GUI_App::on_init_inner() #endif // ENABLE_GCODE_VIEWER scrn->SetText(_L("Creating settings tabs...")); + TaskTimer timer2("Creating settings tabs"); + mainframe = new MainFrame(); // hide settings tabs after first Layout - mainframe->select_tab(0); + mainframe->select_tab(size_t(0)); sidebar().obj_list()->init_objects(); // propagate model objects to object list // update_mode(); // !!! do that later @@ -1007,7 +981,7 @@ void GUI_App::recreate_GUI(const wxString& msg_name) MainFrame *old_main_frame = mainframe; mainframe = new MainFrame(); // hide settings tabs after first Layout - mainframe->select_tab(0); + mainframe->select_tab(size_t(0)); // Propagate model objects to object list. sidebar().obj_list()->init_objects(); SetTopWindow(mainframe); @@ -1456,7 +1430,7 @@ void GUI_App::add_config_menu(wxMenuBar *menu) // hide full main_sizer for mainFrame mainframe->GetSizer()->Show(false); mainframe->update_layout(); - mainframe->select_tab(0); + mainframe->select_tab(size_t(0)); } break; } diff --git a/src/slic3r/GUI/GUI_Utils.hpp b/src/slic3r/GUI/GUI_Utils.hpp index 1c88de570..ea2f0e782 100644 --- a/src/slic3r/GUI/GUI_Utils.hpp +++ b/src/slic3r/GUI/GUI_Utils.hpp @@ -18,6 +18,8 @@ #include #include +#include + #include "Event.hpp" class wxCheckBox; @@ -396,6 +398,32 @@ inline int hex_digit_to_int(const char c) } #endif // ENABLE_GCODE_VIEWER +class TaskTimer +{ + std::chrono::milliseconds start_timer; + std::string task_name; +public: + TaskTimer(std::string task_name): + task_name(task_name.empty() ? "task" : task_name) + { + start_timer = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()); + } + + ~TaskTimer() + { + 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(); + std::string out = (boost::format("\n!!! %1% duration = %2% ms \n\n") % task_name % process_duration).str(); + printf(out.c_str()); +#ifdef __WXMSW__ + std::wstring stemp = std::wstring(out.begin(), out.end()); + OutputDebugString(stemp.c_str()); +#endif + } +}; + }} #endif diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 941841f6f..3165b625b 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -595,7 +595,7 @@ void MainFrame::init_tabpanel() m_last_selected_tab = m_tabpanel->GetSelection(); } else - select_tab(0); // select Plater + select_tab(size_t(0)); // select Plater }); m_plater = new Plater(this, this); @@ -650,6 +650,24 @@ void MainFrame::add_created_tab(Tab* panel) m_tabpanel->AddPage(panel, panel->title()); } +bool MainFrame::is_active_and_shown_tab(Tab* tab) +{ + if (!this) + return false; + int page_id = m_tabpanel->FindPage(tab); + + if (m_tabpanel->GetSelection() != page_id) + return false; + + if (m_layout == ESettingsLayout::Dlg) + return m_settings_dialog.IsShown(); + + if (m_layout == ESettingsLayout::New) + return m_main_sizer->IsShown(m_tabpanel); + + return true; +} + bool MainFrame::can_start_new_project() const { return (m_plater != nullptr) && !m_plater->model().objects.empty(); @@ -1167,7 +1185,7 @@ void MainFrame::init_menubar() { if (m_plater) { append_menu_item(windowMenu, wxID_HIGHEST + 1, _L("&Plater Tab") + "\tCtrl+1", _L("Show the plater"), - [this](wxCommandEvent&) { select_tab(0); }, "plater", nullptr, + [this](wxCommandEvent&) { select_tab(size_t(0)); }, "plater", nullptr, [this]() {return true; }, this); windowMenu->AppendSeparator(); } @@ -1723,9 +1741,35 @@ void MainFrame::load_config(const DynamicPrintConfig& config) #endif } +void MainFrame::select_tab(Tab* tab) +{ + if (!tab) + return; + int page_idx = m_tabpanel->FindPage(tab); + if (page_idx != wxNOT_FOUND && m_layout == ESettingsLayout::Dlg) + page_idx++; + select_tab(size_t(page_idx)); +} + void MainFrame::select_tab(size_t tab/* = size_t(-1)*/) { bool tabpanel_was_hidden = false; + + // Controls on page are created on active page of active tab now. + // We should select/activate tab before its showing to avoid an UI-flickering + auto select = [this, tab](bool was_hidden) { + // when tab == -1, it means we should show the last selected tab + size_t new_selection = tab == (size_t)(-1) ? m_last_selected_tab : (m_layout == ESettingsLayout::Dlg && tab != 0) ? tab - 1 : tab; + + if (m_tabpanel->GetSelection() != new_selection) + m_tabpanel->SetSelection(new_selection); + else if (was_hidden) { + Tab* cur_tab = dynamic_cast(m_tabpanel->GetPage(new_selection)); + if (cur_tab) + cur_tab->OnActivate(); + } + }; + if (m_layout == ESettingsLayout::Dlg) { if (tab==0) { if (m_settings_dialog.IsShown()) @@ -1739,14 +1783,20 @@ void MainFrame::select_tab(size_t tab/* = size_t(-1)*/) #ifdef __WXOSX__ // Don't call SetFont under OSX to avoid name cutting in ObjectList if (m_settings_dialog.IsShown()) m_settings_dialog.Hide(); - + else + tabpanel_was_hidden = true; + + select(tabpanel_was_hidden); m_tabpanel->Show(); m_settings_dialog.Show(); #else - if (m_settings_dialog.IsShown()) + if (m_settings_dialog.IsShown()) { + select(false); m_settings_dialog.SetFocus(); + } else { tabpanel_was_hidden = true; + select(tabpanel_was_hidden); m_tabpanel->Show(); m_settings_dialog.Show(); } @@ -1755,6 +1805,7 @@ void MainFrame::select_tab(size_t tab/* = size_t(-1)*/) else if (m_layout == ESettingsLayout::New) { m_main_sizer->Show(m_plater, tab == 0); tabpanel_was_hidden = !m_main_sizer->IsShown(m_tabpanel); + select(tabpanel_was_hidden); m_main_sizer->Show(m_tabpanel, tab != 0); // plater should be focused for correct navigation inside search window @@ -1762,17 +1813,23 @@ void MainFrame::select_tab(size_t tab/* = size_t(-1)*/) m_plater->SetFocus(); Layout(); } + else + select(false); // When we run application in ESettingsLayout::New or ESettingsLayout::Dlg mode, tabpanel is hidden from the very beginning // and as a result Tab::update_changed_tree_ui() function couldn't update m_is_nonsys_values values, // which are used for update TreeCtrl and "revert_buttons". // So, force the call of this function for Tabs, if tab panel was hidden if (tabpanel_was_hidden) - for (auto tab : wxGetApp().tabs_list) - tab->update_changed_tree_ui(); + for (auto cur_tab : wxGetApp().tabs_list) + cur_tab->update_changed_tree_ui(); - // when tab == -1, it means we should show the last selected tab - m_tabpanel->SetSelection(tab == (size_t)(-1) ? m_last_selected_tab : (m_layout == ESettingsLayout::Dlg && tab != 0) ? tab - 1 : tab); + //// when tab == -1, it means we should show the last selected tab + //size_t new_selection = tab == (size_t)(-1) ? m_last_selected_tab : (m_layout == ESettingsLayout::Dlg && tab != 0) ? tab - 1 : tab; + //if (m_tabpanel->GetSelection() != new_selection) + // m_tabpanel->SetSelection(new_selection); + //if (tabpanel_was_hidden) + // static_cast(m_tabpanel->GetPage(new_selection))->OnActivate(); } // Set a camera direction, zoom to all objects. @@ -1919,7 +1976,7 @@ SettingsDialog::SettingsDialog(MainFrame* mainframe) auto key_up_handker = [this](wxKeyEvent& evt) { if ((evt.GetModifiers() & wxMOD_CONTROL) != 0) { switch (evt.GetKeyCode()) { - case '1': { m_main_frame->select_tab(0); break; } + case '1': { m_main_frame->select_tab(size_t(0)); break; } case '2': { m_main_frame->select_tab(1); break; } case '3': { m_main_frame->select_tab(2); break; } case '4': { m_main_frame->select_tab(3); break; } diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index 868a68492..18d2a73bd 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -159,6 +159,7 @@ public: void init_tabpanel(); void create_preset_tabs(); void add_created_tab(Tab* panel); + bool is_active_and_shown_tab(Tab* tab); #if ENABLE_GCODE_VIEWER void init_menubar_as_editor(); void init_menubar_as_gcodeviewer(); @@ -184,6 +185,7 @@ public: void load_config(const DynamicPrintConfig& config); // Select tab in m_tabpanel // When tab == -1, will be selected last selected tab + void select_tab(Tab* tab); void select_tab(size_t tab = size_t(-1)); void select_view(const std::string& direction); // Propagate changed configuration from the Tab to the Plater and save changes to the AppConfig diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index d96b0565a..13c577662 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -138,7 +138,6 @@ 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()) ) @@ -156,14 +155,9 @@ void OptionsGroup::append_line(const Line& line) 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); - return; - } if (line.widget != nullptr) { sizer->Add(line.widget(this->ctrl_parent()), 0, wxEXPAND | wxALL, wxOSX ? 0 : 15); return; @@ -585,7 +579,7 @@ bool ConfigOptionsGroup::is_visible(ConfigOptionMode mode) bool ConfigOptionsGroup::update_visibility(ConfigOptionMode mode) { - if (m_options_mode.empty()) + if (m_options_mode.empty() || !m_grid_sizer) return true; int opt_mode_size = m_options_mode.size(); if (m_grid_sizer->GetEffectiveRowsCount() != opt_mode_size && diff --git a/src/slic3r/GUI/OptionsGroup.hpp b/src/slic3r/GUI/OptionsGroup.hpp index 2a4c2cdb6..b3198137b 100644 --- a/src/slic3r/GUI/OptionsGroup.hpp +++ b/src/slic3r/GUI/OptionsGroup.hpp @@ -49,7 +49,6 @@ public: 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 }; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 19f735714..6607bd575 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -305,11 +305,12 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent) : if (!tab_print) return; if (opt_key == "fill_density") { - value = m_og->get_config_value(*config, opt_key); - tab_print->set_value(opt_key, value); + tab_print->update_dirty(); + tab_print->reload_config(); tab_print->update(); } - else{ + else + { DynamicPrintConfig new_conf = *config; if (opt_key == "brim") { double new_val; @@ -350,8 +351,6 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent) : } tab_print->load_config(new_conf); } - - tab_print->update_dirty(); }; @@ -982,7 +981,7 @@ void Sidebar::jump_to_option(size_t selected) wxGetApp().get_tab(opt.type)->activate_option(boost::nowide::narrow(opt.opt_key), boost::nowide::narrow(opt.category)); // Switch to the Settings NotePad - wxGetApp().mainframe->select_tab(); +// wxGetApp().mainframe->select_tab(); } ObjectManipulation* Sidebar::obj_manipul() diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 47c4cf8f9..8d1560448 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -67,8 +67,10 @@ void Tab::Highlighter::invalidate() { timer.Stop(); - bbmp->invalidate(); - bbmp = nullptr; + if (bbmp) { + bbmp->invalidate(); + bbmp = nullptr; + } blink_counter = 0; } @@ -385,19 +387,24 @@ Slic3r::GUI::PageShp Tab::add_options_page(const wxString& title, const std::str void Tab::OnActivate() { -#ifdef __WXOSX__ wxWindowUpdateLocker noUpdates(this); - +#ifdef __WXOSX__ +// wxWindowUpdateLocker noUpdates(this); auto size = GetSizer()->GetSize(); m_tmp_panel->GetSizer()->SetMinSize(size.x + m_size_move, size.y); Fit(); m_size_move *= -1; #endif // __WXOSX__ + + // create controls on active page + active_selected_page(); + m_active_page->Show(); + m_hsizer->Layout(); + Refresh(); } void Tab::update_labels_colour() { -// Freeze(); //update options "decoration" for (const auto opt : m_options_list) { @@ -426,7 +433,6 @@ void Tab::update_labels_colour() if (field == nullptr) continue; field->set_label_colour_force(color); } -// Thaw(); auto cur_item = m_treectrl->GetFirstVisibleItem(); if (!cur_item || !m_treectrl->IsVisible(cur_item)) @@ -722,6 +728,8 @@ void Tab::update_undo_buttons() void Tab::on_roll_back_value(const bool to_sys /*= true*/) { + if (!m_active_page) return; + int os; if (to_sys) { if (!m_is_nonsys_values) return; @@ -734,10 +742,10 @@ void Tab::on_roll_back_value(const bool to_sys /*= true*/) m_postpone_update_ui = true; - auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection()); - for (auto page : m_pages) - if (_(page->title()) == selection) { - for (auto group : page->m_optgroups) { + //auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection()); + //for (auto page : m_pages) + // if (_(page->title()) == selection) { + for (auto group : /*page*/m_active_page->m_optgroups) { if (group->title == "Capabilities") { if ((m_options_list["extruders_count"] & os) == 0) to_sys ? group->back_to_sys_value("extruders_count") : group->back_to_initial_value("extruders_count"); @@ -778,8 +786,8 @@ void Tab::on_roll_back_value(const bool to_sys /*= true*/) to_sys ? group->back_to_sys_value(opt_key) : group->back_to_initial_value(opt_key); } } - break; - } + // break; + //} m_postpone_update_ui = false; update_changed_ui(); @@ -819,10 +827,10 @@ void Tab::load_config(const DynamicPrintConfig& config) // Reload current $self->{config} (aka $self->{presets}->edited_preset->config) into the UI fields. void Tab::reload_config() { -// Freeze(); - for (auto page : m_pages) - page->reload_config(); -// Thaw(); + //for (auto page : m_pages) + // page->reload_config(); + if (m_active_page) + m_active_page->reload_config(); } void Tab::update_mode() @@ -884,8 +892,6 @@ void Tab::msw_rescale() // rescale options_groups if (m_active_page) m_active_page->msw_rescale(); - //for (auto page : m_pages) - // page->msw_rescale(); Layout(); } @@ -918,14 +924,16 @@ void Tab::sys_color_changed() update_labels_colour(); // update options_groups - for (auto page : m_pages) - page->sys_color_changed(); + if (m_active_page) + m_active_page->msw_rescale(); Layout(); } Field* Tab::get_field(const t_config_option_key& opt_key, int opt_index/* = -1*/) const { + return m_active_page ? m_active_page->get_field(opt_key, opt_index) : nullptr; + Field* field = nullptr; for (auto page : m_pages) { field = page->get_field(opt_key, opt_index); @@ -960,14 +968,14 @@ void Tab::toggle_option(const std::string& opt_key, bool toggle, int opt_index/* // 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. -bool Tab::set_value(const t_config_option_key& opt_key, const boost::any& value) { - bool changed = false; - for(auto page: m_pages) { - if (page->set_value(opt_key, value)) - changed = true; - } - return changed; -} +//bool Tab::set_value(const t_config_option_key& opt_key, const boost::any& value) { +// bool changed = false; +// for(auto page: m_pages) { +// if (page->set_value(opt_key, value)) +// changed = true; +// } +// return changed; +//} // To be called by custom widgets, load a value into a config, // update the preset selection boxes (the dirty flags) @@ -1020,7 +1028,7 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value) if (opt_key == "pad_around_object") { for (PageShp &pg : m_pages) { - Field * fld = pg->get_field(opt_key); + Field * fld = pg->get_field(opt_key); /// !!! ysFIXME ???? if (fld) fld->set_value(value, false); } } @@ -1064,11 +1072,20 @@ void Tab::update_wiping_button_visibility() { void Tab::activate_option(const std::string& opt_key, const wxString& category) { - Page* page {nullptr}; - Field* field = get_field(opt_key, &page); +// wxWindowUpdateLocker noUpdates(this); + + // we should to activate a tab with searched option, if it doesn't. + //if (!wxGetApp().mainframe->is_active_tab(this)) { + // wxNotebook* tap_panel = wxGetApp().tab_panel(); + // tap_panel->SetSelection(tap_panel->FindPage(this)); + //} +// Page* page {nullptr}; +// Field* field = get_field(opt_key, &page); // for option, which doesn't have field but just a text or button - wxString page_title = (!field || !page) ? category : page->title(); +// wxString page_title = (!field || !page) ? category : page->title(); + + wxString page_title = _(category); auto cur_item = m_treectrl->GetFirstVisibleItem(); if (!cur_item || !m_treectrl->IsVisible(cur_item)) @@ -1076,7 +1093,7 @@ void Tab::activate_option(const std::string& opt_key, const wxString& category) while (cur_item) { auto title = m_treectrl->GetItemText(cur_item); - if (_(page_title) != title) { + if (page_title != title) { cur_item = m_treectrl->GetNextVisible(cur_item); continue; } @@ -1086,10 +1103,14 @@ void Tab::activate_option(const std::string& opt_key, const wxString& category) } // we should to activate a tab with searched option, if it doesn't. - wxNotebook* tap_panel = wxGetApp().tab_panel(); - int page_id = tap_panel->FindPage(this); - if (tap_panel->GetSelection() != page_id) - tap_panel->SetSelection(page_id); + wxGetApp().mainframe->select_tab(this); + Field* field = get_field(opt_key); + + // we should to activate a tab with searched option, if it doesn't. + //wxNotebook* tap_panel = wxGetApp().tab_panel(); + //int page_id = tap_panel->FindPage(this); + //if (tap_panel->GetSelection() != page_id) + // tap_panel->SetSelection(page_id); // focused selected field if (field) { @@ -1973,7 +1994,7 @@ bool Tab::current_preset_is_dirty() { return m_presets->current_is_dirty(); } - +/* void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup) { const PrinterTechnology tech = m_presets->get_selected_preset().printer_technology(); @@ -2090,7 +2111,7 @@ void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup) \tOn this system, %s uses HTTPS certificates from the system Certificate Store or Keychain.\n\ \tTo use a custom CA file, please import your CA file into Certificate Store / Keychain."))) % SLIC3R_APP_NAME).str() % std::string(ca_file_hint.ToUTF8())).str())); -*/ txt->SetFont(Slic3r::GUI::wxGetApp().normal_font()); +* / txt->SetFont(Slic3r::GUI::wxGetApp().normal_font()); auto sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(txt, 1, wxEXPAND); return sizer; @@ -2099,7 +2120,7 @@ void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup) optgroup->append_line(line); } } - +*/ void TabPrinter::build() { m_presets = &m_preset_bundle->printers; @@ -2423,14 +2444,14 @@ void TabPrinter::build_sla() build_preset_description_line(optgroup.get()); } - +/* void TabPrinter::update_serial_ports() { Field *field = get_field("serial_port"); Choice *choice = static_cast(field); choice->set_values(Utils::scan_serial_ports()); } - +*/ void TabPrinter::extruders_count_changed(size_t extruders_count) { bool is_count_changed = false; @@ -2728,7 +2749,7 @@ void TabPrinter::on_preset_loaded() // update the extruders count field auto *nozzle_diameter = dynamic_cast(m_config->option("nozzle_diameter")); size_t extruders_count = nozzle_diameter->values.size(); - set_value("extruders_count", int(extruders_count)); +// set_value("extruders_count", int(extruders_count)); // update the GUI field according to the number of nozzle diameters supplied extruders_count_changed(extruders_count); } @@ -3297,6 +3318,8 @@ bool Tab::may_switch_to_SLA_preset() void Tab::clear_pages() { + // invalidated highlighter, if any exists + m_highlighter.invalidate(); // clear pages from the controlls for (auto p : m_pages) p->clear(); @@ -3310,6 +3333,8 @@ void Tab::clear_pages() m_compatible_prints.checkbox = nullptr; m_compatible_prints.btn = nullptr; + + m_blinking_ikons.clear(); } void Tab::update_description_lines() @@ -3372,7 +3397,10 @@ void Tab::OnTreeSelChange(wxTreeEvent& event) for (auto& el : m_pages) el.get()->Hide(); - active_selected_page(); + if (wxGetApp().mainframe->is_active_and_shown_tab(this)) { + active_selected_page(); + m_active_page->Show(); + } #ifdef __linux__ no_updates.reset(nullptr); @@ -3380,7 +3408,7 @@ void Tab::OnTreeSelChange(wxTreeEvent& event) update_undo_buttons(); - m_active_page->Show(); +// m_active_page->Show(); m_hsizer->Layout(); Refresh(); } @@ -3592,7 +3620,6 @@ wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &dep { deps.checkbox = new wxCheckBox(parent, wxID_ANY, _(L("All"))); deps.checkbox->SetFont(Slic3r::GUI::wxGetApp().normal_font()); -// add_scaled_button(parent, &deps.btn, "printer_white", from_u8((boost::format(" %s %s") % _utf8(L("Set")) % std::string(dots.ToUTF8())).str()), wxBU_LEFT | wxBU_EXACTFIT); deps.btn = new ScalableButton(parent, wxID_ANY, "printer_white", from_u8((boost::format(" %s %s") % _utf8(L("Set")) % std::string(dots.ToUTF8())).str()), wxDefaultSize, wxDefaultPosition, wxBU_LEFT | wxBU_EXACTFIT, true); deps.btn->SetFont(Slic3r::GUI::wxGetApp().normal_font()); @@ -3674,7 +3701,6 @@ wxSizer* TabPrinter::create_bed_shape_widget(wxWindow* parent) { ScalableButton* btn = new ScalableButton(parent, wxID_ANY, "printer_white", " " + _(L("Set")) + " " + dots, wxDefaultSize, wxDefaultPosition, wxBU_LEFT | wxBU_EXACTFIT, true); -// add_scaled_button(parent, &btn, "printer_white", " " + _(L("Set")) + " " + dots, wxBU_LEFT | wxBU_EXACTFIT); btn->SetFont(wxGetApp().normal_font()); BlinkingBitmap* bbmp = new BlinkingBitmap(parent); @@ -4103,7 +4129,6 @@ void TabSLAPrint::build() optgroup->append_single_option_line("support_base_safety_distance"); // Mirrored parameter from Pad page for toggling elevation on the same page -// optgroup->append_single_option_line("pad_around_object"); optgroup->append_single_option_line("support_object_elevation"); Line line{ "", "" }; diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index 89dc2d131..0a9d17c0e 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -223,9 +223,9 @@ protected: void set_timer_owner(wxEvtHandler* owner, int timerid = wxID_ANY); void init(BlinkingBitmap* bmp); void blink(); + void invalidate(); private: - void invalidate(); BlinkingBitmap* bbmp {nullptr}; int blink_counter {0}; @@ -327,7 +327,7 @@ public: 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); +// 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(); @@ -417,7 +417,7 @@ class TabPrinter : public Tab std::vector m_pages_fff; std::vector m_pages_sla; - void build_printhost(ConfigOptionsGroup *optgroup); +// void build_printhost(ConfigOptionsGroup *optgroup); public: wxButton* m_serial_test_btn = nullptr; ScalableButton* m_print_host_test_btn = nullptr; @@ -447,7 +447,7 @@ public: void update_fff(); void update_sla(); void update_pages(); // update m_pages according to printer technology - void update_serial_ports(); +// void update_serial_ports(); void extruders_count_changed(size_t extruders_count); PageShp build_kinematics_page(); void build_unregular_pages(); From d5bd76776f1960c3d69797ceb956228c7bee7b63 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 24 Sep 2020 18:54:54 +0200 Subject: [PATCH 06/11] Page class is used as a container of option groups and doesn't inherited from wxScrolledWindow now --- src/slic3r/GUI/GUI_ObjectLayers.cpp | 1 + src/slic3r/GUI/GUI_ObjectManipulation.cpp | 1 + src/slic3r/GUI/GUI_ObjectSettings.cpp | 1 + src/slic3r/GUI/OptionsGroup.cpp | 37 ++++++++---- src/slic3r/GUI/OptionsGroup.hpp | 2 +- src/slic3r/GUI/Tab.cpp | 71 +++++++++++++++-------- src/slic3r/GUI/Tab.hpp | 5 +- 7 files changed, 80 insertions(+), 38 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectLayers.cpp b/src/slic3r/GUI/GUI_ObjectLayers.cpp index 90a725fbf..09b4f36ab 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.cpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.cpp @@ -34,6 +34,7 @@ ObjectLayers::ObjectLayers(wxWindow* parent) : m_grid_sizer->Add(temp); } + m_og->activate(); m_og->sizer->Clear(true); m_og->sizer->Add(m_grid_sizer, 0, wxEXPAND | wxALL, wxOSX ? 0 : 5); diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 7243e8c73..4b1197a75 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -431,6 +431,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) : m_main_grid_sizer->Add(m_check_inch, 1, wxEXPAND); + m_og->activate(); m_og->sizer->Clear(true); m_og->sizer->Add(m_main_grid_sizer, 1, wxEXPAND | wxALL, border); } diff --git a/src/slic3r/GUI/GUI_ObjectSettings.cpp b/src/slic3r/GUI/GUI_ObjectSettings.cpp index e157cb385..1fbf32e11 100644 --- a/src/slic3r/GUI/GUI_ObjectSettings.cpp +++ b/src/slic3r/GUI/GUI_ObjectSettings.cpp @@ -58,6 +58,7 @@ wxSizer* OG_Settings::get_sizer() ObjectSettings::ObjectSettings(wxWindow* parent) : OG_Settings(parent, true) { + m_og->activate(); m_og->set_name(_(L("Additional Settings"))); m_settings_list_sizer = new wxBoxSizer(wxVERTICAL); diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index 13c577662..310dc9544 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -110,13 +110,13 @@ OptionsGroup::OptionsGroup( wxWindow* _parent, const wxString& title, m_show_modified_btns(is_tab_opt), staticbox(title!=""), extra_column(extra_clmn) { - if (staticbox) { + /*if (staticbox) { stb = new wxStaticBox(_parent, wxID_ANY, _(title)); if (!wxOSX) stb->SetBackgroundStyle(wxBG_STYLE_PAINT); stb->SetFont(wxOSX ? wxGetApp().normal_font() : wxGetApp().bold_font()); } else stb = nullptr; - sizer = (staticbox ? new wxStaticBoxSizer(stb, wxVERTICAL) : new wxBoxSizer(wxVERTICAL)); + sizer = (staticbox ? new wxStaticBoxSizer(stb, wxVERTICAL) : new wxBoxSizer(wxVERTICAL));*/ } void OptionsGroup::add_undo_buttons_to_sizer(wxSizer* sizer, const t_field& field) @@ -362,10 +362,19 @@ void OptionsGroup::activate_line(Line& line) } // create all controls for the option group from the m_lines -void OptionsGroup::activate() +bool OptionsGroup::activate() { - if (!sizer->IsEmpty()) - return; + if (sizer)//(!sizer->IsEmpty()) + return false; + + if (staticbox) { + stb = new wxStaticBox(m_parent, wxID_ANY, _(title)); + if (!wxOSX) stb->SetBackgroundStyle(wxBG_STYLE_PAINT); + stb->SetFont(wxOSX ? wxGetApp().normal_font() : wxGetApp().bold_font()); + } + else + stb = nullptr; + sizer = (staticbox ? new wxStaticBoxSizer(stb, wxVERTICAL) : new wxBoxSizer(wxVERTICAL)); auto num_columns = 1U; size_t grow_col = 1; @@ -389,24 +398,30 @@ void OptionsGroup::activate() // activate lines for (Line& line: m_lines) activate_line(line); + + return true; } // delete all controls from the option group void OptionsGroup::clear() { - if (sizer->IsEmpty()) + if (!sizer)//(sizer->IsEmpty()) return; - m_grid_sizer->Clear(true); - sizer->Clear(true); +// m_grid_sizer->Clear(true); + m_grid_sizer = nullptr; + +// sizer->Clear(true); + //if (stb) { + // stb->SetContainingSizer(NULL); + // stb->Destroy(); + //} + sizer = nullptr; 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(); } diff --git a/src/slic3r/GUI/OptionsGroup.hpp b/src/slic3r/GUI/OptionsGroup.hpp index b3198137b..4d70347aa 100644 --- a/src/slic3r/GUI/OptionsGroup.hpp +++ b/src/slic3r/GUI/OptionsGroup.hpp @@ -124,7 +124,7 @@ public: void activate_line(Line& line); // create all controls for the option group from the m_lines - void activate(); + bool activate(); // delete all controls from the option group void clear(); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 8d1560448..b0dfe44bc 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -296,6 +296,19 @@ void Tab::create_preset_tab() m_treectrl->Bind(wxEVT_TREE_SEL_CHANGED, &Tab::OnTreeSelChange, this); m_treectrl->Bind(wxEVT_KEY_DOWN, &Tab::OnKeyDown, this); + // Initialize the page. +#ifdef __WXOSX__ + auto page_parent = m_tmp_panel; +#else + auto page_parent = this; +#endif + + m_page_view = new wxScrolledWindow(page_parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); + m_page_sizer = new wxBoxSizer(wxVERTICAL); + m_page_view->SetSizer(m_page_sizer); + m_page_view->SetScrollbars(1, 20, 1, 2); + m_hsizer->Add(m_page_view, 1, wxEXPAND | wxLEFT, 5); + m_btn_save_preset->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) { save_preset(); })); m_btn_delete_preset->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) { delete_preset(); })); m_btn_hide_incompatible_presets->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) { @@ -368,15 +381,16 @@ Slic3r::GUI::PageShp Tab::add_options_page(const wxString& title, const std::str #else auto panel = this; #endif - PageShp page(new Page(panel, title, icon_idx, m_mode_bitmap_cache)); + PageShp page(new Page(/*panel*/m_page_view, title, icon_idx, m_mode_bitmap_cache)); // page->SetBackgroundStyle(wxBG_STYLE_SYSTEM); #ifdef __WINDOWS__ // page->SetDoubleBuffered(true); #endif //__WINDOWS__ - page->SetScrollbars(1, 20, 1, 2); - page->Hide(); - m_hsizer->Add(page.get(), 1, wxEXPAND | wxLEFT, 5); + //page->SetScrollbars(1, 20, 1, 2); + //page->Hide(); + //m_hsizer->Add(page.get(), 1, wxEXPAND | wxLEFT, 5); +// m_hsizer->Add(page->vsizer(), 1, wxEXPAND | wxLEFT, 5); if (!is_extruder_pages) m_pages.push_back(page); @@ -398,7 +412,7 @@ void Tab::OnActivate() // create controls on active page active_selected_page(); - m_active_page->Show(); +// m_active_page->Show(); m_hsizer->Layout(); Refresh(); } @@ -2562,12 +2576,12 @@ void TabPrinter::build_unregular_pages() /* Workaround for correct layout of controls inside the created page: * In some _strange_ way we should we should imitate page resizing. */ - auto layout_page = [this](PageShp page) +/* auto layout_page = [this](PageShp page) { const wxSize& sz = page->GetSize(); page->SetSize(sz.x + 1, sz.y + 1); page->SetSize(sz); - }; + };*/ #endif //__WXMSW__ // Add/delete Kinematics page according to is_marlin_flavor @@ -2584,7 +2598,7 @@ void TabPrinter::build_unregular_pages() if (existed_page < n_before_extruders && is_marlin_flavor) { auto page = build_kinematics_page(); #ifdef __WXMSW__ - layout_page(page); +// layout_page(page); #endif m_pages.insert(m_pages.begin() + n_before_extruders, page); } @@ -2722,7 +2736,7 @@ void TabPrinter::build_unregular_pages() optgroup->append_line(line); #ifdef __WXMSW__ - layout_page(page); +// layout_page(page); #endif } @@ -2762,8 +2776,8 @@ void TabPrinter::update_pages() return; // hide all old pages - for (auto& el : m_pages) - el.get()->Hide(); + //for (auto& el : m_pages) + // el.get()->Hide(); // set m_pages to m_pages_(technology before changing) m_printer_technology == ptFFF ? m_pages.swap(m_pages_fff) : m_pages.swap(m_pages_sla); @@ -3320,9 +3334,11 @@ void Tab::clear_pages() { // invalidated highlighter, if any exists m_highlighter.invalidate(); + m_page_sizer->Clear(true); // clear pages from the controlls for (auto p : m_pages) - p->clear(); + p->clear(); + int i = m_page_sizer->GetItemCount(); // nulling pointers m_parent_preset_description_line = nullptr; @@ -3369,7 +3385,7 @@ 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__ // Use Freeze/Thaw to avoid flickering during cleare/activate new page +//#ifdef __WXOSX__ // Use Freeze/Thaw to avoid flickering during clear/activate new page wxWindowUpdateLocker noUpdates(this); //#endif #endif @@ -3394,12 +3410,12 @@ void Tab::OnTreeSelChange(wxTreeEvent& event) m_active_page = page; clear_pages(); - for (auto& el : m_pages) - el.get()->Hide(); + //for (auto& el : m_pages) + // el.get()->Hide(); if (wxGetApp().mainframe->is_active_and_shown_tab(this)) { active_selected_page(); - m_active_page->Show(); +// m_active_page->Show(); } #ifdef __linux__ @@ -3843,10 +3859,11 @@ Page::Page(wxWindow* parent, const wxString& title, const int iconID, const std: m_iconID(iconID), m_mode_bitmap_cache(mode_bmp_cache) { - Create(m_parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); - m_vsizer = new wxBoxSizer(wxVERTICAL); +// Create(m_parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); +// m_vsizer = new wxBoxSizer(wxVERTICAL); + m_vsizer = (wxBoxSizer*)parent->GetSizer(); m_item_color = &wxGetApp().get_label_clr_default(); - SetSizer(m_vsizer); +// SetSizer(m_vsizer); } void Page::reload_config() @@ -3870,8 +3887,12 @@ void Page::update_visibility(ConfigOptionMode mode, bool update_contolls_visibil void Page::activate(ConfigOptionMode mode) { + //if (m_parent) + //m_parent->SetSizer(m_vsizer); for (auto group : m_optgroups) { - group->activate(); + if (!group->activate()) + continue; + m_vsizer->Add(group->sizer, 0, wxEXPAND | wxALL, 10); group->update_visibility(mode); group->reload_config(); } @@ -3910,7 +3931,7 @@ bool Page::set_value(const t_config_option_key& opt_key, const boost::any& value bool changed = false; for(auto optgroup: m_optgroups) { if (optgroup->set_value(opt_key, value)) - changed = 1 ; + changed = true ; } return changed; } @@ -3933,15 +3954,15 @@ ConfigOptionsGroupShp Page::new_optgroup(const wxString& title, int noncommon_la }; //! config_ have to be "right" - ConfigOptionsGroupShp optgroup = std::make_shared(this, title, m_config, true, extra_column); + ConfigOptionsGroupShp optgroup = std::make_shared(/*this*/m_parent, title, m_config, true, extra_column); optgroup->config_category = m_title.ToStdString(); if (noncommon_label_width >= 0) optgroup->label_width = noncommon_label_width; #ifdef __WXOSX__ - auto tab = GetParent()->GetParent(); + auto tab = parent()->GetParent()->GetParent();// GetParent()->GetParent(); #else - auto tab = GetParent(); + auto tab = parent()->GetParent();// GetParent(); #endif optgroup->m_on_change = [this, tab](t_config_option_key opt_key, boost::any value) { //! This function will be called from OptionGroup. @@ -3975,7 +3996,7 @@ ConfigOptionsGroupShp Page::new_optgroup(const wxString& title, int noncommon_la ctrl->SetBitmap(reinterpret_cast(ctrl->GetClientData())->bmp()); }; - vsizer()->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 10); +// vsizer()->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 10); m_optgroups.push_back(optgroup); return optgroup; diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index 0a9d17c0e..9df68592b 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -44,7 +44,7 @@ class TabPresetComboBox; // Single Tab page containing a{ vsizer } of{ optgroups } // package Slic3r::GUI::Tab::Page; using ConfigOptionsGroupShp = std::shared_ptr; -class Page : public wxScrolledWindow +class Page// : public wxScrolledWindow { wxWindow* m_parent; wxString m_title; @@ -127,6 +127,9 @@ protected: wxTreeCtrl* m_treectrl; wxImageList* m_icons; + wxScrolledWindow* m_page_view {nullptr}; + wxBoxSizer* m_page_sizer {nullptr}; + ModeSizer* m_mode_sizer; struct PresetDependencies { From 5243d3e53c1da2443fbb8d118f6ceae01dcd1dba Mon Sep 17 00:00:00 2001 From: YuSanka Date: Fri, 25 Sep 2020 10:44:22 +0200 Subject: [PATCH 07/11] Fixed crash on BedShapeDialog creation --- src/slic3r/GUI/BedShapeDialog.cpp | 14 ++++++++++---- src/slic3r/GUI/BedShapeDialog.hpp | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/slic3r/GUI/BedShapeDialog.cpp b/src/slic3r/GUI/BedShapeDialog.cpp index 3caf168b5..781838233 100644 --- a/src/slic3r/GUI/BedShapeDialog.cpp +++ b/src/slic3r/GUI/BedShapeDialog.cpp @@ -229,11 +229,11 @@ void BedShapePanel::build_panel(const ConfigOptionPoints& default_pt, const Conf auto optgroup = init_shape_options_page(BedShape::get_name(BedShape::Type::Rectangular)); BedShape::append_option_line(optgroup, BedShape::Parameter::RectSize); BedShape::append_option_line(optgroup, BedShape::Parameter::RectOrigin); - optgroup->activate(); + activate_options_page(optgroup); optgroup = init_shape_options_page(BedShape::get_name(BedShape::Type::Circular)); BedShape::append_option_line(optgroup, BedShape::Parameter::Diameter); - optgroup->activate(); + activate_options_page(optgroup); optgroup = init_shape_options_page(BedShape::get_name(BedShape::Type::Custom)); @@ -254,7 +254,7 @@ void BedShapePanel::build_panel(const ConfigOptionPoints& default_pt, const Conf return sizer; }; optgroup->append_line(line); - optgroup->activate(); + activate_options_page(optgroup); wxPanel* texture_panel = init_texture_panel(); wxPanel* model_panel = init_model_panel(); @@ -297,12 +297,18 @@ ConfigOptionsGroupShp BedShapePanel::init_shape_options_page(const wxString& tit }; m_optgroups.push_back(optgroup); - panel->SetSizerAndFit(optgroup->sizer); +// panel->SetSizerAndFit(optgroup->sizer); m_shape_options_book->AddPage(panel, title); return optgroup; } +void BedShapePanel::activate_options_page(ConfigOptionsGroupShp options_group) +{ + options_group->activate(); + options_group->parent()->SetSizerAndFit(options_group->sizer); +} + wxPanel* BedShapePanel::init_texture_panel() { wxPanel* panel = new wxPanel(this); diff --git a/src/slic3r/GUI/BedShapeDialog.hpp b/src/slic3r/GUI/BedShapeDialog.hpp index 2cfbc73ae..370129f2e 100644 --- a/src/slic3r/GUI/BedShapeDialog.hpp +++ b/src/slic3r/GUI/BedShapeDialog.hpp @@ -75,6 +75,7 @@ public: private: ConfigOptionsGroupShp init_shape_options_page(const wxString& title); + void activate_options_page(ConfigOptionsGroupShp options_group); wxPanel* init_texture_panel(); wxPanel* init_model_panel(); void set_shape(const ConfigOptionPoints& points); From ec8602f8d9b261ac8ea211337bff14fe74267dbe Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 29 Sep 2020 11:04:25 +0200 Subject: [PATCH 08/11] Faster switching of parameter pages if the page is switched by cursor keys in the tree control: The page update is delayed to idle. --- src/slic3r/GUI/Tab.cpp | 29 ++++++++++++++++++----------- src/slic3r/GUI/Tab.hpp | 6 +++++- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index b0dfe44bc..7352c7037 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -293,7 +293,20 @@ void Tab::create_preset_tab() m_treectrl->AddRoot("root"); m_treectrl->SetIndent(0); - m_treectrl->Bind(wxEVT_TREE_SEL_CHANGED, &Tab::OnTreeSelChange, this); + // Delay processing of the following handler until the message queue is flushed. + // This helps to process all the cursor key events on Windows in the tree control, + // so that the cursor jumps to the last item. + m_treectrl->Bind(wxEVT_TREE_SEL_CHANGED, [this](wxTreeEvent&) { + if (!m_disable_tree_sel_changed_event && !m_pages.empty()) + m_page_switch_planned = true; + }); + m_treectrl->Bind(wxEVT_IDLE, [this](wxIdleEvent&) { + if (m_page_switch_planned) { + this->tree_sel_change_delayed(); + m_page_switch_planned = false; + } + }); + m_treectrl->Bind(wxEVT_KEY_DOWN, &Tab::OnKeyDown, this); // Initialize the page. @@ -3370,14 +3383,11 @@ void Tab::active_selected_page() toggle_options(); } -void Tab::OnTreeSelChange(wxTreeEvent& event) +void Tab::tree_sel_change_delayed() { - if (m_disable_tree_sel_changed_event) - return; - -// There is a bug related to Ubuntu overlay scrollbars, see https://github.com/prusa3d/PrusaSlicer/issues/898 and https://github.com/prusa3d/PrusaSlicer/issues/952. -// The issue apparently manifests when Show()ing a window with overlay scrollbars while the UI is frozen. For this reason, -// we will Thaw the UI prematurely on Linux. This means destroing the no_updates object prematurely. + // There is a bug related to Ubuntu overlay scrollbars, see https://github.com/prusa3d/PrusaSlicer/issues/898 and https://github.com/prusa3d/PrusaSlicer/issues/952. + // The issue apparently manifests when Show()ing a window with overlay scrollbars while the UI is frozen. For this reason, + // we will Thaw the UI prematurely on Linux. This means destroing the no_updates object prematurely. #ifdef __linux__ std::unique_ptr no_updates(new wxWindowUpdateLocker(this)); #else @@ -3390,9 +3400,6 @@ void Tab::OnTreeSelChange(wxTreeEvent& event) //#endif #endif - if (m_pages.empty()) - return; - Page* page = nullptr; const auto sel_item = m_treectrl->GetSelection(); const auto selection = sel_item ? m_treectrl->GetItemText(sel_item) : ""; diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index 9df68592b..9d65d767a 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -130,7 +130,7 @@ protected: wxScrolledWindow* m_page_view {nullptr}; wxBoxSizer* m_page_sizer {nullptr}; - ModeSizer* m_mode_sizer; + ModeSizer* m_mode_sizer; struct PresetDependencies { Preset::Type type = Preset::TYPE_INVALID; @@ -238,6 +238,9 @@ protected: DynamicPrintConfig m_cache_config; + + bool m_page_switch_planned = false; + public: PresetBundle* m_preset_bundle; bool m_show_btn_incompatible_presets = false; @@ -351,6 +354,7 @@ protected: void compatible_widget_reload(PresetDependencies &deps); void load_key_value(const std::string& opt_key, const boost::any& value, bool saved_value = false); + void tree_sel_change_delayed(); void on_presets_changed(); void build_preset_description_line(ConfigOptionsGroup* optgroup); void update_preset_description_line(); From b15023dfa946682975a5bff8fada6fb187eab33f Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 29 Sep 2020 13:36:56 +0200 Subject: [PATCH 09/11] Cancellation of parameter page build process. --- src/slic3r/GUI/OptionsGroup.cpp | 72 ++++++++++++++----------- src/slic3r/GUI/OptionsGroup.hpp | 5 +- src/slic3r/GUI/Tab.cpp | 93 +++++++++++++++++++++++---------- src/slic3r/GUI/Tab.hpp | 10 ++-- 4 files changed, 116 insertions(+), 64 deletions(-) diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index 310dc9544..3d55237df 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -362,42 +362,52 @@ void OptionsGroup::activate_line(Line& line) } // create all controls for the option group from the m_lines -bool OptionsGroup::activate() +bool OptionsGroup::activate(std::function throw_if_canceled) { if (sizer)//(!sizer->IsEmpty()) return false; - if (staticbox) { - stb = new wxStaticBox(m_parent, wxID_ANY, _(title)); - if (!wxOSX) stb->SetBackgroundStyle(wxBG_STYLE_PAINT); - stb->SetFont(wxOSX ? wxGetApp().normal_font() : wxGetApp().bold_font()); + try { + if (staticbox) { + stb = new wxStaticBox(m_parent, wxID_ANY, _(title)); + if (!wxOSX) stb->SetBackgroundStyle(wxBG_STYLE_PAINT); + stb->SetFont(wxOSX ? wxGetApp().normal_font() : wxGetApp().bold_font()); + } + else + stb = nullptr; + sizer = (staticbox ? new wxStaticBoxSizer(stb, wxVERTICAL) : new wxBoxSizer(wxVERTICAL)); + + 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) { + throw_if_canceled(); + activate_line(line); + } + } catch (UIBuildCanceled&) { + auto p = sizer; + this->clear(); + p->Clear(true); + delete p; + throw; } - else - stb = nullptr; - sizer = (staticbox ? new wxStaticBoxSizer(stb, wxVERTICAL) : new wxBoxSizer(wxVERTICAL)); - - 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); return true; } diff --git a/src/slic3r/GUI/OptionsGroup.hpp b/src/slic3r/GUI/OptionsGroup.hpp index 4d70347aa..8dcba2213 100644 --- a/src/slic3r/GUI/OptionsGroup.hpp +++ b/src/slic3r/GUI/OptionsGroup.hpp @@ -24,6 +24,9 @@ namespace Slic3r { namespace GUI { +// Thrown if the building of a parameter page is canceled. +class UIBuildCanceled : public std::exception {}; + /// Widget type describes a function object that returns a wxWindow (our widget) and accepts a wxWidget (parent window). using widget_t = std::function;//!std::function; @@ -124,7 +127,7 @@ public: void activate_line(Line& line); // create all controls for the option group from the m_lines - bool activate(); + bool activate(std::function throw_if_canceled = [](){}); // delete all controls from the option group void clear(); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 7352c7037..e68803471 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -297,15 +297,28 @@ void Tab::create_preset_tab() // This helps to process all the cursor key events on Windows in the tree control, // so that the cursor jumps to the last item. m_treectrl->Bind(wxEVT_TREE_SEL_CHANGED, [this](wxTreeEvent&) { - if (!m_disable_tree_sel_changed_event && !m_pages.empty()) - m_page_switch_planned = true; + if (!m_disable_tree_sel_changed_event && !m_pages.empty()) { + if (m_page_switch_running) + m_page_switch_planned = true; + else { + m_page_switch_running = true; + do { + m_page_switch_planned = false; + } while (this->tree_sel_change_delayed()); + m_page_switch_running = false; + } + } + m_treectrl->Update(); }); +#if 0 m_treectrl->Bind(wxEVT_IDLE, [this](wxIdleEvent&) { if (m_page_switch_planned) { - this->tree_sel_change_delayed(); - m_page_switch_planned = false; + do { + m_page_switch_planned = false; + } while (this->tree_sel_change_delayed()); } }); +#endif m_treectrl->Bind(wxEVT_KEY_DOWN, &Tab::OnKeyDown, this); @@ -424,7 +437,7 @@ void Tab::OnActivate() #endif // __WXOSX__ // create controls on active page - active_selected_page(); + activate_selected_page(); // m_active_page->Show(); m_hsizer->Layout(); Refresh(); @@ -2820,9 +2833,9 @@ void TabPrinter::update_pages() rebuild_page_tree(); } -void TabPrinter::active_selected_page() +void TabPrinter::activate_selected_page(std::function throw_if_canceled) { - Tab::active_selected_page(); + Tab::activate_selected_page(throw_if_canceled); // "extruders_count" doesn't update from the update_config(), // so update it implicitly @@ -3372,19 +3385,20 @@ void Tab::update_description_lines() update_preset_description_line(); } -void Tab::active_selected_page() +void Tab::activate_selected_page(std::function throw_if_canceled) { if (!m_active_page) return; - m_active_page->activate(m_mode); + m_active_page->activate(m_mode, throw_if_canceled); update_changed_ui(); update_description_lines(); toggle_options(); } -void Tab::tree_sel_change_delayed() +bool Tab::tree_sel_change_delayed() { +#if 1 // There is a bug related to Ubuntu overlay scrollbars, see https://github.com/prusa3d/PrusaSlicer/issues/898 and https://github.com/prusa3d/PrusaSlicer/issues/952. // The issue apparently manifests when Show()ing a window with overlay scrollbars while the UI is frozen. For this reason, // we will Thaw the UI prematurely on Linux. This means destroing the no_updates object prematurely. @@ -3398,6 +3412,7 @@ void Tab::tree_sel_change_delayed() //#ifdef __WXOSX__ // Use Freeze/Thaw to avoid flickering during clear/activate new page wxWindowUpdateLocker noUpdates(this); //#endif +#endif #endif Page* page = nullptr; @@ -3411,29 +3426,50 @@ void Tab::tree_sel_change_delayed() m_is_modified_values = page->m_is_modified_values; break; } - if (page == nullptr || m_active_page == page) return; + if (page == nullptr || m_active_page == page) + return false; // clear pages from the controls m_active_page = page; - clear_pages(); + + auto throw_if_canceled = std::function([this](){ +#ifdef WIN32 + wxCheckForInterrupt(m_treectrl); + if (m_page_switch_planned) + throw UIBuildCanceled(); +#endif // WIN32 + }); - //for (auto& el : m_pages) - // el.get()->Hide(); + try { + clear_pages(); + throw_if_canceled(); - if (wxGetApp().mainframe->is_active_and_shown_tab(this)) { - active_selected_page(); -// m_active_page->Show(); + //for (auto& el : m_pages) + // el.get()->Hide(); + + if (wxGetApp().mainframe->is_active_and_shown_tab(this)) { + activate_selected_page(throw_if_canceled); + // m_active_page->Show(); + } + + #ifdef __linux__ + no_updates.reset(nullptr); + #endif + + update_undo_buttons(); + throw_if_canceled(); + + // m_active_page->Show(); + m_hsizer->Layout(); + throw_if_canceled(); + Refresh(); + } catch (const UIBuildCanceled&) { + if (m_active_page) + m_active_page->clear(); + return true; } - #ifdef __linux__ - no_updates.reset(nullptr); - #endif - - update_undo_buttons(); - -// m_active_page->Show(); - m_hsizer->Layout(); - Refresh(); + return false; } void Tab::OnKeyDown(wxKeyEvent& event) @@ -3892,16 +3928,17 @@ void Page::update_visibility(ConfigOptionMode mode, bool update_contolls_visibil m_show = ret_val; } -void Page::activate(ConfigOptionMode mode) +void Page::activate(ConfigOptionMode mode, std::function throw_if_canceled) { //if (m_parent) //m_parent->SetSizer(m_vsizer); for (auto group : m_optgroups) { - if (!group->activate()) + if (!group->activate(throw_if_canceled)) continue; m_vsizer->Add(group->sizer, 0, wxEXPAND | wxALL, 10); group->update_visibility(mode); group->reload_config(); + throw_if_canceled(); } } diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index 9d65d767a..a3711f453 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -73,7 +73,7 @@ public: void set_config(DynamicPrintConfig* config_in) { m_config = config_in; } void reload_config(); void update_visibility(ConfigOptionMode mode, bool update_contolls_visibility); - void activate(ConfigOptionMode mode); + void activate(ConfigOptionMode mode, std::function throw_if_canceled); void clear(); void msw_rescale(); void sys_color_changed(); @@ -239,6 +239,7 @@ protected: DynamicPrintConfig m_cache_config; + bool m_page_switch_running = false; bool m_page_switch_planned = false; public: @@ -294,7 +295,7 @@ public: virtual void clear_pages(); virtual void update_description_lines(); - virtual void active_selected_page(); + virtual void activate_selected_page(std::function throw_if_canceled); void OnTreeSelChange(wxTreeEvent& event); void OnKeyDown(wxKeyEvent& event); @@ -354,7 +355,8 @@ protected: void compatible_widget_reload(PresetDependencies &deps); void load_key_value(const std::string& opt_key, const boost::any& value, bool saved_value = false); - void tree_sel_change_delayed(); + // return true if cancelled + bool tree_sel_change_delayed(); void on_presets_changed(); void build_preset_description_line(ConfigOptionsGroup* optgroup); void update_preset_description_line(); @@ -447,7 +449,7 @@ public: void build() override; void build_fff(); void build_sla(); - void active_selected_page() override; + void activate_selected_page(std::function throw_if_canceled) override; void clear_pages() override; void toggle_options() override; void update() override; From 2583522e43345d4b53d2d3a5a6ba3417b16bf04b Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 29 Sep 2020 14:47:03 +0200 Subject: [PATCH 10/11] Refresh the page tree immediately after key press. --- src/slic3r/GUI/Tab.cpp | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index e68803471..e6363b3d0 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -304,21 +304,12 @@ void Tab::create_preset_tab() m_page_switch_running = true; do { m_page_switch_planned = false; + m_treectrl->Update(); } while (this->tree_sel_change_delayed()); m_page_switch_running = false; } } - m_treectrl->Update(); }); -#if 0 - m_treectrl->Bind(wxEVT_IDLE, [this](wxIdleEvent&) { - if (m_page_switch_planned) { - do { - m_page_switch_planned = false; - } while (this->tree_sel_change_delayed()); - } - }); -#endif m_treectrl->Bind(wxEVT_KEY_DOWN, &Tab::OnKeyDown, this); @@ -437,7 +428,7 @@ void Tab::OnActivate() #endif // __WXOSX__ // create controls on active page - activate_selected_page(); + activate_selected_page([](){}); // m_active_page->Show(); m_hsizer->Layout(); Refresh(); From b17c829c9ad3302e4960f16929fdd10698c4ad79 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Thu, 1 Oct 2020 19:16:23 +0200 Subject: [PATCH 11/11] Fixed crash on Linux on startup --- src/slic3r/GUI/Tab.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index e6363b3d0..c99ddeecd 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -298,6 +298,7 @@ void Tab::create_preset_tab() // so that the cursor jumps to the last item. m_treectrl->Bind(wxEVT_TREE_SEL_CHANGED, [this](wxTreeEvent&) { if (!m_disable_tree_sel_changed_event && !m_pages.empty()) { +#ifdef WIN32 if (m_page_switch_running) m_page_switch_planned = true; else { @@ -308,6 +309,10 @@ void Tab::create_preset_tab() } while (this->tree_sel_change_delayed()); m_page_switch_running = false; } +#else + // Crashes on Linux on start-up without CallAfter. + this->CallAfter([this]() { this->tree_sel_change_delayed(); }); +#endif } }); @@ -3389,10 +3394,9 @@ void Tab::activate_selected_page(std::function throw_if_canceled) bool Tab::tree_sel_change_delayed() { -#if 1 - // There is a bug related to Ubuntu overlay scrollbars, see https://github.com/prusa3d/PrusaSlicer/issues/898 and https://github.com/prusa3d/PrusaSlicer/issues/952. - // The issue apparently manifests when Show()ing a window with overlay scrollbars while the UI is frozen. For this reason, - // we will Thaw the UI prematurely on Linux. This means destroing the no_updates object prematurely. + // There is a bug related to Ubuntu overlay scrollbars, see https://github.com/prusa3d/PrusaSlicer/issues/898 and https://github.com/prusa3d/PrusaSlicer/issues/952. + // The issue apparently manifests when Show()ing a window with overlay scrollbars while the UI is frozen. For this reason, + // we will Thaw the UI prematurely on Linux. This means destroing the no_updates object prematurely. #ifdef __linux__ std::unique_ptr no_updates(new wxWindowUpdateLocker(this)); #else @@ -3401,9 +3405,8 @@ bool Tab::tree_sel_change_delayed() * But under OSX (builds compiled with MacOSX10.14.sdk) wxStaticBitmap rendering is broken without Freeze/Thaw call. */ //#ifdef __WXOSX__ // Use Freeze/Thaw to avoid flickering during clear/activate new page - wxWindowUpdateLocker noUpdates(this); + wxWindowUpdateLocker noUpdates(this); //#endif -#endif #endif Page* page = nullptr;