From 66b5deccf5b90e24ecf5935f263b7f893dd5440e Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Tue, 18 Dec 2018 14:34:16 +0100 Subject: [PATCH 1/3] PrintHost: Basic SL1 support --- src/libslic3r/PrintConfig.hpp | 2 +- src/slic3r/GUI/Plater.cpp | 2 + src/slic3r/GUI/Preset.cpp | 1 + src/slic3r/GUI/Tab.cpp | 197 ++++++++++++++++++--------------- src/slic3r/GUI/Tab.hpp | 2 + src/slic3r/Utils/OctoPrint.cpp | 188 +++++++++++++++++-------------- src/slic3r/Utils/OctoPrint.hpp | 45 +++++--- src/slic3r/Utils/PrintHost.cpp | 14 ++- 8 files changed, 255 insertions(+), 196 deletions(-) diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 487e35bf2..08f42f39b 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -36,7 +36,7 @@ enum GCodeFlavor { }; enum PrintHostType { - htOctoPrint, htDuet, + htOctoPrint, htDuet, htSL1, }; enum InfillPattern { diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 6544da789..51735fe67 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -3244,6 +3244,8 @@ void Plater::on_config_change(const DynamicPrintConfig &config) #endif // ENABLE_REMOVE_TABS_FROM_PLATER if (p->preview) p->preview->set_bed_shape(p->config->option("bed_shape")->values); update_scheduled = true; + } else if (opt_key == "host_type" && this->p->printer_technology == ptSLA) { + p->config->option>(opt_key)->value = htSL1; } } diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index 90372ecd4..bfda0a2f3 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -456,6 +456,7 @@ const std::vector& Preset::sla_printer_options() "display_width", "display_height", "display_pixels_x", "display_pixels_y", "display_orientation", "printer_correction", + "print_host", "printhost_apikey", "printhost_cafile", "printer_notes", "inherits" }; diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 30d83d845..f46ad2142 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1538,6 +1538,108 @@ bool Tab::current_preset_is_dirty() return m_presets->current_is_dirty(); } +void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup) +{ + const bool sla = m_presets->get_selected_preset().printer_technology() == ptSLA; + + // Only offer the host type selection for FFF, for SLA it's always the SL1 printer (at the moment) + if (! sla) { + optgroup->append_single_option_line("host_type"); + } else { + m_config->option>("host_type", true)->value = htSL1; + } + + auto printhost_browse = [this, optgroup] (wxWindow* parent) { + + // TODO: SLA + + auto btn = m_printhost_browse_btn = new wxButton(parent, wxID_ANY, _(L(" Browse "))+dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT); + btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("zoom.png")), wxBITMAP_TYPE_PNG)); + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(btn); + + btn->Bind(wxEVT_BUTTON, [this, parent, optgroup](wxCommandEvent e) { + BonjourDialog dialog(parent); + if (dialog.show_and_lookup()) { + optgroup->set_value("print_host", std::move(dialog.get_selected()), true); + } + }); + + return sizer; + }; + + auto print_host_test = [this](wxWindow* parent) { + auto btn = m_print_host_test_btn = new wxButton(parent, wxID_ANY, _(L("Test")), + wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); + btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("wrench.png")), wxBITMAP_TYPE_PNG)); + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(btn); + + btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent e) { + std::unique_ptr host(PrintHost::get_print_host(m_config)); + if (! host) { + const auto text = wxString::Format("%s", + _(L("Could not get a valid Printer Host reference"))); + show_error(this, text); + return; + } + wxString msg; + if (host->test(msg)) { + show_info(this, host->get_test_ok_msg(), _(L("Success!"))); + } else { + show_error(this, host->get_test_failed_msg(msg)); + } + }); + + return sizer; + }; + + Line host_line = optgroup->create_single_option_line("print_host"); + host_line.append_widget(printhost_browse); + host_line.append_widget(print_host_test); + optgroup->append_line(host_line); + optgroup->append_single_option_line("printhost_apikey"); + + if (Http::ca_file_supported()) { + + Line cafile_line = optgroup->create_single_option_line("printhost_cafile"); + + auto printhost_cafile_browse = [this, optgroup] (wxWindow* parent) { + auto btn = new wxButton(parent, wxID_ANY, _(L(" Browse "))+dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT); + btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("zoom.png")), wxBITMAP_TYPE_PNG)); + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(btn); + + btn->Bind(wxEVT_BUTTON, [this, optgroup] (wxCommandEvent e) { + static const auto filemasks = _(L("Certificate files (*.crt, *.pem)|*.crt;*.pem|All files|*.*")); + wxFileDialog openFileDialog(this, _(L("Open CA certificate file")), "", "", filemasks, wxFD_OPEN | wxFD_FILE_MUST_EXIST); + if (openFileDialog.ShowModal() != wxID_CANCEL) { + optgroup->set_value("printhost_cafile", std::move(openFileDialog.GetPath()), true); + } + }); + + return sizer; + }; + + cafile_line.append_widget(printhost_cafile_browse); + optgroup->append_line(cafile_line); + + auto printhost_cafile_hint = [this, optgroup] (wxWindow* parent) { + auto txt = new wxStaticText(parent, wxID_ANY, + _(L("HTTPS CA file is optional. It is only needed if you use HTTPS with a self-signed certificate."))); + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(txt); + return sizer; + }; + + Line cafile_hint { "", "" }; + cafile_hint.full_width = 1; + cafile_hint.widget = std::move(printhost_cafile_hint); + optgroup->append_line(cafile_hint); + + } +} + void TabPrinter::build() { m_presets = &m_preset_bundle->printers; @@ -1665,96 +1767,8 @@ void TabPrinter::build_fff() } #endif - optgroup = page->new_optgroup(_(L("Printer Host upload"))); - - optgroup->append_single_option_line("host_type"); - - auto printhost_browse = [this, optgroup] (wxWindow* parent) { - auto btn = m_printhost_browse_btn = new wxButton(parent, wxID_ANY, _(L(" Browse "))+dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT); - btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("zoom.png")), wxBITMAP_TYPE_PNG)); - auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(btn); - - btn->Bind(wxEVT_BUTTON, [this, parent, optgroup](wxCommandEvent e) { - BonjourDialog dialog(parent); - if (dialog.show_and_lookup()) { - optgroup->set_value("print_host", std::move(dialog.get_selected()), true); - } - }); - - return sizer; - }; - - auto print_host_test = [this](wxWindow* parent) { - auto btn = m_print_host_test_btn = new wxButton(parent, wxID_ANY, _(L("Test")), - wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); - btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("wrench.png")), wxBITMAP_TYPE_PNG)); - auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(btn); - - btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent e) { - std::unique_ptr host(PrintHost::get_print_host(m_config)); - if (! host) { - const auto text = wxString::Format("%s", - _(L("Could not get a valid Printer Host reference"))); - show_error(this, text); - return; - } - wxString msg; - if (host->test(msg)) { - show_info(this, host->get_test_ok_msg(), _(L("Success!"))); - } else { - show_error(this, host->get_test_failed_msg(msg)); - } - }); - - return sizer; - }; - - Line host_line = optgroup->create_single_option_line("print_host"); - host_line.append_widget(printhost_browse); - host_line.append_widget(print_host_test); - optgroup->append_line(host_line); - optgroup->append_single_option_line("printhost_apikey"); - - if (Http::ca_file_supported()) { - - Line cafile_line = optgroup->create_single_option_line("printhost_cafile"); - - auto printhost_cafile_browse = [this, optgroup] (wxWindow* parent) { - auto btn = new wxButton(parent, wxID_ANY, _(L(" Browse "))+dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT); - btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("zoom.png")), wxBITMAP_TYPE_PNG)); - auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(btn); - - btn->Bind(wxEVT_BUTTON, [this, optgroup] (wxCommandEvent e) { - static const auto filemasks = _(L("Certificate files (*.crt, *.pem)|*.crt;*.pem|All files|*.*")); - wxFileDialog openFileDialog(this, _(L("Open CA certificate file")), "", "", filemasks, wxFD_OPEN | wxFD_FILE_MUST_EXIST); - if (openFileDialog.ShowModal() != wxID_CANCEL) { - optgroup->set_value("printhost_cafile", std::move(openFileDialog.GetPath()), true); - } - }); - - return sizer; - }; - - cafile_line.append_widget(printhost_cafile_browse); - optgroup->append_line(cafile_line); - - auto printhost_cafile_hint = [this, optgroup] (wxWindow* parent) { - auto txt = new wxStaticText(parent, wxID_ANY, - _(L("HTTPS CA file is optional. It is only needed if you use HTTPS with a self-signed certificate."))); - auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(txt); - return sizer; - }; - - Line cafile_hint { "", "" }; - cafile_hint.full_width = 1; - cafile_hint.widget = std::move(printhost_cafile_hint); - optgroup->append_line(cafile_hint); - - } + optgroup = page->new_optgroup(_(L("Print Host upload"))); + build_printhost(optgroup.get()); optgroup = page->new_optgroup(_(L("Firmware"))); optgroup->append_single_option_line("gcode_flavor"); @@ -1897,6 +1911,9 @@ void TabPrinter::build_sla() } optgroup->append_line(line); + optgroup = page->new_optgroup(_(L("Print Host upload"))); + build_printhost(optgroup.get()); + page = add_options_page(_(L("Notes")), "note.png"); optgroup = page->new_optgroup(_(L("Notes")), 0); option = optgroup->get_option("printer_notes"); diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index 337fbf006..93db1383a 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -325,6 +325,8 @@ class TabPrinter : public Tab std::vector m_pages_fff; std::vector m_pages_sla; + + void build_printhost(ConfigOptionsGroup *optgroup); public: wxButton* m_serial_test_btn = nullptr; wxButton* m_print_host_test_btn = nullptr; diff --git a/src/slic3r/Utils/OctoPrint.cpp b/src/slic3r/Utils/OctoPrint.cpp index 67c58a972..cbb81c54f 100644 --- a/src/slic3r/Utils/OctoPrint.cpp +++ b/src/slic3r/Utils/OctoPrint.cpp @@ -17,141 +17,161 @@ namespace fs = boost::filesystem; namespace Slic3r { OctoPrint::OctoPrint(DynamicPrintConfig *config) : - host(config->opt_string("print_host")), - apikey(config->opt_string("printhost_apikey")), - cafile(config->opt_string("printhost_cafile")) + host(config->opt_string("print_host")), + apikey(config->opt_string("printhost_apikey")), + cafile(config->opt_string("printhost_cafile")) {} OctoPrint::~OctoPrint() {} bool OctoPrint::test(wxString &msg) const { - // Since the request is performed synchronously here, - // it is ok to refer to `msg` from within the closure + // Since the request is performed synchronously here, + // it is ok to refer to `msg` from within the closure - bool res = true; - auto url = make_url("api/version"); + bool res = true; + auto url = make_url("api/version"); - BOOST_LOG_TRIVIAL(info) << boost::format("Octoprint: Get version at: %1%") % url; + BOOST_LOG_TRIVIAL(info) << boost::format("Octoprint: Get version at: %1%") % url; - auto http = Http::get(std::move(url)); - set_auth(http); - http.on_error([&](std::string body, std::string error, unsigned status) { - BOOST_LOG_TRIVIAL(error) << boost::format("Octoprint: Error getting version: %1%, HTTP %2%, body: `%3%`") % error % status % body; - res = false; - msg = format_error(body, error, status); - }) - .on_complete([&](std::string body, unsigned) { - BOOST_LOG_TRIVIAL(debug) << boost::format("Octoprint: Got version: %1%") % body; - }) - .perform_sync(); + auto http = Http::get(std::move(url)); + set_auth(http); + http.on_error([&](std::string body, std::string error, unsigned status) { + BOOST_LOG_TRIVIAL(error) << boost::format("Octoprint: Error getting version: %1%, HTTP %2%, body: `%3%`") % error % status % body; + res = false; + msg = format_error(body, error, status); + }) + .on_complete([&](std::string body, unsigned) { + BOOST_LOG_TRIVIAL(debug) << boost::format("Octoprint: Got version: %1%") % body; - return res; + // TODO: parse body, call validate_version_text + + }) + .perform_sync(); + + return res; } wxString OctoPrint::get_test_ok_msg () const { - return wxString::Format("%s", _(L("Connection to OctoPrint works correctly."))); + return wxString::Format("%s", _(L("Connection to OctoPrint works correctly."))); } wxString OctoPrint::get_test_failed_msg (wxString &msg) const { - return wxString::Format("%s: %s\n\n%s", - _(L("Could not connect to OctoPrint")), msg, _(L("Note: OctoPrint version at least 1.1.0 is required."))); + return wxString::Format("%s: %s\n\n%s", + _(L("Could not connect to OctoPrint")), msg, _(L("Note: OctoPrint version at least 1.1.0 is required."))); } bool OctoPrint::upload(PrintHostUpload upload_data, Http::ProgressFn prorgess_fn, Http::ErrorFn error_fn) const { - const auto upload_filename = upload_data.upload_path.filename(); - const auto upload_parent_path = upload_data.upload_path.parent_path(); + const auto upload_filename = upload_data.upload_path.filename(); + const auto upload_parent_path = upload_data.upload_path.parent_path(); - wxString test_msg; - if (! test(test_msg)) { + wxString test_msg; + if (! test(test_msg)) { - // TODO: + // TODO: - // auto errormsg = wxString::Format("%s: %s", errortitle, test_msg); - // GUI::show_error(&progress_dialog, std::move(errormsg)); - // return false; - } + // auto errormsg = wxString::Format("%s: %s", errortitle, test_msg); + // GUI::show_error(&progress_dialog, std::move(errormsg)); + // return false; + } - bool res = true; + bool res = true; - auto url = make_url("api/files/local"); + auto url = make_url("api/files/local"); - BOOST_LOG_TRIVIAL(info) << boost::format("Octoprint: Uploading file %1% at %2%, filename: %3%, path: %4%, print: %5%") - % upload_data.source_path.string() - % url - % upload_filename.string() - % upload_parent_path.string() - % upload_data.start_print; + BOOST_LOG_TRIVIAL(info) << boost::format("Octoprint: Uploading file %1% at %2%, filename: %3%, path: %4%, print: %5%") + % upload_data.source_path.string() + % url + % upload_filename.string() + % upload_parent_path.string() + % upload_data.start_print; - auto http = Http::post(std::move(url)); - set_auth(http); - http.form_add("print", upload_data.start_print ? "true" : "false") - .form_add("path", upload_parent_path.string()) // XXX: slashes on windows ??? - .form_add_file("file", upload_data.source_path.string(), upload_filename.string()) - .on_complete([&](std::string body, unsigned status) { - BOOST_LOG_TRIVIAL(debug) << boost::format("Octoprint: File uploaded: HTTP %1%: %2%") % status % body; - }) - .on_error([&](std::string body, std::string error, unsigned status) { - BOOST_LOG_TRIVIAL(error) << boost::format("Octoprint: Error uploading file: %1%, HTTP %2%, body: `%3%`") % error % status % body; - error_fn(std::move(body), std::move(error), status); - res = false; - }) - .on_progress([&](Http::Progress progress, bool &cancel) { - prorgess_fn(std::move(progress), cancel); - if (cancel) { - // Upload was canceled - BOOST_LOG_TRIVIAL(error) << "Octoprint: Upload canceled"; - res = false; - } - }) - .perform_sync(); + auto http = Http::post(std::move(url)); + set_auth(http); + http.form_add("print", upload_data.start_print ? "true" : "false") + .form_add("path", upload_parent_path.string()) // XXX: slashes on windows ??? + .form_add_file("file", upload_data.source_path.string(), upload_filename.string()) + .on_complete([&](std::string body, unsigned status) { + BOOST_LOG_TRIVIAL(debug) << boost::format("Octoprint: File uploaded: HTTP %1%: %2%") % status % body; + }) + .on_error([&](std::string body, std::string error, unsigned status) { + BOOST_LOG_TRIVIAL(error) << boost::format("Octoprint: Error uploading file: %1%, HTTP %2%, body: `%3%`") % error % status % body; + error_fn(std::move(body), std::move(error), status); + res = false; + }) + .on_progress([&](Http::Progress progress, bool &cancel) { + prorgess_fn(std::move(progress), cancel); + if (cancel) { + // Upload was canceled + BOOST_LOG_TRIVIAL(error) << "Octoprint: Upload canceled"; + res = false; + } + }) + .perform_sync(); - return res; + return res; } bool OctoPrint::has_auto_discovery() const { - return true; + return true; } bool OctoPrint::can_test() const { - return true; + return true; +} + +bool OctoPrint::validate_version_text(const std::string &version_text) +{ + // FIXME + return true; } void OctoPrint::set_auth(Http &http) const { - http.header("X-Api-Key", apikey); + http.header("X-Api-Key", apikey); - if (! cafile.empty()) { - http.ca_file(cafile); - } + if (! cafile.empty()) { + http.ca_file(cafile); + } } std::string OctoPrint::make_url(const std::string &path) const { - if (host.find("http://") == 0 || host.find("https://") == 0) { - if (host.back() == '/') { - return (boost::format("%1%%2%") % host % path).str(); - } else { - return (boost::format("%1%/%2%") % host % path).str(); - } - } else { - return (boost::format("http://%1%/%2%") % host % path).str(); - } + if (host.find("http://") == 0 || host.find("https://") == 0) { + if (host.back() == '/') { + return (boost::format("%1%%2%") % host % path).str(); + } else { + return (boost::format("%1%/%2%") % host % path).str(); + } + } else { + return (boost::format("http://%1%/%2%") % host % path).str(); + } } wxString OctoPrint::format_error(const std::string &body, const std::string &error, unsigned status) { - if (status != 0) { - auto wxbody = wxString::FromUTF8(body.data()); - return wxString::Format("HTTP %u: %s", status, wxbody); - } else { - return wxString::FromUTF8(error.data()); - } + if (status != 0) { + auto wxbody = wxString::FromUTF8(body.data()); + return wxString::Format("HTTP %u: %s", status, wxbody); + } else { + return wxString::FromUTF8(error.data()); + } +} + + +// SL1 + +SL1Host::~SL1Host() {} + +bool SL1Host::validate_version_text(const std::string &version_text) +{ + // FIXME + return true; } diff --git a/src/slic3r/Utils/OctoPrint.hpp b/src/slic3r/Utils/OctoPrint.hpp index 9267b4c83..4d6555e13 100644 --- a/src/slic3r/Utils/OctoPrint.hpp +++ b/src/slic3r/Utils/OctoPrint.hpp @@ -16,24 +16,39 @@ class Http; class OctoPrint : public PrintHost { public: - OctoPrint(DynamicPrintConfig *config); - virtual ~OctoPrint(); + OctoPrint(DynamicPrintConfig *config); + virtual ~OctoPrint(); + + bool test(wxString &curl_msg) const; + wxString get_test_ok_msg () const; + wxString get_test_failed_msg (wxString &msg) const; + bool upload(PrintHostUpload upload_data, Http::ProgressFn prorgess_fn, Http::ErrorFn error_fn) const; + bool has_auto_discovery() const; + bool can_test() const; + virtual std::string get_host() const { return host; } + +protected: + virtual bool validate_version_text(const std::string &version_text); - bool test(wxString &curl_msg) const; - wxString get_test_ok_msg () const; - wxString get_test_failed_msg (wxString &msg) const; - bool upload(PrintHostUpload upload_data, Http::ProgressFn prorgess_fn, Http::ErrorFn error_fn) const; - bool has_auto_discovery() const; - bool can_test() const; - virtual std::string get_host() const { return host; } private: - std::string host; - std::string apikey; - std::string cafile; + std::string host; + std::string apikey; + std::string cafile; - void set_auth(Http &http) const; - std::string make_url(const std::string &path) const; - static wxString format_error(const std::string &body, const std::string &error, unsigned status); + void set_auth(Http &http) const; + std::string make_url(const std::string &path) const; + static wxString format_error(const std::string &body, const std::string &error, unsigned status); +}; + + +class SL1Host: public OctoPrint +{ +public: + SL1Host(DynamicPrintConfig *config) : OctoPrint(config) {} + virtual ~SL1Host(); + +protected: + virtual bool validate_version_text(const std::string &version_text); }; diff --git a/src/slic3r/Utils/PrintHost.cpp b/src/slic3r/Utils/PrintHost.cpp index 48f504884..863da5d43 100644 --- a/src/slic3r/Utils/PrintHost.cpp +++ b/src/slic3r/Utils/PrintHost.cpp @@ -24,13 +24,15 @@ PrintHost::~PrintHost() {} PrintHost* PrintHost::get_print_host(DynamicPrintConfig *config) { - PrintHostType kind = config->option>("host_type")->value; - if (kind == htOctoPrint) { - return new OctoPrint(config); - } else if (kind == htDuet) { - return new Duet(config); + const auto opt = config->option>("host_type"); + if (opt == nullptr) { return nullptr; } + + switch (opt->value) { + case htOctoPrint: return new OctoPrint(config); + case htSL1: return new SL1Host(config); + case htDuet: return new Duet(config); + default: return nullptr; } - return nullptr; } From 7d1fb201e725a2c83ceb5a226ed76e652154fb4a Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 18 Dec 2018 13:22:22 +0100 Subject: [PATCH 2/3] Implemented updating of the settings values for PointCtrl and Choice. * wx_EVT_KILL_FOCES doesn't handled on OSX, so values are updating on wx_EVT_TEXT like a temporary workaround. --- src/slic3r/GUI/Field.cpp | 59 ++++++++++++++++++++++++++++++++------- src/slic3r/GUI/Field.hpp | 2 +- src/slic3r/GUI/Plater.cpp | 2 +- src/slic3r/GUI/Tab.cpp | 2 +- 4 files changed, 52 insertions(+), 13 deletions(-) diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index fc428ac0d..0283b7c29 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -193,9 +193,10 @@ void Field::get_value_by_opt_type(wxString& str) } } -bool TextCtrl::is_defined_input_value() const +template +bool is_defined_input_value(wxWindow* win, const ConfigOptionType& type) { - if (static_cast(window)->GetValue().empty() && m_opt.type != coString && m_opt.type != coStrings) + if (static_cast(win)->GetValue().empty() && type != coString && type != coStrings) return false; return true; } @@ -274,7 +275,7 @@ void TextCtrl::BUILD() { temp->GetToolTip()->Enable(true); #endif // __WXGTK__ // if (!is_defined_input_value()) - if (is_defined_input_value()) + if (is_defined_input_value(window, m_opt.type)) on_change_field(); else on_kill_focus(e); @@ -399,6 +400,9 @@ void SpinCtrl::BUILD() { 0, min_val, max_val, default_value); // temp->Bind(wxEVT_SPINCTRL, ([this](wxCommandEvent e) { tmp_value = undef_spin_val; on_change_field(); }), temp->GetId()); + + // #ys_FIXME_KILL_FOCUS + // wxEVT_KILL_FOCUS doesn't handled on OSX now temp->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) { if (tmp_value < 0) @@ -408,6 +412,7 @@ void SpinCtrl::BUILD() { on_change_field(); } }), temp->GetId()); + temp->Bind(wxEVT_TEXT, ([this](wxCommandEvent e) { // # On OSX / Cocoa, wxSpinCtrl::GetValue() doesn't return the new value @@ -420,9 +425,15 @@ void SpinCtrl::BUILD() { tmp_value = std::stoi(value); else tmp_value = -9999; // on_change_field(); -// # We don't reset tmp_value here because _on_change might put callbacks -// # in the CallAfter queue, and we want the tmp value to be available from -// # them as well. +#ifdef __WXOSX__ + // #ys_FIXME_KILL_FOCUS so call on_change_field() inside wxEVT_TEXT + if (tmp_value < 0) { + if (m_on_kill_focus != nullptr) + m_on_kill_focus(m_opt_id); + } + else + on_change_field(); +#endif }), temp->GetId()); temp->SetToolTip(get_tooltip_text(text_value)); @@ -454,9 +465,24 @@ void Choice::BUILD() { } set_selection(); } - temp->Bind(wxEVT_TEXT, ([this](wxCommandEvent e) { on_change_field(); }), temp->GetId()); +// temp->Bind(wxEVT_TEXT, ([this](wxCommandEvent e) { on_change_field(); }), temp->GetId()); temp->Bind(wxEVT_COMBOBOX, ([this](wxCommandEvent e) { on_change_field(); }), temp->GetId()); + if (temp->GetWindowStyle() != wxCB_READONLY) { + temp->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) { + e.Skip(); + double old_val = !m_value.empty() ? boost::any_cast(m_value) : -99999; + if (is_defined_input_value(window, m_opt.type)) { + if (fabs(old_val - boost::any_cast(get_value())) <= 0.0001) + return; + else + on_change_field(); + } + else + on_kill_focus(e); + }), temp->GetId()); + } + temp->SetToolTip(get_tooltip_text(temp->GetValue())); } @@ -666,7 +692,7 @@ boost::any& Choice::get_value() if (ret_enum < 0 || m_opt.enum_values.empty()) get_value_by_opt_type(ret_str); else - m_value = m_opt.enum_values[ret_enum]; + m_value = atof(m_opt.enum_values[ret_enum].c_str()); } else get_value_by_opt_type(ret_str); @@ -733,8 +759,11 @@ void PointCtrl::BUILD() temp->Add(new wxStaticText(m_parent, wxID_ANY, " y : "), 0, wxALIGN_CENTER_VERTICAL, 0); temp->Add(y_textctrl); - x_textctrl->Bind(wxEVT_TEXT, ([this](wxCommandEvent e) { on_change_field(); }), x_textctrl->GetId()); - y_textctrl->Bind(wxEVT_TEXT, ([this](wxCommandEvent e) { on_change_field(); }), y_textctrl->GetId()); +// x_textctrl->Bind(wxEVT_TEXT, ([this](wxCommandEvent e) { on_change_field(); }), x_textctrl->GetId()); +// y_textctrl->Bind(wxEVT_TEXT, ([this](wxCommandEvent e) { on_change_field(); }), y_textctrl->GetId()); + + x_textctrl->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) { OnKillFocus(e, x_textctrl); }), x_textctrl->GetId()); + y_textctrl->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) { OnKillFocus(e, x_textctrl); }), y_textctrl->GetId()); // // recast as a wxWindow to fit the calling convention sizer = dynamic_cast(temp); @@ -743,6 +772,16 @@ void PointCtrl::BUILD() y_textctrl->SetToolTip(get_tooltip_text(X+", "+Y)); } +void PointCtrl::OnKillFocus(wxEvent& e, wxTextCtrl* win) +{ + e.Skip(); + if (!win->GetValue().empty()) { + on_change_field(); + } + else + on_kill_focus(e); +} + void PointCtrl::set_value(const Vec2d& value, bool change_event) { m_disable_change_event = !change_event; diff --git a/src/slic3r/GUI/Field.hpp b/src/slic3r/GUI/Field.hpp index 0097d3ec0..4a19b6103 100644 --- a/src/slic3r/GUI/Field.hpp +++ b/src/slic3r/GUI/Field.hpp @@ -266,7 +266,6 @@ public: } boost::any& get_value() override; - bool is_defined_input_value() const ; virtual void enable(); virtual void disable(); @@ -395,6 +394,7 @@ public: void BUILD() override; + void OnKillFocus(wxEvent& e, wxTextCtrl* win); void set_value(const Vec2d& value, bool change_event = false); void set_value(const boost::any& value, bool change_event = false); boost::any& get_value() override; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 51735fe67..ab7141e91 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -484,7 +484,7 @@ Sidebar::Sidebar(Plater *parent) : wxPanel(parent), p(new priv(parent)) { p->scrolled = new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxSize(400, -1)); - p->scrolled->SetScrollbars(0, 1, 1, 1); + p->scrolled->SetScrollbars(0, 20, 1, 2); // Sizer in the scrolled area auto *scrolled_sizer = new wxBoxSizer(wxVERTICAL); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index f46ad2142..0b59a21ab 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -270,7 +270,7 @@ Slic3r::GUI::PageShp Tab::add_options_page(const wxString& title, const std::str auto panel = this; #endif PageShp page(new Page(panel, title, icon_idx)); - page->SetScrollbars(1, 1, 1, 2); + page->SetScrollbars(1, 20, 1, 2); page->Hide(); m_hsizer->Add(page.get(), 1, wxEXPAND | wxLEFT, 5); From 1dc3145e69ea522228b7ce18795f28578ab44260 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 18 Dec 2018 15:29:09 +0100 Subject: [PATCH 3/3] Suppressed selection's update if SettingsItem for the current object/part is selected --- src/slic3r/GUI/GUI_ObjectList.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index cba42470a..e7b84e289 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1399,6 +1399,20 @@ void ObjectList::update_selections() auto& selection = wxGetApp().plater()->canvas3D()->get_selection(); wxDataViewItemArray sels; + // We doesn't update selection if SettingsItem for the current object/part is selected + if (GetSelectedItemsCount() == 1 && m_objects_model->GetItemType(GetSelection()) == itSettings ) + { + const auto item = GetSelection(); + if (selection.is_single_full_object() && + m_objects_model->GetIdByItem(m_objects_model->GetParent(item)) == selection.get_object_idx()) + return; + if (selection.is_single_volume() || selection.is_modifier()) { + const auto gl_vol = selection.get_volume(*selection.get_volume_idxs().begin()); + if (m_objects_model->GetVolumeIdByItem(m_objects_model->GetParent(item)) == gl_vol->volume_idx()) + return; + } + } + if (selection.is_single_full_object()) { sels.Add(m_objects_model->GetItemById(selection.get_object_idx()));