ConfigWizard refactoring

This commit is contained in:
Vojtech Kral 2019-01-30 15:22:17 +01:00
parent f0cee79170
commit b0f54e5709
9 changed files with 1065 additions and 818 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 55 KiB

View File

@ -5,6 +5,7 @@
#include <unordered_map>
#include <boost/format.hpp>
#include <boost/log/trivial.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <wx/settings.h>
#include <wx/stattext.h>
@ -13,6 +14,10 @@
#include <wx/statbmp.h>
#include <wx/checkbox.h>
#include <wx/statline.h>
#include <wx/dataview.h>
#include <wx/notebook.h>
#include <wx/display.h>
#include <wx/debug.h>
#include "libslic3r/Utils.hpp"
#include "PresetBundle.hpp"
@ -33,12 +38,12 @@ struct PrinterPickerEvent : public wxEvent
std::string variant_name;
bool enable;
PrinterPickerEvent(wxEventType eventType, int winid, std::string vendor_id, std::string model_id, std::string variant_name, bool enable) :
wxEvent(winid, eventType),
vendor_id(std::move(vendor_id)),
model_id(std::move(model_id)),
variant_name(std::move(variant_name)),
enable(enable)
PrinterPickerEvent(wxEventType eventType, int winid, std::string vendor_id, std::string model_id, std::string variant_name, bool enable)
: wxEvent(winid, eventType)
, vendor_id(std::move(vendor_id))
, model_id(std::move(model_id))
, variant_name(std::move(variant_name))
, enable(enable)
{}
virtual wxEvent *Clone() const
@ -49,21 +54,17 @@ struct PrinterPickerEvent : public wxEvent
wxDEFINE_EVENT(EVT_PRINTER_PICK, PrinterPickerEvent);
PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, const AppConfig &appconfig_vendors) :
wxPanel(parent),
vendor_id(vendor.id),
variants_checked(0)
PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxString title, size_t max_cols, const AppConfig &appconfig_vendors, const ModelFilter &filter)
: wxPanel(parent)
, vendor_id(vendor.id)
{
const auto &models = vendor.models;
auto *sizer = new wxBoxSizer(wxVERTICAL);
auto *printer_grid = new wxFlexGridSizer(models.size(), 0, 20);
printer_grid->SetFlexibleDirection(wxVERTICAL | wxHORIZONTAL);
sizer->Add(printer_grid);
auto namefont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
namefont.SetWeight(wxFONTWEIGHT_BOLD);
const auto font_title = GetFont().MakeBold().Scaled(1.3);
const auto font_name = GetFont().MakeBold();
const auto font_alt_nozzle = GetFont().Scaled(0.9);
// wxGrid appends widgets by rows, but we need to construct them in columns.
// These vectors are used to hold the elements so that they can be appended in the right order.
@ -72,10 +73,12 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, cons
std::vector<wxPanel*> variants_panels;
for (const auto &model : models) {
if (! filter(model)) { continue; }
wxBitmap bitmap(GUI::from_u8(Slic3r::var((boost::format("printers/%1%_%2%.png") % vendor.id % model.id).str())), wxBITMAP_TYPE_PNG);
auto *title = new wxStaticText(this, wxID_ANY, model.name, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
title->SetFont(namefont);
title->SetFont(font_name);
title->Wrap(std::max((int)MODEL_MIN_WRAP, bitmap.GetWidth()));
titles.push_back(title);
@ -87,45 +90,105 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, cons
variants_panel->SetSizer(variants_sizer);
const auto model_id = model.id;
bool default_variant = true; // Mark the first variant as default in the GUI
for (const auto &variant : model.variants) {
const auto label = wxString::Format("%s %s %s %s", variant.name, _(L("mm")), _(L("nozzle")),
(default_variant ? "(" + _(L("default")) + ")" : wxString()));
default_variant = false;
for (size_t i = 0; i < model.variants.size(); i++) {
const auto &variant = model.variants[i];
const auto label = model.technology == ptFFF
? wxString::Format("%s %s %s", variant.name, _(L("mm")), _(L("nozzle")))
: from_u8(model.name);
if (i == 1) {
auto *alt_label = new wxStaticText(variants_panel, wxID_ANY, _(L("Alternate nozzles:")));
alt_label->SetFont(font_alt_nozzle);
variants_sizer->Add(alt_label, 0, wxBOTTOM, 3);
}
auto *cbox = new Checkbox(variants_panel, label, model_id, variant.name);
const size_t idx = cboxes.size();
cboxes.push_back(cbox);
i == 0 ? cboxes.push_back(cbox) : cboxes_alt.push_back(cbox);
bool enabled = appconfig_vendors.get_variant("PrusaResearch", model_id, variant.name);
variants_checked += enabled;
cbox->SetValue(enabled);
variants_sizer->Add(cbox, 0, wxBOTTOM, 3);
cbox->Bind(wxEVT_CHECKBOX, [this, idx](wxCommandEvent &event) {
if (idx >= this->cboxes.size()) { return; }
this->on_checkbox(this->cboxes[idx], event.IsChecked());
cbox->Bind(wxEVT_CHECKBOX, [this, cbox](wxCommandEvent &event) {
on_checkbox(cbox, event.IsChecked());
});
}
variants_panels.push_back(variants_panel);
}
for (auto title : titles) { printer_grid->Add(title, 0, wxBOTTOM, 3); }
for (auto bitmap : bitmaps) { printer_grid->Add(bitmap, 0, wxBOTTOM, 20); }
for (auto vp : variants_panels) { printer_grid->Add(vp); }
const size_t cols = std::min(max_cols, titles.size());
auto *all_none_sizer = new wxBoxSizer(wxHORIZONTAL);
auto *sel_all = new wxButton(this, wxID_ANY, _(L("Select all")));
auto *sel_none = new wxButton(this, wxID_ANY, _(L("Select none")));
auto *printer_grid = new wxFlexGridSizer(cols, 0, 20);
printer_grid->SetFlexibleDirection(wxVERTICAL | wxHORIZONTAL);
if (titles.size() > 0) {
const size_t odd_items = titles.size() % cols;
for (size_t i = 0; i < titles.size() - odd_items; i += cols) {
for (size_t j = i; j < i + cols; j++) { printer_grid->Add(titles[j], 0, wxBOTTOM, 3); }
for (size_t j = i; j < i + cols; j++) { printer_grid->Add(bitmaps[j], 0, wxBOTTOM, 20); }
for (size_t j = i; j < i + cols; j++) { printer_grid->Add(variants_panels[j]); }
// Add separator space
if (i > 0) {
for (size_t j = i; j < i + cols; j++) { printer_grid->Add(1, 100); }
}
}
if (odd_items > 0) {
for (size_t i = 0; i < cols; i++) { printer_grid->Add(1, 100); }
const size_t rem = titles.size() - odd_items;
for (size_t i = rem; i < titles.size(); i++) { printer_grid->Add(titles[i], 0, wxBOTTOM, 3); }
for (size_t i = 0; i < cols - odd_items; i++) { printer_grid->AddSpacer(1); }
for (size_t i = rem; i < titles.size(); i++) { printer_grid->Add(bitmaps[i], 0, wxBOTTOM, 20); }
for (size_t i = 0; i < cols - odd_items; i++) { printer_grid->AddSpacer(1); }
for (size_t i = rem; i < titles.size(); i++) { printer_grid->Add(variants_panels[i]); }
}
}
auto *title_sizer = new wxBoxSizer(wxHORIZONTAL);
auto *title_widget = new wxStaticText(this, wxID_ANY, title);
title_widget->SetFont(font_title);
title_sizer->Add(title_widget);
title_sizer->AddStretchSpacer();
if (titles.size() > 1) {
// It only makes sense to add the All / None buttons if there's multiple printers
auto *sel_all = new wxButton(this, wxID_ANY, _(L("All")));
auto *sel_none = new wxButton(this, wxID_ANY, _(L("None")));
sel_all->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &event) { this->select_all(true); });
sel_none->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &event) { this->select_all(false); });
all_none_sizer->AddStretchSpacer();
all_none_sizer->Add(sel_all);
all_none_sizer->Add(sel_none);
sizer->AddStretchSpacer();
sizer->Add(all_none_sizer, 0, wxEXPAND);
title_sizer->Add(sel_all, 0, wxRIGHT, BTN_SPACING);
title_sizer->Add(sel_none);
}
sizer->Add(title_sizer, 0, wxEXPAND | wxBOTTOM, BTN_SPACING);
sizer->Add(printer_grid);
// auto *all_none_sizer = new wxBoxSizer(wxHORIZONTAL);
// auto *sel_all = new wxButton(this, wxID_ANY, _(L("Select all")));
// auto *sel_none = new wxButton(this, wxID_ANY, _(L("Select none")));
// sel_all->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &event) { this->select_all(true); });
// sel_none->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &event) { this->select_all(false); });
// all_none_sizer->AddStretchSpacer();
// all_none_sizer->Add(sel_all);
// all_none_sizer->Add(sel_none);
// sizer->AddStretchSpacer();
// sizer->Add(all_none_sizer, 0, wxEXPAND);
SetSizer(sizer);
}
PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxString title, size_t max_cols, const AppConfig &appconfig_vendors)
: PrinterPicker(parent, vendor, std::move(title), max_cols, appconfig_vendors, [](const VendorProfile::PrinterModel&) { return true; })
{}
void PrinterPicker::select_all(bool select)
{
for (const auto &cb : cboxes) {
@ -134,6 +197,16 @@ void PrinterPicker::select_all(bool select)
on_checkbox(cb, select);
}
}
// Alt nozzles are de-selected if this is an all-deselect, left intact otherwise
if (! select) {
for (const auto &cb : cboxes_alt) {
if (cb->GetValue()) {
cb->SetValue(false);
on_checkbox(cb, false);
}
}
}
}
void PrinterPicker::select_one(size_t i, bool select)
@ -146,7 +219,6 @@ void PrinterPicker::select_one(size_t i, bool select)
void PrinterPicker::on_checkbox(const Checkbox *cbox, bool checked)
{
variants_checked += checked ? 1 : -1;
PrinterPickerEvent evt(EVT_PRINTER_PICK, GetId(), vendor_id, cbox->model, cbox->variant, checked);
AddPendingEvent(evt);
}
@ -154,19 +226,16 @@ void PrinterPicker::on_checkbox(const Checkbox *cbox, bool checked)
// Wizard page base
ConfigWizardPage::ConfigWizardPage(ConfigWizard *parent, wxString title, wxString shortname) :
wxPanel(parent->p->hscroll),
parent(parent),
shortname(std::move(shortname)),
p_prev(nullptr),
p_next(nullptr)
ConfigWizardPage::ConfigWizardPage(ConfigWizard *parent, wxString title, wxString shortname, unsigned indent)
: wxPanel(parent->p->hscroll)
, parent(parent)
, shortname(std::move(shortname))
, indent(indent)
{
auto *sizer = new wxBoxSizer(wxVERTICAL);
auto *text = new wxStaticText(this, wxID_ANY, std::move(title), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
auto font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
font.SetWeight(wxFONTWEIGHT_BOLD);
font.SetPointSize(14);
const auto font = GetFont().MakeBold().Scaled(1.5);
text->SetFont(font);
sizer->Add(text, 0, wxALIGN_LEFT, 0);
sizer->AddSpacer(10);
@ -186,18 +255,6 @@ ConfigWizardPage::ConfigWizardPage(ConfigWizard *parent, wxString title, wxStrin
ConfigWizardPage::~ConfigWizardPage() {}
ConfigWizardPage* ConfigWizardPage::chain(ConfigWizardPage *page)
{
if (p_next != nullptr) { p_next->p_prev = nullptr; }
p_next = page;
if (page != nullptr) {
if (page->p_prev != nullptr) { page->p_prev->p_next = nullptr; }
page->p_prev = this;
}
return page;
}
void ConfigWizardPage::append_text(wxString text)
{
auto *widget = new wxStaticText(this, wxID_ANY, text, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
@ -217,16 +274,12 @@ bool ConfigWizardPage::Show(bool show)
return wxPanel::Show(show);
}
void ConfigWizardPage::enable_next(bool enable) { parent->p->enable_next(enable); }
// Wizard pages
PageWelcome::PageWelcome(ConfigWizard *parent, bool check_first_variant) :
ConfigWizardPage(parent, wxString::Format(_(L("Welcome to the Slic3r %s")), ConfigWizard::name()), _(L("Welcome"))),
printer_picker(nullptr),
others_buttons(new wxPanel(parent)),
cbox_reset(nullptr)
PageWelcome::PageWelcome(ConfigWizard *parent)
: ConfigWizardPage(parent, wxString::Format(_(L("Welcome to the Slic3r %s")), ConfigWizard::name()), _(L("Welcome")))
, cbox_reset(nullptr)
{
if (wizard_p()->run_reason == ConfigWizard::RR_DATA_EMPTY) {
wxString::Format(_(L("Run %s")), ConfigWizard::name());
@ -239,56 +292,81 @@ PageWelcome::PageWelcome(ConfigWizard *parent, bool check_first_variant) :
append(cbox_reset);
}
const auto &vendors = wizard_p()->vendors;
const auto vendor_prusa = vendors.find("PrusaResearch");
Show();
}
PagePrinters::PagePrinters(ConfigWizard *parent, wxString title, wxString shortname, const VendorProfile &vendor, unsigned indent, Technology technology)
: ConfigWizardPage(parent, std::move(title), std::move(shortname), indent)
{
enum {
COL_SIZE = 200,
};
bool check_first_variant = wizard_p()->check_first_variant();
if (vendor_prusa != vendors.cend()) {
AppConfig &appconfig_vendors = this->wizard_p()->appconfig_vendors;
printer_picker = new PrinterPicker(this, vendor_prusa->second, appconfig_vendors);
const auto families = vendor.families();
for (const auto &family : families) {
const auto filter = [&](const VendorProfile::PrinterModel &model) {
return (model.technology == ptFFF && technology & T_FFF
|| model.technology == ptSLA && technology & T_SLA)
&& model.family == family;
};
if (std::find_if(vendor.models.begin(), vendor.models.end(), filter) == vendor.models.end()) {
continue;
}
const auto picker_title = family.empty() ? wxString() : wxString::Format(_(L("%s Family")), family);
auto *picker = new PrinterPicker(this, vendor, picker_title, MAX_COLS, appconfig_vendors, filter);
if (check_first_variant) {
// Select the default (first) model/variant on the Prusa vendor
printer_picker->select_one(0, true);
picker->select_one(0, true);
check_first_variant = false;
}
printer_picker->Bind(EVT_PRINTER_PICK, [this, &appconfig_vendors](const PrinterPickerEvent &evt) {
picker->Bind(EVT_PRINTER_PICK, [this, &appconfig_vendors](const PrinterPickerEvent &evt) {
appconfig_vendors.set_variant(evt.vendor_id, evt.model_id, evt.variant_name, evt.enable);
this->on_variant_checked();
});
append(printer_picker);
append(new wxStaticLine(this));
append(picker);
printer_pickers.push_back(picker);
}
const size_t num_other_vendors = vendors.size() - (vendor_prusa != vendors.cend());
auto *sizer = new wxBoxSizer(wxHORIZONTAL);
auto *other_vendors = new wxButton(others_buttons, wxID_ANY, _(L("Other vendors")));
other_vendors->Enable(num_other_vendors > 0);
auto *custom_setup = new wxButton(others_buttons, wxID_ANY, _(L("Custom setup")));
sizer->Add(other_vendors);
sizer->AddSpacer(BTN_SPACING);
sizer->Add(custom_setup);
other_vendors->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &event) { this->wizard_p()->on_other_vendors(); });
custom_setup->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &event) { this->wizard_p()->on_custom_setup(); });
others_buttons->SetSizer(sizer);
}
void PageWelcome::on_page_set()
void PagePrinters::select_all(bool select)
{
chain(wizard_p()->page_update);
on_variant_checked();
for (auto picker : printer_pickers) {
picker->select_all(select);
}
}
void PageWelcome::on_variant_checked()
PageCustom::PageCustom(ConfigWizard *parent)
: ConfigWizardPage(parent, _(L("Custom Printer Setup")), _(L("Custom Printer")))
{
enable_next(printer_picker != nullptr ? printer_picker->variants_checked > 0 : false);
cb_custom = new wxCheckBox(this, wxID_ANY, _(L("Define a custom printer profile")));
tc_profile_name = new wxTextCtrl(this, wxID_ANY, "My Settings");
auto *label = new wxStaticText(this, wxID_ANY, _(L("Custom profile name:")));
cb_custom->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent &event) {
wizard_p()->on_custom_setup(custom_wanted());
});
append(cb_custom);
append(label);
append(tc_profile_name);
}
PageUpdate::PageUpdate(ConfigWizard *parent) :
ConfigWizardPage(parent, _(L("Automatic updates")), _(L("Updates"))),
version_check(true),
preset_update(true)
PageUpdate::PageUpdate(ConfigWizard *parent)
: ConfigWizardPage(parent, _(L("Automatic updates")), _(L("Updates")))
, version_check(true)
, preset_update(true)
{
const AppConfig *app_config = GUI::get_app_config();
auto boldfont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
@ -316,8 +394,8 @@ PageUpdate::PageUpdate(ConfigWizard *parent) :
box_presets->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent &event) { this->preset_update = event.IsChecked(); });
}
PageVendors::PageVendors(ConfigWizard *parent) :
ConfigWizardPage(parent, _(L("Other Vendors")), _(L("Other Vendors")))
PageVendors::PageVendors(ConfigWizard *parent)
: ConfigWizardPage(parent, _(L("Other Vendors")), _(L("Other Vendors")))
{
append_text(_(L("Pick another vendor supported by Slic3r PE:")));
@ -331,14 +409,13 @@ PageVendors::PageVendors(ConfigWizard *parent) :
const auto &vendor = vendor_pair.second;
if (vendor.id == "PrusaResearch") { continue; }
auto *picker = new PrinterPicker(this, vendor, appconfig_vendors);
auto *picker = new PrinterPicker(this, vendor, "", MAX_COLS, appconfig_vendors);
picker->Hide();
pickers.push_back(picker);
choices_vendors.Add(vendor.name);
picker->Bind(EVT_PRINTER_PICK, [this, &appconfig_vendors](const PrinterPickerEvent &evt) {
appconfig_vendors.set_variant(evt.vendor_id, evt.model_id, evt.variant_name, evt.enable);
this->on_variant_checked();
});
}
@ -356,31 +433,19 @@ PageVendors::PageVendors(ConfigWizard *parent) :
for (PrinterPicker *picker : pickers) { this->append(picker); }
}
void PageVendors::on_page_set()
{
on_variant_checked();
}
void PageVendors::on_vendor_pick(size_t i)
{
for (PrinterPicker *picker : pickers) { picker->Hide(); }
if (i < pickers.size()) {
pickers[i]->Show();
wizard_p()->layout_fit();
parent->Layout();
}
}
void PageVendors::on_variant_checked()
{
size_t variants_checked = 0;
for (const PrinterPicker *picker : pickers) { variants_checked += picker->variants_checked; }
enable_next(variants_checked > 0);
}
PageFirmware::PageFirmware(ConfigWizard *parent) :
ConfigWizardPage(parent, _(L("Firmware Type")), _(L("Firmware"))),
gcode_opt(*print_config_def.get("gcode_flavor")),
gcode_picker(nullptr)
PageFirmware::PageFirmware(ConfigWizard *parent)
: ConfigWizardPage(parent, _(L("Firmware Type")), _(L("Firmware")), 1)
, gcode_opt(*print_config_def.get("gcode_flavor"))
, gcode_picker(nullptr)
{
append_text(_(L("Choose the type of firmware used by your printer.")));
append_text(gcode_opt.tooltip);
@ -409,15 +474,15 @@ PageFirmware::PageFirmware(ConfigWizard *parent) :
void PageFirmware::apply_custom_config(DynamicPrintConfig &config)
{
auto sel = gcode_picker->GetSelection();
if (sel >= 0 && sel < gcode_opt.enum_labels.size()) {
if (sel >= 0 && (size_t)sel < gcode_opt.enum_labels.size()) {
auto *opt = new ConfigOptionEnum<GCodeFlavor>(static_cast<GCodeFlavor>(sel));
config.set_key_value("gcode_flavor", opt);
}
}
PageBedShape::PageBedShape(ConfigWizard *parent) :
ConfigWizardPage(parent, _(L("Bed Shape and Size")), _(L("Bed Shape"))),
shape_panel(new BedShapePanel(this))
PageBedShape::PageBedShape(ConfigWizard *parent)
: ConfigWizardPage(parent, _(L("Bed Shape and Size")), _(L("Bed Shape")), 1)
, shape_panel(new BedShapePanel(this))
{
append_text(_(L("Set the shape of your printer's bed.")));
@ -432,10 +497,10 @@ void PageBedShape::apply_custom_config(DynamicPrintConfig &config)
config.set_key_value("bed_shape", opt);
}
PageDiameters::PageDiameters(ConfigWizard *parent) :
ConfigWizardPage(parent, _(L("Filament and Nozzle Diameters")), _(L("Print Diameters"))),
spin_nozzle(new wxSpinCtrlDouble(this, wxID_ANY)),
spin_filam(new wxSpinCtrlDouble(this, wxID_ANY))
PageDiameters::PageDiameters(ConfigWizard *parent)
: ConfigWizardPage(parent, _(L("Filament and Nozzle Diameters")), _(L("Print Diameters")), 1)
, spin_nozzle(new wxSpinCtrlDouble(this, wxID_ANY))
, spin_filam(new wxSpinCtrlDouble(this, wxID_ANY))
{
spin_nozzle->SetDigits(2);
spin_nozzle->SetIncrement(0.1);
@ -483,10 +548,10 @@ void PageDiameters::apply_custom_config(DynamicPrintConfig &config)
config.set_key_value("filament_diameter", opt_filam);
}
PageTemperatures::PageTemperatures(ConfigWizard *parent) :
ConfigWizardPage(parent, _(L("Extruder and Bed Temperatures")), _(L("Temperatures"))),
spin_extr(new wxSpinCtrlDouble(this, wxID_ANY)),
spin_bed(new wxSpinCtrlDouble(this, wxID_ANY))
PageTemperatures::PageTemperatures(ConfigWizard *parent)
: ConfigWizardPage(parent, _(L("Extruder and Bed Temperatures")), _(L("Temperatures")), 1)
, spin_extr(new wxSpinCtrlDouble(this, wxID_ANY))
, spin_bed(new wxSpinCtrlDouble(this, wxID_ANY))
{
spin_extr->SetIncrement(5.0);
const auto &def_extr = *print_config_def.get("temperature");
@ -542,17 +607,21 @@ void PageTemperatures::apply_custom_config(DynamicPrintConfig &config)
// Index
ConfigWizardIndex::ConfigWizardIndex(wxWindow *parent) :
wxPanel(parent),
bg(GUI::from_u8(Slic3r::var("Slic3r_192px_transparent.png")), wxBITMAP_TYPE_PNG),
bullet_black(GUI::from_u8(Slic3r::var("bullet_black.png")), wxBITMAP_TYPE_PNG),
bullet_blue(GUI::from_u8(Slic3r::var("bullet_blue.png")), wxBITMAP_TYPE_PNG),
bullet_white(GUI::from_u8(Slic3r::var("bullet_white.png")), wxBITMAP_TYPE_PNG)
ConfigWizardIndex::ConfigWizardIndex(wxWindow *parent)
: wxPanel(parent)
, bg(GUI::from_u8(Slic3r::var("Slic3r_192px_transparent.png")), wxBITMAP_TYPE_PNG)
, bullet_black(GUI::from_u8(Slic3r::var("bullet_black.png")), wxBITMAP_TYPE_PNG)
, bullet_blue(GUI::from_u8(Slic3r::var("bullet_blue.png")), wxBITMAP_TYPE_PNG)
, bullet_white(GUI::from_u8(Slic3r::var("bullet_white.png")), wxBITMAP_TYPE_PNG)
, item_active(0)
, item_hover(-1)
, last_page((size_t)-1)
{
SetMinSize(bg.GetSize());
wxClientDC dc(this);
text_height = dc.GetCharHeight();
const wxSize size = GetTextExtent("m");
em = size.x;
em_h = size.y;
// Add logo bitmap.
// This could be done in on_paint() along with the index labels, but I've found it tricky
@ -566,33 +635,103 @@ ConfigWizardIndex::ConfigWizardIndex(wxWindow *parent) :
SetSizer(sizer);
Bind(wxEVT_PAINT, &ConfigWizardIndex::on_paint, this);
}
Bind(wxEVT_MOTION, &ConfigWizardIndex::on_mouse_move, this);
void ConfigWizardIndex::load_items(ConfigWizardPage *firstpage)
{
items.clear();
item_active = items.cend();
for (auto *page = firstpage; page != nullptr; page = page->page_next()) {
items.emplace_back(page->shortname);
Bind(wxEVT_LEAVE_WINDOW, [this](wxMouseEvent &evt) {
if (item_hover != -1) {
item_hover = -1;
Refresh();
}
evt.Skip();
});
Bind(wxEVT_LEFT_UP, [this](wxMouseEvent &evt) {
if (item_hover >= 0) { go_to(item_hover); }
});
}
wxDECLARE_EVENT(EVT_INDEX_PAGE, wxCommandEvent);
void ConfigWizardIndex::add_page(ConfigWizardPage *page)
{
last_page = items.size();
items.emplace_back(Item { page->shortname, page->indent, page });
Refresh();
}
void ConfigWizardIndex::set_active(ConfigWizardPage *page)
void ConfigWizardIndex::add_label(wxString label, unsigned indent)
{
item_active = std::find(items.cbegin(), items.cend(), page->shortname);
items.emplace_back(Item { std::move(label), indent, nullptr });
Refresh();
}
ConfigWizardPage* ConfigWizardIndex::active_page() const
{
if (item_active >= items.size()) { return nullptr; }
return items[item_active].page;
}
void ConfigWizardIndex::go_prev()
{
// Search for a preceiding item that is a page (not a label, ie. page != nullptr)
for (size_t i = item_active; i > 0; i--) {
if (items[i - 1].page != nullptr) {
go_to(i - 1);
return;
}
}
}
void ConfigWizardIndex::go_next()
{
// Search for a next item that is a page (not a label, ie. page != nullptr)
for (size_t i = item_active + 1; i < items.size(); i++) {
if (items[i].page != nullptr) {
go_to(i);
return;
}
}
}
void ConfigWizardIndex::go_to(size_t i)
{
if (i < items.size() && items[i].page != nullptr) {
auto *former_active = active_page();
if (former_active != nullptr) { former_active->Hide(); }
item_active = i;
items[i].page->Show();
wxCommandEvent evt(EVT_INDEX_PAGE, GetId());
AddPendingEvent(evt);
Refresh();
}
}
void ConfigWizardIndex::go_to(ConfigWizardPage *page)
{
if (page == nullptr) { return; }
for (size_t i = 0; i < items.size(); i++) {
if (items[i].page == page) { go_to(i); }
}
}
void ConfigWizardIndex::clear()
{
auto *former_active = active_page();
if (former_active != nullptr) { former_active->Hide(); }
items.clear();
item_active = 0;
}
void ConfigWizardIndex::on_paint(wxPaintEvent & evt)
{
enum {
MARGIN = 10,
SPACING = 5,
};
const auto size = GetClientSize();
if (size.GetHeight() == 0 || size.GetWidth() == 0) { return; }
@ -600,20 +739,40 @@ void ConfigWizardIndex::on_paint(wxPaintEvent & evt)
const auto bullet_w = bullet_black.GetSize().GetWidth();
const auto bullet_h = bullet_black.GetSize().GetHeight();
const int yoff_icon = bullet_h < text_height ? (text_height - bullet_h) / 2 : 0;
const int yoff_text = bullet_h > text_height ? (bullet_h - text_height) / 2 : 0;
const int yinc = std::max(bullet_h, text_height) + SPACING;
const int yoff_icon = bullet_h < em_h ? (em_h - bullet_h) / 2 : 0;
const int yoff_text = bullet_h > em_h ? (bullet_h - em_h) / 2 : 0;
const int yinc = item_height();
unsigned y = 0;
for (auto it = items.cbegin(); it != items.cend(); ++it) {
if (it < item_active) { dc.DrawBitmap(bullet_black, MARGIN, y + yoff_icon, false); }
if (it == item_active) { dc.DrawBitmap(bullet_blue, MARGIN, y + yoff_icon, false); }
if (it > item_active) { dc.DrawBitmap(bullet_white, MARGIN, y + yoff_icon, false); }
dc.DrawText(*it, MARGIN + bullet_w + SPACING, y + yoff_text);
for (size_t i = 0; i < items.size(); i++) {
const Item& item = items[i];
unsigned x = em/2 + item.indent * em;
if (i == item_active || item_hover >= 0 && i == (size_t)item_hover) {
dc.DrawBitmap(bullet_blue, x, y + yoff_icon, false);
}
else if (i < item_active) { dc.DrawBitmap(bullet_black, x, y + yoff_icon, false); }
else if (i > item_active) { dc.DrawBitmap(bullet_white, x, y + yoff_icon, false); }
dc.DrawText(item.label, x + bullet_w + em/2, y + yoff_text);
y += yinc;
}
}
void ConfigWizardIndex::on_mouse_move(wxMouseEvent &evt)
{
const wxClientDC dc(this);
const wxPoint pos = evt.GetLogicalPosition(dc);
const ssize_t item_hover_new = pos.y / item_height();
if (item_hover_new < items.size() && item_hover_new != item_hover) {
item_hover = item_hover_new;
Refresh();
}
evt.Skip();
}
// priv
@ -629,6 +788,36 @@ static const std::unordered_map<std::string, std::pair<std::string, std::string>
{ "Original Prusa i3 MK3.ini", std::make_pair("MK3", "0.4") },
}};
void ConfigWizard::priv::load_pages(bool custom_setup)
{
const auto former_active = index->active_item();
index->clear();
index->add_page(page_welcome);
index->add_page(page_fff);
index->add_page(page_msla);
index->add_page(page_custom);
if (custom_setup) {
index->add_page(page_firmware);
index->add_page(page_bed);
index->add_page(page_diams);
index->add_page(page_temps);
}
index->add_page(page_update);
index->go_to(former_active); // Will restore the active item/page if possible
q->Layout();
}
bool ConfigWizard::priv::check_first_variant() const
{
return run_reason == RR_DATA_EMPTY || run_reason == RR_DATA_LEGACY;
}
void ConfigWizard::priv::load_vendors()
{
const auto vendor_dir = fs::path(Slic3r::data_dir()) / "vendor";
@ -681,44 +870,9 @@ void ConfigWizard::priv::load_vendors()
}
}
void ConfigWizard::priv::index_refresh()
{
index->load_items(page_welcome);
}
void ConfigWizard::priv::add_page(ConfigWizardPage *page)
{
hscroll_sizer->Add(page, 0, wxEXPAND);
auto *extra_buttons = page->extra_buttons();
if (extra_buttons != nullptr) {
btnsizer->Prepend(extra_buttons, 0);
}
}
void ConfigWizard::priv::set_page(ConfigWizardPage *page)
{
if (page == nullptr) { return; }
if (page_current != nullptr) { page_current->Hide(); }
page_current = page;
enable_next(true);
page->on_page_set();
index->load_items(page_welcome);
index->set_active(page);
page->Show();
btn_prev->Enable(page->page_prev() != nullptr);
btn_next->Show(page->page_next() != nullptr);
btn_finish->Show(page->page_next() == nullptr);
layout_fit();
}
void ConfigWizard::priv::layout_fit()
{
q->Layout();
q->Fit();
}
void ConfigWizard::priv::enable_next(bool enable)
@ -727,26 +881,13 @@ void ConfigWizard::priv::enable_next(bool enable)
btn_finish->Enable(enable);
}
void ConfigWizard::priv::on_other_vendors()
void ConfigWizard::priv::on_custom_setup(bool custom_wanted)
{
page_welcome
->chain(page_vendors)
->chain(page_update);
set_page(page_vendors);
}
void ConfigWizard::priv::on_custom_setup()
{
page_welcome->chain(page_firmware);
page_temps->chain(page_update);
set_page(page_firmware);
load_pages(custom_wanted);
}
void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater)
{
const bool is_custom_setup = page_welcome->page_next() == page_firmware;
if (! is_custom_setup) {
const auto enabled_vendors = appconfig_vendors.vendors();
// Install bundles from resources if needed:
@ -788,21 +929,27 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
app_config->set("preset_update", page_update->preset_update ? "1" : "0");
app_config->reset_selections();
preset_bundle->load_presets(*app_config);
} else {
for (ConfigWizardPage *page = page_firmware; page != nullptr; page = page->page_next()) {
page->apply_custom_config(*custom_config);
}
preset_bundle->load_config("My Settings", *custom_config);
if (page_custom->custom_wanted()) {
page_firmware->apply_custom_config(*custom_config);
page_bed->apply_custom_config(*custom_config);
page_diams->apply_custom_config(*custom_config);
page_temps->apply_custom_config(*custom_config);
const std::string profile_name = page_custom->profile_name();
preset_bundle->load_config(profile_name, *custom_config);
}
// Update the selections from the compatibilty.
preset_bundle->export_selections(*app_config);
}
// Public
ConfigWizard::ConfigWizard(wxWindow *parent, RunReason reason) :
wxDialog(parent, wxID_ANY, _(name().ToStdString()), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER),
p(new priv(this))
ConfigWizard::ConfigWizard(wxWindow *parent, RunReason reason)
: wxDialog(parent, wxID_ANY, _(name().ToStdString()), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
, p(new priv(this))
{
p->run_reason = reason;
@ -828,6 +975,9 @@ ConfigWizard::ConfigWizard(wxWindow *parent, RunReason reason) :
topsizer->AddSpacer(INDEX_MARGIN);
topsizer->Add(p->hscroll, 1, wxEXPAND);
auto *btn_sel_all = new wxButton(this, wxID_ANY, _(L("Select all printers")));
p->btnsizer->Add(btn_sel_all);
p->btn_prev = new wxButton(this, wxID_ANY, _(L("< &Back")));
p->btn_next = new wxButton(this, wxID_ANY, _(L("&Next >")));
p->btn_finish = new wxButton(this, wxID_APPLY, _(L("&Finish")));
@ -838,45 +988,78 @@ ConfigWizard::ConfigWizard(wxWindow *parent, RunReason reason) :
p->btnsizer->Add(p->btn_finish, 0, wxLEFT, BTN_SPACING);
p->btnsizer->Add(p->btn_cancel, 0, wxLEFT, BTN_SPACING);
p->add_page(p->page_welcome = new PageWelcome(this, reason == RR_DATA_EMPTY || reason == RR_DATA_LEGACY));
const auto &vendors = p->vendors;
const auto vendor_prusa_it = vendors.find("PrusaResearch");
wxCHECK_RET(vendor_prusa_it != vendors.cend(), "Vendor PrusaResearch not found");
const VendorProfile &vendor_prusa = vendor_prusa_it->second;
p->add_page(p->page_welcome = new PageWelcome(this));
p->page_fff = new PagePrinters(this, _(L("Prusa FFF Technology Printers")), "Prusa FFF", vendor_prusa, 0, PagePrinters::T_FFF);
p->add_page(p->page_fff);
p->page_msla = new PagePrinters(this, _(L("Prusa MSLA Technology Printers")), "Prusa MSLA", vendor_prusa, 0, PagePrinters::T_SLA);
p->add_page(p->page_msla);
p->add_page(p->page_custom = new PageCustom(this));
p->add_page(p->page_update = new PageUpdate(this));
p->add_page(p->page_vendors = new PageVendors(this));
p->add_page(p->page_firmware = new PageFirmware(this));
p->add_page(p->page_bed = new PageBedShape(this));
p->add_page(p->page_diams = new PageDiameters(this));
p->add_page(p->page_temps = new PageTemperatures(this));
p->index_refresh();
p->page_welcome->chain(p->page_update);
p->page_firmware
->chain(p->page_bed)
->chain(p->page_diams)
->chain(p->page_temps);
p->load_pages(false);
vsizer->Add(topsizer, 1, wxEXPAND | wxALL, DIALOG_MARGIN);
vsizer->Add(hline, 0, wxEXPAND);
vsizer->Add(p->btnsizer, 0, wxEXPAND | wxALL, DIALOG_MARGIN);
p->set_page(p->page_welcome);
SetSizer(vsizer);
SetSizerAndFit(vsizer);
// We can now enable scrolling on hscroll
p->hscroll->SetScrollRate(30, 30);
// Compare current ("ideal") wizard size with the size of the current screen.
// If the screen is smaller, resize wizrad to match, which will enable scrollbars.
auto wizard_size = GetSize();
unsigned width, height;
if (GUI::get_current_screen_size(this, width, height)) {
wizard_size.SetWidth(std::min(wizard_size.GetWidth(), (int)(width - 2 * DIALOG_MARGIN)));
wizard_size.SetHeight(std::min(wizard_size.GetHeight(), (int)(height - 2 * DIALOG_MARGIN)));
SetMinSize(wizard_size);
}
Fit();
p->btn_prev->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &evt) { this->p->go_prev(); });
p->btn_next->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &evt) { this->p->go_next(); });
p->btn_finish->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &evt) { this->EndModal(wxID_OK); });
// XXX: set size right away on windows, create util function
Bind(wxEVT_CREATE, [this](wxWindowCreateEvent &event) {
CallAfter([this]() {
// Clamp the Wizard size based on screen dimensions
// Note: Using EVT_SHOW + CallAfter because any sooner than this
// on some Linux boxes wxDisplay::GetFromWindow() returns 0 no matter what.
const auto idx = wxDisplay::GetFromWindow(this);
wxDisplay display(idx != wxNOT_FOUND ? idx : 0u);
const auto disp_rect = display.GetClientArea();
wxRect window_rect(
disp_rect.x + disp_rect.width / 20,
disp_rect.y + disp_rect.height / 20,
9*disp_rect.width / 10,
9*disp_rect.height / 10);
SetSize(window_rect);
});
});
p->btn_prev->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &) { this->p->index->go_prev(); });
p->btn_next->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &) { this->p->index->go_next(); });
p->btn_finish->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &) { this->EndModal(wxID_OK); });
p->btn_finish->Hide();
btn_sel_all->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &) {
p->page_fff->select_all(true);
p->page_msla->select_all(true);
p->index->go_to(p->page_update);
});
p->index->Bind(EVT_INDEX_PAGE, [this](const wxCommandEvent &) {
const bool is_last = p->index->active_is_last();
p->btn_next->Show(! is_last);
p->btn_finish->Show(is_last);
Layout();
});
}
ConfigWizard::~ConfigWizard() {}

