From 61247fe8d3e2d36ea760beb692baae63ee6cd505 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Fri, 22 Dec 2017 11:50:28 +0100 Subject: [PATCH] Filling the Filament's and Printer's Tabs. Finished. It's need to adding functions to work with presets --- lib/Slic3r/GUI/MainFrame.pm | 2 +- xs/src/slic3r/GUI/Field.cpp | 206 +++++++++++-- xs/src/slic3r/GUI/Field.hpp | 62 ++++ xs/src/slic3r/GUI/GUI.cpp | 25 +- xs/src/slic3r/GUI/GUI.hpp | 18 +- xs/src/slic3r/GUI/OptionsGroup.cpp | 51 +++- xs/src/slic3r/GUI/OptionsGroup.hpp | 9 +- xs/src/slic3r/GUI/Tab.cpp | 445 +++++++++++++++++++++++++++-- xs/src/slic3r/GUI/Tab.h | 55 +++- xs/xsp/GUI.xsp | 4 +- 10 files changed, 802 insertions(+), 75 deletions(-) diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index 9712329c2..024c13513 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -152,7 +152,7 @@ sub _init_tabpanel { } #TODO this is an example of a Slic3r XS interface call to add a new preset editor page to the main view. - Slic3r::GUI::create_preset_tab("print"); + Slic3r::GUI::create_preset_tabs(wxTheApp->{preset_bundle}); if ($self->{plater}) { $self->{plater}->on_select_preset(sub { diff --git a/xs/src/slic3r/GUI/Field.cpp b/xs/src/slic3r/GUI/Field.cpp index b047bb7ce..dd9d7f70b 100644 --- a/xs/src/slic3r/GUI/Field.cpp +++ b/xs/src/slic3r/GUI/Field.cpp @@ -55,23 +55,43 @@ namespace Slic3r { namespace GUI { text_value = wxString::Format(_T("%i"), int(opt.default_value->getFloat())); text_value += "%"; break; + } + case coPercents: + { + const ConfigOptionPercents *vec = static_cast(opt.default_value); + if (vec == nullptr || vec->empty()) break; + if (vec->size() > 1) + break; + double val = vec->get_at(0); + text_value = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2); + break; } case coFloat: { double val = opt.default_value->getFloat(); text_value = (val - int(val)) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2); break; + } + case coFloats: + { + const ConfigOptionFloats *vec = static_cast(opt.default_value); + if (vec == nullptr || vec->empty()) break; + if (vec->size() > 1) + break; + double val = vec->get_at(0); + text_value = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2); + break; } case coString: - text_value += static_cast(opt.default_value)->value; + text_value = static_cast(opt.default_value)->value; break; case coStrings: { - const ConfigOptionVectorBase *vec = static_cast(opt.default_value); - if (vec == nullptr) break; - if (vec->empty()) break; - for (size_t id = 0; id < vec->size(); ++id) - text_value += static_cast(opt.default_value)->value[id]; + const ConfigOptionStrings *vec = static_cast(opt.default_value); + if (vec == nullptr || vec->empty()) break; + if (vec->size() > 1) + break; + text_value = vec->values.at(0); break; } default: @@ -99,8 +119,13 @@ void CheckBox::BUILD() { if (opt.height >= 0) size.SetHeight(opt.height); if (opt.width >= 0) size.SetWidth(opt.width); + bool check_value = opt.type == coBool ? + opt.default_value->getBool() : opt.type == coBools ? + static_cast(opt.default_value)->values.at(0) : + false; + auto temp = new wxCheckBox(parent, wxID_ANY, wxString(""), wxDefaultPosition, size); - temp->SetValue(opt.default_value->getBool()); + temp->SetValue(check_value); if (opt.readonly) temp->Disable(); temp->Bind(wxEVT_CHECKBOX, ([this](wxCommandEvent e) { _on_change(e); }), temp->GetId()); @@ -118,8 +143,31 @@ void SpinCtrl::BUILD() { if (opt.height >= 0) size.SetHeight(opt.height); if (opt.width >= 0) size.SetWidth(opt.width); - auto temp = new wxSpinCtrl(parent, wxID_ANY, wxString::Format(_T("%i"), opt.default_value->getInt()), wxDefaultPosition, size, - 0, opt.min >0 ? opt.min : 0, opt.max < 2147483647 ? opt.max : 2147483647, opt.default_value->getInt()); + wxString text_value = wxString(""); + int default_value = 0; + + switch (opt.type) { + case coInt: + default_value = opt.default_value->getInt(); + text_value = wxString::Format(_T("%i"), default_value); + break; + case coInts: + { + const ConfigOptionInts *vec = static_cast(opt.default_value); + if (vec == nullptr || vec->empty()) break; + for (size_t id = 0; id < vec->size(); ++id) + { + default_value = vec->get_at(id); + text_value += wxString::Format(_T("%i"), default_value); + } + break; + } + default: + break; + } + + auto temp = new wxSpinCtrl(parent, wxID_ANY, text_value, wxDefaultPosition, size, + 0, opt.min >0 ? opt.min : 0, opt.max < 2147483647 ? opt.max : 2147483647, default_value); temp->Bind(wxEVT_SPINCTRL, ([=](wxCommandEvent e) { tmp_value = undef_spin_val; _on_change(e); }), temp->GetId()); temp->Bind(wxEVT_KILL_FOCUS, ([this](wxFocusEvent e) { tmp_value = undef_spin_val; _on_kill_focus(e); }), temp->GetId()); @@ -152,17 +200,17 @@ void Choice::BUILD() { if (opt.width >= 0) size.SetWidth(opt.width); auto temp = new wxComboBox(parent, wxID_ANY, wxString(""), wxDefaultPosition, size); - if (opt.gui_type.compare("") != 0 && opt.gui_type.compare("select_open") == 0) - temp->SetWindowStyle(wxCB_READONLY); -// // recast as a wxWindow to fit the calling convention + if (opt.gui_type.compare("select_open") != 0) + temp->SetExtraStyle(wxCB_READONLY); + + // recast as a wxWindow to fit the calling convention window = dynamic_cast(temp); - if (!opt.enum_labels.empty() && !opt.enum_values.empty()) - { - for (auto el : opt.enum_labels) + if (opt.enum_labels.empty() && opt.enum_values.empty()){ + } + else{ + for (auto el : opt.enum_labels.empty() ? opt.enum_values : opt.enum_labels) temp->Append(wxString(el)); - // temp->SetSelection(static_cast*>(opt.default_value)->value); - //set_value(opt.default_value); set_selection(); } temp->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { _on_change(e); }), temp->GetId()); @@ -197,6 +245,51 @@ void Choice::set_selection() dynamic_cast(window)->SetSelection(id_value); break; } + case coInt:{ + int val = opt.default_value->getInt(); //!! + text_value = wxString::Format(_T("%i"), int(val)); + auto idx = 0; + for (auto el : opt.enum_values) + { + if (el.compare(text_value) == 0) + break; + ++idx; + } + idx == opt.enum_values.size() ? + dynamic_cast(window)->SetValue(text_value) : + dynamic_cast(window)->SetSelection(idx); + break; + } +// case coString:{ +// text_value = static_cast(opt.default_value)->value; +// +// auto idx = 0; +// for (auto el : opt.enum_values) +// { +// if (el.compare(text_value) == 0) +// break; +// ++idx; +// } +// idx == opt.enum_values.size() ? +// dynamic_cast(window)->SetValue(text_value) : +// dynamic_cast(window)->SetSelection(idx); +// break; +// } + case coStrings:{ + text_value = static_cast(opt.default_value)->values.at(0); + + auto idx = 0; + for (auto el : opt.enum_values) + { + if (el.compare(text_value) == 0) + break; + ++idx; + } + idx == opt.enum_values.size() ? + dynamic_cast(window)->SetValue(text_value) : + dynamic_cast(window)->SetSelection(idx); + break; + } } } @@ -236,6 +329,85 @@ void Choice::set_values(const std::vector values) disable_change_event = false; } +void ColourPicker::BUILD() +{ + auto size = wxSize(wxDefaultSize); + if (opt.height >= 0) size.SetHeight(opt.height); + if (opt.width >= 0) size.SetWidth(opt.width); + + wxString clr(static_cast(opt.default_value)->values.at(0)); + auto temp = new wxColourPickerCtrl(parent, wxID_ANY, clr, wxDefaultPosition, size); + + // // recast as a wxWindow to fit the calling convention + window = dynamic_cast(temp); + + temp->Bind(wxEVT_COLOURPICKER_CHANGED, ([=](wxCommandEvent e) { _on_change(e); }), temp->GetId()); + + if (opt.tooltip.length() > 0) temp->SetToolTip(opt.tooltip); + +} + +void Point::BUILD() +{ + auto size = wxSize(wxDefaultSize); + if (opt.height >= 0) size.SetHeight(opt.height); + if (opt.width >= 0) size.SetWidth(opt.width); + + auto temp = new wxBoxSizer(wxHORIZONTAL); + // $self->wxSizer($sizer); + // + wxSize field_size(40, -1); + + auto default_pt = static_cast(opt.default_value)->values.at(0); + double val = default_pt.x; + wxString X = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2); + val = default_pt.y; + wxString Y = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2); + + x_textctrl = new wxTextCtrl(parent, wxID_ANY, X, wxDefaultPosition, field_size); + y_textctrl = new wxTextCtrl(parent, wxID_ANY, Y, wxDefaultPosition, field_size); + + temp->Add(new wxStaticText(parent, wxID_ANY, "x:")/*, 0, wxALIGN_CENTER_VERTICAL, 0*/); + temp->Add(x_textctrl); + temp->Add(new wxStaticText(parent, wxID_ANY, "y:")/*, 0, wxALIGN_CENTER_VERTICAL, 0*/); + temp->Add(y_textctrl); + + x_textctrl->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { _on_change(e/*$self->option->opt_id*/); }), x_textctrl->GetId()); + y_textctrl->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { _on_change(e/*$self->option->opt_id*/); }), x_textctrl->GetId()); + + // // recast as a wxWindow to fit the calling convention + sizer = dynamic_cast(temp); + + if (opt.tooltip.length() > 0) + { + x_textctrl->SetToolTip(opt.tooltip); + y_textctrl->SetToolTip(opt.tooltip); + } +} + +void Point::set_value(const Pointf value) +{ + disable_change_event = true; + + double val = value.x; + x_textctrl->SetValue(val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2)); + val = value.y; + y_textctrl->SetValue(val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2)); + + disable_change_event = false; +} + +boost::any Point::get_value() +{ + Pointf ret_point; + double val; + x_textctrl->GetValue().ToDouble(&val); + ret_point.x = val; + y_textctrl->GetValue().ToDouble(&val); + ret_point.y = val; + return ret_point; +} + } // GUI } // Slic3r diff --git a/xs/src/slic3r/GUI/Field.hpp b/xs/src/slic3r/GUI/Field.hpp index 4645e6d3f..470073e18 100644 --- a/xs/src/slic3r/GUI/Field.hpp +++ b/xs/src/slic3r/GUI/Field.hpp @@ -11,6 +11,7 @@ #include #include +#include #include "../../libslic3r/libslic3r.h" #include "../../libslic3r/Config.hpp" @@ -212,6 +213,67 @@ public: void set_tooltip(const wxString& tip) override {}; //! Redundant }; +class ColourPicker : public Field { + using Field::Field; +public: + ColourPicker(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {} + ColourPicker(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {} + + wxWindow* window{ nullptr }; + void BUILD() override; + + void set_selection(); + void set_value(const std::string value) { + dynamic_cast(window)->SetColour(value); + } + void set_value(boost::any value) { + dynamic_cast(window)->SetColour(boost::any_cast(value)); + } + void set_values(const std::vector values); + boost::any get_value() override { + return boost::any(dynamic_cast(window)->GetColour()); + } + + void enable() override { dynamic_cast(window)->Enable(); }; + void disable() override{ dynamic_cast(window)->Disable(); }; + wxWindow* getWindow() override { return window; } + void set_tooltip(const wxString& tip) override {}; //! Redundant +}; + +class Point : public Field { + using Field::Field; +public: + Point(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {} + Point(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {} + + wxSizer* sizer{ nullptr }; + wxTextCtrl* x_textctrl; + wxTextCtrl* y_textctrl; + + void BUILD() override; + + void set_value(const Pointf value);// { +// dynamic_cast(sizer)->SetColour(value); + +// } + void set_value(boost::any value) { +// dynamic_cast(sizer)->SetColour(boost::any_cast(value)); + } + boost::any get_value() override; //{ +// return boost::any(dynamic_cast(sizer)->GetColour()); +// } + + void enable() override { /*dynamic_cast(window)*/ + x_textctrl->Enable(); + y_textctrl->Enable(); }; + void disable() override{ /*dynamic_cast(window)*/ + x_textctrl->Disable(); + y_textctrl->Disable(); }; + wxSizer* getSizer() override { return sizer; } + void set_tooltip(const wxString& tip) override {}; //! Redundant +}; + + #endif } // GUI } // Slic3r diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp index 4f2a4f879..369cb84f2 100644 --- a/xs/src/slic3r/GUI/GUI.cpp +++ b/xs/src/slic3r/GUI/GUI.cpp @@ -188,12 +188,27 @@ void add_debug_menu(wxMenuBar *menu) #endif } -// -void create_preset_tab(const char *name) +void create_preset_tabs(PresetBundle *preset_bundle) { - CTabPrint* panel = new CTabPrint(g_wxTabPanel, name); - panel->create_preset_tab(); - g_wxTabPanel->AddPage(panel, name); + add_created_tab(new CTabPrint (g_wxTabPanel, "Print"), preset_bundle); + add_created_tab(new CTabFilament(g_wxTabPanel, "Filament"), preset_bundle); + add_created_tab(new CTabPrinter (g_wxTabPanel, "Printer"), preset_bundle); +} + +void add_created_tab(CTab* panel, PresetBundle *preset_bundle) +{ + panel->create_preset_tab(preset_bundle); + g_wxTabPanel->AddPage(panel, panel->title()); +} + +void show_error(wxWindow* parent, std::string message){ + auto msg_wingow = new wxMessageDialog(parent, message, "Error", wxOK | wxICON_ERROR); + msg_wingow->ShowModal(); +} + +void show_info(wxWindow* parent, std::string message, std::string title){ + auto msg_wingow = new wxMessageDialog(parent, message, title.empty() ? "Notise" : title, wxOK | wxICON_INFORMATION); + msg_wingow->ShowModal(); } } } diff --git a/xs/src/slic3r/GUI/GUI.hpp b/xs/src/slic3r/GUI/GUI.hpp index 3634e0bc8..a2902fe7b 100644 --- a/xs/src/slic3r/GUI/GUI.hpp +++ b/xs/src/slic3r/GUI/GUI.hpp @@ -6,10 +6,17 @@ class wxApp; class wxFrame; +class wxWindow; class wxMenuBar; class wxNotebook; -namespace Slic3r { namespace GUI { +namespace Slic3r { + +class PresetBundle; + +namespace GUI { + +class CTab; void disable_screensaver(); void enable_screensaver(); @@ -23,9 +30,14 @@ void set_main_frame(wxFrame *main_frame); void set_tab_panel(wxNotebook *tab_panel); void add_debug_menu(wxMenuBar *menu); -// Create a new preset tab (print, filament or printer), +// Create a new preset tab (print, filament and printer), +void create_preset_tabs(PresetBundle *preset_bundle); // add it at the end of the tab panel. -void create_preset_tab(const char *name); +void add_created_tab(CTab* panel, PresetBundle *preset_bundle); + +void show_error(wxWindow* parent, std::string message); +void show_info(wxWindow* parent, std::string message, std::string title); + } } diff --git a/xs/src/slic3r/GUI/OptionsGroup.cpp b/xs/src/slic3r/GUI/OptionsGroup.cpp index cbece3fee..981d2a36b 100644 --- a/xs/src/slic3r/GUI/OptionsGroup.cpp +++ b/xs/src/slic3r/GUI/OptionsGroup.cpp @@ -19,7 +19,9 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co // is the normal type. if (opt.gui_type.compare("select") == 0) { } else if (opt.gui_type.compare("select_open") == 0) { + fields.emplace(id, STDMOVE(Choice::Create(_parent, opt, id))); } else if (opt.gui_type.compare("color") == 0) { + fields.emplace(id, STDMOVE(ColourPicker::Create(_parent, opt, id))); } else if (opt.gui_type.compare("f_enum_open") == 0 || opt.gui_type.compare("i_enum_open") == 0 || opt.gui_type.compare("i_enum_closed") == 0) { @@ -30,7 +32,9 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co switch (opt.type) { case coFloatOrPercent: case coFloat: + case coFloats: case coPercent: + case coPercents: case coString: case coStrings: fields.emplace(id, STDMOVE(TextCtrl::Create(_parent, opt, id))); @@ -46,6 +50,9 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co case coEnum: fields.emplace(id, STDMOVE(Choice::Create(_parent, opt, id))); break; + case coPoints: + fields.emplace(id, STDMOVE(Point::Create(_parent, opt, id))); + break; case coNone: break; default: throw /*//!ConfigGUITypeError("")*/std::logic_error("This control doesn't exist till now"); break; @@ -60,8 +67,9 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co } void OptionsGroup::append_line(const Line& line) { - if (line.sizer != nullptr || (line.widget != nullptr && line.full_width > 0)){ - if (line.sizer != nullptr) { +//! if (line.sizer != nullptr || (line.widget != nullptr && line.full_width > 0)){ + if ( (line.sizer != nullptr || line.widget != nullptr) && line.full_width){ + if (line.sizer != nullptr) { sizer->Add(line.sizer, 0, wxEXPAND | wxALL, wxOSX ? 0 : 15); return; } @@ -71,6 +79,22 @@ void OptionsGroup::append_line(const Line& line) { } } + auto option_set = line.get_options(); + + // 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.sidetext.size() == 0 && option_set.front().side_widget == nullptr && + line.get_extra_widgets().size() == 0) { + const auto& option = option_set.front(); + const auto& field = build_field(option); + + if (is_window_field(field)) + sizer->Add(field->getWindow(), 0, wxEXPAND | wxALL, wxOSX ? 0 : 5); + if (is_sizer_field(field)) + sizer->Add(field->getSizer(), 0, wxEXPAND | wxALL, wxOSX ? 0 : 5); + return; + } + auto grid_sizer = _grid_sizer; // Build a label if we have it @@ -92,7 +116,7 @@ void OptionsGroup::append_line(const Line& line) { // if we have a single option with no sidetext just add it directly to the grid sizer - auto option_set = line.get_options(); +//! auto option_set = line.get_options(); if (option_set.size() == 1 && option_set.front().opt.sidetext.size() == 0 && option_set.front().side_widget == nullptr && line.get_extra_widgets().size() == 0) { const auto& option = option_set.front(); @@ -122,8 +146,12 @@ void OptionsGroup::append_line(const Line& line) { // add field const Option& opt_ref = opt; - auto field = build_field(opt_ref)->getWindow(); ; - sizer->Add(field, 0, wxALIGN_CENTER_VERTICAL, 0); +//! auto field = build_field(opt_ref)->getWindow(); +//! sizer->Add(field, 0, wxALIGN_CENTER_VERTICAL, 0); + auto& field = build_field(opt_ref); + is_sizer_field(field) ? + sizer->Add(field->getSizer(), 0, wxALIGN_CENTER_VERTICAL, 0) : + sizer->Add(field->getWindow(), 0, wxALIGN_CENTER_VERTICAL, 0); // add sidetext if any if (option.sidetext != "") { @@ -134,23 +162,22 @@ void OptionsGroup::append_line(const Line& line) { // add side widget if any if (opt.side_widget != nullptr) { - sizer->Add(opt.side_widget.target(), 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 1); //! requires verification + sizer->Add(opt.side_widget(parent())/*!.target()*/, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 1); //! requires verification } if (opt.opt_id != option_set.back().opt_id) //! istead of (opt != option_set.back()) { sizer->AddSpacer(4); } - - // add extra sizers if any - for (auto extra_widget : line.get_extra_widgets()) { - sizer->Add(extra_widget.target(), 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 4); //! requires verification - } + } + // add extra sizers if any + for (auto extra_widget : line.get_extra_widgets()) { + sizer->Add(extra_widget(parent())/*!.target()*/, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 4); //! requires verification } } Line OptionsGroup::create_single_option_line(const Option& option) const { - Line retval {option.opt.label, option.opt.tooltip}; + Line retval {option.opt.label, option.opt.tooltip}; Option tmp(option); tmp.opt.label = std::string(""); retval.append_option(tmp); diff --git a/xs/src/slic3r/GUI/OptionsGroup.hpp b/xs/src/slic3r/GUI/OptionsGroup.hpp index 75348628b..ce6a147e6 100644 --- a/xs/src/slic3r/GUI/OptionsGroup.hpp +++ b/xs/src/slic3r/GUI/OptionsGroup.hpp @@ -51,8 +51,11 @@ public: wxSizer* sizer {nullptr}; widget_t widget {nullptr}; - inline void append_option(const Option& option) { + void append_option(const Option& option) { _options.push_back(option); + } + void append_widget(const widget_t widget) { + _extra_widgets.push_back(widget); } Line(std::string label, std::string tooltip) : label(wxString(label)), label_tooltip(wxString(tooltip)) {} ; @@ -71,7 +74,7 @@ public: const bool staticbox {true}; const wxString title {wxString("")}; - size_t label_width {180}; + size_t label_width {200}; wxSizer* sizer {nullptr}; column_t extra_column {nullptr}; // t_change on_change {nullptr}; @@ -86,7 +89,7 @@ public: void append_line(const Line& line); - virtual Line create_single_option_line(const Option& option) const; + /*virtual*/ Line create_single_option_line(const Option& option) const; inline void append_single_option_line(const Option& option) { append_line(create_single_option_line(option)); } // return a non-owning pointer reference diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index 0aa57ef0a..06dc65282 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -8,16 +8,19 @@ #include #include #include +#include #include "Tab.h" #include "PresetBundle.hpp" +//#include "GCodeSender.hpp" namespace Slic3r { namespace GUI { // sub new -void CTab::create_preset_tab() +void CTab::create_preset_tab(PresetBundle *preset_bundle) { + preset_bundle_ = preset_bundle; // Vertical sizer to hold the choice menu and the rest of the page. CTab *panel = this; auto *sizer = new wxBoxSizer(wxVERTICAL); @@ -128,12 +131,26 @@ CPageShp CTab::add_options_page(wxString title, wxString icon) return page; } +void CTab::load_key_value_(std::string opt_key, std::vector value) +{ + // # To be called by custom widgets, load a value into a config, + // # update the preset selection boxes (the dirty flags) + // $self->{config}->set($opt_key, $value); + // # Mark the print & filament enabled if they are compatible with the currently selected preset. + if (opt_key.compare("compatible_printers") == 0) { + // wxTheApp->{preset_bundle}->update_compatible_with_printer(0); + // $self->{presets}->update_tab_ui($self->{presets_choice}, $self->{show_incompatible_presets}); + // } else { + // $self->{presets}->update_dirty_ui($self->{presets_choice}); + } + // $self->_on_presets_changed; + // $self->_update; +} + void CTabPrint::build() { -// $self->{presets} = wxTheApp->{preset_bundle}->print; - PresetCollection *prints = new PresetCollection(Preset::TYPE_PRINT, Preset::print_options()); - config_ = prints->get_edited_preset().config; - config_def = config_.def(); // initialization. It will be used in get_option_(const std::string title) + config_ = preset_bundle_->prints.get_edited_preset().config; + config_def_ = config_.def(); auto page = add_options_page("Layers and perimeters", "layers.png"); auto optgroup = page->new_optgroup("Layer height"); @@ -268,7 +285,7 @@ void CTabPrint::build() optgroup->append_single_option_line(get_option_("interface_shells")); page = add_options_page("Advanced", "wrench.png"); - optgroup = page->new_optgroup("Extrusion width", 200); + optgroup = page->new_optgroup("Extrusion width", 180); optgroup->append_single_option_line(get_option_("extrusion_width")); optgroup->append_single_option_line(get_option_("first_layer_extrusion_width")); optgroup->append_single_option_line(get_option_("perimeter_extrusion_width")); @@ -309,14 +326,14 @@ void CTabPrint::build() option.opt.full_width = true; optgroup->append_single_option_line(option); - optgroup = page->new_optgroup("Post-processing scripts"); //! label_width = > 0, + optgroup = page->new_optgroup("Post-processing scripts", 0); option = get_option_("post_process"); option.opt.full_width = true; option.opt.height = 50; optgroup->append_single_option_line(option); page = add_options_page("Notes", "note.png"); - optgroup = page->new_optgroup("Notes"); + optgroup = page->new_optgroup("Notes", 0); option = get_option_("notes"); option.opt.full_width = true; option.opt.height = 250; @@ -329,6 +346,382 @@ void CTabPrint::build() optgroup->append_line(line); } +void CTabFilament::build() +{ + config_ = preset_bundle_->filaments.get_edited_preset().config; + config_def_ = config_.def(); + + auto page = add_options_page("Filament", "spool.png"); + auto optgroup = page->new_optgroup("Filament"); + optgroup->append_single_option_line(get_option_("filament_colour")); + optgroup->append_single_option_line(get_option_("filament_diameter")); + optgroup->append_single_option_line(get_option_("extrusion_multiplier")); + optgroup->append_single_option_line(get_option_("filament_density")); + optgroup->append_single_option_line(get_option_("filament_cost")); + + optgroup = page->new_optgroup("Temperature (°C)"); + Line line = { "Extruder", "" }; + line.append_option(get_option_("first_layer_temperature")); + line.append_option(get_option_("temperature")); + optgroup->append_line(line); + + line = { "Bed", "" }; + line.append_option(get_option_("first_layer_bed_temperature")); + line.append_option(get_option_("bed_temperature")); + optgroup->append_line(line); + + page = add_options_page("Cooling", "hourglass.png"); + optgroup = page->new_optgroup("Enable"); + optgroup->append_single_option_line(get_option_("fan_always_on")); + optgroup->append_single_option_line(get_option_("cooling")); + + line = { "", "" }; + line.full_width = 1; + line.widget = cooling_description_line_widget_; + optgroup->append_line(line); + + optgroup = page->new_optgroup("Fan settings"); + line = {"Fan speed",""}; + line.append_option(get_option_("min_fan_speed")); + line.append_option(get_option_("max_fan_speed")); + optgroup->append_line(line); + + optgroup->append_single_option_line(get_option_("bridge_fan_speed")); + optgroup->append_single_option_line(get_option_("disable_fan_first_layers")); + + optgroup = page->new_optgroup("Cooling thresholds", 250); + optgroup->append_single_option_line(get_option_("fan_below_layer_time")); + optgroup->append_single_option_line(get_option_("slowdown_below_layer_time")); + optgroup->append_single_option_line(get_option_("min_print_speed")); + + page = add_options_page("Advanced", "wrench.png"); + optgroup = page->new_optgroup("Filament properties"); + optgroup->append_single_option_line(get_option_("filament_type")); + optgroup->append_single_option_line(get_option_("filament_soluble")); + + optgroup = page->new_optgroup("Print speed override"); + optgroup->append_single_option_line(get_option_("filament_max_volumetric_speed")); + + line = {"",""}; + line.full_width = 1; + line.widget = volumetric_speed_description_line_widget_; + optgroup->append_line(line); + + page = add_options_page("Custom G-code", "cog.png"); + optgroup = page->new_optgroup("Start G-code", 0); + Option option = get_option_("start_filament_gcode"); + option.opt.full_width = true; + option.opt.height = 150; + optgroup->append_single_option_line(option); + + optgroup = page->new_optgroup("End G-code", 0); + option = get_option_("end_filament_gcode"); + option.opt.full_width = true; + option.opt.height = 150; + optgroup->append_single_option_line(option); + + page = add_options_page("Notes", "note.png"); + optgroup = page->new_optgroup("Notes", 0); + optgroup->label_width = 0; + option = get_option_("filament_notes"); + option.opt.full_width = true; + option.opt.height = 250; + optgroup->append_single_option_line(option); + + page = add_options_page("Dependencies", "wrench.png"); + optgroup = page->new_optgroup("Profile dependencies"); + line = {"Compatible printers", ""}; + line.widget = compatible_printers_widget_; + optgroup->append_line(line); +} + +wxStaticText* CTabFilament::cooling_description_line_; +wxStaticText* CTabFilament::volumetric_speed_description_line_; +wxSizer* CTabFilament::description_line_widget_(wxWindow* parent, wxStaticText* StaticText) +{ + StaticText = new wxStaticText(parent, wxID_ANY, "gfghjkkl;\n fgdsufhsreotklg\n iesrftorsikgyfkh\nauiwrhfidj", wxDefaultPosition, wxDefaultSize); + auto font = (new wxSystemSettings)->GetFont(wxSYS_DEFAULT_GUI_FONT); + StaticText->SetFont(font); + StaticText->Wrap(400); + StaticText->GetParent()->Layout(); + + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(StaticText); + return sizer; +} + +//#include "../../libslic3r/GCodeSender.hpp"; +void CTabPrinter::build() +{ + config_ = preset_bundle_->printers.get_edited_preset().config; + config_def_ = config_.def(); // It will be used in get_option_(const std::string title) + +// $self->{extruders_count} = scalar @{$self->{config}->nozzle_diameter}; + auto *nozzle_diameter = dynamic_cast(config_.option("nozzle_diameter")); +// size_t extruders_count = nozzle_diameter->values.size(); + + auto page = add_options_page("General", "printer_empty.png"); + auto optgroup = page->new_optgroup("Size and coordinates"); + + Line line = { "Bed shape", "" }; + line.widget = bed_shape_widget_; + optgroup->append_line(line); + optgroup->append_single_option_line(get_option_("z_offset")); + + optgroup = page->new_optgroup("Capabilities"); + ConfigOptionDef def; + def.type = coInt, + def.default_value = new ConfigOptionInt(1); + def.label = "Extruders"; + def.tooltip = "Number of extruders of the printer."; + def.min = 1; + Option option(def, "extruders_count"); + optgroup->append_single_option_line(option); + optgroup->append_single_option_line(get_option_("single_extruder_multi_material")); + +// $optgroup->on_change(sub{ +// my($opt_key, $value) = @_; +// wxTheApp->CallAfter(sub{ +// if ($opt_key eq 'extruders_count') { +// $self->_extruders_count_changed($optgroup->get_value('extruders_count')); +// $self->update_dirty; +// } +// else { +// $self->update_dirty; +// $self->_on_value_change($opt_key, $value); +// } +// }); +// }); + +// if (!$params{ no_controller }) +// { + optgroup = page->new_optgroup("USB/Serial connection"); + line = {"Serial port", ""}; + Option serial_port = get_option_("serial_port"); + serial_port.side_widget = ([](wxWindow* parent){ + auto btn = new wxBitmapButton(parent, wxID_ANY, wxBitmap(wxT("var\\arrow_rotate_clockwise.png"), wxBITMAP_TYPE_PNG), + wxDefaultPosition, wxDefaultSize, wxBORDER_NONE); + /*if (btn->can('SetToolTipString')*/btn->SetToolTip("Rescan serial ports"); + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(btn); + + btn->Bind(wxEVT_BUTTON, [=](wxCommandEvent e) {/*_update_serial_ports*/; }); + return sizer; + }); + auto serial_test = ([/*serial_test_btn*/](wxWindow* parent){ + auto btn = /*serial_test_btn =*/ new wxButton(parent, wxID_ANY, + "Test", wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); +// btn->SetFont($Slic3r::GUI::small_font); + btn->SetBitmap(wxBitmap(wxT("var\\wrench.png"), wxBITMAP_TYPE_PNG)); + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(btn); + +// btn->Bind(wxEVT_BUTTON, []{ +// auto sender = new GCodeSender(); +// auto res = true;// sender->connect( +// // s_cache_HostConfig.serial_port, +// // config_->serial_speed +// // ); +// if (res && sender->wait_connected()) { +// show_info(parent, "Connection to printer works correctly.", "Success!"); +// } +// else { +// show_error(parent, "Connection failed."); +// } +// }); + return sizer; + }); + + line.append_option(serial_port); + line.append_option(get_option_("serial_speed")); + line.append_widget(serial_test); + optgroup->append_line(line); +// } + optgroup = page->new_optgroup("OctoPrint upload"); + // # append two buttons to the Host line + auto octoprint_host_browse = ([] (wxWindow* parent) { + auto btn = new wxButton(parent, wxID_ANY, "Browse…", wxDefaultPosition, wxDefaultSize, wxBU_LEFT); +// btn->SetFont($Slic3r::GUI::small_font); + btn->SetBitmap(wxBitmap(wxT("var\\zoom.png"), wxBITMAP_TYPE_PNG)); + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(btn); + +// if (!eval "use Net::Bonjour; 1") { +// btn->Disable; +// } + +// btn->Bind(wxEVT_BUTTON, []{ + // # look for devices +// my $entries; +// { +// my $res = Net::Bonjour->new('http'); +// $res->discover; +// $entries = [$res->entries]; +// } +// if (@{$entries}) { +// my $dlg = Slic3r::GUI::BonjourBrowser->new($self, $entries); +// $self->_load_key_value('octoprint_host', $dlg->GetValue . ":".$dlg->GetPort) +// if $dlg->ShowModal == wxID_OK; +// } +// else { +// auto msg_window = new wxMessageDialog(parent, "No Bonjour device found", "Device Browser", wxOK | wxICON_INFORMATION); +// msg_window->ShowModal(); +// } +// }); + + return sizer; + }); + auto octoprint_host_test = ([/*serial_test_btn*/](wxWindow* parent) { + auto btn = /*serial_test_btn =*/ new wxButton(parent, wxID_ANY, + "Test", wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); +// btn->SetFont($Slic3r::GUI::small_font); + btn->SetBitmap(wxBitmap(wxT("var\\wrench.png"), wxBITMAP_TYPE_PNG)); + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(btn); + + btn->Bind(wxEVT_BUTTON, [](wxCommandEvent e) { +// my $ua = LWP::UserAgent->new; +// $ua->timeout(10); +// +// my $res = $ua->get( +// "http://".$self->{config}->octoprint_host . "/api/version", +// 'X-Api-Key' = > $self->{config}->octoprint_apikey, +// ); +// if ($res->is_success) { +// Slic3r::GUI::show_info($self, "Connection to OctoPrint works correctly.", "Success!"); +// } +// else { +// Slic3r::GUI::show_error($self, +// "I wasn't able to connect to OctoPrint (".$res->status_line . "). " +// . "Check hostname and OctoPrint version (at least 1.1.0 is required)."); +// } + }); + return sizer; + }); + + Line host_line = optgroup->create_single_option_line(get_option_("octoprint_host")); + host_line.append_widget(octoprint_host_browse); + host_line.append_widget(octoprint_host_test); + optgroup->append_line(host_line); + optgroup->append_single_option_line(get_option_("octoprint_apikey")); + + optgroup = page->new_optgroup("Firmware"); + optgroup->append_single_option_line(get_option_("gcode_flavor")); + + optgroup = page->new_optgroup("Advanced"); + optgroup->append_single_option_line(get_option_("use_relative_e_distances")); + optgroup->append_single_option_line(get_option_("use_firmware_retraction")); + optgroup->append_single_option_line(get_option_("use_volumetric_e")); + optgroup->append_single_option_line(get_option_("variable_layer_height")); + + page = add_options_page("Custom G-code", "cog.png"); + optgroup = page->new_optgroup("Start G-code", 0); + option = get_option_("start_gcode"); + option.opt.full_width = true; + option.opt.height = 150; + optgroup->append_single_option_line(option); + + optgroup = page->new_optgroup("End G-code", 0); + option = get_option_("end_gcode"); + option.opt.full_width = true; + option.opt.height = 150; + optgroup->append_single_option_line(option); + + optgroup = page->new_optgroup("Before layer change G-code", 0); + option = get_option_("before_layer_gcode"); + option.opt.full_width = true; + option.opt.height = 150; + optgroup->append_single_option_line(option); + + optgroup = page->new_optgroup("After layer change G-code", 0); + option = get_option_("layer_gcode"); + option.opt.full_width = true; + option.opt.height = 150; + optgroup->append_single_option_line(option); + + optgroup = page->new_optgroup("Tool change G-code", 0); + option = get_option_("toolchange_gcode"); + option.opt.full_width = true; + option.opt.height = 150; + optgroup->append_single_option_line(option); + + optgroup = page->new_optgroup("Between objects G-code (for sequential printing)", 0); + option = get_option_("between_objects_gcode"); + option.opt.full_width = true; + option.opt.height = 150; + optgroup->append_single_option_line(option); + + page = add_options_page("Notes", "note.png"); + optgroup = page->new_optgroup("Notes", 0); + option = get_option_("printer_notes"); + option.opt.full_width = true; + option.opt.height = 250; + optgroup->append_single_option_line(option); + +// $self->{extruder_pages} = []; + build_extruder_pages_(); + +// $self->_update_serial_ports if (!$params{ no_controller }); +} + +void CTabPrinter::build_extruder_pages_(){ +// my $default_config = Slic3r::Config::Full->new; +// +// foreach my $extruder_idx(@{$self->{extruder_pages}} ..$self->{extruders_count}-1) { + //# build page + auto page = /*$self->{extruder_pages}[$extruder_idx] =*/ add_options_page("Extruder "/* . ($extruder_idx + 1)*/, "funnel.png"); + auto optgroup = page->new_optgroup("Size"); + optgroup->append_single_option_line(get_option_("nozzle_diameter"/*, $extruder_idx*/)); + + optgroup = page->new_optgroup("Layer height limits"); + optgroup->append_single_option_line(get_option_("min_layer_height"/*, $extruder_idx*/)); + optgroup->append_single_option_line(get_option_("max_layer_height"/*, $extruder_idx*/)); + + + optgroup = page->new_optgroup("Position (for multi-extruder printers)"); + optgroup->append_single_option_line(get_option_("extruder_offset"/*, $extruder_idx*/)); + + optgroup = page->new_optgroup("Retraction"); + optgroup->append_single_option_line(get_option_("retract_length"/*, $extruder_idx*/)); + optgroup->append_single_option_line(get_option_("retract_lift"/*, $extruder_idx*/)); + Line line = { "Only lift Z", "" }; + line.append_option(get_option_("retract_lift_above"/*, $extruder_idx*/)); + line.append_option(get_option_("retract_lift_below"/*, $extruder_idx*/)); + optgroup->append_line(line); + + optgroup->append_single_option_line(get_option_("retract_speed"/*, $extruder_idx*/)); + optgroup->append_single_option_line(get_option_("deretract_speed"/*, $extruder_idx*/)); + optgroup->append_single_option_line(get_option_("retract_restart_extra"/*, $extruder_idx*/)); + optgroup->append_single_option_line(get_option_("retract_before_travel"/*, $extruder_idx*/)); + optgroup->append_single_option_line(get_option_("retract_layer_change"/*, $extruder_idx*/)); + optgroup->append_single_option_line(get_option_("wipe"/*, $extruder_idx*/)); + optgroup->append_single_option_line(get_option_("retract_before_wipe"/*, $extruder_idx*/)); + + optgroup = page->new_optgroup("Retraction when tool is disabled (advanced settings for multi-extruder setups)"); + optgroup->append_single_option_line(get_option_("retract_length_toolchange"/*, $extruder_idx*/)); + optgroup->append_single_option_line(get_option_("retract_restart_extra_toolchange"/*, $extruder_idx*/)); + + optgroup = page->new_optgroup("Preview"); + optgroup->append_single_option_line(get_option_("extruder_colour"/*, $extruder_idx*/)); +// } +// +// // # remove extra pages +// if ($self->{extruders_count} <= $#{$self->{extruder_pages}}) { +// $_->Destroy for @{$self->{extruder_pages}}[$self->{extruders_count}..$#{$self->{extruder_pages}}]; +// splice @{$self->{extruder_pages}}, $self->{extruders_count}; +// } +// +// // # rebuild page list +// my @pages_without_extruders = (grep $_->{title} !~/ ^Extruder \d + / , @{$self->{pages}}); +// my $page_notes = pop @pages_without_extruders; +// @{$self->{pages}} = ( +// @pages_without_extruders, +// @{$self->{extruder_pages}}[0 ..$self->{extruders_count}-1], +// $page_notes +// ); + rebuild_page_tree(); +} + //Regerenerate content of the page tree. void CTab::rebuild_page_tree() { @@ -459,29 +852,33 @@ wxSizer* CTab::compatible_printers_widget_(wxWindow* parent) return sizer; } -void CTab::load_key_value_(std::string opt_key, std::vector value) +wxSizer* CTab::bed_shape_widget_(wxWindow* parent) { - // # To be called by custom widgets, load a value into a config, - // # update the preset selection boxes (the dirty flags) - // $self->{config}->set($opt_key, $value); - // # Mark the print & filament enabled if they are compatible with the currently selected preset. - if (opt_key.compare("compatible_printers")==0) { - // wxTheApp->{preset_bundle}->update_compatible_with_printer(0); - // $self->{presets}->update_tab_ui($self->{presets_choice}, $self->{show_incompatible_presets}); - // } else { - // $self->{presets}->update_dirty_ui($self->{presets_choice}); - } - // $self->_on_presets_changed; - // $self->_update; + auto btn = new wxButton(parent, wxID_ANY, "Set…", wxDefaultPosition, wxDefaultSize, + wxBU_LEFT | wxBU_EXACTFIT); +// btn->SetFont(Slic3r::GUI::small_font); + btn->SetBitmap(wxBitmap(wxT("var\\printer_empty.png"), wxBITMAP_TYPE_PNG)); + + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(btn); + + btn->Bind(wxEVT_BUTTON, ([=](wxCommandEvent e) + { +// auto dlg = new BedShapeDialog->new($self, $self->{config}->bed_shape); +// if (dlg->ShowModal == wxID_OK) + ;// load_key_value_("bed_shape", dlg->GetValue); + })); + + return sizer; } // package Slic3r::GUI::Tab::Page; -ConfigOptionsGroupShp CPage::new_optgroup(std::string title, size_t label_width /*= 0*/) +ConfigOptionsGroupShp CPage::new_optgroup(std::string title, int noncommon_label_width /*= -1*/) { //! config_ have to be "right" ConfigOptionsGroupShp optgroup = std::make_shared(this, title, config_); - if (label_width != 0) - optgroup->label_width = label_width; + if (noncommon_label_width >= 0) + optgroup->label_width = noncommon_label_width; // on_change => sub { // my ($opt_key, $value) = @_; diff --git a/xs/src/slic3r/GUI/Tab.h b/xs/src/slic3r/GUI/Tab.h index 7de862b51..a2e03b418 100644 --- a/xs/src/slic3r/GUI/Tab.h +++ b/xs/src/slic3r/GUI/Tab.h @@ -64,7 +64,7 @@ public: size_t iconID() const { return iconID_; } void set_config(DynamicPrintConfig* config_in) { config_ = config_in; } - ConfigOptionsGroupShp new_optgroup(std::string title, size_t label_width = 0); + ConfigOptionsGroupShp new_optgroup(std::string title, int noncommon_label_width = -1); }; // Slic3r::GUI::Tab; @@ -74,7 +74,7 @@ class CTab: public wxPanel { wxNotebook* parent_; protected: - const char* title_; + const wxString title_; wxBitmapComboBox* presets_choice_; wxBitmapButton* btn_save_preset_; wxBitmapButton* btn_delete_preset_; @@ -87,14 +87,16 @@ protected: wxImageList* icons_; wxCheckBox* compatible_printers_checkbox_; wxButton* compatible_printers_btn; + int icon_count; std::map icon_index_; // Map from an icon file name to its index in $self->{icons}. std::vector pages_; // $self->{pages} = []; bool disable_tree_sel_changed_event_; public: - DynamicPrintConfig config_; //! tmp_val - const ConfigDef* config_def; //! tmp_val + PresetBundle* preset_bundle_; + DynamicPrintConfig config_; //! tmp_val + const ConfigDef* config_def_; // It will be used in get_option_(const std::string title) public: CTab() {} @@ -104,12 +106,15 @@ public: ~CTab(){} wxWindow* parent() const { return parent_; } + wxString title() const { return title_; } - void create_preset_tab(); + void create_preset_tab(PresetBundle *preset_bundle); void rebuild_page_tree(); void select_preset(wxString preset_name){}; - static wxSizer* compatible_printers_widget_(wxWindow* parent); + static wxSizer* compatible_printers_widget_(wxWindow* parent); + static wxSizer* bed_shape_widget_(wxWindow* parent); + void load_key_value_(std::string opt_key, std::vector value); void OnTreeSelChange(wxTreeEvent& event); @@ -125,7 +130,7 @@ public: // virtual void _update(); Option get_option_(const std::string title){ - return Option(*config_def->get(title), title); + return Option(*config_def_->get(title), title); } }; @@ -134,11 +139,45 @@ class CTabPrint : public CTab { public: CTabPrint() {} - CTabPrint(wxNotebook* parent, const char *title/*, someParams*/) : CTab(parent, title) {} + CTabPrint(wxNotebook* parent, const char *title) : CTab(parent, title) {} ~CTabPrint(){} void build() override; }; +//Slic3r::GUI::Tab::Print; +class CTabFilament : public CTab +{ + static wxStaticText* cooling_description_line_; + static wxStaticText* volumetric_speed_description_line_; +public: + CTabFilament() {} + CTabFilament(wxNotebook* parent, const char *title) : CTab(parent, title) {} + ~CTabFilament(){} + + static wxSizer* description_line_widget_(wxWindow* parent, wxStaticText* StaticText); + static wxSizer* cooling_description_line_widget_(wxWindow* parent) { + return description_line_widget_(parent, cooling_description_line_); } + static wxSizer* volumetric_speed_description_line_widget_(wxWindow* parent) { + return description_line_widget_(parent, volumetric_speed_description_line_); } + + void build() override; +}; + +//Slic3r::GUI::Tab::Print; +class CTabPrinter : public CTab +{ +public: + wxButton* serial_test_btn; + wxButton* octoprint_host_test_btn; +public: + CTabPrinter() {} + CTabPrinter(wxNotebook* parent, const char *title) : CTab(parent, title) {} + ~CTabPrinter(){} + + void build() override; + void build_extruder_pages_(); +}; + } // GUI } // Slic3r diff --git a/xs/xsp/GUI.xsp b/xs/xsp/GUI.xsp index d6b55dbf1..10a235197 100644 --- a/xs/xsp/GUI.xsp +++ b/xs/xsp/GUI.xsp @@ -35,5 +35,5 @@ void set_tab_panel(SV *ui) void add_debug_menu(SV *ui) %code%{ Slic3r::GUI::add_debug_menu((wxMenuBar*)wxPli_sv_2_object(aTHX_ ui, "Wx::MenuBar")); %}; -void create_preset_tab(const char *name) - %code%{ Slic3r::GUI::create_preset_tab(name); %}; +void create_preset_tabs(PresetBundle *preset_bundle) + %code%{ Slic3r::GUI::create_preset_tabs(preset_bundle); %};