2018-03-13 11:39:57 +00:00
# include "ConfigWizard_private.hpp"
# include <algorithm>
2019-02-12 09:10:46 +00:00
# include <numeric>
2018-03-13 11:39:57 +00:00
# include <utility>
2018-04-16 14:52:11 +00:00
# include <unordered_map>
2018-06-04 07:07:29 +00:00
# include <boost/format.hpp>
2018-05-02 10:44:53 +00:00
# include <boost/log/trivial.hpp>
2019-01-30 14:22:17 +00:00
# include <boost/algorithm/string/predicate.hpp>
2018-05-02 10:44:53 +00:00
2018-03-13 11:39:57 +00:00
# include <wx/settings.h>
# include <wx/stattext.h>
# include <wx/textctrl.h>
# include <wx/dcclient.h>
# include <wx/statbmp.h>
# include <wx/checkbox.h>
# include <wx/statline.h>
2019-01-30 14:22:17 +00:00
# include <wx/dataview.h>
# include <wx/notebook.h>
# include <wx/display.h>
2019-04-24 14:02:49 +00:00
# include <wx/filefn.h>
2019-01-30 14:22:17 +00:00
# include <wx/debug.h>
2018-03-13 11:39:57 +00:00
# include "libslic3r/Utils.hpp"
# include "PresetBundle.hpp"
# include "GUI.hpp"
2019-02-07 14:55:47 +00:00
# include "GUI_Utils.hpp"
2018-04-11 11:12:08 +00:00
# include "slic3r/Utils/PresetUpdater.hpp"
2018-03-13 11:39:57 +00:00
namespace Slic3r {
namespace GUI {
2018-04-05 16:30:03 +00:00
// Printer model picker GUI control
struct PrinterPickerEvent : public wxEvent
{
2019-01-30 14:22:17 +00:00
std : : string vendor_id ;
std : : string model_id ;
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 )
{ }
virtual wxEvent * Clone ( ) const
{
return new PrinterPickerEvent ( * this ) ;
}
2018-04-05 16:30:03 +00:00
} ;
wxDEFINE_EVENT ( EVT_PRINTER_PICK , PrinterPickerEvent ) ;
2019-01-30 14:22:17 +00:00
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 )
2019-02-12 09:10:46 +00:00
, width ( 0 )
2019-01-30 14:22:17 +00:00
{
const auto & models = vendor . models ;
auto * sizer = new wxBoxSizer ( wxVERTICAL ) ;
2019-02-19 13:57:59 +00:00
const auto font_title = GetFont ( ) . MakeBold ( ) . Scaled ( 1.3f ) ;
2019-01-30 14:22:17 +00:00
const auto font_name = GetFont ( ) . MakeBold ( ) ;
2019-02-19 13:57:59 +00:00
const auto font_alt_nozzle = GetFont ( ) . Scaled ( 0.9f ) ;
2019-01-30 14:22:17 +00:00
// 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.
std : : vector < wxStaticText * > titles ;
std : : vector < wxStaticBitmap * > bitmaps ;
std : : vector < wxPanel * > variants_panels ;
2019-02-12 09:10:46 +00:00
int max_row_width = 0 ;
int current_row_width = 0 ;
2019-01-30 14:22:17 +00:00
for ( const auto & model : models ) {
if ( ! filter ( model ) ) { continue ; }
2019-04-24 14:02:49 +00:00
wxBitmap bitmap ;
int bitmap_width = 0 ;
const wxString bitmap_file = GUI : : from_u8 ( Slic3r : : var ( ( boost : : format ( " printers/%1%_%2%.png " ) % vendor . id % model . id ) . str ( ) ) ) ;
if ( wxFileExists ( bitmap_file ) ) {
bitmap . LoadFile ( bitmap_file , wxBITMAP_TYPE_PNG ) ;
bitmap_width = bitmap . GetWidth ( ) ;
}
2019-01-30 14:22:17 +00:00
auto * title = new wxStaticText ( this , wxID_ANY , model . name , wxDefaultPosition , wxDefaultSize , wxALIGN_LEFT ) ;
title - > SetFont ( font_name ) ;
2019-04-24 14:02:49 +00:00
const int wrap_width = std : : max ( ( int ) MODEL_MIN_WRAP , bitmap_width ) ;
2019-02-12 09:10:46 +00:00
title - > Wrap ( wrap_width ) ;
current_row_width + = wrap_width ;
if ( titles . size ( ) % max_cols = = max_cols - 1 ) {
max_row_width = std : : max ( max_row_width , current_row_width ) ;
current_row_width = 0 ;
}
2019-01-30 14:22:17 +00:00
titles . push_back ( title ) ;
auto * bitmap_widget = new wxStaticBitmap ( this , wxID_ANY , bitmap ) ;
bitmaps . push_back ( bitmap_widget ) ;
auto * variants_panel = new wxPanel ( this ) ;
auto * variants_sizer = new wxBoxSizer ( wxVERTICAL ) ;
variants_panel - > SetSizer ( variants_sizer ) ;
const auto model_id = model . id ;
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 ) ;
i = = 0 ? cboxes . push_back ( cbox ) : cboxes_alt . push_back ( cbox ) ;
bool enabled = appconfig_vendors . get_variant ( " PrusaResearch " , model_id , variant . name ) ;
cbox - > SetValue ( enabled ) ;
variants_sizer - > Add ( cbox , 0 , wxBOTTOM , 3 ) ;
cbox - > Bind ( wxEVT_CHECKBOX , [ this , cbox ] ( wxCommandEvent & event ) {
on_checkbox ( cbox , event . IsChecked ( ) ) ;
} ) ;
}
variants_panels . push_back ( variants_panel ) ;
}
2019-02-12 09:10:46 +00:00
width = std : : max ( max_row_width , current_row_width ) ;
2019-01-30 14:22:17 +00:00
const size_t cols = std : : min ( max_cols , titles . size ( ) ) ;
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 ) ;
2019-02-07 14:55:47 +00:00
if ( ! title . IsEmpty ( ) ) {
auto * title_widget = new wxStaticText ( this , wxID_ANY , title ) ;
title_widget - > SetFont ( font_title ) ;
title_sizer - > Add ( title_widget ) ;
}
2019-01-30 14:22:17 +00:00
title_sizer - > AddStretchSpacer ( ) ;
if ( titles . size ( ) > 1 ) {
// It only makes sense to add the All / None buttons if there's multiple printers
2019-02-12 10:01:15 +00:00
auto * sel_all_std = new wxButton ( this , wxID_ANY , _ ( L ( " All standard " ) ) ) ;
2019-01-30 14:22:17 +00:00
auto * sel_all = new wxButton ( this , wxID_ANY , _ ( L ( " All " ) ) ) ;
auto * sel_none = new wxButton ( this , wxID_ANY , _ ( L ( " None " ) ) ) ;
2019-02-12 10:01:15 +00:00
sel_all_std - > Bind ( wxEVT_BUTTON , [ this ] ( const wxCommandEvent & event ) { this - > select_all ( true , false ) ; } ) ;
sel_all - > Bind ( wxEVT_BUTTON , [ this ] ( const wxCommandEvent & event ) { this - > select_all ( true , true ) ; } ) ;
2019-01-30 14:22:17 +00:00
sel_none - > Bind ( wxEVT_BUTTON , [ this ] ( const wxCommandEvent & event ) { this - > select_all ( false ) ; } ) ;
2019-02-12 10:01:15 +00:00
title_sizer - > Add ( sel_all_std , 0 , wxRIGHT , BTN_SPACING ) ;
2019-01-30 14:22:17 +00:00
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 ) ;
SetSizer ( sizer ) ;
2018-04-16 14:52:11 +00:00
}
2019-01-30 14:22:17 +00:00
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 ; } )
{ }
2019-02-12 10:01:15 +00:00
void PrinterPicker : : select_all ( bool select , bool alternates )
2018-04-16 14:52:11 +00:00
{
2019-01-30 14:22:17 +00:00
for ( const auto & cb : cboxes ) {
if ( cb - > GetValue ( ) ! = select ) {
cb - > SetValue ( select ) ;
on_checkbox ( cb , select ) ;
}
}
2019-02-12 10:01:15 +00:00
if ( ! select ) { alternates = false ; }
for ( const auto & cb : cboxes_alt ) {
if ( cb - > GetValue ( ) ! = alternates ) {
cb - > SetValue ( alternates ) ;
on_checkbox ( cb , alternates ) ;
2019-01-30 14:22:17 +00:00
}
}
2018-04-16 14:52:11 +00:00
}
2018-06-22 13:01:33 +00:00
void PrinterPicker : : select_one ( size_t i , bool select )
{
2019-01-30 14:22:17 +00:00
if ( i < cboxes . size ( ) & & cboxes [ i ] - > GetValue ( ) ! = select ) {
cboxes [ i ] - > SetValue ( select ) ;
on_checkbox ( cboxes [ i ] , select ) ;
}
2018-06-22 13:01:33 +00:00
}
2018-04-16 14:52:11 +00:00
void PrinterPicker : : on_checkbox ( const Checkbox * cbox , bool checked )
{
2019-01-30 14:22:17 +00:00
PrinterPickerEvent evt ( EVT_PRINTER_PICK , GetId ( ) , vendor_id , cbox - > model , cbox - > variant , checked ) ;
AddPendingEvent ( evt ) ;
2018-04-05 16:30:03 +00:00
}
2018-03-13 11:39:57 +00:00
// Wizard page base
2019-01-30 14:22:17 +00:00
ConfigWizardPage : : ConfigWizardPage ( ConfigWizard * parent , wxString title , wxString shortname , unsigned indent )
: wxPanel ( parent - > p - > hscroll )
, parent ( parent )
, shortname ( std : : move ( shortname ) )
, indent ( indent )
2018-03-13 11:39:57 +00:00
{
2019-01-30 14:22:17 +00:00
auto * sizer = new wxBoxSizer ( wxVERTICAL ) ;
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
auto * text = new wxStaticText ( this , wxID_ANY , std : : move ( title ) , wxDefaultPosition , wxDefaultSize , wxALIGN_LEFT ) ;
const auto font = GetFont ( ) . MakeBold ( ) . Scaled ( 1.5 ) ;
text - > SetFont ( font ) ;
sizer - > Add ( text , 0 , wxALIGN_LEFT , 0 ) ;
sizer - > AddSpacer ( 10 ) ;
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
content = new wxBoxSizer ( wxVERTICAL ) ;
sizer - > Add ( content , 1 ) ;
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
SetSizer ( sizer ) ;
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
this - > Hide ( ) ;
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
Bind ( wxEVT_SIZE , [ this ] ( wxSizeEvent & event ) {
this - > Layout ( ) ;
event . Skip ( ) ;
} ) ;
2018-03-13 11:39:57 +00:00
}
ConfigWizardPage : : ~ ConfigWizardPage ( ) { }
void ConfigWizardPage : : append_text ( wxString text )
{
2019-01-30 14:22:17 +00:00
auto * widget = new wxStaticText ( this , wxID_ANY , text , wxDefaultPosition , wxDefaultSize , wxALIGN_LEFT ) ;
widget - > Wrap ( WRAP_WIDTH ) ;
widget - > SetMinSize ( wxSize ( WRAP_WIDTH , - 1 ) ) ;
append ( widget ) ;
2018-03-13 11:39:57 +00:00
}
void ConfigWizardPage : : append_spacer ( int space )
{
2019-01-30 14:22:17 +00:00
content - > AddSpacer ( space ) ;
2018-03-13 11:39:57 +00:00
}
// Wizard pages
2019-01-30 14:22:17 +00:00
PageWelcome : : PageWelcome ( ConfigWizard * parent )
2019-04-15 14:14:19 +00:00
: ConfigWizardPage ( parent , wxString : : Format ( _ ( L ( " Welcome to the %s %s " ) ) , SLIC3R_APP_NAME , ConfigWizard : : name ( ) ) , _ ( L ( " Welcome " ) ) )
2019-01-30 14:22:17 +00:00
, cbox_reset ( nullptr )
2018-04-18 09:40:43 +00:00
{
2019-01-30 14:22:17 +00:00
if ( wizard_p ( ) - > run_reason = = ConfigWizard : : RR_DATA_EMPTY ) {
wxString : : Format ( _ ( L ( " Run %s " ) ) , ConfigWizard : : name ( ) ) ;
append_text ( wxString : : Format (
2019-04-15 14:14:19 +00:00
_ ( L ( " Hello, welcome to %s! This %s helps you with the initial configuration; just a few settings and you will be ready to print. " ) ) ,
SLIC3R_APP_NAME ,
2019-01-30 14:22:17 +00:00
ConfigWizard : : name ( ) )
) ;
} else {
cbox_reset = new wxCheckBox ( this , wxID_ANY , _ ( L ( " Remove user profiles - install from scratch (a snapshot will be taken beforehand) " ) ) ) ;
append ( cbox_reset ) ;
}
Show ( ) ;
}
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
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 ,
} ;
2018-04-05 16:30:03 +00:00
2019-01-30 14:22:17 +00:00
bool check_first_variant = wizard_p ( ) - > check_first_variant ( ) ;
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
AppConfig & appconfig_vendors = this - > wizard_p ( ) - > appconfig_vendors ;
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
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 ;
} ;
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
if ( std : : find_if ( vendor . models . begin ( ) , vendor . models . end ( ) , filter ) = = vendor . models . end ( ) ) {
continue ;
}
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
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 ) ;
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
if ( check_first_variant ) {
// Select the default (first) model/variant on the Prusa vendor
picker - > select_one ( 0 , true ) ;
check_first_variant = false ;
}
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
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 ) ;
} ) ;
append ( new wxStaticLine ( this ) ) ;
append ( picker ) ;
printer_pickers . push_back ( picker ) ;
}
2018-03-13 11:39:57 +00:00
}
2019-02-12 10:01:15 +00:00
void PagePrinters : : select_all ( bool select , bool alternates )
2018-03-13 11:39:57 +00:00
{
2019-01-30 14:22:17 +00:00
for ( auto picker : printer_pickers ) {
2019-02-12 10:01:15 +00:00
picker - > select_all ( select , alternates ) ;
2019-01-30 14:22:17 +00:00
}
2018-03-13 11:39:57 +00:00
}
2019-02-12 09:10:46 +00:00
int PagePrinters : : get_width ( ) const
{
return std : : accumulate ( printer_pickers . begin ( ) , printer_pickers . end ( ) , 0 ,
[ ] ( int acc , const PrinterPicker * picker ) { return std : : max ( acc , picker - > get_width ( ) ) ; } ) ;
}
2018-04-05 14:10:44 +00:00
2019-02-07 14:55:47 +00:00
const char * PageCustom : : default_profile_name = " My Settings " ;
2019-01-30 14:22:17 +00:00
PageCustom : : PageCustom ( ConfigWizard * parent )
: ConfigWizardPage ( parent , _ ( L ( " Custom Printer Setup " ) ) , _ ( L ( " Custom Printer " ) ) )
{
cb_custom = new wxCheckBox ( this , wxID_ANY , _ ( L ( " Define a custom printer profile " ) ) ) ;
2019-02-07 14:55:47 +00:00
tc_profile_name = new wxTextCtrl ( this , wxID_ANY , default_profile_name ) ;
2019-01-30 14:22:17 +00:00
auto * label = new wxStaticText ( this , wxID_ANY , _ ( L ( " Custom profile name: " ) ) ) ;
2018-04-17 09:54:59 +00:00
2019-02-12 10:01:15 +00:00
tc_profile_name - > Enable ( false ) ;
2019-02-07 14:55:47 +00:00
tc_profile_name - > Bind ( wxEVT_KILL_FOCUS , [ this ] ( wxFocusEvent & evt ) {
if ( tc_profile_name - > GetValue ( ) . IsEmpty ( ) ) {
if ( profile_name_prev . IsEmpty ( ) ) { tc_profile_name - > SetValue ( default_profile_name ) ; }
else { tc_profile_name - > SetValue ( profile_name_prev ) ; }
} else {
profile_name_prev = tc_profile_name - > GetValue ( ) ;
}
evt . Skip ( ) ;
} ) ;
2019-01-30 14:22:17 +00:00
cb_custom - > Bind ( wxEVT_CHECKBOX , [ this ] ( wxCommandEvent & event ) {
2019-02-12 10:01:15 +00:00
tc_profile_name - > Enable ( custom_wanted ( ) ) ;
2019-01-30 14:22:17 +00:00
wizard_p ( ) - > on_custom_setup ( custom_wanted ( ) ) ;
} ) ;
2018-03-29 15:54:43 +00:00
2019-01-30 14:22:17 +00:00
append ( cb_custom ) ;
append ( label ) ;
append ( tc_profile_name ) ;
}
2018-03-29 15:54:43 +00:00
2019-01-30 14:22:17 +00:00
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 ) ;
boldfont . SetWeight ( wxFONTWEIGHT_BOLD ) ;
auto * box_slic3r = new wxCheckBox ( this , wxID_ANY , _ ( L ( " Check for application updates " ) ) ) ;
box_slic3r - > SetValue ( app_config - > get ( " version_check " ) = = " 1 " ) ;
append ( box_slic3r ) ;
2019-04-15 14:14:19 +00:00
append_text ( wxString : : Format ( _ ( L ( " If enabled, Slic3r checks for new versions of %s online. When a new version becomes available, "
" a notification is displayed at the next application startup (never during program usage). "
" This is only a notification mechanisms, no automatic installation is done. " ) ) , SLIC3R_APP_NAME ) ) ;
2019-01-30 14:22:17 +00:00
append_spacer ( VERTICAL_SPACING ) ;
auto * box_presets = new wxCheckBox ( this , wxID_ANY , _ ( L ( " Update built-in Presets automatically " ) ) ) ;
box_presets - > SetValue ( app_config - > get ( " preset_update " ) = = " 1 " ) ;
append ( box_presets ) ;
append_text ( _ ( L ( " If enabled, Slic3r downloads updates of built-in system presets in the background. These updates are downloaded into a separate temporary location. When a new preset version becomes available it is offered at application startup. " ) ) ) ;
const auto text_bold = _ ( L ( " Updates are never applied without user's consent and never overwrite user's customized settings. " ) ) ;
auto * label_bold = new wxStaticText ( this , wxID_ANY , text_bold ) ;
label_bold - > SetFont ( boldfont ) ;
label_bold - > Wrap ( WRAP_WIDTH ) ;
append ( label_bold ) ;
append_text ( _ ( L ( " Additionally a backup snapshot of the whole configuration is created before an update is applied. " ) ) ) ;
box_slic3r - > Bind ( wxEVT_CHECKBOX , [ this ] ( wxCommandEvent & event ) { this - > version_check = event . IsChecked ( ) ; } ) ;
box_presets - > Bind ( wxEVT_CHECKBOX , [ this ] ( wxCommandEvent & event ) { this - > preset_update = event . IsChecked ( ) ; } ) ;
2018-03-13 11:39:57 +00:00
}
2019-01-30 14:22:17 +00:00
PageVendors : : PageVendors ( ConfigWizard * parent )
: ConfigWizardPage ( parent , _ ( L ( " Other Vendors " ) ) , _ ( L ( " Other Vendors " ) ) )
2018-03-29 15:54:43 +00:00
{
2019-04-15 14:14:19 +00:00
append_text ( wxString : : Format ( _ ( L ( " Pick another vendor supported by %s: " ) ) , SLIC3R_APP_NAME ) ) ;
2018-04-05 16:30:03 +00:00
2019-01-30 14:22:17 +00:00
auto boldfont = wxSystemSettings : : GetFont ( wxSYS_DEFAULT_GUI_FONT ) ;
boldfont . SetWeight ( wxFONTWEIGHT_BOLD ) ;
2018-03-29 15:54:43 +00:00
2019-01-30 14:22:17 +00:00
AppConfig & appconfig_vendors = this - > wizard_p ( ) - > appconfig_vendors ;
wxArrayString choices_vendors ;
2018-04-05 16:30:03 +00:00
2019-01-30 14:22:17 +00:00
for ( const auto vendor_pair : wizard_p ( ) - > vendors ) {
const auto & vendor = vendor_pair . second ;
if ( vendor . id = = " PrusaResearch " ) { continue ; }
2018-03-29 15:54:43 +00:00
2019-01-30 14:22:17 +00:00
auto * picker = new PrinterPicker ( this , vendor , " " , MAX_COLS , appconfig_vendors ) ;
picker - > Hide ( ) ;
pickers . push_back ( picker ) ;
choices_vendors . Add ( vendor . name ) ;
2018-04-05 16:30:03 +00:00
2019-01-30 14:22:17 +00:00
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 ) ;
} ) ;
}
2018-03-29 15:54:43 +00:00
2019-01-30 14:22:17 +00:00
auto * vendor_picker = new wxChoice ( this , wxID_ANY , wxDefaultPosition , wxDefaultSize , choices_vendors ) ;
if ( choices_vendors . GetCount ( ) > 0 ) {
vendor_picker - > SetSelection ( 0 ) ;
on_vendor_pick ( 0 ) ;
}
2018-04-05 16:30:03 +00:00
2019-01-30 14:22:17 +00:00
vendor_picker - > Bind ( wxEVT_CHOICE , [ this ] ( wxCommandEvent & evt ) {
this - > on_vendor_pick ( evt . GetInt ( ) ) ;
} ) ;
2018-04-05 16:30:03 +00:00
2019-01-30 14:22:17 +00:00
append ( vendor_picker ) ;
for ( PrinterPicker * picker : pickers ) { this - > append ( picker ) ; }
2018-03-29 15:54:43 +00:00
}
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
void PageVendors : : on_vendor_pick ( size_t i )
2018-04-05 16:30:03 +00:00
{
2019-01-30 14:22:17 +00:00
for ( PrinterPicker * picker : pickers ) { picker - > Hide ( ) ; }
if ( i < pickers . size ( ) ) {
pickers [ i ] - > Show ( ) ;
parent - > Layout ( ) ;
}
2018-04-05 16:30:03 +00:00
}
2019-01-30 14:22:17 +00:00
PageFirmware : : PageFirmware ( ConfigWizard * parent )
: ConfigWizardPage ( parent , _ ( L ( " Firmware Type " ) ) , _ ( L ( " Firmware " ) ) , 1 )
, gcode_opt ( * print_config_def . get ( " gcode_flavor " ) )
, gcode_picker ( nullptr )
2018-04-05 16:30:03 +00:00
{
2019-01-30 14:22:17 +00:00
append_text ( _ ( L ( " Choose the type of firmware used by your printer. " ) ) ) ;
append_text ( gcode_opt . tooltip ) ;
wxArrayString choices ;
choices . Alloc ( gcode_opt . enum_labels . size ( ) ) ;
for ( const auto & label : gcode_opt . enum_labels ) {
choices . Add ( label ) ;
}
gcode_picker = new wxChoice ( this , wxID_ANY , wxDefaultPosition , wxDefaultSize , choices ) ;
const auto & enum_values = gcode_opt . enum_values ;
auto needle = enum_values . cend ( ) ;
if ( gcode_opt . default_value ! = nullptr ) {
needle = std : : find ( enum_values . cbegin ( ) , enum_values . cend ( ) , gcode_opt . default_value - > serialize ( ) ) ;
}
if ( needle ! = enum_values . cend ( ) ) {
gcode_picker - > SetSelection ( needle - enum_values . cbegin ( ) ) ;
} else {
gcode_picker - > SetSelection ( 0 ) ;
}
append ( gcode_picker ) ;
2018-04-05 16:30:03 +00:00
}
2019-01-30 14:22:17 +00:00
void PageFirmware : : apply_custom_config ( DynamicPrintConfig & config )
2018-04-05 16:30:03 +00:00
{
2019-01-30 14:22:17 +00:00
auto sel = gcode_picker - > GetSelection ( ) ;
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 ) ;
}
2018-04-05 16:30:03 +00:00
}
2018-04-05 14:10:44 +00:00
2019-01-30 14:22:17 +00:00
PageBedShape : : PageBedShape ( ConfigWizard * parent )
: ConfigWizardPage ( parent , _ ( L ( " Bed Shape and Size " ) ) , _ ( L ( " Bed Shape " ) ) , 1 )
, shape_panel ( new BedShapePanel ( this ) )
2018-04-05 14:10:44 +00:00
{
2019-01-30 14:22:17 +00:00
append_text ( _ ( L ( " Set the shape of your printer's bed. " ) ) ) ;
2018-04-05 14:10:44 +00:00
2019-01-30 14:22:17 +00:00
shape_panel - > build_panel ( wizard_p ( ) - > custom_config - > option < ConfigOptionPoints > ( " bed_shape " ) ) ;
append ( shape_panel ) ;
2018-04-05 14:10:44 +00:00
}
2019-01-30 14:22:17 +00:00
void PageBedShape : : apply_custom_config ( DynamicPrintConfig & config )
2018-04-05 14:10:44 +00:00
{
2019-01-30 14:22:17 +00:00
const auto points ( shape_panel - > GetValue ( ) ) ;
auto * opt = new ConfigOptionPoints ( points ) ;
config . set_key_value ( " bed_shape " , opt ) ;
2018-04-05 14:10:44 +00:00
}
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
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 ) )
2018-04-05 14:10:44 +00:00
{
2019-01-30 14:22:17 +00:00
spin_nozzle - > SetDigits ( 2 ) ;
spin_nozzle - > SetIncrement ( 0.1 ) ;
const auto & def_nozzle = * print_config_def . get ( " nozzle_diameter " ) ;
auto * default_nozzle = dynamic_cast < const ConfigOptionFloats * > ( def_nozzle . default_value ) ;
spin_nozzle - > SetValue ( default_nozzle ! = nullptr & & default_nozzle - > size ( ) > 0 ? default_nozzle - > get_at ( 0 ) : 0.5 ) ;
spin_filam - > SetDigits ( 2 ) ;
spin_filam - > SetIncrement ( 0.25 ) ;
const auto & def_filam = * print_config_def . get ( " filament_diameter " ) ;
auto * default_filam = dynamic_cast < const ConfigOptionFloats * > ( def_filam . default_value ) ;
spin_filam - > SetValue ( default_filam ! = nullptr & & default_filam - > size ( ) > 0 ? default_filam - > get_at ( 0 ) : 3.0 ) ;
append_text ( _ ( L ( " Enter the diameter of your printer's hot end nozzle. " ) ) ) ;
auto * sizer_nozzle = new wxFlexGridSizer ( 3 , 5 , 5 ) ;
auto * text_nozzle = new wxStaticText ( this , wxID_ANY , _ ( L ( " Nozzle Diameter: " ) ) ) ;
auto * unit_nozzle = new wxStaticText ( this , wxID_ANY , _ ( L ( " mm " ) ) ) ;
sizer_nozzle - > AddGrowableCol ( 0 , 1 ) ;
sizer_nozzle - > Add ( text_nozzle , 0 , wxALIGN_CENTRE_VERTICAL ) ;
sizer_nozzle - > Add ( spin_nozzle ) ;
sizer_nozzle - > Add ( unit_nozzle , 0 , wxALIGN_CENTRE_VERTICAL ) ;
append ( sizer_nozzle ) ;
append_spacer ( VERTICAL_SPACING ) ;
append_text ( _ ( L ( " Enter the diameter of your filament. " ) ) ) ;
append_text ( _ ( L ( " Good precision is required, so use a caliper and do multiple measurements along the filament, then compute the average. " ) ) ) ;
auto * sizer_filam = new wxFlexGridSizer ( 3 , 5 , 5 ) ;
auto * text_filam = new wxStaticText ( this , wxID_ANY , _ ( L ( " Filament Diameter: " ) ) ) ;
auto * unit_filam = new wxStaticText ( this , wxID_ANY , _ ( L ( " mm " ) ) ) ;
sizer_filam - > AddGrowableCol ( 0 , 1 ) ;
sizer_filam - > Add ( text_filam , 0 , wxALIGN_CENTRE_VERTICAL ) ;
sizer_filam - > Add ( spin_filam ) ;
sizer_filam - > Add ( unit_filam , 0 , wxALIGN_CENTRE_VERTICAL ) ;
append ( sizer_filam ) ;
2018-04-05 14:10:44 +00:00
}
2019-01-30 14:22:17 +00:00
void PageDiameters : : apply_custom_config ( DynamicPrintConfig & config )
2018-04-05 14:10:44 +00:00
{
2019-01-30 14:22:17 +00:00
auto * opt_nozzle = new ConfigOptionFloats ( 1 , spin_nozzle - > GetValue ( ) ) ;
config . set_key_value ( " nozzle_diameter " , opt_nozzle ) ;
auto * opt_filam = new ConfigOptionFloats ( 1 , spin_filam - > GetValue ( ) ) ;
config . set_key_value ( " filament_diameter " , opt_filam ) ;
2018-04-05 14:10:44 +00:00
}
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
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 ) )
2018-04-05 14:10:44 +00:00
{
2019-01-30 14:22:17 +00:00
spin_extr - > SetIncrement ( 5.0 ) ;
const auto & def_extr = * print_config_def . get ( " temperature " ) ;
spin_extr - > SetRange ( def_extr . min , def_extr . max ) ;
auto * default_extr = dynamic_cast < const ConfigOptionInts * > ( def_extr . default_value ) ;
spin_extr - > SetValue ( default_extr ! = nullptr & & default_extr - > size ( ) > 0 ? default_extr - > get_at ( 0 ) : 200 ) ;
spin_bed - > SetIncrement ( 5.0 ) ;
const auto & def_bed = * print_config_def . get ( " bed_temperature " ) ;
spin_bed - > SetRange ( def_bed . min , def_bed . max ) ;
auto * default_bed = dynamic_cast < const ConfigOptionInts * > ( def_bed . default_value ) ;
spin_bed - > SetValue ( default_bed ! = nullptr & & default_bed - > size ( ) > 0 ? default_bed - > get_at ( 0 ) : 0 ) ;
append_text ( _ ( L ( " Enter the temperature needed for extruding your filament. " ) ) ) ;
append_text ( _ ( L ( " A rule of thumb is 160 to 230 °C for PLA, and 215 to 250 °C for ABS. " ) ) ) ;
auto * sizer_extr = new wxFlexGridSizer ( 3 , 5 , 5 ) ;
auto * text_extr = new wxStaticText ( this , wxID_ANY , _ ( L ( " Extrusion Temperature: " ) ) ) ;
auto * unit_extr = new wxStaticText ( this , wxID_ANY , _ ( L ( " °C " ) ) ) ;
sizer_extr - > AddGrowableCol ( 0 , 1 ) ;
sizer_extr - > Add ( text_extr , 0 , wxALIGN_CENTRE_VERTICAL ) ;
sizer_extr - > Add ( spin_extr ) ;
sizer_extr - > Add ( unit_extr , 0 , wxALIGN_CENTRE_VERTICAL ) ;
append ( sizer_extr ) ;
append_spacer ( VERTICAL_SPACING ) ;
append_text ( _ ( L ( " Enter the bed temperature needed for getting your filament to stick to your heated bed. " ) ) ) ;
append_text ( _ ( L ( " A rule of thumb is 60 °C for PLA and 110 °C for ABS. Leave zero if you have no heated bed. " ) ) ) ;
auto * sizer_bed = new wxFlexGridSizer ( 3 , 5 , 5 ) ;
auto * text_bed = new wxStaticText ( this , wxID_ANY , _ ( L ( " Bed Temperature: " ) ) ) ;
auto * unit_bed = new wxStaticText ( this , wxID_ANY , _ ( L ( " °C " ) ) ) ;
sizer_bed - > AddGrowableCol ( 0 , 1 ) ;
sizer_bed - > Add ( text_bed , 0 , wxALIGN_CENTRE_VERTICAL ) ;
sizer_bed - > Add ( spin_bed ) ;
sizer_bed - > Add ( unit_bed , 0 , wxALIGN_CENTRE_VERTICAL ) ;
append ( sizer_bed ) ;
}
2018-04-05 14:10:44 +00:00
2019-01-30 14:22:17 +00:00
void PageTemperatures : : apply_custom_config ( DynamicPrintConfig & config )
{
auto * opt_extr = new ConfigOptionInts ( 1 , spin_extr - > GetValue ( ) ) ;
config . set_key_value ( " temperature " , opt_extr ) ;
auto * opt_extr1st = new ConfigOptionInts ( 1 , spin_extr - > GetValue ( ) ) ;
config . set_key_value ( " first_layer_temperature " , opt_extr1st ) ;
auto * opt_bed = new ConfigOptionInts ( 1 , spin_bed - > GetValue ( ) ) ;
config . set_key_value ( " bed_temperature " , opt_bed ) ;
auto * opt_bed1st = new ConfigOptionInts ( 1 , spin_bed - > GetValue ( ) ) ;
config . set_key_value ( " first_layer_bed_temperature " , opt_bed1st ) ;
}
2018-04-05 14:10:44 +00:00
2019-01-30 14:22:17 +00:00
// Index
2018-04-05 14:10:44 +00:00
2019-01-30 14:22:17 +00:00
ConfigWizardIndex : : ConfigWizardIndex ( wxWindow * parent )
: wxPanel ( parent )
2019-04-18 00:03:40 +00:00
/* #ys_FIXME_delete_after_testing by VK
2019-01-30 14:22:17 +00:00
, 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 )
2019-04-18 00:03:40 +00:00
*/
2019-04-24 23:45:00 +00:00
, bg ( ScalableBitmap ( parent , " Slic3r_192px_transparent.png " , 192 ) )
, bullet_black ( ScalableBitmap ( parent , " bullet_black.png " ) )
, bullet_blue ( ScalableBitmap ( parent , " bullet_blue.png " ) )
, bullet_white ( ScalableBitmap ( parent , " bullet_white.png " ) )
2019-01-30 14:22:17 +00:00
, item_active ( 0 )
, item_hover ( - 1 )
, last_page ( ( size_t ) - 1 )
{
2019-04-18 00:03:40 +00:00
SetMinSize ( bg . bmp ( ) . GetSize ( ) ) ;
2019-01-30 14:22:17 +00:00
const wxSize size = GetTextExtent ( " m " ) ;
2019-04-18 15:21:46 +00:00
em_w = size . x ;
2019-01-30 14:22:17 +00:00
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
// to get the bitmap rendered well on all platforms with transparent background.
// In some cases it didn't work at all. And so wxStaticBitmap is used here instead,
// because it has all the platform quirks figured out.
auto * sizer = new wxBoxSizer ( wxVERTICAL ) ;
2019-04-18 00:03:40 +00:00
/* #ys_FIXME_delete_after_testing by VK
2019-01-30 14:22:17 +00:00
auto * logo = new wxStaticBitmap ( this , wxID_ANY , bg ) ;
2019-04-18 00:03:40 +00:00
*/
logo = new wxStaticBitmap ( this , wxID_ANY , bg . bmp ( ) ) ;
2019-01-30 14:22:17 +00:00
sizer - > AddStretchSpacer ( ) ;
sizer - > Add ( logo ) ;
SetSizer ( sizer ) ;
Bind ( wxEVT_PAINT , & ConfigWizardIndex : : on_paint , this ) ;
Bind ( wxEVT_MOTION , & ConfigWizardIndex : : on_mouse_move , this ) ;
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 ) ; }
} ) ;
}
2018-04-05 14:10:44 +00:00
2019-01-30 14:22:17 +00:00
wxDECLARE_EVENT ( EVT_INDEX_PAGE , wxCommandEvent ) ;
2018-04-05 14:10:44 +00:00
2019-01-30 14:22:17 +00:00
void ConfigWizardIndex : : add_page ( ConfigWizardPage * page )
{
last_page = items . size ( ) ;
items . emplace_back ( Item { page - > shortname , page - > indent , page } ) ;
Refresh ( ) ;
2018-04-05 14:10:44 +00:00
}
2019-01-30 14:22:17 +00:00
void ConfigWizardIndex : : add_label ( wxString label , unsigned indent )
2018-04-05 14:10:44 +00:00
{
2019-01-30 14:22:17 +00:00
items . emplace_back ( Item { std : : move ( label ) , indent , nullptr } ) ;
Refresh ( ) ;
2018-04-05 14:10:44 +00:00
}
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
ConfigWizardPage * ConfigWizardIndex : : active_page ( ) const
2018-04-05 14:10:44 +00:00
{
2019-01-30 14:22:17 +00:00
if ( item_active > = items . size ( ) ) { return nullptr ; }
2018-04-05 14:10:44 +00:00
2019-01-30 14:22:17 +00:00
return items [ item_active ] . page ;
2018-04-05 14:10:44 +00:00
}
2019-01-30 14:22:17 +00:00
void ConfigWizardIndex : : go_prev ( )
2018-04-05 14:10:44 +00:00
{
2019-01-30 14:22:17 +00:00
// 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 ;
}
}
2018-04-05 14:10:44 +00:00
}
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
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 ;
}
}
}
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
void ConfigWizardIndex : : go_to ( size_t i )
2018-03-13 11:39:57 +00:00
{
2019-01-30 14:22:17 +00:00
if ( i < items . size ( ) & & items [ i ] . page ! = nullptr ) {
auto * former_active = active_page ( ) ;
if ( former_active ! = nullptr ) { former_active - > Hide ( ) ; }
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
item_active = i ;
items [ i ] . page - > Show ( ) ;
2018-04-09 08:41:34 +00:00
2019-01-30 14:22:17 +00:00
wxCommandEvent evt ( EVT_INDEX_PAGE , GetId ( ) ) ;
AddPendingEvent ( evt ) ;
2018-04-09 08:41:34 +00:00
2019-01-30 14:22:17 +00:00
Refresh ( ) ;
}
2018-03-13 11:39:57 +00:00
}
2019-01-30 14:22:17 +00:00
void ConfigWizardIndex : : go_to ( ConfigWizardPage * page )
2018-03-13 11:39:57 +00:00
{
2019-01-30 14:22:17 +00:00
if ( page = = nullptr ) { return ; }
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
for ( size_t i = 0 ; i < items . size ( ) ; i + + ) {
if ( items [ i ] . page = = page ) { go_to ( i ) ; }
}
2018-03-13 11:39:57 +00:00
}
2019-01-30 14:22:17 +00:00
void ConfigWizardIndex : : clear ( )
2018-03-13 11:39:57 +00:00
{
2019-01-30 14:22:17 +00:00
auto * former_active = active_page ( ) ;
if ( former_active ! = nullptr ) { former_active - > Hide ( ) ; }
items . clear ( ) ;
item_active = 0 ;
2018-03-13 11:39:57 +00:00
}
void ConfigWizardIndex : : on_paint ( wxPaintEvent & evt )
{
2019-01-30 14:22:17 +00:00
const auto size = GetClientSize ( ) ;
if ( size . GetHeight ( ) = = 0 | | size . GetWidth ( ) = = 0 ) { return ; }
wxPaintDC dc ( this ) ;
2019-04-18 00:03:40 +00:00
/* #ys_FIXME_delete_after_testing by VK
2019-01-30 14:22:17 +00:00
const auto bullet_w = bullet_black . GetSize ( ) . GetWidth ( ) ;
const auto bullet_h = bullet_black . GetSize ( ) . GetHeight ( ) ;
2019-04-18 00:03:40 +00:00
*/
const auto bullet_w = bullet_black . bmp ( ) . GetSize ( ) . GetWidth ( ) ;
const auto bullet_h = bullet_black . bmp ( ) . GetSize ( ) . GetHeight ( ) ;
2019-01-30 14:22:17 +00:00
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 ( ) ;
2019-04-17 14:47:15 +00:00
int index_width = 0 ;
2019-01-30 14:22:17 +00:00
unsigned y = 0 ;
for ( size_t i = 0 ; i < items . size ( ) ; i + + ) {
const Item & item = items [ i ] ;
2019-04-18 15:21:46 +00:00
unsigned x = em_w / 2 + item . indent * em_w ;
2019-01-30 14:22:17 +00:00
if ( i = = item_active | | item_hover > = 0 & & i = = ( size_t ) item_hover ) {
2019-04-18 00:03:40 +00:00
/*#ys_FIXME_delete_after_testing by VK
2019-01-30 14:22:17 +00:00
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 ) ; }
2019-04-18 00:03:40 +00:00
*/
dc . DrawBitmap ( bullet_blue . bmp ( ) , x , y + yoff_icon , false ) ;
}
else if ( i < item_active ) { dc . DrawBitmap ( bullet_black . bmp ( ) , x , y + yoff_icon , false ) ; }
else if ( i > item_active ) { dc . DrawBitmap ( bullet_white . bmp ( ) , x , y + yoff_icon , false ) ; }
2019-01-30 14:22:17 +00:00
2019-04-18 15:21:46 +00:00
x + = + bullet_w + em_w / 2 ;
2019-04-17 14:47:15 +00:00
const auto text_size = dc . GetTextExtent ( item . label ) ;
dc . DrawText ( item . label , x , y + yoff_text ) ;
2019-01-30 14:22:17 +00:00
y + = yinc ;
2019-04-17 14:47:15 +00:00
index_width = std : : max ( index_width , ( int ) x + text_size . x ) ;
}
if ( GetMinSize ( ) . x < index_width ) {
CallAfter ( [ this , index_width ] ( ) {
SetMinSize ( wxSize ( index_width , GetMinSize ( ) . y ) ) ;
2019-04-18 15:21:46 +00:00
Refresh ( ) ;
2019-04-17 14:47:15 +00:00
} ) ;
2019-01-30 14:22:17 +00:00
}
}
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
void ConfigWizardIndex : : on_mouse_move ( wxMouseEvent & evt )
{
const wxClientDC dc ( this ) ;
const wxPoint pos = evt . GetLogicalPosition ( dc ) ;
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
const ssize_t item_hover_new = pos . y / item_height ( ) ;
2018-03-13 11:39:57 +00:00
2019-02-19 13:57:59 +00:00
if ( item_hover_new < ssize_t ( items . size ( ) ) & & item_hover_new ! = item_hover ) {
2019-01-30 14:22:17 +00:00
item_hover = item_hover_new ;
Refresh ( ) ;
}
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
evt . Skip ( ) ;
2018-03-13 11:39:57 +00:00
}
2019-04-24 23:45:00 +00:00
void ConfigWizardIndex : : msw_rescale ( )
2019-04-18 00:03:40 +00:00
{
2019-04-24 23:45:00 +00:00
bg . msw_rescale ( ) ;
2019-04-18 00:03:40 +00:00
SetMinSize ( bg . bmp ( ) . GetSize ( ) ) ;
logo - > SetBitmap ( bg . bmp ( ) ) ;
2019-04-24 23:45:00 +00:00
bullet_black . msw_rescale ( ) ;
bullet_blue . msw_rescale ( ) ;
bullet_white . msw_rescale ( ) ;
2019-04-18 00:03:40 +00:00
Refresh ( ) ;
}
2018-03-13 11:39:57 +00:00
// priv
2018-04-16 14:52:11 +00:00
static const std : : unordered_map < std : : string , std : : pair < std : : string , std : : string > > legacy_preset_map { {
2019-01-30 14:22:17 +00:00
{ " Original Prusa i3 MK2.ini " , std : : make_pair ( " MK2S " , " 0.4 " ) } ,
{ " Original Prusa i3 MK2 MM Single Mode.ini " , std : : make_pair ( " MK2SMM " , " 0.4 " ) } ,
{ " Original Prusa i3 MK2 MM Single Mode 0.6 nozzle.ini " , std : : make_pair ( " MK2SMM " , " 0.6 " ) } ,
{ " Original Prusa i3 MK2 MultiMaterial.ini " , std : : make_pair ( " MK2SMM " , " 0.4 " ) } ,
{ " Original Prusa i3 MK2 MultiMaterial 0.6 nozzle.ini " , std : : make_pair ( " MK2SMM " , " 0.6 " ) } ,
{ " Original Prusa i3 MK2 0.25 nozzle.ini " , std : : make_pair ( " MK2S " , " 0.25 " ) } ,
{ " Original Prusa i3 MK2 0.6 nozzle.ini " , std : : make_pair ( " MK2S " , " 0.6 " ) } ,
{ " Original Prusa i3 MK3.ini " , std : : make_pair ( " MK3 " , " 0.4 " ) } ,
2018-04-16 14:52:11 +00:00
} } ;
2019-01-30 14:22:17 +00:00
void ConfigWizard : : priv : : load_pages ( bool custom_setup )
2018-03-29 15:54:43 +00:00
{
2019-01-30 14:22:17 +00:00
const auto former_active = index - > active_item ( ) ;
2018-04-12 18:04:48 +00:00
2019-01-30 14:22:17 +00:00
index - > clear ( ) ;
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
index - > add_page ( page_welcome ) ;
index - > add_page ( page_fff ) ;
index - > add_page ( page_msla ) ;
index - > add_page ( page_custom ) ;
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
if ( custom_setup ) {
index - > add_page ( page_firmware ) ;
index - > add_page ( page_bed ) ;
index - > add_page ( page_diams ) ;
index - > add_page ( page_temps ) ;
}
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
index - > add_page ( page_update ) ;
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
index - > go_to ( former_active ) ; // Will restore the active item/page if possible
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
q - > Layout ( ) ;
}
2018-03-13 11:39:57 +00:00
2019-01-30 14:22:17 +00:00
bool ConfigWizard : : priv : : check_first_variant ( ) const
{
return run_reason = = RR_DATA_EMPTY | | run_reason = = RR_DATA_LEGACY ;
2018-04-06 10:15:28 +00:00
}
2019-01-30 14:22:17 +00:00
void ConfigWizard : : priv : : load_vendors ( )
2018-04-06 10:15:28 +00:00
{
2019-01-30 14:22:17 +00:00
const auto vendor_dir = fs : : path ( Slic3r : : data_dir ( ) ) / " vendor " ;
const auto rsrc_vendor_dir = fs : : path ( resources_dir ( ) ) / " profiles " ;
// Load vendors from the "vendors" directory in datadir
for ( auto & dir_entry : boost : : filesystem : : directory_iterator ( vendor_dir ) )
if ( Slic3r : : is_ini_file ( dir_entry ) ) {
try {
auto vp = VendorProfile : : from_ini ( dir_entry . path ( ) ) ;
vendors [ vp . id ] = std : : move ( vp ) ;
}
catch ( const std : : exception & e ) {
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " Error loading vendor bundle %1%: %2% " ) % dir_entry . path ( ) % e . what ( ) ;
}
}
// Additionally load up vendors from the application resources directory, but only those not seen in the datadir
for ( auto & dir_entry : boost : : filesystem : : directory_iterator ( rsrc_vendor_dir ) )
if ( Slic3r : : is_ini_file ( dir_entry ) ) {
const auto id = dir_entry . path ( ) . stem ( ) . string ( ) ;
if ( vendors . find ( id ) = = vendors . end ( ) ) {
try {
auto vp = VendorProfile : : from_ini ( dir_entry . path ( ) ) ;
vendors_rsrc [ vp . id ] = dir_entry . path ( ) . filename ( ) . string ( ) ;
vendors [ vp . id ] = std : : move ( vp ) ;
}
catch ( const std : : exception & e ) {
BOOST_LOG_TRIVIAL ( error ) < < boost : : format ( " Error loading vendor bundle %1%: %2% " ) % dir_entry . path ( ) % e . what ( ) ;
}
}
}
// Load up the set of vendors / models / variants the user has had enabled up till now
const AppConfig * app_config = GUI : : get_app_config ( ) ;
if ( ! app_config - > legacy_datadir ( ) ) {
appconfig_vendors . set_vendors ( * app_config ) ;
} else {
// In case of legacy datadir, try to guess the preference based on the printer preset files that are present
const auto printer_dir = fs : : path ( Slic3r : : data_dir ( ) ) / " printer " ;
for ( auto & dir_entry : boost : : filesystem : : directory_iterator ( printer_dir ) )
if ( Slic3r : : is_ini_file ( dir_entry ) ) {
auto needle = legacy_preset_map . find ( dir_entry . path ( ) . filename ( ) . string ( ) ) ;
if ( needle = = legacy_preset_map . end ( ) ) { continue ; }
const auto & model = needle - > second . first ;
const auto & variant = needle - > second . second ;
appconfig_vendors . set_variant ( " PrusaResearch " , model , variant , true ) ;
}
}
2018-03-13 11:39:57 +00:00
}
2019-01-30 14:22:17 +00:00
void ConfigWizard : : priv : : add_page ( ConfigWizardPage * page )
2018-03-13 11:39:57 +00:00
{
2019-01-30 14:22:17 +00:00
hscroll_sizer - > Add ( page , 0 , wxEXPAND ) ;
2018-03-13 11:39:57 +00:00
}
2019-01-30 14:22:17 +00:00
void ConfigWizard : : priv : : enable_next ( bool enable )
2018-03-13 11:39:57 +00:00
{
2019-01-30 14:22:17 +00:00
btn_next - > Enable ( enable ) ;
btn_finish - > Enable ( enable ) ;
2018-03-13 11:39:57 +00:00
}
2019-01-30 14:22:17 +00:00
void ConfigWizard : : priv : : on_custom_setup ( bool custom_wanted )
2018-03-13 11:39:57 +00:00
{
2019-01-30 14:22:17 +00:00
load_pages ( custom_wanted ) ;
2018-03-13 11:39:57 +00:00
}
2018-04-24 16:06:42 +00:00
void ConfigWizard : : priv : : apply_config ( AppConfig * app_config , PresetBundle * preset_bundle , const PresetUpdater * updater )
2018-03-29 15:54:43 +00:00
{
2019-01-30 14:22:17 +00:00
const auto enabled_vendors = appconfig_vendors . vendors ( ) ;
// Install bundles from resources if needed:
std : : vector < std : : string > install_bundles ;
for ( const auto & vendor_rsrc : vendors_rsrc ) {
const auto vendor = enabled_vendors . find ( vendor_rsrc . first ) ;
if ( vendor = = enabled_vendors . end ( ) ) { continue ; }
size_t size_sum = 0 ;
for ( const auto & model : vendor - > second ) { size_sum + = model . second . size ( ) ; }
if ( size_sum = = 0 ) { continue ; }
// This vendor needs to be installed
install_bundles . emplace_back ( vendor_rsrc . second ) ;
}
// Decide whether to create snapshot based on run_reason and the reset profile checkbox
bool snapshot = true ;
switch ( run_reason ) {
case ConfigWizard : : RR_DATA_EMPTY : snapshot = false ; break ;
case ConfigWizard : : RR_DATA_LEGACY : snapshot = true ; break ;
case ConfigWizard : : RR_DATA_INCOMPAT : snapshot = false ; break ; // In this case snapshot is done by PresetUpdater with the appropriate reason
case ConfigWizard : : RR_USER : snapshot = page_welcome - > reset_user_profile ( ) ; break ;
}
if ( install_bundles . size ( ) > 0 ) {
// Install bundles from resources.
updater - > install_bundles_rsrc ( std : : move ( install_bundles ) , snapshot ) ;
} else {
BOOST_LOG_TRIVIAL ( info ) < < " No bundles need to be installed from resources " ;
}
if ( page_welcome - > reset_user_profile ( ) ) {
BOOST_LOG_TRIVIAL ( info ) < < " Resetting user profiles... " ;
preset_bundle - > reset ( true ) ;
}
app_config - > set_vendors ( appconfig_vendors ) ;
app_config - > set ( " version_check " , page_update - > version_check ? " 1 " : " 0 " ) ;
app_config - > set ( " preset_update " , page_update - > preset_update ? " 1 " : " 0 " ) ;
app_config - > reset_selections ( ) ;
preset_bundle - > load_presets ( * app_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 ) ;
2018-03-29 15:54:43 +00:00
}
2018-03-13 11:39:57 +00:00
// Public
2019-01-30 14:22:17 +00:00
ConfigWizard : : ConfigWizard ( wxWindow * parent , RunReason reason )
2019-04-18 00:03:40 +00:00
: DPIDialog ( parent , wxID_ANY , _ ( name ( ) . ToStdString ( ) ) , wxDefaultPosition , wxDefaultSize , wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER )
2019-01-30 14:22:17 +00:00
, p ( new priv ( this ) )
{
2019-04-18 00:03:40 +00:00
this - > SetFont ( wxGetApp ( ) . normal_font ( ) ) ;
2019-01-30 14:22:17 +00:00
p - > run_reason = reason ;
p - > load_vendors ( ) ;
p - > custom_config . reset ( DynamicPrintConfig : : new_from_defaults_keys ( {
" gcode_flavor " , " bed_shape " , " nozzle_diameter " , " filament_diameter " , " temperature " , " bed_temperature " ,
} ) ) ;
p - > index = new ConfigWizardIndex ( this ) ;
auto * vsizer = new wxBoxSizer ( wxVERTICAL ) ;
auto * topsizer = new wxBoxSizer ( wxHORIZONTAL ) ;
auto * hline = new wxStaticLine ( this ) ;
p - > btnsizer = new wxBoxSizer ( wxHORIZONTAL ) ;
// Initially we _do not_ SetScrollRate in order to figure out the overall width of the Wizard without scrolling.
// Later, we compare that to the size of the current screen and set minimum width based on that (see below).
p - > hscroll = new wxScrolledWindow ( this ) ;
p - > hscroll_sizer = new wxBoxSizer ( wxHORIZONTAL ) ;
p - > hscroll - > SetSizer ( p - > hscroll_sizer ) ;
topsizer - > Add ( p - > index , 0 , wxEXPAND ) ;
topsizer - > AddSpacer ( INDEX_MARGIN ) ;
topsizer - > Add ( p - > hscroll , 1 , wxEXPAND ) ;
2019-02-12 10:01:15 +00:00
auto * btn_sel_all = new wxButton ( this , wxID_ANY , _ ( L ( " Select all standard printers " ) ) ) ;
2019-01-30 14:22:17 +00:00
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 " ) ) ) ;
2019-02-28 12:04:37 +00:00
p - > btn_cancel = new wxButton ( this , wxID_CANCEL , _ ( L ( " Cancel " ) ) ) ; // Note: The label needs to be present, otherwise we get accelerator bugs on Mac
2019-01-30 14:22:17 +00:00
p - > btnsizer - > AddStretchSpacer ( ) ;
p - > btnsizer - > Add ( p - > btn_prev , 0 , wxLEFT , BTN_SPACING ) ;
p - > btnsizer - > Add ( p - > btn_next , 0 , wxLEFT , BTN_SPACING ) ;
p - > btnsizer - > Add ( p - > btn_finish , 0 , wxLEFT , BTN_SPACING ) ;
p - > btnsizer - > Add ( p - > btn_cancel , 0 , wxLEFT , BTN_SPACING ) ;
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 - > 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 ) ;
SetSizer ( vsizer ) ;
SetSizerAndFit ( vsizer ) ;
// We can now enable scrolling on hscroll
p - > hscroll - > SetScrollRate ( 30 , 30 ) ;
2019-02-07 14:55:47 +00:00
on_window_geometry ( this , [ this ] ( ) {
// Clamp the Wizard size based on screen dimensions
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 ) ;
2019-04-18 15:21:46 +00:00
const int width_hint = p - > index - > GetSize ( ) . GetWidth ( ) + p - > page_fff - > get_width ( ) + 30 * p - > em ( ) ; // XXX: magic constant, I found no better solution
2019-02-12 09:10:46 +00:00
if ( width_hint < window_rect . width ) {
window_rect . x + = ( window_rect . width - width_hint ) / 2 ;
window_rect . width = width_hint ;
}
2019-02-07 14:55:47 +00:00
SetSize ( window_rect ) ;
2019-01-30 14:22:17 +00:00
} ) ;
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 & ) {
2019-02-12 10:01:15 +00:00
p - > page_fff - > select_all ( true , false ) ;
p - > page_msla - > select_all ( true , false ) ;
2019-01-30 14:22:17 +00:00
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 ( ) ;
} ) ;
2018-03-13 11:39:57 +00:00
}
ConfigWizard : : ~ ConfigWizard ( ) { }
2018-04-24 16:06:42 +00:00
bool ConfigWizard : : run ( PresetBundle * preset_bundle , const PresetUpdater * updater )
2018-03-13 11:39:57 +00:00
{
2019-01-30 14:22:17 +00:00
BOOST_LOG_TRIVIAL ( info ) < < " Running ConfigWizard, reason: " < < p - > run_reason ;
if ( ShowModal ( ) = = wxID_OK ) {
auto * app_config = GUI : : get_app_config ( ) ;
p - > apply_config ( app_config , preset_bundle , updater ) ;
app_config - > set_legacy_datadir ( false ) ;
BOOST_LOG_TRIVIAL ( info ) < < " ConfigWizard applied " ;
return true ;
} else {
BOOST_LOG_TRIVIAL ( info ) < < " ConfigWizard cancelled " ;
return false ;
}
2018-03-13 11:39:57 +00:00
}
2019-01-21 11:34:28 +00:00
const wxString & ConfigWizard : : name ( const bool from_menu /* = false*/ )
2018-04-17 09:54:59 +00:00
{
2019-01-30 14:22:17 +00:00
// A different naming convention is used for the Wizard on Windows vs. OSX & GTK.
2018-04-17 09:54:59 +00:00
# if WIN32
2019-01-21 11:34:28 +00:00
static const wxString config_wizard_name = L ( " Configuration Wizard " ) ;
static const wxString config_wizard_name_menu = L ( " Configuration &Wizard " ) ;
2018-04-17 09:54:59 +00:00
# else
2019-01-30 14:22:17 +00:00
static const wxString config_wizard_name = L ( " Configuration Assistant " ) ;
2019-01-21 11:34:28 +00:00
static const wxString config_wizard_name_menu = L ( " Configuration &Assistant " ) ;
2018-04-17 09:54:59 +00:00
# endif
2019-01-30 14:22:17 +00:00
return from_menu ? config_wizard_name_menu : config_wizard_name ;
2018-04-17 09:54:59 +00:00
}
2019-04-18 00:03:40 +00:00
void ConfigWizard : : on_dpi_changed ( const wxRect & suggested_rect )
{
2019-04-24 23:45:00 +00:00
p - > index - > msw_rescale ( ) ;
2019-04-18 00:03:40 +00:00
Refresh ( ) ;
}
2018-03-13 11:39:57 +00:00
}
}