Almost working c++ status bar

Signed-off-by: tamasmeszaros <meszaros.q@gmail.com>
This commit is contained in:
tamasmeszaros 2018-08-29 18:02:10 +02:00
parent 5ee106fbf9
commit 9e2d48ff3b
13 changed files with 442 additions and 156 deletions

View file

@ -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})

View file

@ -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");

View file

@ -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<libnest2d::PointImpl>;
using Coord = libnest2d::TCoord<libnest2d::PointImpl>;
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<Coord>(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.")));
}
}

View file

@ -7,7 +7,7 @@
#include <atomic>
#include <iostream>
#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<IProgressIndicator>;
using ProgresIndicatorPtr = std::shared_ptr<ProgressIndicator>;
private:
class PriData; // Some structure to store progress indication data

View file

@ -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<int>(val));
IProgressIndicator::max(val);
ProgressIndicator::max(val);
}
}

View file

@ -0,0 +1,156 @@
#include "ProgressStatusBar.hpp"
#include <wx/timer.h>
#include <wx/gauge.h>
#include <wx/button.h>
#include <wx/statusbr.h>
#include <wx/frame.h>
#include "GUI.hpp"
#include <iostream>
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();
}
}

View file

@ -0,0 +1,61 @@
#ifndef PROGRESSSTATUSBAR_HPP
#define PROGRESSSTATUSBAR_HPP
#include <memory>
#include <functional>
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<void()>;
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

View file

@ -10,7 +10,7 @@ namespace Slic3r {
/**
* @brief Generic progress indication interface.
*/
class IProgressIndicator {
class ProgressIndicator {
public:
using CancelFn = std::function<void(void)>; // 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_; }

View file

@ -0,0 +1,41 @@
%module{Slic3r::XS};
%{
#include <xsinit.h>
#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();
};

View file

@ -233,8 +233,10 @@ PresetCollection* O_OBJECT_SLIC3R
Ref<PresetCollection> O_OBJECT_SLIC3R_T
PresetBundle* O_OBJECT_SLIC3R
Ref<PresetBundle> O_OBJECT_SLIC3R_T
TabIface* O_OBJECT_SLIC3R
Ref<TabIface> O_OBJECT_SLIC3R_T
TabIface* O_OBJECT_SLIC3R
Ref<TabIface> O_OBJECT_SLIC3R_T
ProgressStatusBar* O_OBJECT_SLIC3R
Ref<ProgressStatusBar> O_OBJECT_SLIC3R_T
PresetUpdater* O_OBJECT_SLIC3R
Ref<PresetUpdater> O_OBJECT_SLIC3R_T

View file

@ -213,6 +213,7 @@
%typemap{PresetHints*};
%typemap{Ref<PresetHints>}{simple};
%typemap{TabIface*};
%typemap{ProgressStatusBar*};
%typemap{PrintRegionPtrs*};
%typemap{PrintObjectPtrs*};