diff --git a/xs/CMakeLists.txt b/xs/CMakeLists.txt index 75bfd43d9..45a4501d7 100644 --- a/xs/CMakeLists.txt +++ b/xs/CMakeLists.txt @@ -265,6 +265,7 @@ add_library(libslic3r_gui STATIC ${LIBDIR}/slic3r/IProgressIndicator.hpp ${LIBDIR}/slic3r/AppController.hpp ${LIBDIR}/slic3r/AppController.cpp + ${LIBDIR}/slic3r/AppControllerWx.cpp ) add_library(admesh STATIC diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 4257f3a60..e603b241f 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -1540,7 +1540,7 @@ void Print::print_to(std::string dirpath, // Save the print into the file system. set_status(0, "Writing layers to disk"); printer.save(dir); - set_status(100, "Writing layers to disk"); + set_status(100, "Writing layers completed"); } void Print::print_to_png(std::string dirpath, long width_px, long height_px, diff --git a/xs/src/slic3r/AppController.cpp b/xs/src/slic3r/AppController.cpp index 44d129f01..d95853490 100644 --- a/xs/src/slic3r/AppController.cpp +++ b/xs/src/slic3r/AppController.cpp @@ -1,28 +1,47 @@ #include "AppController.hpp" #include -#include #include #include +#include +#include -#include +//#include #include -#include #include #include #include #include -#include -#include -#include -#include -#include -#include - namespace Slic3r { +class AppControllerBoilerplate::PriMap { +public: + using M = std::unordered_map; + std::mutex m; + M store; + std::thread::id ui_thread; + + inline explicit PriMap(std::thread::id uit): ui_thread(uit) {} +}; + +AppControllerBoilerplate::AppControllerBoilerplate() + :progressind_(new PriMap(std::this_thread::get_id())) {} + +AppControllerBoilerplate::~AppControllerBoilerplate() { + progressind_.reset(); +} + +bool AppControllerBoilerplate::is_main_thread() const +{ + return progressind_->ui_thread == std::this_thread::get_id(); +} + +namespace GUI { +PresetBundle* get_preset_bundle(); +} + static const PrintObjectStep STEP_SLICE = posSlice; static const PrintObjectStep STEP_PERIMETERS = posPerimeters; static const PrintObjectStep STEP_PREPARE_INFILL = posPrepareInfill; @@ -32,119 +51,39 @@ static const PrintStep STEP_SKIRT = psSkirt; static const PrintStep STEP_BRIM = psBrim; static const PrintStep STEP_WIPE_TOWER = psWipeTower; -AppControllerBoilerplate::PathList -AppControllerBoilerplate::query_destination_paths( - const std::string &title, - const std::string &extensions) const -{ - - wxFileDialog dlg(wxTheApp->GetTopWindow(), wxString(title) ); - dlg.SetWildcard(extensions); - - dlg.ShowModal(); - - wxArrayString paths; - dlg.GetFilenames(paths); - - PathList ret(paths.size(), ""); - for(auto& p : paths) ret.push_back(p.ToStdString()); - - return ret; +void AppControllerBoilerplate::progress_indicator( + AppControllerBoilerplate::ProgresIndicatorPtr progrind) { + progressind_->m.lock(); + progressind_->store[std::this_thread::get_id()] = progrind; + progressind_->m.unlock(); } -AppControllerBoilerplate::Path -AppControllerBoilerplate::query_destination_path( - const std::string &title, - const std::string &extensions, - const std::string& hint) const +void AppControllerBoilerplate::progress_indicator(unsigned statenum, + const std::string &title, + const std::string &firstmsg) { - wxFileDialog dlg(wxTheApp->GetTopWindow(), title ); - dlg.SetWildcard(extensions); - - dlg.SetFilename(hint); - - Path ret; - - if(dlg.ShowModal() == wxID_OK) { - ret = Path(dlg.GetPath()); - - std::cout << "Filename: " << ret << std::endl; - } - - return ret; -} - -void AppControllerBoilerplate::report_issue(IssueType issuetype, - const std::string &description, - const std::string &brief) -{ - auto icon = wxICON_INFORMATION; - switch(issuetype) { - case IssueType::INFO: break; - case IssueType::WARN: icon = wxICON_WARNING; break; - case IssueType::ERR: - case IssueType::FATAL: icon = wxICON_ERROR; - } - - wxString str = _("Proba szoveg"); - wxMessageBox(str + _(description), _(brief), icon); + progressind_->m.lock(); + progressind_->store[std::this_thread::get_id()] = + create_progress_indicator(statenum, title, firstmsg);; + progressind_->m.unlock(); } AppControllerBoilerplate::ProgresIndicatorPtr -AppControllerBoilerplate::createProgressIndicator(unsigned statenum, - const std::string& title, - const std::string& firstmsg) const -{ - class GuiProgressIndicator: public IProgressIndicator { - wxProgressDialog gauge_; - using Base = IProgressIndicator; - wxString message_; - public: +AppControllerBoilerplate::progress_indicator() { - inline GuiProgressIndicator(int range, const std::string& title, - const std::string& firstmsg): - gauge_(_(title), _(firstmsg), range, wxTheApp->GetTopWindow()) - { - gauge_.Show(false); - Base::max(static_cast(range)); - Base::states(static_cast(range)); - } + PriMap::M::iterator pret; + ProgresIndicatorPtr ret; - virtual void state(float val) override { - if( val <= max() && val >= 1.0) { - Base::state(val); - gauge_.Update(static_cast(val), message_); - } - } + progressind_->m.lock(); + if( (pret = progressind_->store.find(std::this_thread::get_id())) + == progressind_->store.end()) + { + progressind_->store[std::this_thread::get_id()] = ret = + global_progressind_; + } else ret = pret->second; + progressind_->m.unlock(); - virtual void state(unsigned st) override { - if( st <= max() ) { - if(!gauge_.IsShown()) gauge_.ShowModal(); - Base::state(st); - gauge_.Update(static_cast(st), message_); - } - } - - virtual void message(const std::string & msg) override { - message_ = _(msg); - } - - virtual void message_fmt(const std::string& fmt, ...) { - va_list arglist; - va_start(arglist, fmt); - message_ = wxString::Format(_(fmt), arglist); - va_end(arglist); - } - - virtual void title(const std::string & title) override { - gauge_.SetTitle(_(title)); - } - }; - - auto pri = - std::make_shared(statenum, title, firstmsg); - - return pri; + return ret; } void PrintController::make_skirt() @@ -245,7 +184,7 @@ void PrintController::make_perimeters(PrintObject *pobj) slice(pobj); - auto&& prgind = progressIndicator(); + auto&& prgind = progress_indicator(); if (!pobj->state.is_done(STEP_PERIMETERS)) { pobj->_make_perimeters(); @@ -294,33 +233,33 @@ void PrintController::slice() { Slic3r::trace(3, "Starting the slicing process."); - progressIndicator()->update(20u, "Generating perimeters"); + progress_indicator()->update(20u, "Generating perimeters"); for(auto obj : print_->objects) make_perimeters(obj); - progressIndicator()->update(60u, "Infilling layers"); + progress_indicator()->update(60u, "Infilling layers"); for(auto obj : print_->objects) infill(obj); - progressIndicator()->update(70u, "Generating support material"); + progress_indicator()->update(70u, "Generating support material"); for(auto obj : print_->objects) gen_support_material(obj); - progressIndicator()->message_fmt("Weight: %.1fg, Cost: %.1f", + progress_indicator()->message_fmt("Weight: %.1fg, Cost: %.1f", print_->total_weight, print_->total_cost); - progressIndicator()->state(85u); + progress_indicator()->state(85u); - progressIndicator()->update(88u, "Generating skirt"); + progress_indicator()->update(88u, "Generating skirt"); make_skirt(); - progressIndicator()->update(90u, "Generating brim"); + progress_indicator()->update(90u, "Generating brim"); make_brim(); - progressIndicator()->update(95u, "Generating wipe tower"); + progress_indicator()->update(95u, "Generating wipe tower"); make_wipe_tower(); - progressIndicator()->update(100u, "Done"); + progress_indicator()->update(100u, "Done"); // time to make some statistics.. @@ -331,16 +270,6 @@ void PrintController::slice_to_png() { assert(model_ != nullptr); -// auto pri = globalProgressIndicator(); - -// pri->title("Operation"); -// pri->message("..."); - -// for(unsigned i = 1; i <= 100; i++ ) { -// pri->state(i); -// wxMilliSleep(100); -// } - auto zipfilepath = query_destination_path( "Path to zip file...", "*.zip"); @@ -361,92 +290,17 @@ void PrintController::slice_to_png() report_issue(IssueType::ERR, e.what(), "Error"); } - auto bak = progressIndicator(); - progressIndicator(100, "Slicing to zipped png files..."); - std::async(std::launch::async, [this, bak, zipfilepath](){ + std::async(std::launch::async, [this, zipfilepath]() { + progress_indicator(100, "Slicing to zipped png files..."); + progress_indicator()->procedure_count(3); slice(); auto pbak = print_->progressindicator; - print_->progressindicator = progressIndicator(); + print_->progressindicator = progress_indicator(); print_->print_to_png(zipfilepath); print_->progressindicator = pbak; - progressIndicator(bak); }); - -} - -void AppController::set_global_progress_indicator_id( - unsigned gid, - unsigned sid) -{ - - class Wrapper: public IProgressIndicator { - wxGauge *gauge_; - wxStatusBar *stbar_; - using Base = IProgressIndicator; - std::string message_; - - void showProgress(bool show = true) { - gauge_->Show(show); - gauge_->Pulse(); - } - public: - - inline Wrapper(wxGauge *gauge, wxStatusBar *stbar): - gauge_(gauge), stbar_(stbar) - { - Base::max(static_cast(gauge->GetRange())); - Base::states(static_cast(gauge->GetRange())); - } - - virtual void state(float val) override { - if( val <= max() && val >= 1.0) { - Base::state(val); - stbar_->SetStatusText(message_); - gauge_->SetValue(static_cast(val)); - } - } - - virtual void state(unsigned st) override { - if( st <= max() ) { - Base::state(st); - - if(!gauge_->IsShown()) showProgress(true); - - stbar_->SetStatusText(message_); - if(st == gauge_->GetRange()) { - gauge_->SetValue(0); - showProgress(false); - } else { - gauge_->SetValue(static_cast(st)); - } - } - } - - virtual void message(const std::string & msg) override { - message_ = msg; - } - - virtual void message_fmt(const std::string& fmt, ...) { - va_list arglist; - va_start(arglist, fmt); - message_ = wxString::Format(_(fmt), arglist); - va_end(arglist); - } - - virtual void title(const std::string & /*title*/) override {} - - }; - - wxGauge* gauge = dynamic_cast(wxWindow::FindWindowById(gid)); - wxStatusBar* sb = dynamic_cast(wxWindow::FindWindowById(sid)); - - if(gauge && sb) { - auto&& progind = std::make_shared(gauge, sb); - progressIndicator(progind); - if(printctl) printctl->progressIndicator(progind); - } } void IProgressIndicator::message_fmt( diff --git a/xs/src/slic3r/AppController.hpp b/xs/src/slic3r/AppController.hpp index 6ed6e6934..1b98560fc 100644 --- a/xs/src/slic3r/AppController.hpp +++ b/xs/src/slic3r/AppController.hpp @@ -4,6 +4,9 @@ #include #include #include +#include +#include + #include "IProgressIndicator.hpp" namespace Slic3r { @@ -13,7 +16,18 @@ class Print; class PrintObject; class AppControllerBoilerplate { + class PriMap; + public: + using ProgresIndicatorPtr = std::shared_ptr; + +private: + std::unique_ptr progressind_; + +public: + + AppControllerBoilerplate(); + ~AppControllerBoilerplate(); using Path = std::string; using PathList = std::vector; @@ -41,35 +55,24 @@ public: const std::string& description, const std::string& brief = ""); - using ProgresIndicatorPtr = std::shared_ptr; + void progress_indicator(ProgresIndicatorPtr progrind); - - inline void progressIndicator(ProgresIndicatorPtr progrind) { - progressind_ = progrind; - } - - inline void progressIndicator(unsigned statenum, + void progress_indicator(unsigned statenum, const std::string& title, - const std::string& firstmsg = "") { - progressind_ = createProgressIndicator(statenum, title, firstmsg); - } + const std::string& firstmsg = ""); - inline ProgresIndicatorPtr progressIndicator() { - if(!progressind_) - progressind_ = createProgressIndicator(100, "Progress"); - - return progressind_; - } + ProgresIndicatorPtr progress_indicator(); protected: - ProgresIndicatorPtr createProgressIndicator( + ProgresIndicatorPtr create_progress_indicator( unsigned statenum, const std::string& title, const std::string& firstmsg = "") const; -private: - ProgresIndicatorPtr progressind_; + bool is_main_thread() const; + + ProgresIndicatorPtr global_progressind_; }; class PrintController: public AppControllerBoilerplate { @@ -80,6 +83,10 @@ protected: void make_brim(); void make_wipe_tower(); + void make_perimeters(PrintObject *pobj); + void infill(PrintObject *pobj); + void gen_support_material(PrintObject *pobj); + public: using Ptr = std::unique_ptr; @@ -91,13 +98,9 @@ public: } void slice(PrintObject *pobj); - void make_perimeters(PrintObject *pobj); - void infill(PrintObject *pobj); - void gen_support_material(PrintObject *pobj); void slice(); void slice_to_png(); - }; class AppController: protected AppControllerBoilerplate { @@ -111,7 +114,7 @@ public: void set_print(Print *print) { printctl = PrintController::create(print); - printctl->progressIndicator(progressIndicator()); + printctl->progress_indicator(progress_indicator()); } void set_global_progress_indicator_id(unsigned gauge_id, diff --git a/xs/src/slic3r/appcontrollerwx.cpp b/xs/src/slic3r/appcontrollerwx.cpp new file mode 100644 index 000000000..2dd37a831 --- /dev/null +++ b/xs/src/slic3r/appcontrollerwx.cpp @@ -0,0 +1,314 @@ +#include "AppController.hpp" + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace Slic3r { + +AppControllerBoilerplate::PathList +AppControllerBoilerplate::query_destination_paths( + const std::string &title, + const std::string &extensions) const +{ + + wxFileDialog dlg(wxTheApp->GetTopWindow(), wxString(title) ); + dlg.SetWildcard(extensions); + + dlg.ShowModal(); + + wxArrayString paths; + dlg.GetPaths(paths); + + PathList ret(paths.size(), ""); + for(auto& p : paths) ret.push_back(p.ToStdString()); + + return ret; +} + +AppControllerBoilerplate::Path +AppControllerBoilerplate::query_destination_path( + const std::string &title, + const std::string &extensions, + const std::string& hint) const +{ + wxFileDialog dlg(wxTheApp->GetTopWindow(), title ); + dlg.SetWildcard(extensions); + + dlg.SetFilename(hint); + + Path ret; + + if(dlg.ShowModal() == wxID_OK) { + ret = Path(dlg.GetPath()); + } + + return ret; +} + +void AppControllerBoilerplate::report_issue(IssueType issuetype, + const std::string &description, + const std::string &brief) +{ + auto icon = wxICON_INFORMATION; + switch(issuetype) { + case IssueType::INFO: break; + case IssueType::WARN: icon = wxICON_WARNING; break; + case IssueType::ERR: + case IssueType::FATAL: icon = wxICON_ERROR; + } + + wxString str = _("Proba szoveg"); + wxMessageBox(str + _(description), _(brief), icon); +} + +wxDEFINE_EVENT(PROGRESS_STATUS_UPDATE_EVENT, wxCommandEvent); + +namespace { +class GuiProgressIndicator: + public IProgressIndicator, public wxEvtHandler { + + std::shared_ptr gauge_; + using Base = IProgressIndicator; + wxString message_; + int range_; wxString title_; + unsigned prc_ = 0; + bool is_asynch_ = false; + + // status update handler + void _state( wxCommandEvent& evt) { + unsigned st = evt.GetInt(); + _state(st); + } + + void _state( unsigned st) { + if(st < max()) { + if(!gauge_) gauge_ = std::make_shared( + title_, message_, range_, wxTheApp->GetTopWindow(), + wxPD_APP_MODAL | wxPD_AUTO_HIDE + ); + + if(!gauge_->IsShown()) gauge_->ShowModal(); + Base::state(st); + gauge_->Update(static_cast(st), message_); + } + + if(st == max()) { + prc_++; + if(prc_ == Base::procedure_count()) { + gauge_.reset(); + prc_ = 0; + } + } + } + +public: + + inline void asynch(bool is) { is_asynch_ = is; } + inline bool asynch() const { return is_asynch_; } + + inline GuiProgressIndicator(int range, const std::string& title, + const std::string& firstmsg) : + range_(range), message_(_(firstmsg)), title_(_(title)) + { + Base::max(static_cast(range)); + Base::states(static_cast(range)); + + Bind(PROGRESS_STATUS_UPDATE_EVENT, + &GuiProgressIndicator::_state, + this); + } + + virtual void state(float val) override { + if( val >= 1.0) state(static_cast(val)); + } + + virtual void state(unsigned st) override { + // send status update event + if(is_asynch_) { + auto evt = new wxCommandEvent(PROGRESS_STATUS_UPDATE_EVENT); + evt->SetInt(st); + wxQueueEvent(this, evt); + } else _state(st); + } + + virtual void message(const std::string & msg) override { + message_ = _(msg); + } + + virtual void messageFmt(const std::string& fmt, ...) { + va_list arglist; + va_start(arglist, fmt); + message_ = wxString::Format(_(fmt), arglist); + va_end(arglist); + } + + virtual void title(const std::string & title) override { + title_ = _(title); + } +}; +} + +AppControllerBoilerplate::ProgresIndicatorPtr +AppControllerBoilerplate::create_progress_indicator( + unsigned statenum, const std::string& title, + const std::string& firstmsg) const +{ + auto pri = + std::make_shared(statenum, title, firstmsg); + + pri->asynch(!is_main_thread()); + + return pri; +} + +//AppControllerBoilerplate::ProgresIndicatorPtr +//AppControllerBoilerplate::create_progress_indicator(unsigned statenum, +// const std::string& title, +// const std::string& firstmsg) const +//{ +// class GuiProgressIndicator: public IProgressIndicator, public wxEvtHandler { +// using Base = IProgressIndicator; +// wxString message_, title_; +// wxProgressDialog gauge_; + +// void _state( wxCommandEvent& evt) { +// unsigned st = evt.GetInt(); + +// if(title_.compare(gauge_.GetTitle())) +// gauge_.SetTitle(title_); + +// if(!gauge_.IsShown()) gauge_.ShowModal(); +// Base::state(st); +// gauge_.Update(static_cast(st), message_); + +// } +// public: + +// inline GuiProgressIndicator(int range, const std::string& title, +// const std::string& firstmsg): +// message_(_(firstmsg)), title_(_(title)), +// gauge_(title_, message_, range, wxTheApp->GetTopWindow()) +// { +// gauge_.Show(false); + +// Base::max(static_cast(range)); +// Base::states(static_cast(range)); + +// Bind(PROGRESS_STATUS_UPDATE_EVENT, +// &GuiProgressIndicator::_state, +// this); +// } + +// virtual void state(float val) override { +// if( val >= 1.0) state(static_cast(val)); +// } + +// virtual void state(unsigned st) override { +// // send status update event +// auto evt = new wxCommandEvent(PROGRESS_STATUS_UPDATE_EVENT); +// evt->SetInt(st); +// wxQueueEvent(this, evt); +// } + +// virtual void message(const std::string & msg) override { +// message_ = _(msg); +// } + +// virtual void message_fmt(const std::string& fmt, ...) override { +// va_list arglist; +// va_start(arglist, fmt); +// message_ = wxString::Format(_(fmt), arglist); +// va_end(arglist); +// } + +// virtual void title(const std::string & title) override { +// title_ = _(title); +// } +// }; + +// auto pri = +// std::make_shared(statenum, title, firstmsg); + +// return pri; +//} + +void AppController::set_global_progress_indicator_id( + unsigned gid, + unsigned sid) +{ + + class Wrapper: public IProgressIndicator { + wxGauge *gauge_; + wxStatusBar *stbar_; + using Base = IProgressIndicator; + std::string message_; + + void showProgress(bool show = true) { + gauge_->Show(show); + gauge_->Pulse(); + } + + public: + + inline Wrapper(wxGauge *gauge, wxStatusBar *stbar): + gauge_(gauge), stbar_(stbar) + { + Base::max(static_cast(gauge->GetRange())); + Base::states(static_cast(gauge->GetRange())); + } + + virtual void state(float val) override { + if( val <= max() && val >= 1.0) { + Base::state(val); + stbar_->SetStatusText(message_); + gauge_->SetValue(static_cast(val)); + } + } + + virtual void state(unsigned st) override { + if( st <= max() ) { + Base::state(st); + + if(!gauge_->IsShown()) showProgress(true); + + stbar_->SetStatusText(message_); + if(st == gauge_->GetRange()) { + gauge_->SetValue(0); + showProgress(false); + } else { + gauge_->SetValue(static_cast(st)); + } + } + } + + virtual void message(const std::string & msg) override { + message_ = msg; + } + + virtual void message_fmt(const std::string& fmt, ...) override { + va_list arglist; + va_start(arglist, fmt); + message_ = wxString::Format(_(fmt), arglist); + va_end(arglist); + } + + virtual void title(const std::string & /*title*/) override {} + + }; + + wxGauge* gauge = dynamic_cast(wxWindow::FindWindowById(gid)); + wxStatusBar* sb = dynamic_cast(wxWindow::FindWindowById(sid)); + + if(gauge && sb) { + global_progressind_ = std::make_shared(gauge, sb); + } +} + +} diff --git a/xs/src/slic3r/iprogressindicator.hpp b/xs/src/slic3r/iprogressindicator.hpp index eef0cfb4e..d71c50653 100644 --- a/xs/src/slic3r/iprogressindicator.hpp +++ b/xs/src/slic3r/iprogressindicator.hpp @@ -13,7 +13,7 @@ public: private: float state_ = .0f, max_ = 1.f, step_; std::function cancelfunc_ = [](){}; - + unsigned proc_count_ = 1; public: inline virtual ~IProgressIndicator() {} @@ -36,6 +36,9 @@ public: inline void on_cancel(CancelFn func) { cancelfunc_ = func; } inline void on_cancel() { cancelfunc_(); } + inline void procedure_count(unsigned pc) { proc_count_ = pc; } + inline unsigned procedure_count() const { return proc_count_; } + template void update(T st, const std::string& msg) { message(msg); state(st); }