View File

@ -6,6 +6,7 @@
#include <vector>
#include <set>
#include <unordered_map>
#include <functional>
#include <boost/filesystem.hpp>
#include <wx/sizer.h>
@ -13,6 +14,7 @@
#include <wx/button.h>
#include <wx/choice.h>
#include <wx/spinctrl.h>
#include <wx/textctrl.h>
#include "libslic3r/PrintConfig.hpp"
#include "slic3r/Utils/PresetUpdater.hpp"
@ -34,8 +36,13 @@ enum {
BTN_SPACING = 10,
INDENT_SPACING = 30,
VERTICAL_SPACING = 10,
MAX_COLS = 4,
ROW_SPACING = 75,
};
typedef std::function<bool(const VendorProfile::PrinterModel&)> ModelFilter;
struct PrinterPicker: wxPanel
{
struct Checkbox : wxCheckBox
@ -52,9 +59,10 @@ struct PrinterPicker: wxPanel
const std::string vendor_id;
std::vector<Checkbox*> cboxes;
unsigned variants_checked;
std::vector<Checkbox*> cboxes_alt;
PrinterPicker(wxWindow *parent, const VendorProfile &vendor, const AppConfig &appconfig_vendors);
PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxString title, size_t max_cols, const AppConfig &appconfig_vendors, const ModelFilter &filter);
PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxString title, size_t max_cols, const AppConfig &appconfig_vendors);
void select_all(bool select);
void select_one(size_t i, bool select);
@ -66,15 +74,11 @@ struct ConfigWizardPage: wxPanel
ConfigWizard *parent;
const wxString shortname;
wxBoxSizer *content;
const unsigned indent;
ConfigWizardPage(ConfigWizard *parent, wxString title, wxString shortname);
ConfigWizardPage(ConfigWizard *parent, wxString title, wxString shortname, unsigned indent = 0);
virtual ~ConfigWizardPage();
ConfigWizardPage* page_prev() const { return p_prev; }
ConfigWizardPage* page_next() const { return p_next; }
ConfigWizardPage* chain(ConfigWizardPage *page);
template<class T>
void append(T *thing, int proportion = 0, int flag = wxEXPAND|wxTOP|wxBOTTOM, int border = 10)
{
@ -88,29 +92,46 @@ struct ConfigWizardPage: wxPanel
virtual bool Show(bool show = true);
virtual bool Hide() { return Show(false); }
virtual wxPanel* extra_buttons() { return nullptr; }
virtual void on_page_set() {}
virtual wxPanel* extra_buttons() { return nullptr; } // XXX
virtual void apply_custom_config(DynamicPrintConfig &config) {}
void enable_next(bool enable);
private:
ConfigWizardPage *p_prev;
ConfigWizardPage *p_next;
};
struct PageWelcome: ConfigWizardPage
{
PrinterPicker *printer_picker;
wxPanel *others_buttons;
wxCheckBox *cbox_reset;
PageWelcome(ConfigWizard *parent, bool check_first_variant);
virtual wxPanel* extra_buttons() { return others_buttons; }
virtual void on_page_set();
PageWelcome(ConfigWizard *parent);
bool reset_user_profile() const { return cbox_reset != nullptr ? cbox_reset->GetValue() : false; }
void on_variant_checked();
};
struct PagePrinters: ConfigWizardPage
{
enum Technology {
// Bitflag equivalent of PrinterTechnology
T_FFF = 0x1,
T_SLA = 0x2,
T_Any = ~0,
};
std::vector<PrinterPicker *> printer_pickers;
PagePrinters(ConfigWizard *parent, wxString title, wxString shortname, const VendorProfile &vendor, unsigned indent, Technology technology);
void select_all(bool select);
};
struct PageCustom: ConfigWizardPage
{
PageCustom(ConfigWizard *parent);
bool custom_wanted() const { return cb_custom->GetValue(); }
std::string profile_name() const { return into_u8(tc_profile_name->GetValue()); }
private:
wxCheckBox *cb_custom;
wxTextCtrl *tc_profile_name;
};
struct PageUpdate: ConfigWizardPage
@ -127,10 +148,7 @@ struct PageVendors: ConfigWizardPage
PageVendors(ConfigWizard *parent);
virtual void on_page_set();
void on_vendor_pick(size_t i);
void on_variant_checked();
};
struct PageFirmware: ConfigWizardPage
@ -174,21 +192,62 @@ class ConfigWizardIndex: public wxPanel
public:
ConfigWizardIndex(wxWindow *parent);
void load_items(ConfigWizardPage *firstpage);
void set_active(ConfigWizardPage *page);
void add_page(ConfigWizardPage *page);
void add_label(wxString label, unsigned indent = 0);
size_t active_item() const { return item_active; }
ConfigWizardPage* active_page() const;
bool active_is_last() const { return item_active < items.size() && item_active == last_page; }
void go_prev();
void go_next();
void go_to(size_t i);
void go_to(ConfigWizardPage *page);
void clear();
// XXX
// void load_items(ConfigWizardPage *firstpage);
// void set_active(ConfigWizardPage *page);
private:
// enum {
// // Units in em
// MARGIN = 1,
// SPACING = 1,
// };
struct Item
{
wxString label;
unsigned indent;
ConfigWizardPage *page; // nullptr page => label-only item
// bool operator==(const wxString &label) const { return this->label == label; }
bool operator==(ConfigWizardPage *page) const { return this->page == page; }
};
int em;
int em_h;
const wxBitmap bg;
const wxBitmap bullet_black;
const wxBitmap bullet_blue;
const wxBitmap bullet_white;
int text_height;
std::vector<wxString> items;
std::vector<wxString>::const_iterator item_active;
std::vector<Item> items;
// std::vector<Item>::const_iterator item_active;
size_t item_active;
ssize_t item_hover;
size_t last_page;
int item_height() const { return std::max(bullet_black.GetSize().GetHeight(), em) + em; }
void on_paint(wxPaintEvent &evt);
void on_mouse_move(wxMouseEvent &evt);
};
wxDEFINE_EVENT(EVT_INDEX_PAGE, wxCommandEvent);
struct ConfigWizard::priv
{
ConfigWizard *q;
@ -209,8 +268,13 @@ struct ConfigWizard::priv
wxButton *btn_cancel = nullptr;
PageWelcome *page_welcome = nullptr;
PagePrinters *page_fff = nullptr;
PagePrinters *page_msla = nullptr;
PageCustom *page_custom = nullptr;
PageUpdate *page_update = nullptr;
PageVendors *page_vendors = nullptr;
PageVendors *page_vendors = nullptr; // XXX: ?
// Custom setup pages
PageFirmware *page_firmware = nullptr;
PageBedShape *page_bed = nullptr;
PageDiameters *page_diams = nullptr;
@ -218,17 +282,14 @@ struct ConfigWizard::priv
priv(ConfigWizard *q) : q(q) {}
void load_pages(bool custom_setup);
bool check_first_variant() const;
void load_vendors();
void add_page(ConfigWizardPage *page);
void index_refresh();
void set_page(ConfigWizardPage *page);
void layout_fit();
void go_prev() { if (page_current != nullptr) { set_page(page_current->page_prev()); } }
void go_next() { if (page_current != nullptr) { set_page(page_current->page_next()); } }
void enable_next(bool enable);
void on_other_vendors();
void on_custom_setup();
void on_custom_setup(bool custom_wanted);
void apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater);
};

