Polymorphic AppController for cli and gui modes.

This commit is contained in:
tamasmeszaros 2018-09-19 18:02:04 +02:00
parent c9acd1252a
commit 2306c1589a
8 changed files with 338 additions and 183 deletions

View File

@ -109,6 +109,7 @@ if ((!@ARGV || $opt{gui}) && !$opt{no_gui} && !$opt{save} && eval "require Slic3
$Slic3r::GUI::no_plater = $opt{no_plater};
$Slic3r::GUI::autosave = $opt{autosave};
}
Slic3r::GUI::set_gui_appctl();
$gui = Slic3r::GUI->new;
#setlocale(LC_NUMERIC, 'C');
$gui->{mainframe}->load_config_file($_) for @{$opt{load}};
@ -121,6 +122,9 @@ if ((!@ARGV || $opt{gui}) && !$opt{no_gui} && !$opt{save} && eval "require Slic3
die $@ if $@ && $opt{gui};
if (@ARGV) { # slicing from command line
Slic3r::GUI::set_cli_appctl();
my $appctl = Slic3r::AppController->new();
$config->validate;
if ($opt{repair}) {
@ -210,7 +214,10 @@ if (@ARGV) { # slicing from command line
$sprint->apply_config($config);
if ($opt{export_png}) {
$sprint->export_png;
# $sprint->export_png;
$appctl->set_model($model);
$appctl->set_print($sprint->_print);
$appctl->print_ctl()->slice_to_png();
} else {
my $t0 = [gettimeofday];
# The following call may die if the output_filename_format template substitution fails,

View File

@ -292,59 +292,59 @@ protected:
using Distance = TCoord<PointImpl>;
using Pile = sl::Shapes<PolygonImpl>;
Packer pck_;
PConfig pconf_; // Placement configuration
double bin_area_;
SpatIndex rtree_;
SpatIndex smallsrtree_;
double norm_;
Pile merged_pile_;
Box pilebb_;
ItemGroup remaining_;
ItemGroup items_;
Packer m_pck;
PConfig m_pconf; // Placement configuration
double m_bin_area;
SpatIndex m_rtree;
SpatIndex m_smallsrtree;
double m_norm;
Pile m_merged_pile;
Box m_pilebb;
ItemGroup m_remaining;
ItemGroup m_items;
public:
_ArrBase(const TBin& bin, Distance dist,
std::function<void(unsigned)> progressind,
std::function<bool(void)> stopcond):
pck_(bin, dist), bin_area_(sl::area(bin)),
norm_(std::sqrt(sl::area(bin)))
m_pck(bin, dist), m_bin_area(sl::area(bin)),
m_norm(std::sqrt(sl::area(bin)))
{
fillConfig(pconf_);
fillConfig(m_pconf);
pconf_.before_packing =
m_pconf.before_packing =
[this](const Pile& merged_pile, // merged pile
const ItemGroup& items, // packed items
const ItemGroup& remaining) // future items to be packed
{
items_ = items;
merged_pile_ = merged_pile;
remaining_ = remaining;
m_items = items;
m_merged_pile = merged_pile;
m_remaining = remaining;
pilebb_ = sl::boundingBox(merged_pile);
m_pilebb = sl::boundingBox(merged_pile);
rtree_.clear();
smallsrtree_.clear();
m_rtree.clear();
m_smallsrtree.clear();
// We will treat big items (compared to the print bed) differently
auto isBig = [this](double a) {
return a/bin_area_ > BIG_ITEM_TRESHOLD ;
return a/m_bin_area > BIG_ITEM_TRESHOLD ;
};
for(unsigned idx = 0; idx < items.size(); ++idx) {
Item& itm = items[idx];
if(isBig(itm.area())) rtree_.insert({itm.boundingBox(), idx});
smallsrtree_.insert({itm.boundingBox(), idx});
if(isBig(itm.area())) m_rtree.insert({itm.boundingBox(), idx});
m_smallsrtree.insert({itm.boundingBox(), idx});
}
};
pck_.progressIndicator(progressind);
pck_.stopCondition(stopcond);
m_pck.progressIndicator(progressind);
m_pck.stopCondition(stopcond);
}
template<class...Args> inline IndexedPackGroup operator()(Args&&...args) {
rtree_.clear();
return pck_.executeIndexed(std::forward<Args>(args)...);
m_rtree.clear();
return m_pck.executeIndexed(std::forward<Args>(args)...);
}
};
@ -358,18 +358,18 @@ public:
_ArrBase<Box>(bin, dist, progressind, stopcond)
{
pconf_.object_function = [this, bin] (const Item &item) {
m_pconf.object_function = [this, bin] (const Item &item) {
auto result = objfunc(bin.center(),
merged_pile_,
pilebb_,
items_,
m_merged_pile,
m_pilebb,
m_items,
item,
bin_area_,
norm_,
rtree_,
smallsrtree_,
remaining_);
m_bin_area,
m_norm,
m_rtree,
m_smallsrtree,
m_remaining);
double score = std::get<0>(result);
auto& fullbb = std::get<1>(result);
@ -381,7 +381,7 @@ public:
return score;
};
pck_.configure(pconf_);
m_pck.configure(m_pconf);
}
};
@ -396,27 +396,27 @@ public:
std::function<bool(void)> stopcond):
_ArrBase<lnCircle>(bin, dist, progressind, stopcond) {
pconf_.object_function = [this, &bin] (const Item &item) {
m_pconf.object_function = [this, &bin] (const Item &item) {
auto result = objfunc(bin.center(),
merged_pile_,
pilebb_,
items_,
m_merged_pile,
m_pilebb,
m_items,
item,
bin_area_,
norm_,
rtree_,
smallsrtree_,
remaining_);
m_bin_area,
m_norm,
m_rtree,
m_smallsrtree,
m_remaining);
double score = std::get<0>(result);
auto isBig = [this](const Item& itm) {
return itm.area()/bin_area_ > BIG_ITEM_TRESHOLD ;
return itm.area()/m_bin_area > BIG_ITEM_TRESHOLD ;
};
if(isBig(item)) {
auto mp = merged_pile_;
auto mp = m_merged_pile;
mp.push_back(item.transformedShape());
auto chull = sl::convexHull(mp);
double miss = Placer::overfit(chull, bin);
@ -427,7 +427,7 @@ public:
return score;
};
pck_.configure(pconf_);
m_pck.configure(m_pconf);
}
};
@ -439,25 +439,25 @@ public:
std::function<bool(void)> stopcond):
_ArrBase<PolygonImpl>(bin, dist, progressind, stopcond)
{
pconf_.object_function = [this, &bin] (const Item &item) {
m_pconf.object_function = [this, &bin] (const Item &item) {
auto binbb = sl::boundingBox(bin);
auto result = objfunc(binbb.center(),
merged_pile_,
pilebb_,
items_,
m_merged_pile,
m_pilebb,
m_items,
item,
bin_area_,
norm_,
rtree_,
smallsrtree_,
remaining_);
m_bin_area,
m_norm,
m_rtree,
m_smallsrtree,
m_remaining);
double score = std::get<0>(result);
return score;
};
pck_.configure(pconf_);
m_pck.configure(m_pconf);
}
};
@ -469,22 +469,22 @@ public:
std::function<bool(void)> stopcond):
_ArrBase<Box>(Box(0, 0), dist, progressind, stopcond)
{
this->pconf_.object_function = [this] (const Item &item) {
this->m_pconf.object_function = [this] (const Item &item) {
auto result = objfunc({0, 0},
merged_pile_,
pilebb_,
items_,
m_merged_pile,
m_pilebb,
m_items,
item,
0,
norm_,
rtree_,
smallsrtree_,
remaining_);
m_norm,
m_rtree,
m_smallsrtree,
m_remaining);
return std::get<0>(result);
};
this->pck_.configure(pconf_);
this->m_pck.configure(m_pconf);
}
};
@ -530,11 +530,11 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model) {
item.rotation(objinst->rotation);
item.translation( {
#if ENABLE_MODELINSTANCE_3D_OFFSET
ClipperLib::cInt(objinst->get_offset(X) / SCALING_FACTOR),
ClipperLib::cInt(objinst->get_offset(Y) / SCALING_FACTOR)
ClipperLib::cInt(objinst->get_offset(X)/SCALING_FACTOR),
ClipperLib::cInt(objinst->get_offset(Y)/SCALING_FACTOR)
#else
ClipperLib::cInt(objinst->offset(0)/SCALING_FACTOR),
ClipperLib::cInt(objinst->offset(1)/SCALING_FACTOR)
ClipperLib::cInt(objinst->offset(0)/SCALING_FACTOR),
ClipperLib::cInt(objinst->offset(1)/SCALING_FACTOR)
#endif // ENABLE_MODELINSTANCE_3D_OFFSET
});
ret.emplace_back(objinst, item);
@ -668,17 +668,19 @@ void applyResult(
// Get the model instance from the shapemap using the index
ModelInstance *inst_ptr = shapemap[idx].first;
// Get the tranformation data from the item object and scale it
// Get the transformation data from the item object and scale it
// appropriately
auto off = item.translation();
Radians rot = item.rotation();
#if ENABLE_MODELINSTANCE_3D_OFFSET
Vec3d foff(off.X*SCALING_FACTOR + batch_offset, off.Y*SCALING_FACTOR, 0.0);
Vec3d foff(off.X*SCALING_FACTOR + batch_offset,
off.Y*SCALING_FACTOR,
0.0);
#else
Vec2d foff(off.X*SCALING_FACTOR + batch_offset, off.Y*SCALING_FACTOR);
#endif // ENABLE_MODELINSTANCE_3D_OFFSET
// write the tranformation data into the model instance
// write the transformation data into the model instance
inst_ptr->rotation = rot;
#if ENABLE_MODELINSTANCE_3D_OFFSET
inst_ptr->set_offset(foff);
@ -695,7 +697,7 @@ void applyResult(
* The arrangement considers multiple bins (aka. print beds) for placing all
* the items provided in the model argument. If the items don't fit on one
* print bed, the remaining will be placed onto newly created print beds.
* The first_bin_only parameter, if set to true, disables this behaviour and
* The first_bin_only parameter, if set to true, disables this behavior and
* makes sure that only one print bed is filled and the remaining items will be
* untouched. When set to false, the items which could not fit onto the
* print bed will be placed next to the print bed so the user should see a
@ -741,6 +743,7 @@ bool arrange(Model &model, coordf_t min_obj_distance,
IndexedPackGroup result;
// If there is no hint about the shape, we will try to guess
if(bedhint.type == BedShapeType::WHO_KNOWS) bedhint = bedShape(bed);
BoundingBox bbb(bed);

View File

@ -21,7 +21,7 @@
namespace Slic3r {
class AppControllerBoilerplate::PriData {
class AppControllerGui::PriData {
public:
std::mutex m;
std::thread::id ui_thread;
@ -29,14 +29,14 @@ public:
inline explicit PriData(std::thread::id uit): ui_thread(uit) {}
};
AppControllerBoilerplate::AppControllerBoilerplate()
AppControllerGui::AppControllerGui()
:m_pri_data(new PriData(std::this_thread::get_id())) {}
AppControllerBoilerplate::~AppControllerBoilerplate() {
AppControllerGui::~AppControllerGui() {
m_pri_data.reset();
}
bool AppControllerBoilerplate::is_main_thread() const
bool AppControllerGui::is_main_thread() const
{
return m_pri_data->ui_thread == std::this_thread::get_id();
}
@ -54,8 +54,7 @@ static const PrintStep STEP_SKIRT = psSkirt;
static const PrintStep STEP_BRIM = psBrim;
static const PrintStep STEP_WIPE_TOWER = psWipeTower;
AppControllerBoilerplate::ProgresIndicatorPtr
AppControllerBoilerplate::global_progress_indicator() {
ProgresIndicatorPtr AppControllerGui::global_progress_indicator() {
ProgresIndicatorPtr ret;
m_pri_data->m.lock();
@ -65,8 +64,7 @@ AppControllerBoilerplate::global_progress_indicator() {
return ret;
}
void AppControllerBoilerplate::global_progress_indicator(
AppControllerBoilerplate::ProgresIndicatorPtr gpri)
void AppControllerGui::global_progress_indicator(ProgresIndicatorPtr gpri)
{
m_pri_data->m.lock();
m_global_progressind = gpri;
@ -78,7 +76,10 @@ PrintController::query_png_export_data(const DynamicPrintConfig& conf)
{
PngExportData ret;
auto zippath = query_destination_path("Output zip file", "*.zip", "out");
auto c = GUI::get_appctl();
auto zippath = c->query_destination_path("Output zip file", "*.zip",
"export-png",
"out");
ret.zippath = zippath;
@ -102,7 +103,7 @@ PrintController::query_png_export_data(const DynamicPrintConfig& conf)
return ret;
}
void PrintController::slice(AppControllerBoilerplate::ProgresIndicatorPtr pri)
void PrintController::slice(ProgresIndicatorPtr pri)
{
m_print->set_status_callback([pri](int st, const std::string& msg){
pri->update(unsigned(st), msg);
@ -113,8 +114,9 @@ void PrintController::slice(AppControllerBoilerplate::ProgresIndicatorPtr pri)
void PrintController::slice()
{
auto pri = global_progress_indicator();
if(!pri) pri = create_progress_indicator(100, L("Slicing"));
auto ctl = GUI::get_appctl();
auto pri = ctl->global_progress_indicator();
if(!pri) pri = ctl->create_progress_indicator(100, L("Slicing"));
slice(pri);
}
@ -139,13 +141,15 @@ void PrintController::slice_to_png()
{
using Pointf3 = Vec3d;
auto ctl = GUI::get_appctl();
auto presetbundle = GUI::get_preset_bundle();
assert(presetbundle);
// FIXME: this crashes in command line mode
auto pt = presetbundle->printers.get_selected_preset().printer_technology();
if(pt != ptSLA) {
report_issue(IssueType::ERR, L("Printer technology is not SLA!"),
ctl->report_issue(IssueType::ERR, L("Printer technology is not SLA!"),
L("Error"));
return;
}
@ -162,7 +166,7 @@ void PrintController::slice_to_png()
print->apply_config(conf);
print->validate();
} catch(std::exception& e) {
report_issue(IssueType::ERR, e.what(), "Error");
ctl->report_issue(IssueType::ERR, e.what(), "Error");
return;
}
@ -208,13 +212,13 @@ void PrintController::slice_to_png()
<< L("Width needed: ") << px(punsc) << " mm\n"
<< L("Height needed: ") << py(punsc) << " mm\n";
if(!report_issue(IssueType::WARN_Q, ss.str(), L("Warning"))) {
if(!ctl->report_issue(IssueType::WARN_Q, ss.str(), L("Warning"))) {
scale_back();
return;
}
}
auto pri = create_progress_indicator(
auto pri = ctl->create_progress_indicator(
200, L("Slicing to zipped png files..."));
pri->on_cancel([&print](){ print->cancel(); });
@ -223,7 +227,7 @@ void PrintController::slice_to_png()
pri->update(0, L("Slicing..."));
slice(pri);
} catch (std::exception& e) {
report_issue(IssueType::ERR, e.what(), L("Exception occurred"));
ctl->report_issue(IssueType::ERR, e.what(), L("Exception occurred"));
scale_back();
if(print->canceled()) print->restart();
return;
@ -242,7 +246,7 @@ void PrintController::slice_to_png()
exd.exp_time_s, exd.exp_time_first_s);
} catch (std::exception& e) {
report_issue(IssueType::ERR, e.what(), L("Exception occurred"));
ctl->report_issue(IssueType::ERR, e.what(), L("Exception occurred"));
}
scale_back();
@ -286,6 +290,8 @@ void AppController::arrange_model()
{
using Coord = libnest2d::TCoord<libnest2d::PointImpl>;
auto ctl = GUI::get_appctl();
if(m_arranging.load()) return;
// to prevent UI reentrancies
@ -294,7 +300,7 @@ void AppController::arrange_model()
unsigned count = 0;
for(auto obj : m_model->objects) count += obj->instances.size();
auto pind = global_progress_indicator();
auto pind = ctl->global_progress_indicator();
float pmax = 1.0;
@ -331,15 +337,15 @@ void AppController::arrange_model()
bed,
hint,
false, // create many piles not just one pile
[this, pind, count](unsigned rem) {
[this, pind, &ctl, count](unsigned rem) {
if(pind)
pind->update(count - rem, L("Arranging objects..."));
process_events();
ctl->process_events();
}, [this] () { return !m_arranging.load(); });
} catch(std::exception& e) {
std::cerr << e.what() << std::endl;
report_issue(IssueType::ERR,
ctl->report_issue(IssueType::ERR,
L("Could not arrange model objects! "
"Some geometries may be invalid."),
L("Exception occurred"));

View File

@ -20,6 +20,21 @@ class PrintConfig;
class ProgressStatusBar;
class DynamicPrintConfig;
/// A Progress indicator object smart pointer
using ProgresIndicatorPtr = std::shared_ptr<ProgressIndicator>;
using FilePath = std::string;
using FilePathList = std::vector<FilePath>;
/// Common runtime issue types
enum class IssueType {
INFO,
WARN,
WARN_Q, // Warning with a question to continue
ERR,
FATAL
};
/**
* @brief A boilerplate class for creating application logic. It should provide
* features as issue reporting and progress indication, etc...
@ -32,34 +47,12 @@ class DynamicPrintConfig;
* UI toolkit dependencies. We can implement it with any UI framework or make it
* a cli client.
*/
class AppControllerBoilerplate {
class AppControllerBase {
public:
/// A Progress indicator object smart pointer
using ProgresIndicatorPtr = std::shared_ptr<ProgressIndicator>;
using Ptr = std::shared_ptr<AppControllerBase>;
private:
class PriData; // Some structure to store progress indication data
// Pimpl data for thread safe progress indication features
std::unique_ptr<PriData> m_pri_data;
public:
AppControllerBoilerplate();
~AppControllerBoilerplate();
using Path = std::string;
using PathList = std::vector<Path>;
/// Common runtime issue types
enum class IssueType {
INFO,
WARN,
WARN_Q, // Warning with a question to continue
ERR,
FATAL
};
inline virtual ~AppControllerBase() {}
/**
* @brief Query some paths from the user.
@ -69,23 +62,28 @@ public:
* @param extensions Recognized file extensions.
* @return Returns a list of paths chosen by the user.
*/
PathList query_destination_paths(
virtual FilePathList query_destination_paths(
const std::string& title,
const std::string& extensions) const;
const std::string& extensions,
const std::string& functionid = "",
const std::string& hint = "") const = 0;
/**
* @brief Same as query_destination_paths but works for directories only.
*/
PathList query_destination_dirs(
const std::string& title) const;
virtual FilePathList query_destination_dirs(
const std::string& title,
const std::string& functionid = "",
const std::string& hint = "") const = 0;
/**
* @brief Same as query_destination_paths but returns only one path.
*/
Path query_destination_path(
virtual FilePath query_destination_path(
const std::string& title,
const std::string& extensions,
const std::string& hint = "") const;
const std::string& functionid = "",
const std::string& hint = "") const = 0;
/**
* @brief Report an issue to the user be it fatal or recoverable.
@ -97,12 +95,9 @@ public:
* @param brief A very brief description. Can be used for message dialog
* title.
*/
bool report_issue(IssueType issuetype,
const std::string& description,
const std::string& brief);
bool report_issue(IssueType issuetype,
const std::string& description);
virtual bool report_issue(IssueType issuetype,
const std::string& description,
const std::string& brief) = 0;
/**
* @brief Return the global progress indicator for the current controller.
@ -110,9 +105,9 @@ public:
*
* Only one thread should use the global indicator at a time.
*/
ProgresIndicatorPtr global_progress_indicator();
virtual ProgresIndicatorPtr global_progress_indicator() = 0;
void global_progress_indicator(ProgresIndicatorPtr gpri);
virtual void global_progress_indicator(ProgresIndicatorPtr gpri) = 0;
/**
* @brief A predicate telling the caller whether it is the thread that
@ -122,7 +117,7 @@ public:
* @return Return true for the same caller thread that created this
* object and false for every other.
*/
bool is_main_thread() const;
virtual bool is_main_thread() const = 0;
/**
* @brief The frontend supports asynch execution.
@ -138,11 +133,9 @@ public:
* @return true if a job or method can be executed asynchronously, false
* otherwise.
*/
bool supports_asynch() const;
virtual bool supports_asynch() const = 0;
void process_events();
protected:
virtual void process_events() = 0;
/**
* @brief Create a new progress indicator and return a smart pointer to it.
@ -151,14 +144,138 @@ protected:
* @param firstmsg The message for the first subtask to be displayed.
* @return Smart pointer to the created object.
*/
ProgresIndicatorPtr create_progress_indicator(
virtual ProgresIndicatorPtr create_progress_indicator(
unsigned statenum,
const std::string& title,
const std::string& firstmsg) const;
const std::string& firstmsg = "") const = 0;
};
ProgresIndicatorPtr create_progress_indicator(
/**
* @brief Implementation of AppControllerBase for the GUI app
*/
class AppControllerGui: public AppControllerBase {
private:
class PriData; // Some structure to store progress indication data
// Pimpl data for thread safe progress indication features
std::unique_ptr<PriData> m_pri_data;
public:
AppControllerGui();
virtual ~AppControllerGui();
virtual FilePathList query_destination_paths(
const std::string& title,
const std::string& extensions,
const std::string& functionid,
const std::string& hint) const override;
virtual FilePathList query_destination_dirs(
const std::string& /*title*/,
const std::string& /*functionid*/,
const std::string& /*hint*/) const override { return {}; }
virtual FilePath query_destination_path(
const std::string& title,
const std::string& extensions,
const std::string& functionid,
const std::string& hint) const override;
virtual bool report_issue(IssueType issuetype,
const std::string& description,
const std::string& brief = std::string()) override;
virtual ProgresIndicatorPtr global_progress_indicator() override;
virtual void global_progress_indicator(ProgresIndicatorPtr gpri) override;
virtual bool is_main_thread() const override;
virtual bool supports_asynch() const override;
virtual void process_events() override;
virtual ProgresIndicatorPtr create_progress_indicator(
unsigned statenum,
const std::string& title) const;
const std::string& title,
const std::string& firstmsg) const override;
protected:
// This is a global progress indicator placeholder. In the Slic3r UI it can
// contain the progress indicator on the statusbar.
ProgresIndicatorPtr m_global_progressind;
};
class AppControllerCli: public AppControllerBase {
class CliProgress : public ProgressIndicator {
std::string m_msg, m_title;
public:
virtual void message(const std::string& msg) override {
m_msg = msg;
}
virtual void title(const std::string& title) override {
m_title = title;
}
};
public:
AppControllerCli() {
std::cout << "Cli AppController ready..." << std::endl;
m_global_progressind = std::make_shared<CliProgress>();
}
virtual ~AppControllerCli() {}
virtual FilePathList query_destination_paths(
const std::string& /*title*/,
const std::string& /*extensions*/,
const std::string& /*functionid*/,
const std::string& /*hint*/) const override { return {}; }
virtual FilePathList query_destination_dirs(
const std::string& /*title*/,
const std::string& /*functionid*/,
const std::string& /*hint*/) const override { return {}; }
virtual FilePath query_destination_path(
const std::string& /*title*/,
const std::string& /*extensions*/,
const std::string& /*functionid*/,
const std::string& /*hint*/) const override { return "out.zip"; }
virtual bool report_issue(IssueType /*issuetype*/,
const std::string& description,
const std::string& brief) override {
std::cerr << brief << ": " << description << std::endl;
return true;
}
virtual ProgresIndicatorPtr global_progress_indicator() override {
return m_global_progressind;
}
virtual void global_progress_indicator(ProgresIndicatorPtr) override {}
virtual bool is_main_thread() const override { return true; }
virtual bool supports_asynch() const override { return false; }
virtual void process_events() override {}
virtual ProgresIndicatorPtr create_progress_indicator(
unsigned /*statenum*/,
const std::string& /*title*/,
const std::string& /*firstmsg*/) const override {
return std::make_shared<CliProgress>();
}
protected:
// This is a global progress indicator placeholder. In the Slic3r UI it can
// contain the progress indicator on the statusbar.
@ -185,7 +302,7 @@ public:
/**
* @brief Implementation of the printing logic.
*/
class PrintController: public AppControllerBoilerplate {
class PrintController {
Print *m_print = nullptr;
std::function<void()> m_rempools;
protected:
@ -241,7 +358,7 @@ public:
/**
* @brief Top level controller.
*/
class AppController: public AppControllerBoilerplate {
class AppController {
Model *m_model = nullptr;
PrintController::Ptr printctl;
std::atomic<bool> m_arranging;

View File

@ -25,40 +25,43 @@
namespace Slic3r {
bool AppControllerBoilerplate::supports_asynch() const
bool AppControllerGui::supports_asynch() const
{
return true;
}
void AppControllerBoilerplate::process_events()
void AppControllerGui::process_events()
{
wxYieldIfNeeded();
}
AppControllerBoilerplate::PathList
AppControllerBoilerplate::query_destination_paths(
FilePathList AppControllerGui::query_destination_paths(
const std::string &title,
const std::string &extensions) const
const std::string &extensions,
const std::string &/*functionid*/,
const std::string& hint) const
{
wxFileDialog dlg(wxTheApp->GetTopWindow(), _(title) );
dlg.SetWildcard(extensions);
dlg.ShowModal();
dlg.SetFilename(hint);
wxArrayString paths;
dlg.GetPaths(paths);
FilePathList ret;
PathList ret(paths.size(), "");
for(auto& p : paths) ret.push_back(p.ToStdString());
if(dlg.ShowModal() == wxID_OK) {
wxArrayString paths;
dlg.GetPaths(paths);
for(auto& p : paths) ret.push_back(p.ToStdString());
}
return ret;
}
AppControllerBoilerplate::Path
AppControllerBoilerplate::query_destination_path(
FilePath AppControllerGui::query_destination_path(
const std::string &title,
const std::string &extensions,
const std::string &/*functionid*/,
const std::string& hint) const
{
wxFileDialog dlg(wxTheApp->GetTopWindow(), _(title) );
@ -66,16 +69,16 @@ AppControllerBoilerplate::query_destination_path(
dlg.SetFilename(hint);
Path ret;
FilePath ret;
if(dlg.ShowModal() == wxID_OK) {
ret = Path(dlg.GetPath());
ret = FilePath(dlg.GetPath());
}
return ret;
}
bool AppControllerBoilerplate::report_issue(IssueType issuetype,
bool AppControllerGui::report_issue(IssueType issuetype,
const std::string &description,
const std::string &brief)
{
@ -93,13 +96,6 @@ bool AppControllerBoilerplate::report_issue(IssueType issuetype,
return ret != wxCANCEL;
}
bool AppControllerBoilerplate::report_issue(
AppControllerBoilerplate::IssueType issuetype,
const std::string &description)
{
return report_issue(issuetype, description, std::string());
}
wxDEFINE_EVENT(PROGRESS_STATUS_UPDATE_EVENT, wxCommandEvent);
struct Zipper::Impl {
@ -235,8 +231,7 @@ public:
};
}
AppControllerBoilerplate::ProgresIndicatorPtr
AppControllerBoilerplate::create_progress_indicator(
ProgresIndicatorPtr AppControllerGui::create_progress_indicator(
unsigned statenum,
const std::string& title,
const std::string& firstmsg) const
@ -251,20 +246,13 @@ AppControllerBoilerplate::create_progress_indicator(
return pri;
}
AppControllerBoilerplate::ProgresIndicatorPtr
AppControllerBoilerplate::create_progress_indicator(
unsigned statenum, const std::string &title) const
{
return create_progress_indicator(statenum, title, std::string());
}
namespace {
class Wrapper: public ProgressIndicator, public wxEvtHandler {
ProgressStatusBar *m_sbar;
using Base = ProgressIndicator;
wxString m_message;
AppControllerBoilerplate& m_ctl;
AppControllerBase& m_ctl;
void showProgress(bool show = true) {
m_sbar->show_progress(show);
@ -288,7 +276,7 @@ class Wrapper: public ProgressIndicator, public wxEvtHandler {
public:
inline Wrapper(ProgressStatusBar *sbar,
AppControllerBoilerplate& ctl):
AppControllerBase& ctl):
m_sbar(sbar), m_ctl(ctl)
{
Base::max(static_cast<float>(m_sbar->get_range()));
@ -344,7 +332,8 @@ public:
void AppController::set_global_progress_indicator(ProgressStatusBar *prsb)
{
if(prsb) {
global_progress_indicator(std::make_shared<Wrapper>(prsb, *this));
auto ctl = GUI::get_appctl();
ctl->global_progress_indicator(std::make_shared<Wrapper>(prsb, *ctl));
}
}

View File

@ -1,4 +1,5 @@
#include "GUI.hpp"
#include "../AppController.hpp"
#include "WipeTowerDialog.hpp"
#include <assert.h>
@ -1405,4 +1406,23 @@ void desktop_open_datadir_folder()
#endif
}
namespace {
AppControllerPtr g_appctl;
}
AppControllerPtr get_appctl()
{
return g_appctl;
}
void set_cli_appctl()
{
g_appctl = std::make_shared<AppControllerCli>();
}
void set_gui_appctl()
{
g_appctl = std::make_shared<AppControllerGui>();
}
} }

View File

@ -42,6 +42,9 @@ class TabIface;
class PreviewIface;
class Print;
class GCodePreviewData;
class AppControllerBase;
using AppControllerPtr = std::shared_ptr<AppControllerBase>;
#define _(s) Slic3r::GUI::I18N::translate((s))
@ -129,6 +132,10 @@ ProgressStatusBar* get_progress_status_bar();
wxNotebook * get_tab_panel();
wxNotebook* get_tab_panel();
AppControllerPtr get_appctl();
void set_cli_appctl();
void set_gui_appctl();
const wxColour& get_label_clr_modified();
const wxColour& get_label_clr_sys();
const wxColour& get_label_clr_default();

View File

@ -35,6 +35,12 @@ bool is_windows10()
void set_wxapp(SV *ui)
%code%{ Slic3r::GUI::set_wxapp((wxApp*)wxPli_sv_2_object(aTHX_ ui, "Wx::App")); %};
void set_gui_appctl()
%code%{ Slic3r::GUI::set_gui_appctl(); %};
void set_cli_appctl()
%code%{ Slic3r::GUI::set_cli_appctl(); %};
void set_progress_status_bar(ProgressStatusBar *prs)
%code%{ Slic3r::GUI::set_progress_status_bar(prs); %};