From 9e2d48ff3b5ad09a65b8039ed9cd6bd9d40db488 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Wed, 29 Aug 2018 18:02:10 +0200 Subject: [PATCH 1/3] Almost working c++ status bar Signed-off-by: tamasmeszaros --- lib/Slic3r/GUI/MainFrame.pm | 9 +- lib/Slic3r/GUI/ProgressStatusBar.pm | 232 +++++++++--------- xs/CMakeLists.txt | 5 +- xs/src/perlglue.cpp | 1 + xs/src/slic3r/AppController.cpp | 64 +++-- xs/src/slic3r/AppController.hpp | 4 +- xs/src/slic3r/AppControllerWx.cpp | 14 +- xs/src/slic3r/GUI/ProgressStatusBar.cpp | 156 ++++++++++++ xs/src/slic3r/GUI/ProgressStatusBar.hpp | 61 +++++ ...essIndicator.hpp => ProgressIndicator.hpp} | 4 +- xs/xsp/ProgressStatusBar.xsp | 41 ++++ xs/xsp/my.map | 6 +- xs/xsp/typemap.xspt | 1 + 13 files changed, 442 insertions(+), 156 deletions(-) create mode 100644 xs/src/slic3r/GUI/ProgressStatusBar.cpp create mode 100644 xs/src/slic3r/GUI/ProgressStatusBar.hpp rename xs/src/slic3r/{IProgressIndicator.hpp => ProgressIndicator.hpp} (96%) create mode 100644 xs/xsp/ProgressStatusBar.xsp diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index 6baefa545..6b932f92f 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -62,13 +62,14 @@ sub new { eval { Wx::ToolTip::SetAutoPop(32767) }; # initialize status bar - $self->{statusbar} = Slic3r::GUI::ProgressStatusBar->new($self, Wx::NewId); + $self->{statusbar} = Slic3r::GUI::ProgressStatusBar->new(); + # $self->{statusbar}->SetParent($self, Wx::NewId); + $self->{statusbar}->Embed; $self->{statusbar}->SetStatusText(L("Version ").$Slic3r::VERSION.L(" - Remember to check for updates at http://github.com/prusa3d/slic3r/releases")); - $self->SetStatusBar($self->{statusbar}); - + # Make the global status bar and its progress indicator available in C++ $appController->set_global_progress_indicator( - $self->{statusbar}->{prog}->GetId(), + $self->{statusbar}->GetProgId(), $self->{statusbar}->GetId(), ); diff --git a/lib/Slic3r/GUI/ProgressStatusBar.pm b/lib/Slic3r/GUI/ProgressStatusBar.pm index 32fd52680..a696feb7f 100644 --- a/lib/Slic3r/GUI/ProgressStatusBar.pm +++ b/lib/Slic3r/GUI/ProgressStatusBar.pm @@ -4,141 +4,143 @@ package Slic3r::GUI::ProgressStatusBar; use strict; use warnings; -use Wx qw(:gauge :misc); -use base 'Wx::StatusBar'; +# use Wx qw(:gauge :misc); +# use base 'Wx::StatusBar'; -sub new { - my $class = shift; - my $self = $class->SUPER::new(@_); - - $self->{busy} = 0; - $self->{timer} = Wx::Timer->new($self); - $self->{prog} = Wx::Gauge->new($self, wxGA_HORIZONTAL, 100, wxDefaultPosition, wxDefaultSize); - $self->{prog}->Hide; - $self->{cancelbutton} = Wx::Button->new($self, -1, "Cancel", wxDefaultPosition, wxDefaultSize); - $self->{cancelbutton}->Hide; - - $self->SetFieldsCount(3); - $self->SetStatusWidths(-1, 150, 155); - - Wx::Event::EVT_TIMER($self, \&OnTimer, $self->{timer}); - Wx::Event::EVT_SIZE($self, \&OnSize); - Wx::Event::EVT_BUTTON($self, $self->{cancelbutton}, sub { - $self->{cancel_cb}->(); - $self->{cancelbutton}->Hide; - }); - - return $self; -} +our $cancel_cb; -sub DESTROY { - my $self = shift; - $self->{timer}->Stop if $self->{timer} && $self->{timer}->IsRunning; -} - -sub OnSize { - my ($self, $event) = @_; +# sub new { +# my $class = shift; +# my $self = $class->SUPER::new(@_); - my %fields = ( - # 0 is reserved for status text - 1 => $self->{cancelbutton}, - 2 => $self->{prog}, - ); - - foreach (keys %fields) { - my $rect = $self->GetFieldRect($_); - my $offset = &Wx::wxGTK ? 1 : 0; # add a cosmetic 1 pixel offset on wxGTK - my $pos = [$rect->GetX + $offset, $rect->GetY + $offset]; - $fields{$_}->Move($pos); - $fields{$_}->SetSize($rect->GetWidth - $offset, $rect->GetHeight); - } - - $event->Skip; -} - -sub OnTimer { - my ($self, $event) = @_; +# $self->{busy} = 0; +# $self->{timer} = Wx::Timer->new($self); +# $self->{prog} = Wx::Gauge->new($self, wxGA_HORIZONTAL, 100, wxDefaultPosition, wxDefaultSize); +# $self->{prog}->Hide; +# $self->{cancelbutton} = Wx::Button->new($self, -1, "Cancel", wxDefaultPosition, wxDefaultSize); +# $self->{cancelbutton}->Hide; - if ($self->{prog}->IsShown) { - $self->{timer}->Stop; - } - $self->{prog}->Pulse if $self->{_busy}; -} +# $self->SetFieldsCount(3); +# $self->SetStatusWidths(-1, 150, 155); + +# Wx::Event::EVT_TIMER($self, \&OnTimer, $self->{timer}); +# Wx::Event::EVT_SIZE($self, \&OnSize); +# Wx::Event::EVT_BUTTON($self, $self->{cancelbutton}, sub { +# $self->{cancel_cb}->(); +# $self->{cancelbutton}->Hide; +# }); + +# return $self; +# } + +# sub DESTROY { +# my $self = shift; +# $self->{timer}->Stop if $self->{timer} && $self->{timer}->IsRunning; +# } + +# sub OnSize { +# my ($self, $event) = @_; + +# my %fields = ( +# # 0 is reserved for status text +# 1 => $self->{cancelbutton}, +# 2 => $self->{prog}, +# ); + +# foreach (keys %fields) { +# my $rect = $self->GetFieldRect($_); +# my $offset = &Wx::wxGTK ? 1 : 0; # add a cosmetic 1 pixel offset on wxGTK +# my $pos = [$rect->GetX + $offset, $rect->GetY + $offset]; +# $fields{$_}->Move($pos); +# $fields{$_}->SetSize($rect->GetWidth - $offset, $rect->GetHeight); +# } + +# $event->Skip; +# } + +# sub OnTimer { +# my ($self, $event) = @_; + +# if ($self->{prog}->IsShown) { +# $self->{timer}->Stop; +# } +# $self->{prog}->Pulse if $self->{_busy}; +# } sub SetCancelCallback { my $self = shift; my ($cb) = @_; - $self->{cancel_cb} = $cb; - $cb ? $self->{cancelbutton}->Show : $self->{cancelbutton}->Hide; + $cancel_cb = $cb; + # $cb ? $self->{cancelbutton}->Show : $self->{cancelbutton}->Hide; } -sub Run { - my $self = shift; - my $rate = shift || 100; - if (!$self->{timer}->IsRunning) { - $self->{timer}->Start($rate); - } -} +# sub Run { +# my $self = shift; +# my $rate = shift || 100; +# if (!$self->{timer}->IsRunning) { +# $self->{timer}->Start($rate); +# } +# } -sub GetProgress { - my $self = shift; - return $self->{prog}->GetValue; -} +# sub GetProgress { +# my $self = shift; +# return $self->{prog}->GetValue; +# } -sub SetProgress { - my $self = shift; - my ($val) = @_; - if (!$self->{prog}->IsShown) { - $self->ShowProgress(1); - } - if ($val == $self->{prog}->GetRange) { - $self->{prog}->SetValue(0); - $self->ShowProgress(0); - } else { - $self->{prog}->SetValue($val); - } -} +# sub SetProgress { +# my $self = shift; +# my ($val) = @_; +# if (!$self->{prog}->IsShown) { +# $self->ShowProgress(1); +# } +# if ($val == $self->{prog}->GetRange) { +# $self->{prog}->SetValue(0); +# $self->ShowProgress(0); +# } else { +# $self->{prog}->SetValue($val); +# } +# } -sub SetRange { - my $self = shift; - my ($val) = @_; +# sub SetRange { +# my $self = shift; +# my ($val) = @_; - if ($val != $self->{prog}->GetRange) { - $self->{prog}->SetRange($val); - } -} +# if ($val != $self->{prog}->GetRange) { +# $self->{prog}->SetRange($val); +# } +# } -sub ShowProgress { - my $self = shift; - my ($show) = @_; +# sub ShowProgress { +# my $self = shift; +# my ($show) = @_; - $self->{prog}->Show($show); - $self->{prog}->Pulse; -} +# $self->{prog}->Show($show); +# $self->{prog}->Pulse; +# } -sub StartBusy { - my $self = shift; - my $rate = shift || 100; +# sub StartBusy { +# my $self = shift; +# my $rate = shift || 100; - $self->{_busy} = 1; - $self->ShowProgress(1); - if (!$self->{timer}->IsRunning) { - $self->{timer}->Start($rate); - } -} +# $self->{_busy} = 1; +# $self->ShowProgress(1); +# if (!$self->{timer}->IsRunning) { +# $self->{timer}->Start($rate); +# } +# } -sub StopBusy { - my $self = shift; +# sub StopBusy { +# my $self = shift; - $self->{timer}->Stop; - $self->ShowProgress(0); - $self->{prog}->SetValue(0); - $self->{_busy} = 0; -} +# $self->{timer}->Stop; +# $self->ShowProgress(0); +# $self->{prog}->SetValue(0); +# $self->{_busy} = 0; +# } -sub IsBusy { - my $self = shift; - return $self->{_busy}; -} +# sub IsBusy { +# my $self = shift; +# return $self->{_busy}; +# } 1; diff --git a/xs/CMakeLists.txt b/xs/CMakeLists.txt index 0ab4648eb..2ebcb2d45 100644 --- a/xs/CMakeLists.txt +++ b/xs/CMakeLists.txt @@ -247,6 +247,8 @@ add_library(libslic3r_gui STATIC ${LIBDIR}/slic3r/GUI/UpdateDialogs.hpp ${LIBDIR}/slic3r/GUI/FirmwareDialog.cpp ${LIBDIR}/slic3r/GUI/FirmwareDialog.hpp + ${LIBDIR}/slic3r/GUI/ProgressStatusBar.hpp + ${LIBDIR}/slic3r/GUI/ProgressStatusBar.cpp ${LIBDIR}/slic3r/Utils/Http.cpp ${LIBDIR}/slic3r/Utils/Http.hpp ${LIBDIR}/slic3r/Utils/FixModelByWin10.cpp @@ -267,7 +269,7 @@ add_library(libslic3r_gui STATIC ${LIBDIR}/slic3r/Utils/Time.hpp ${LIBDIR}/slic3r/Utils/HexFile.cpp ${LIBDIR}/slic3r/Utils/HexFile.hpp - ${LIBDIR}/slic3r/IProgressIndicator.hpp + ${LIBDIR}/slic3r/ProgressIndicator.hpp ${LIBDIR}/slic3r/AppController.hpp ${LIBDIR}/slic3r/AppController.cpp ${LIBDIR}/slic3r/AppControllerWx.cpp @@ -420,6 +422,7 @@ set(XS_XSP_FILES ${XSP_DIR}/Utils_PrintHost.xsp ${XSP_DIR}/Utils_PresetUpdater.xsp ${XSP_DIR}/AppController.xsp + ${XSP_DIR}/ProgressStatusBar.xsp ${XSP_DIR}/XS.xsp ) foreach (file ${XS_XSP_FILES}) diff --git a/xs/src/perlglue.cpp b/xs/src/perlglue.cpp index d6bd0e94c..f0c0f4f7e 100644 --- a/xs/src/perlglue.cpp +++ b/xs/src/perlglue.cpp @@ -63,6 +63,7 @@ REGISTER_CLASS(Preset, "GUI::Preset"); REGISTER_CLASS(PresetCollection, "GUI::PresetCollection"); REGISTER_CLASS(PresetBundle, "GUI::PresetBundle"); REGISTER_CLASS(TabIface, "GUI::Tab"); +REGISTER_CLASS(ProgressStatusBar, "GUI::ProgressStatusBar"); REGISTER_CLASS(PresetUpdater, "PresetUpdater"); REGISTER_CLASS(AppController, "AppController"); REGISTER_CLASS(PrintController, "PrintController"); diff --git a/xs/src/slic3r/AppController.cpp b/xs/src/slic3r/AppController.cpp index 58858f5fc..2f1e9a148 100644 --- a/xs/src/slic3r/AppController.cpp +++ b/xs/src/slic3r/AppController.cpp @@ -290,26 +290,22 @@ const PrintConfig &PrintController::config() const void AppController::arrange_model() { - auto ftr = std::async( - supports_asynch()? std::launch::async : std::launch::deferred, - [this]() - { - using Coord = libnest2d::TCoord; + using Coord = libnest2d::TCoord; - unsigned count = 0; - for(auto obj : model_->objects) count += obj->instances.size(); + unsigned count = 0; + for(auto obj : model_->objects) count += obj->instances.size(); - auto pind = global_progress_indicator(); + auto pind = global_progress_indicator(); - float pmax = 1.0; + float pmax = 1.0; - if(pind) { - pmax = pind->max(); + if(pind) { + pmax = pind->max(); - // Set the range of the progress to the object count - pind->max(count); + // Set the range of the progress to the object count + pind->max(count); - } + } auto dist = print_ctl()->config().min_object_distance(); @@ -341,16 +337,38 @@ void AppController::arrange_model() _(L("Exception occurred"))); } - // Restore previous max value - if(pind) { - pind->max(pmax); - pind->update(0, _(L("Arranging done."))); - } - }); + // Create the arranger config + auto min_obj_distance = static_cast(dist/SCALING_FACTOR); - while( ftr.wait_for(std::chrono::milliseconds(10)) - != std::future_status::ready) { - process_events(); + auto& bedpoints = print_ctl()->config().bed_shape.values; + Polyline bed; bed.points.reserve(bedpoints.size()); + for(auto& v : bedpoints) + bed.append(Point::new_scale(v(0), v(1))); + + if(pind) pind->update(0, _(L("Arranging objects..."))); + + try { + arr::arrange(*model_, + min_obj_distance, + bed, + arr::BOX, + false, // create many piles not just one pile + [pind, count](unsigned rem) { + if(pind) + pind->update(count - rem, _(L("Arranging objects..."))); + }); + } catch(std::exception& e) { + std::cerr << e.what() << std::endl; + report_issue(IssueType::ERR, + _(L("Could not arrange model objects! " + "Some geometries may be invalid.")), + _(L("Exception occurred"))); + } + + // Restore previous max value + if(pind) { + pind->max(pmax); + pind->update(0, _(L("Arranging done."))); } } diff --git a/xs/src/slic3r/AppController.hpp b/xs/src/slic3r/AppController.hpp index e9252b50c..58681a7de 100644 --- a/xs/src/slic3r/AppController.hpp +++ b/xs/src/slic3r/AppController.hpp @@ -7,7 +7,7 @@ #include #include -#include "IProgressIndicator.hpp" +#include "ProgressIndicator.hpp" namespace Slic3r { @@ -33,7 +33,7 @@ class AppControllerBoilerplate { public: /// A Progress indicator object smart pointer - using ProgresIndicatorPtr = std::shared_ptr; + using ProgresIndicatorPtr = std::shared_ptr; private: class PriData; // Some structure to store progress indication data diff --git a/xs/src/slic3r/AppControllerWx.cpp b/xs/src/slic3r/AppControllerWx.cpp index 4e116c7b9..64d783356 100644 --- a/xs/src/slic3r/AppControllerWx.cpp +++ b/xs/src/slic3r/AppControllerWx.cpp @@ -104,10 +104,10 @@ namespace { * the main thread as well. */ class GuiProgressIndicator: - public IProgressIndicator, public wxEvtHandler { + public ProgressIndicator, public wxEvtHandler { wxProgressDialog gauge_; - using Base = IProgressIndicator; + using Base = ProgressIndicator; wxString message_; int range_; wxString title_; bool is_asynch_ = false; @@ -153,7 +153,7 @@ public: virtual void cancel() override { update(max(), "Abort"); - IProgressIndicator::cancel(); + ProgressIndicator::cancel(); } virtual void state(float val) override { @@ -211,10 +211,10 @@ AppControllerBoilerplate::create_progress_indicator(unsigned statenum, namespace { // A wrapper progress indicator class around the statusbar created in perl. -class Wrapper: public IProgressIndicator, public wxEvtHandler { +class Wrapper: public ProgressIndicator, public wxEvtHandler { wxGauge *gauge_; wxStatusBar *stbar_; - using Base = IProgressIndicator; + using Base = ProgressIndicator; std::string message_; AppControllerBoilerplate& ctl_; @@ -223,7 +223,7 @@ class Wrapper: public IProgressIndicator, public wxEvtHandler { } void _state(unsigned st) { - if( st <= IProgressIndicator::max() ) { + if( st <= ProgressIndicator::max() ) { Base::state(st); if(!gauge_->IsShown()) showProgress(true); @@ -266,7 +266,7 @@ public: virtual void max(float val) override { if(val > 1.0) { gauge_->SetRange(static_cast(val)); - IProgressIndicator::max(val); + ProgressIndicator::max(val); } } diff --git a/xs/src/slic3r/GUI/ProgressStatusBar.cpp b/xs/src/slic3r/GUI/ProgressStatusBar.cpp new file mode 100644 index 000000000..13ca8cd81 --- /dev/null +++ b/xs/src/slic3r/GUI/ProgressStatusBar.cpp @@ -0,0 +1,156 @@ +#include "ProgressStatusBar.hpp" + +#include +#include +#include +#include +#include + +#include "GUI.hpp" + +#include + +namespace Slic3r { + +ProgressStatusBar::ProgressStatusBar(wxWindow *parent, int id): + self(new wxStatusBar(parent ? parent : GUI::get_main_frame(), + id == -1? wxID_ANY : id)), + timer_(new wxTimer(self)), + prog_ (new wxGauge(self, + wxGA_HORIZONTAL, + 100, + wxDefaultPosition, + wxDefaultSize)), + cancelbutton_(new wxButton(self, + -1, + "Cancel", + wxDefaultPosition, + wxDefaultSize)) +{ + prog_->Hide(); + cancelbutton_->Hide(); + + + self->SetFieldsCount(3); + int w[] = {-1, 150, 155}; + self->SetStatusWidths(3, w); + + self->Bind(wxEVT_TIMER, [this](const wxTimerEvent&) { + if (prog_->IsShown()) timer_->Stop(); + if(is_busy()) prog_->Pulse(); + }); + + self->Bind(wxEVT_SIZE, [this](wxSizeEvent& event){ + wxRect rect; + self->GetFieldRect(1, rect); + auto offset = 0; + cancelbutton_->Move(rect.GetX() + offset, rect.GetY() + offset); + cancelbutton_->SetSize(rect.GetWidth() - offset, rect.GetHeight()); + + self->GetFieldRect(2, rect); + prog_->Move(rect.GetX() + offset, rect.GetY() + offset); + prog_->SetSize(rect.GetWidth() - offset, rect.GetHeight()); + + event.Skip(); + }); + + cancelbutton_->Bind(wxEVT_BUTTON, [this](const wxCommandEvent&) { + if(cancel_cb_) cancel_cb_(); + cancelbutton_->Hide(); + }); +} + +//ProgressStatusBar::ProgressStatusBar(): ProgressStatusBar(nullptr, wxID_ANY) +//{ + +//} + +ProgressStatusBar::~ProgressStatusBar() { + if(timer_->IsRunning()) timer_->Stop(); +} + +int ProgressStatusBar::get_progress() const +{ + return prog_->GetValue(); +} + +void ProgressStatusBar::set_progress(int val) +{ + if(!prog_->IsShown()) show_progress(true); + + if(val == prog_->GetRange()) { + prog_->SetValue(0); + show_progress(false); + } else { + prog_->SetValue(val); + } +} + +void ProgressStatusBar::set_range(int val) +{ + if(val != prog_->GetRange()) { + prog_->SetRange(val); + } +} + +void ProgressStatusBar::show_progress(bool show) +{ + prog_->Show(show); + prog_->Pulse(); +} + +void ProgressStatusBar::start_busy(int rate) +{ + busy_ = true; + show_progress(true); + if (!timer_->IsRunning()) { + timer_->Start(rate); + } +} + +void ProgressStatusBar::stop_busy() +{ + timer_->Stop(); + show_progress(false); + prog_->SetValue(0); + busy_ = false; +} + +void ProgressStatusBar::set_cancel_callback(ProgressStatusBar::CancelFn ccb) { + cancel_cb_ = ccb; + if(ccb) cancelbutton_->Show(); + else cancelbutton_->Hide(); +} + +void ProgressStatusBar::run(int rate) +{ + if(!timer_->IsRunning()) { + timer_->Start(rate); + } +} + +void ProgressStatusBar::Embed() +{ + std::cout << "Embedding" << std::endl; + wxFrame* mf = GUI::get_main_frame(); + std::cout << mf->GetName() << std::endl; + std::cout << self->GetName() << std::endl; + mf->SetStatusBar(self); +} + +void ProgressStatusBar::SetStatusText(std::string txt) +{ + self->SetStatusText(txt); +} + +int ProgressStatusBar::GetId() +{ + return self->GetId(); +} + +int ProgressStatusBar::GetProgId() +{ + return prog_->GetId(); +} + +} diff --git a/xs/src/slic3r/GUI/ProgressStatusBar.hpp b/xs/src/slic3r/GUI/ProgressStatusBar.hpp new file mode 100644 index 000000000..53366aace --- /dev/null +++ b/xs/src/slic3r/GUI/ProgressStatusBar.hpp @@ -0,0 +1,61 @@ +#ifndef PROGRESSSTATUSBAR_HPP +#define PROGRESSSTATUSBAR_HPP + +#include +#include + +class wxTimer; +class wxGauge; +class wxButton; +class wxTimerEvent; +class wxStatusBar; +class wxWindow; + +namespace Slic3r { + +/** + * @brief The ProgressStatusBar class is the widgets occupying the lower area + * of the Slicer main window. It consists of a message area to the left and a + * progress indication area to the right with an optional cancel button. + */ +class ProgressStatusBar { + wxStatusBar *self; // we cheat! It should be the base class but: perl! + wxTimer *timer_; + wxGauge *prog_; + wxButton *cancelbutton_; +public: + + /// Cancel callback function type + using CancelFn = std::function; + + ProgressStatusBar(wxWindow *parent = nullptr, int id = -1); + ~ProgressStatusBar(); + + int get_progress() const; + void set_progress(int); + void set_range(int = 100); + void show_progress(bool); + void start_busy(int = 100); + void stop_busy(); + inline bool is_busy() const { return busy_; } + void set_cancel_callback(CancelFn); + void run(int rate); + + // Temporary methods to satisfy Perl side + void Embed(); + void SetStatusText(std::string txt); + int GetId(); + int GetProgId(); + +private: + bool busy_ = false; + CancelFn cancel_cb_; +}; + +namespace GUI { + using Slic3r::ProgressStatusBar; +} + +} + +#endif // PROGRESSSTATUSBAR_HPP diff --git a/xs/src/slic3r/IProgressIndicator.hpp b/xs/src/slic3r/ProgressIndicator.hpp similarity index 96% rename from xs/src/slic3r/IProgressIndicator.hpp rename to xs/src/slic3r/ProgressIndicator.hpp index 704931574..49d0c251c 100644 --- a/xs/src/slic3r/IProgressIndicator.hpp +++ b/xs/src/slic3r/ProgressIndicator.hpp @@ -10,7 +10,7 @@ namespace Slic3r { /** * @brief Generic progress indication interface. */ -class IProgressIndicator { +class ProgressIndicator { public: using CancelFn = std::function; // Cancel functio signature. @@ -20,7 +20,7 @@ private: public: - inline virtual ~IProgressIndicator() {} + inline virtual ~ProgressIndicator() {} /// Get the maximum of the progress range. float max() const { return max_; } diff --git a/xs/xsp/ProgressStatusBar.xsp b/xs/xsp/ProgressStatusBar.xsp new file mode 100644 index 000000000..3b9be3ba8 --- /dev/null +++ b/xs/xsp/ProgressStatusBar.xsp @@ -0,0 +1,41 @@ +%module{Slic3r::XS}; + +%{ +#include +#include "slic3r/GUI/ProgressStatusBar.hpp" +%} + +%name{Slic3r::GUI::ProgressStatusBar} class ProgressStatusBar { + ProgressStatusBar(); + ~ProgressStatusBar(); + + int GetProgress() const + %code%{ RETVAL=THIS->get_progress(); %}; + + void SetProgress(int val) + %code%{ THIS->set_progress(val); %}; + + void SetRange(int val = 100) + %code%{ THIS->set_range(val); %}; + + void ShowProgress(bool show) + %code%{ THIS->show_progress(show); %}; + + void StartBusy(int val = 100) + %code%{ THIS->start_busy(val); %}; + + void StopBusy() + %code%{ THIS->stop_busy(); %}; + + bool IsBusy() const + %code%{ RETVAL=THIS->is_busy(); %}; + + void Run(int rate) + %code%{ THIS->run(rate); %}; + + void Embed(); + void SetStatusText(std::string txt); + int GetId(); + int GetProgId(); + +}; \ No newline at end of file diff --git a/xs/xsp/my.map b/xs/xsp/my.map index ba20ee236..e92db3346 100644 --- a/xs/xsp/my.map +++ b/xs/xsp/my.map @@ -233,8 +233,10 @@ PresetCollection* O_OBJECT_SLIC3R Ref O_OBJECT_SLIC3R_T PresetBundle* O_OBJECT_SLIC3R Ref O_OBJECT_SLIC3R_T -TabIface* O_OBJECT_SLIC3R -Ref O_OBJECT_SLIC3R_T +TabIface* O_OBJECT_SLIC3R +Ref O_OBJECT_SLIC3R_T +ProgressStatusBar* O_OBJECT_SLIC3R +Ref O_OBJECT_SLIC3R_T PresetUpdater* O_OBJECT_SLIC3R Ref O_OBJECT_SLIC3R_T diff --git a/xs/xsp/typemap.xspt b/xs/xsp/typemap.xspt index cee75fe26..1654bf3b0 100644 --- a/xs/xsp/typemap.xspt +++ b/xs/xsp/typemap.xspt @@ -213,6 +213,7 @@ %typemap{PresetHints*}; %typemap{Ref}{simple}; %typemap{TabIface*}; +%typemap{ProgressStatusBar*}; %typemap{PrintRegionPtrs*}; %typemap{PrintObjectPtrs*}; From 15ad0ef2f2b3f93d1e0e2d0c375bcebc20ad4b85 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Thu, 30 Aug 2018 11:40:06 +0200 Subject: [PATCH 2/3] working C++ status bar. Signed-off-by: tamasmeszaros --- lib/Slic3r.pm | 1 + lib/Slic3r/GUI/MainFrame.pm | 6 +- lib/Slic3r/GUI/Plater.pm | 4 +- lib/Slic3r/GUI/ProgressStatusBar.pm | 136 +----------------------- xs/src/slic3r/AppController.cpp | 7 +- xs/src/slic3r/AppController.hpp | 4 +- xs/src/slic3r/AppControllerWx.cpp | 45 ++++---- xs/src/slic3r/GUI/ProgressStatusBar.cpp | 28 +++-- xs/src/slic3r/GUI/ProgressStatusBar.hpp | 13 ++- xs/src/slic3r/ProgressIndicator.hpp | 14 +-- xs/xsp/AppController.xsp | 3 +- xs/xsp/ProgressStatusBar.xsp | 15 ++- 12 files changed, 75 insertions(+), 201 deletions(-) diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index 46627311f..4a178682c 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -166,6 +166,7 @@ sub thread_cleanup { *Slic3r::GUI::Tab::DESTROY = sub {}; *Slic3r::GUI::PresetHints::DESTROY = sub {}; *Slic3r::GUI::TabIface::DESTROY = sub {}; + *Slic3r::GUI::ProgressStatusBar::DESTROY= sub {}; *Slic3r::OctoPrint::DESTROY = sub {}; *Slic3r::Duet::DESTROY = sub {}; *Slic3r::PresetUpdater::DESTROY = sub {}; diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index 6b932f92f..50aa3e51d 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -63,15 +63,11 @@ sub new { # initialize status bar $self->{statusbar} = Slic3r::GUI::ProgressStatusBar->new(); - # $self->{statusbar}->SetParent($self, Wx::NewId); $self->{statusbar}->Embed; $self->{statusbar}->SetStatusText(L("Version ").$Slic3r::VERSION.L(" - Remember to check for updates at http://github.com/prusa3d/slic3r/releases")); # Make the global status bar and its progress indicator available in C++ - $appController->set_global_progress_indicator( - $self->{statusbar}->GetProgId(), - $self->{statusbar}->GetId(), - ); + $appController->set_global_progress_indicator($self->{statusbar}); $appController->set_model($self->{plater}->{model}); $appController->set_print($self->{plater}->{print}); diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index ee2689d16..ffc3b9640 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -1569,7 +1569,9 @@ sub on_progress_event { my ($self, $percent, $message) = @_; $self->statusbar->SetProgress($percent); - $self->statusbar->SetStatusText("$messageā€¦"); + # TODO: three dot character is not properly translated into C++ + # $self->statusbar->SetStatusText("$messageā€¦"); + $self->statusbar->SetStatusText("$message..."); } # Called when the G-code export finishes, either successfully or with an error. diff --git a/lib/Slic3r/GUI/ProgressStatusBar.pm b/lib/Slic3r/GUI/ProgressStatusBar.pm index a696feb7f..edc0c0ce3 100644 --- a/lib/Slic3r/GUI/ProgressStatusBar.pm +++ b/lib/Slic3r/GUI/ProgressStatusBar.pm @@ -1,146 +1,18 @@ # Status bar at the bottom of the main screen. +# Now it just implements cancel cb on perl side, every other functionality is +# in C++ -package Slic3r::GUI::ProgressStatusBar; +package Slic3r::GUI::ProgressStatusBar; use strict; use warnings; -# use Wx qw(:gauge :misc); -# use base 'Wx::StatusBar'; - our $cancel_cb; -# sub new { -# my $class = shift; -# my $self = $class->SUPER::new(@_); - -# $self->{busy} = 0; -# $self->{timer} = Wx::Timer->new($self); -# $self->{prog} = Wx::Gauge->new($self, wxGA_HORIZONTAL, 100, wxDefaultPosition, wxDefaultSize); -# $self->{prog}->Hide; -# $self->{cancelbutton} = Wx::Button->new($self, -1, "Cancel", wxDefaultPosition, wxDefaultSize); -# $self->{cancelbutton}->Hide; - -# $self->SetFieldsCount(3); -# $self->SetStatusWidths(-1, 150, 155); - -# Wx::Event::EVT_TIMER($self, \&OnTimer, $self->{timer}); -# Wx::Event::EVT_SIZE($self, \&OnSize); -# Wx::Event::EVT_BUTTON($self, $self->{cancelbutton}, sub { -# $self->{cancel_cb}->(); -# $self->{cancelbutton}->Hide; -# }); - -# return $self; -# } - -# sub DESTROY { -# my $self = shift; -# $self->{timer}->Stop if $self->{timer} && $self->{timer}->IsRunning; -# } - -# sub OnSize { -# my ($self, $event) = @_; - -# my %fields = ( -# # 0 is reserved for status text -# 1 => $self->{cancelbutton}, -# 2 => $self->{prog}, -# ); - -# foreach (keys %fields) { -# my $rect = $self->GetFieldRect($_); -# my $offset = &Wx::wxGTK ? 1 : 0; # add a cosmetic 1 pixel offset on wxGTK -# my $pos = [$rect->GetX + $offset, $rect->GetY + $offset]; -# $fields{$_}->Move($pos); -# $fields{$_}->SetSize($rect->GetWidth - $offset, $rect->GetHeight); -# } - -# $event->Skip; -# } - -# sub OnTimer { -# my ($self, $event) = @_; - -# if ($self->{prog}->IsShown) { -# $self->{timer}->Stop; -# } -# $self->{prog}->Pulse if $self->{_busy}; -# } - sub SetCancelCallback { my $self = shift; my ($cb) = @_; $cancel_cb = $cb; - # $cb ? $self->{cancelbutton}->Show : $self->{cancelbutton}->Hide; + $cb ? $self->ShowCancelButton : $self->HideCancelButton; } -# sub Run { -# my $self = shift; -# my $rate = shift || 100; -# if (!$self->{timer}->IsRunning) { -# $self->{timer}->Start($rate); -# } -# } - -# sub GetProgress { -# my $self = shift; -# return $self->{prog}->GetValue; -# } - -# sub SetProgress { -# my $self = shift; -# my ($val) = @_; -# if (!$self->{prog}->IsShown) { -# $self->ShowProgress(1); -# } -# if ($val == $self->{prog}->GetRange) { -# $self->{prog}->SetValue(0); -# $self->ShowProgress(0); -# } else { -# $self->{prog}->SetValue($val); -# } -# } - -# sub SetRange { -# my $self = shift; -# my ($val) = @_; - -# if ($val != $self->{prog}->GetRange) { -# $self->{prog}->SetRange($val); -# } -# } - -# sub ShowProgress { -# my $self = shift; -# my ($show) = @_; - -# $self->{prog}->Show($show); -# $self->{prog}->Pulse; -# } - -# sub StartBusy { -# my $self = shift; -# my $rate = shift || 100; - -# $self->{_busy} = 1; -# $self->ShowProgress(1); -# if (!$self->{timer}->IsRunning) { -# $self->{timer}->Start($rate); -# } -# } - -# sub StopBusy { -# my $self = shift; - -# $self->{timer}->Stop; -# $self->ShowProgress(0); -# $self->{prog}->SetValue(0); -# $self->{_busy} = 0; -# } - -# sub IsBusy { -# my $self = shift; -# return $self->{_busy}; -# } - 1; diff --git a/xs/src/slic3r/AppController.cpp b/xs/src/slic3r/AppController.cpp index 2f1e9a148..cee6d3394 100644 --- a/xs/src/slic3r/AppController.cpp +++ b/xs/src/slic3r/AppController.cpp @@ -305,6 +305,10 @@ void AppController::arrange_model() // Set the range of the progress to the object count pind->max(count); + pind->on_cancel([](){ + std::cout << "Cannot be cancelled!" << std::endl; + }); + } auto dist = print_ctl()->config().min_object_distance(); @@ -353,7 +357,7 @@ void AppController::arrange_model() bed, arr::BOX, false, // create many piles not just one pile - [pind, count](unsigned rem) { + [this, pind, count](unsigned rem) { if(pind) pind->update(count - rem, _(L("Arranging objects..."))); }); @@ -369,6 +373,7 @@ void AppController::arrange_model() if(pind) { pind->max(pmax); pind->update(0, _(L("Arranging done."))); + pind->on_cancel(/*remove cancel function*/); } } diff --git a/xs/src/slic3r/AppController.hpp b/xs/src/slic3r/AppController.hpp index 58681a7de..1106a0558 100644 --- a/xs/src/slic3r/AppController.hpp +++ b/xs/src/slic3r/AppController.hpp @@ -15,6 +15,7 @@ class Model; class Print; class PrintObject; class PrintConfig; +class ProgressStatusBar; /** @@ -255,8 +256,7 @@ public: * @param gauge_id The ID of the gague widget of the status bar. * @param statusbar_id The ID of the status bar. */ - void set_global_progress_indicator(unsigned gauge_id, - unsigned statusbar_id); + void set_global_progress_indicator(ProgressStatusBar *prs); void arrange_model(); }; diff --git a/xs/src/slic3r/AppControllerWx.cpp b/xs/src/slic3r/AppControllerWx.cpp index 64d783356..3aeb4f3e7 100644 --- a/xs/src/slic3r/AppControllerWx.cpp +++ b/xs/src/slic3r/AppControllerWx.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -210,31 +211,21 @@ AppControllerBoilerplate::create_progress_indicator(unsigned statenum, namespace { -// A wrapper progress indicator class around the statusbar created in perl. class Wrapper: public ProgressIndicator, public wxEvtHandler { - wxGauge *gauge_; - wxStatusBar *stbar_; + ProgressStatusBar *sbar_; using Base = ProgressIndicator; std::string message_; AppControllerBoilerplate& ctl_; void showProgress(bool show = true) { - gauge_->Show(show); + sbar_->show_progress(show); } void _state(unsigned st) { if( st <= ProgressIndicator::max() ) { Base::state(st); - - if(!gauge_->IsShown()) showProgress(true); - - stbar_->SetStatusText(message_); - if(static_cast(st) == gauge_->GetRange()) { - gauge_->SetValue(0); - showProgress(false); - } else { - gauge_->SetValue(static_cast(st)); - } + sbar_->set_status_text(message_); + sbar_->set_progress(st); } } @@ -247,12 +238,12 @@ class Wrapper: public ProgressIndicator, public wxEvtHandler { public: - inline Wrapper(wxGauge *gauge, wxStatusBar *stbar, + inline Wrapper(ProgressStatusBar *sbar, AppControllerBoilerplate& ctl): - gauge_(gauge), stbar_(stbar), ctl_(ctl) + sbar_(sbar), ctl_(ctl) { - Base::max(static_cast(gauge->GetRange())); - Base::states(static_cast(gauge->GetRange())); + Base::max(static_cast(sbar_->get_range())); + Base::states(static_cast(sbar_->get_range())); Bind(PROGRESS_STATUS_UPDATE_EVENT, &Wrapper::_state, @@ -265,7 +256,7 @@ public: virtual void max(float val) override { if(val > 1.0) { - gauge_->SetRange(static_cast(val)); + sbar_->set_range(static_cast(val)); ProgressIndicator::max(val); } } @@ -293,18 +284,18 @@ public: virtual void title(const string & /*title*/) override {} + virtual void on_cancel(CancelFn fn) override { + sbar_->set_cancel_callback(fn); + Base::on_cancel(fn); + } + }; } -void AppController::set_global_progress_indicator( - unsigned gid, - unsigned sid) +void AppController::set_global_progress_indicator(ProgressStatusBar *prsb) { - wxGauge* gauge = dynamic_cast(wxWindow::FindWindowById(gid)); - wxStatusBar* sb = dynamic_cast(wxWindow::FindWindowById(sid)); - - if(gauge && sb) { - global_progressind_ = std::make_shared(gauge, sb, *this); + if(prsb) { + global_progress_indicator(std::make_shared(prsb, *this)); } } } diff --git a/xs/src/slic3r/GUI/ProgressStatusBar.cpp b/xs/src/slic3r/GUI/ProgressStatusBar.cpp index 13ca8cd81..dab1a88fa 100644 --- a/xs/src/slic3r/GUI/ProgressStatusBar.cpp +++ b/xs/src/slic3r/GUI/ProgressStatusBar.cpp @@ -30,7 +30,6 @@ ProgressStatusBar::ProgressStatusBar(wxWindow *parent, int id): prog_->Hide(); cancelbutton_->Hide(); - self->SetFieldsCount(3); int w[] = {-1, 150, 155}; self->SetStatusWidths(3, w); @@ -60,11 +59,6 @@ ProgressStatusBar::ProgressStatusBar(wxWindow *parent, int id): }); } -//ProgressStatusBar::ProgressStatusBar(): ProgressStatusBar(nullptr, wxID_ANY) -//{ - -//} - ProgressStatusBar::~ProgressStatusBar() { if(timer_->IsRunning()) timer_->Stop(); } @@ -86,6 +80,11 @@ void ProgressStatusBar::set_progress(int val) } } +int ProgressStatusBar::get_range() const +{ + return prog_->GetRange(); +} + void ProgressStatusBar::set_range(int val) { if(val != prog_->GetRange()) { @@ -129,28 +128,25 @@ void ProgressStatusBar::run(int rate) } } -void ProgressStatusBar::Embed() +void ProgressStatusBar::embed(wxFrame *frame) { - std::cout << "Embedding" << std::endl; - wxFrame* mf = GUI::get_main_frame(); - std::cout << mf->GetName() << std::endl; - std::cout << self->GetName() << std::endl; + wxFrame* mf = frame? frame : GUI::get_main_frame(); mf->SetStatusBar(self); } -void ProgressStatusBar::SetStatusText(std::string txt) +void ProgressStatusBar::set_status_text(const std::string& txt) { self->SetStatusText(txt); } -int ProgressStatusBar::GetId() +void ProgressStatusBar::show_cancel_button() { - return self->GetId(); + cancelbutton_->Show(); } -int ProgressStatusBar::GetProgId() +void ProgressStatusBar::hide_cancel_button() { - return prog_->GetId(); + cancelbutton_->Hide(); } } diff --git a/xs/src/slic3r/GUI/ProgressStatusBar.hpp b/xs/src/slic3r/GUI/ProgressStatusBar.hpp index 53366aace..a117cacfb 100644 --- a/xs/src/slic3r/GUI/ProgressStatusBar.hpp +++ b/xs/src/slic3r/GUI/ProgressStatusBar.hpp @@ -10,6 +10,7 @@ class wxButton; class wxTimerEvent; class wxStatusBar; class wxWindow; +class wxFrame; namespace Slic3r { @@ -33,19 +34,21 @@ public: int get_progress() const; void set_progress(int); + int get_range() const; void set_range(int = 100); void show_progress(bool); void start_busy(int = 100); void stop_busy(); inline bool is_busy() const { return busy_; } - void set_cancel_callback(CancelFn); + void set_cancel_callback(CancelFn = CancelFn()); + inline void remove_cancel_callback() { set_cancel_callback(); } void run(int rate); + void embed(wxFrame *frame = nullptr); + void set_status_text(const std::string& txt); // Temporary methods to satisfy Perl side - void Embed(); - void SetStatusText(std::string txt); - int GetId(); - int GetProgId(); + void show_cancel_button(); + void hide_cancel_button(); private: bool busy_ = false; diff --git a/xs/src/slic3r/ProgressIndicator.hpp b/xs/src/slic3r/ProgressIndicator.hpp index 49d0c251c..4a39e84ab 100644 --- a/xs/src/slic3r/ProgressIndicator.hpp +++ b/xs/src/slic3r/ProgressIndicator.hpp @@ -12,7 +12,7 @@ namespace Slic3r { */ class ProgressIndicator { public: - using CancelFn = std::function; // Cancel functio signature. + using CancelFn = std::function; // Cancel function signature. private: float state_ = .0f, max_ = 1.f, step_; @@ -28,14 +28,14 @@ public: /// Get the current progress state float state() const { return state_; } - /// Set the maximum of hte progress range + /// Set the maximum of the progress range virtual void max(float maxval) { max_ = maxval; } /// Set the current state of the progress. virtual void state(float val) { state_ = val; } /** - * @brief Number of states int the progress. Can be used insted of giving a + * @brief Number of states int the progress. Can be used instead of giving a * maximum value. */ virtual void states(unsigned statenum) { @@ -45,14 +45,14 @@ public: /// Message shown on the next status update. virtual void message(const string&) = 0; - /// Title of the operaton. + /// Title of the operation. virtual void title(const string&) = 0; - /// Formatted message for the next status update. Works just like sprinf. + /// Formatted message for the next status update. Works just like sprintf. virtual void message_fmt(const string& fmt, ...); /// Set up a cancel callback for the operation if feasible. - inline void on_cancel(CancelFn func) { cancelfunc_ = func; } + virtual void on_cancel(CancelFn func = CancelFn()) { cancelfunc_ = func; } /** * Explicitly shut down the progress indicator and call the associated @@ -60,7 +60,7 @@ public: */ virtual void cancel() { cancelfunc_(); } - /// Convinience function to call message and status update in one function. + /// Convenience function to call message and status update in one function. void update(float st, const string& msg) { message(msg); state(st); } diff --git a/xs/xsp/AppController.xsp b/xs/xsp/AppController.xsp index 1b653081d..1355a7d6e 100644 --- a/xs/xsp/AppController.xsp +++ b/xs/xsp/AppController.xsp @@ -5,6 +5,7 @@ #include "slic3r/AppController.hpp" #include "libslic3r/Model.hpp" #include "libslic3r/Print.hpp" +#include "slic3r/GUI/ProgressStatusBar.hpp" %} %name{Slic3r::PrintController} class PrintController { @@ -21,7 +22,7 @@ PrintController *print_ctl(); void set_model(Model *model); void set_print(Print *print); - void set_global_progress_indicator(unsigned gauge_id, unsigned statusbar_id); + void set_global_progress_indicator(ProgressStatusBar *prs); void arrange_model(); }; \ No newline at end of file diff --git a/xs/xsp/ProgressStatusBar.xsp b/xs/xsp/ProgressStatusBar.xsp index 3b9be3ba8..f59895581 100644 --- a/xs/xsp/ProgressStatusBar.xsp +++ b/xs/xsp/ProgressStatusBar.xsp @@ -33,9 +33,16 @@ void Run(int rate) %code%{ THIS->run(rate); %}; - void Embed(); - void SetStatusText(std::string txt); - int GetId(); - int GetProgId(); + void Embed() + %code%{ THIS->embed(); %}; + + void SetStatusText(std::string txt) + %code%{ THIS->set_status_text(txt); %}; + + void ShowCancelButton() + %code%{ THIS->show_cancel_button(); %}; + + void HideCancelButton() + %code%{ THIS->hide_cancel_button(); %}; }; \ No newline at end of file From f5b1729af3e09ffc5ac64d2540227a0286cdb465 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Thu, 30 Aug 2018 12:11:52 +0200 Subject: [PATCH 3/3] fixing build issues --- xs/src/slic3r/AppController.cpp | 36 ++++----------------------------- xs/src/slic3r/GUI/GUI.cpp | 2 ++ xs/src/slic3r/GUI/GUI.hpp | 1 + 3 files changed, 7 insertions(+), 32 deletions(-) diff --git a/xs/src/slic3r/AppController.cpp b/xs/src/slic3r/AppController.cpp index cee6d3394..a93ee63f0 100644 --- a/xs/src/slic3r/AppController.cpp +++ b/xs/src/slic3r/AppController.cpp @@ -256,7 +256,7 @@ void PrintController::slice() slice(pri); } -void IProgressIndicator::message_fmt( +void ProgressIndicator::message_fmt( const string &fmtstr, ...) { std::stringstream ss; va_list args; @@ -311,35 +311,7 @@ void AppController::arrange_model() } - auto dist = print_ctl()->config().min_object_distance(); - - // Create the arranger config - auto min_obj_distance = static_cast(dist/SCALING_FACTOR); - - auto& bedpoints = print_ctl()->config().bed_shape.values; - Polyline bed; bed.points.reserve(bedpoints.size()); - for(auto& v : bedpoints) - bed.append(Point::new_scale(v.x, v.y)); - - if(pind) pind->update(0, _(L("Arranging objects..."))); - - try { - arr::arrange(*model_, - min_obj_distance, - bed, - arr::BOX, - false, // create many piles not just one pile - [pind, count](unsigned rem) { - if(pind) - pind->update(count - rem, _(L("Arranging objects..."))); - }); - } catch(std::exception& e) { - std::cerr << e.what() << std::endl; - report_issue(IssueType::ERR, - _(L("Could not arrange model objects! " - "Some geometries may be invalid.")), - _(L("Exception occurred"))); - } + auto dist = print_ctl()->config().min_object_distance(); // Create the arranger config auto min_obj_distance = static_cast(dist/SCALING_FACTOR); @@ -347,7 +319,7 @@ void AppController::arrange_model() auto& bedpoints = print_ctl()->config().bed_shape.values; Polyline bed; bed.points.reserve(bedpoints.size()); for(auto& v : bedpoints) - bed.append(Point::new_scale(v(0), v(1))); + bed.append(Point::new_scale(v.x, v.y)); if(pind) pind->update(0, _(L("Arranging objects..."))); @@ -357,7 +329,7 @@ void AppController::arrange_model() bed, arr::BOX, false, // create many piles not just one pile - [this, pind, count](unsigned rem) { + [pind, count](unsigned rem) { if(pind) pind->update(count - rem, _(L("Arranging objects..."))); }); diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp index 8555f0b92..a96ad2da3 100644 --- a/xs/src/slic3r/GUI/GUI.cpp +++ b/xs/src/slic3r/GUI/GUI.cpp @@ -181,6 +181,8 @@ void set_main_frame(wxFrame *main_frame) g_wxMainFrame = main_frame; } +wxFrame* get_main_frame() { return g_wxMainFrame; } + void set_tab_panel(wxNotebook *tab_panel) { g_wxTabPanel = tab_panel; diff --git a/xs/src/slic3r/GUI/GUI.hpp b/xs/src/slic3r/GUI/GUI.hpp index 165288819..20e6de667 100644 --- a/xs/src/slic3r/GUI/GUI.hpp +++ b/xs/src/slic3r/GUI/GUI.hpp @@ -97,6 +97,7 @@ void set_3DScene(_3DScene *scene); AppConfig* get_app_config(); wxApp* get_app(); PresetBundle* get_preset_bundle(); +wxFrame* get_main_frame(); const wxColour& get_label_clr_modified(); const wxColour& get_label_clr_sys();