View File

@ -355,21 +355,6 @@ boost::filesystem::path into_path(const wxString &str)
return boost::filesystem::path(str.wx_str());
}
bool get_current_screen_size(wxWindow *window, unsigned &width, unsigned &height)
{
const auto idx = wxDisplay::GetFromWindow(window);
if (idx == wxNOT_FOUND) {
return false;
}
wxDisplay display(idx);
const auto disp_size = display.GetClientArea();
width = disp_size.GetWidth();
height = disp_size.GetHeight();
return true;
}
void about()
{
AboutDialog dlg;

View File

@ -71,9 +71,6 @@ wxString from_path(const boost::filesystem::path &path);
// boost path from wxString
boost::filesystem::path into_path(const wxString &str);
// Returns the dimensions of the screen on which the main frame is displayed
bool get_current_screen_size(wxWindow *window, unsigned &width, unsigned &height);
// Display an About dialog
extern void about();
// Ask the destop to open the datadir using the default file explorer.

View File

@ -12,7 +12,6 @@
#include <wx/sizer.h>
#include <wx/stattext.h>
#include <wx/notebook.h>
#include <wx/button.h>
#include <wx/bmpcbox.h>
#include <wx/statbox.h>

View File

@ -11,6 +11,7 @@
#include <Windows.h>
#endif /* _MSC_VER */
#include <algorithm>
#include <fstream>
#include <stdexcept>
#include <boost/format.hpp>
@ -128,11 +129,14 @@ VendorProfile VendorProfile::from_ini(const ptree &tree, const boost::filesystem
VendorProfile::PrinterModel model;
model.id = section.first.substr(printer_model_key.size());
model.name = section.second.get<std::string>("name", model.id);
auto technology_field = section.second.get<std::string>("technology", "FFF");
if (! ConfigOptionEnum<PrinterTechnology>::from_string(technology_field, model.technology)) {
BOOST_LOG_TRIVIAL(error) << boost::format("Vendor bundle: `%1%`: Invalid printer technology field: `%2%`") % id % technology_field;
model.technology = ptFFF;
}
model.family = section.second.get<std::string>("family", model.id);
#if 0
// Remove SLA printers from the initial alpha.
if (model.technology == ptSLA)
@ -157,6 +161,20 @@ VendorProfile VendorProfile::from_ini(const ptree &tree, const boost::filesystem
return res;
}
std::vector<std::string> VendorProfile::families() const
{
std::vector<std::string> res;
unsigned num_familiies = 0;
for (auto &model : models) {
if (!model.family.empty() && std::find(res.begin(), res.end(), model.family) == res.end()) {
res.push_back(model.family);
num_familiies++;
}
}
return res;
}
// Suffix to be added to a modified preset name in the combo box.
static std::string g_suffix_modified = " (modified)";

View File

@ -54,13 +54,16 @@ public:
std::string id;
std::string name;
PrinterTechnology technology;
std::string family;
std::vector<PrinterVariant> variants;
PrinterVariant* variant(const std::string &name) {
for (auto &v : this->variants)
if (v.name == name)
return &v;
return nullptr;
}
const PrinterVariant* variant(const std::string &name) const { return const_cast<PrinterModel*>(this)->variant(name); }
};
std::vector<PrinterModel> models;
@ -72,6 +75,7 @@ public:
static VendorProfile from_ini(const boost::property_tree::ptree &tree, const boost::filesystem::path &path, bool load_all=true);
size_t num_variants() const { size_t n = 0; for (auto &model : models) n += model.variants.size(); return n; }
std::vector<std::string> families() const;
bool operator< (const VendorProfile &rhs) const { return this->id < rhs.id; }
bool operator==(const VendorProfile &rhs) const { return this->id == rhs.id; }