2019-01-16 12:22:17 +01:00
// #include "libslic3r/GCodeSender.hpp"
2019-03-27 12:14:34 +01:00
#include "slic3r/Utils/Serial.hpp"
2018-01-25 13:46:04 +01:00
#include "Tab.hpp"
#include "PresetBundle.hpp"
#include "PresetHints.hpp"
2018-12-04 17:56:49 +01:00
#include "libslic3r/Utils.hpp"
2018-03-16 14:06:23 +01:00
2018-03-15 18:06:26 +01:00
#include "slic3r/Utils/Http.hpp"
2018-07-08 14:32:48 +02:00
#include "slic3r/Utils/PrintHost.hpp"
2018-03-15 18:06:26 +01:00
#include "BonjourDialog.hpp"
2018-02-28 16:04:56 +01:00
#include "WipeTowerDialog.hpp"
2018-04-20 12:58:07 +02:00
#include "ButtonsDescription.hpp"
2018-01-25 13:46:04 +01:00
2017-12-05 15:54:01 +01:00
#include <wx/app.h>
#include <wx/button.h>
2017-12-13 14:45:10 +01:00
#include <wx/scrolwin.h>
2017-12-05 15:54:01 +01:00
#include <wx/sizer.h>
#include <wx/bmpcbox.h>
#include <wx/bmpbuttn.h>
#include <wx/treectrl.h>
#include <wx/imaglist.h>
2017-12-22 11:50:28 +01:00
#include <wx/settings.h>
2018-03-15 18:06:26 +01:00
#include <wx/filedlg.h>
2017-12-05 15:54:01 +01:00
2018-01-18 11:45:25 +01:00
#include <boost/algorithm/string/predicate.hpp>
2018-04-06 13:37:00 +02:00
#include "wxExtensions.hpp"
2018-04-17 10:15:48 +02:00
#include <wx/wupdlock.h>
2018-01-03 10:12:42 +01:00
2018-09-21 01:33:41 +02:00
#include "GUI_App.hpp"
2018-11-29 12:33:04 +01:00
#include "GUI_ObjectList.hpp"
2019-03-22 15:45:51 +01:00
#include "ConfigWizard.hpp"
2018-01-03 10:12:42 +01:00
2017-12-05 15:54:01 +01:00
namespace Slic3r {
namespace GUI {
2018-10-03 16:27:02 +02:00
wxDEFINE_EVENT ( EVT_TAB_VALUE_CHANGED , wxCommandEvent );
wxDEFINE_EVENT ( EVT_TAB_PRESETS_CHANGED , SimpleEvent );
2019-05-10 15:10:17 +02:00
// Tab::Tab(wxNotebook* parent, const wxString& title, const char* name) :
// m_parent(parent), m_title(title), m_name(name)
Tab :: Tab ( wxNotebook * parent , const wxString & title , Preset :: Type type ) :
m_parent ( parent ), m_title ( title ), m_type ( type )
2018-12-04 17:56:49 +01:00
{
2019-05-10 15:10:17 +02:00
Create ( parent , wxID_ANY , wxDefaultPosition , wxDefaultSize , wxBK_LEFT | wxTAB_TRAVERSAL /*, name*/ );
2019-05-06 18:28:23 +02:00
this -> SetFont ( Slic3r :: GUI :: wxGetApp (). normal_font ());
2018-12-04 17:56:49 +01:00
m_compatible_printers . type = Preset :: TYPE_PRINTER ;
m_compatible_printers . key_list = "compatible_printers" ;
m_compatible_printers . key_condition = "compatible_printers_condition" ;
m_compatible_printers . dialog_title = _ ( L ( "Compatible printers" ));
m_compatible_printers . dialog_label = _ ( L ( "Select the printers this profile is compatible with." ));
m_compatible_prints . type = Preset :: TYPE_PRINT ;
m_compatible_prints . key_list = "compatible_prints" ;
m_compatible_prints . key_condition = "compatible_prints_condition" ;
m_compatible_prints . dialog_title = _ ( L ( "Compatible print profiles" ));
m_compatible_prints . dialog_label = _ ( L ( "Select the print profiles this profile is compatible with." ));
wxGetApp (). tabs_list . push_back ( this );
2019-02-04 12:07:15 +01:00
m_em_unit = wxGetApp (). em_unit ();
2019-03-18 12:48:39 +01:00
Bind ( wxEVT_SIZE , ([ this ]( wxSizeEvent & evt ) {
for ( auto page : m_pages )
if ( ! page . get () -> IsShown ())
page -> layout_valid = false ;
evt . Skip ();
}));
2018-12-04 17:56:49 +01:00
}
2018-10-03 16:27:02 +02:00
2018-10-09 12:41:05 +02:00
void Tab :: set_type ()
{
if ( m_name == "print" ) { m_type = Slic3r :: Preset :: TYPE_PRINT ; }
2018-11-16 17:36:23 +01:00
else if ( m_name == "sla_print" ) { m_type = Slic3r :: Preset :: TYPE_SLA_PRINT ; }
2018-10-09 12:41:05 +02:00
else if ( m_name == "filament" ) { m_type = Slic3r :: Preset :: TYPE_FILAMENT ; }
else if ( m_name == "sla_material" ) { m_type = Slic3r :: Preset :: TYPE_SLA_MATERIAL ; }
else if ( m_name == "printer" ) { m_type = Slic3r :: Preset :: TYPE_PRINTER ; }
2018-12-04 17:56:49 +01:00
else { m_type = Slic3r :: Preset :: TYPE_INVALID ; assert ( false ); }
2018-10-09 12:41:05 +02:00
}
2017-12-05 15:54:01 +01:00
// sub new
2018-10-04 16:43:10 +02:00
void Tab :: create_preset_tab ()
2017-12-05 15:54:01 +01:00
{
2019-03-13 13:13:18 +01:00
#ifdef __WINDOWS__
2019-03-18 12:48:39 +01:00
SetDoubleBuffered ( true );
2019-03-13 13:13:18 +01:00
#endif //__WINDOWS__
2018-10-04 16:43:10 +02:00
m_preset_bundle = wxGetApp (). preset_bundle ;
2018-01-05 15:11:33 +01:00
2017-12-05 15:54:01 +01:00
// Vertical sizer to hold the choice menu and the rest of the page.
2018-06-28 18:30:22 +02:00
#ifdef __WXOSX__
auto * main_sizer = new wxBoxSizer ( wxVERTICAL );
main_sizer -> SetSizeHints ( this );
this -> SetSizer ( main_sizer );
// Create additional panel to Fit() it from OnActivate()
// It's needed for tooltip showing on OSX
m_tmp_panel = new wxPanel ( this , wxID_ANY , wxDefaultPosition , wxDefaultSize , wxBK_LEFT | wxTAB_TRAVERSAL );
auto panel = m_tmp_panel ;
auto sizer = new wxBoxSizer ( wxVERTICAL );
m_tmp_panel -> SetSizer ( sizer );
m_tmp_panel -> Layout ();
main_sizer -> Add ( m_tmp_panel , 1 , wxEXPAND | wxALL , 0 );
#else
2018-01-05 15:11:33 +01:00
Tab * panel = this ;
2017-12-05 15:54:01 +01:00
auto * sizer = new wxBoxSizer ( wxVERTICAL );
sizer -> SetSizeHints ( panel );
panel -> SetSizer ( sizer );
2018-06-28 18:30:22 +02:00
#endif //__WXOSX__
2017-12-05 15:54:01 +01:00
// preset chooser
2019-04-16 10:05:45 +02:00
m_presets_choice = new wxBitmapComboBox ( panel , wxID_ANY , "" , wxDefaultPosition , wxSize ( 35 * m_em_unit , - 1 ), 0 , 0 , wxCB_READONLY );
2018-03-06 09:44:53 +01:00
auto color = wxSystemSettings :: GetColour ( wxSYS_COLOUR_WINDOW );
2017-12-05 15:54:01 +01:00
//buttons
2019-04-13 23:46:52 +02:00
m_scaled_buttons . reserve ( 6 );
m_scaled_buttons . reserve ( 2 );
add_scaled_button ( panel , & m_btn_save_preset , "save" );
add_scaled_button ( panel , & m_btn_delete_preset , "cross" );
2017-12-05 15:54:01 +01:00
2018-01-16 16:28:01 +01:00
m_show_incompatible_presets = false ;
2019-04-13 23:46:52 +02:00
add_scaled_bitmap ( this , m_bmp_show_incompatible_presets , "flag_red" );
add_scaled_bitmap ( this , m_bmp_hide_incompatible_presets , "flag_green" );
2019-04-25 01:45:00 +02:00
2019-04-13 23:46:52 +02:00
add_scaled_button ( panel , & m_btn_hide_incompatible_presets , m_bmp_hide_incompatible_presets . name ());
2017-12-05 15:54:01 +01:00
2019-05-11 23:29:25 +02:00
// TRN "Save current Settings"
m_btn_save_preset -> SetToolTip ( wxString :: Format ( _ ( L ( "Save current %s" )), m_title ));
2018-02-23 09:16:35 +01:00
m_btn_delete_preset -> SetToolTip ( _ ( L ( "Delete this preset" )));
2017-12-26 23:04:54 +01:00
m_btn_delete_preset -> Disable ();
2017-12-05 15:54:01 +01:00
2019-04-13 23:46:52 +02:00
add_scaled_button ( panel , & m_question_btn , "question" );
2018-04-30 14:20:33 +02:00
m_question_btn -> SetToolTip ( _ ( L ( "Hover the cursor over buttons to find more information \n "
"or click this button." )));
2018-04-19 16:20:30 +02:00
2018-04-23 10:27:42 +02:00
// Determine the theme color of OS (dark or light)
2018-10-01 15:09:31 +02:00
auto luma = wxGetApp (). get_colour_approx_luma ( wxSystemSettings :: GetColour ( wxSYS_COLOUR_WINDOW ));
2018-04-16 11:03:08 +02:00
// Bitmaps to be shown on the "Revert to system" aka "Lock to system" button next to each input field.
2019-04-13 23:46:52 +02:00
add_scaled_bitmap ( this , m_bmp_value_lock , luma >= 128 ? "lock_closed" : "lock_closed_white" );
add_scaled_bitmap ( this , m_bmp_value_unlock , "lock_open" );
2018-04-16 11:03:08 +02:00
m_bmp_non_system = & m_bmp_white_bullet ;
// Bitmaps to be shown on the "Undo user changes" button next to each input field.
2019-04-13 23:46:52 +02:00
add_scaled_bitmap ( this , m_bmp_value_revert , "undo" );
2019-04-25 01:45:00 +02:00
add_scaled_bitmap ( this , m_bmp_white_bullet , luma >= 128 ? "dot" : "dot_white" );
2018-04-19 16:20:30 +02:00
2018-04-20 12:58:07 +02:00
fill_icon_descriptions ();
2018-04-24 14:11:23 +02:00
set_tooltips_text ();
2018-04-20 12:58:07 +02:00
2019-04-13 23:46:52 +02:00
add_scaled_button ( panel , & m_undo_btn , m_bmp_white_bullet . name ());
add_scaled_button ( panel , & m_undo_to_sys_btn , m_bmp_white_bullet . name ());
2018-10-31 12:56:08 +01:00
m_undo_btn -> Bind ( wxEVT_BUTTON , ([ this ]( wxCommandEvent ) { on_roll_back_value (); }));
m_undo_to_sys_btn -> Bind ( wxEVT_BUTTON , ([ this ]( wxCommandEvent ) { on_roll_back_value ( true ); }));
2018-04-20 12:58:07 +02:00
m_question_btn -> Bind ( wxEVT_BUTTON , ([ this ]( wxCommandEvent )
{
2019-05-09 19:24:21 +02:00
auto dlg = new ButtonsDescription ( this , m_icon_descriptions );
2018-10-31 12:56:08 +01:00
if ( dlg -> ShowModal () == wxID_OK ) {
2018-04-30 14:20:33 +02:00
// Colors for ui "decoration"
2018-10-31 12:56:08 +01:00
for ( Tab * tab : wxGetApp (). tabs_list ) {
2018-10-01 15:09:31 +02:00
tab -> m_sys_label_clr = wxGetApp (). get_label_clr_sys ();
tab -> m_modified_label_clr = wxGetApp (). get_label_clr_modified ();
2018-04-30 14:20:33 +02:00
tab -> update_labels_colour ();
}
}
2018-04-20 12:58:07 +02:00
}));
2018-03-21 22:21:37 +01:00
2018-04-17 10:15:48 +02:00
// Colors for ui "decoration"
2018-10-01 15:09:31 +02:00
m_sys_label_clr = wxGetApp (). get_label_clr_sys ();
m_modified_label_clr = wxGetApp (). get_label_clr_modified ();
m_default_text_clr = wxGetApp (). get_label_clr_default ();
2018-03-21 22:21:37 +01:00
2019-01-10 11:05:58 +01:00
// Sizer with buttons for mode changing
2019-04-25 01:45:00 +02:00
m_mode_sizer = new ModeSizer ( panel );
2019-01-10 11:05:58 +01:00
2019-02-06 15:29:13 +01:00
const float scale_factor = wxGetApp (). em_unit () * 0.1 ; // GetContentScaleFactor();
2017-12-26 23:04:54 +01:00
m_hsizer = new wxBoxSizer ( wxHORIZONTAL );
2019-01-11 12:47:40 +01:00
sizer -> Add ( m_hsizer , 0 , wxEXPAND | wxBOTTOM , 3 );
m_hsizer -> Add ( m_presets_choice , 0 , wxLEFT | wxRIGHT | wxTOP | wxALIGN_CENTER_VERTICAL , 3 );
2019-02-06 15:29:13 +01:00
m_hsizer -> AddSpacer ( int ( 4 * scale_factor ));
2017-12-26 23:04:54 +01:00
m_hsizer -> Add ( m_btn_save_preset , 0 , wxALIGN_CENTER_VERTICAL );
2019-02-06 15:29:13 +01:00
m_hsizer -> AddSpacer ( int ( 4 * scale_factor ));
2017-12-26 23:04:54 +01:00
m_hsizer -> Add ( m_btn_delete_preset , 0 , wxALIGN_CENTER_VERTICAL );
2019-02-06 15:29:13 +01:00
m_hsizer -> AddSpacer ( int ( 16 * scale_factor ));
2017-12-26 23:04:54 +01:00
m_hsizer -> Add ( m_btn_hide_incompatible_presets , 0 , wxALIGN_CENTER_VERTICAL );
2019-02-06 15:29:13 +01:00
m_hsizer -> AddSpacer ( int ( 64 * scale_factor ));
2018-03-21 22:21:37 +01:00
m_hsizer -> Add ( m_undo_to_sys_btn , 0 , wxALIGN_CENTER_VERTICAL );
m_hsizer -> Add ( m_undo_btn , 0 , wxALIGN_CENTER_VERTICAL );
2019-02-06 15:29:13 +01:00
m_hsizer -> AddSpacer ( int ( 32 * scale_factor ));
2018-04-19 16:20:30 +02:00
m_hsizer -> Add ( m_question_btn , 0 , wxALIGN_CENTER_VERTICAL );
2019-01-11 12:47:40 +01:00
// m_hsizer->AddStretchSpacer(32);
// StretchSpacer has a strange behavior under OSX, so
// There is used just additional sizer for m_mode_sizer with right alignment
auto mode_sizer = new wxBoxSizer ( wxVERTICAL );
mode_sizer -> Add ( m_mode_sizer , 1 , wxALIGN_RIGHT );
m_hsizer -> Add ( mode_sizer , 1 , wxALIGN_CENTER_VERTICAL | wxRIGHT , wxOSX ? 15 : 5 );
2017-12-05 15:54:01 +01:00
//Horizontal sizer to hold the tree and the selected page.
2017-12-26 23:04:54 +01:00
m_hsizer = new wxBoxSizer ( wxHORIZONTAL );
sizer -> Add ( m_hsizer , 1 , wxEXPAND , 0 );
2017-12-05 15:54:01 +01:00
//left vertical sizer
2017-12-26 23:04:54 +01:00
m_left_sizer = new wxBoxSizer ( wxVERTICAL );
m_hsizer -> Add ( m_left_sizer , 0 , wxEXPAND | wxLEFT | wxTOP | wxBOTTOM , 3 );
2017-12-05 15:54:01 +01:00
// tree
2019-02-07 14:44:05 +01:00
m_treectrl = new wxTreeCtrl ( panel , wxID_ANY , wxDefaultPosition , wxSize ( 20 * m_em_unit , - 1 ),
2018-01-18 11:45:25 +01:00
wxTR_NO_BUTTONS | wxTR_HIDE_ROOT | wxTR_SINGLE | wxTR_NO_LINES | wxBORDER_SUNKEN | wxWANTS_CHARS );
2017-12-26 23:04:54 +01:00
m_left_sizer -> Add ( m_treectrl , 1 , wxEXPAND );
2019-02-06 15:29:13 +01:00
m_icons = new wxImageList ( int ( 16 * scale_factor ), int ( 16 * scale_factor ), true , 1 );
2017-12-05 15:54:01 +01:00
// Index of the last icon inserted into $self->{icons}.
2017-12-26 23:04:54 +01:00
m_icon_count = - 1 ;
m_treectrl -> AssignImageList ( m_icons );
m_treectrl -> AddRoot ( "root" );
m_treectrl -> SetIndent ( 0 );
m_disable_tree_sel_changed_event = 0 ;
2017-12-05 15:54:01 +01:00
2018-01-05 15:11:33 +01:00
m_treectrl -> Bind ( wxEVT_TREE_SEL_CHANGED , & Tab :: OnTreeSelChange , this );
m_treectrl -> Bind ( wxEVT_KEY_DOWN , & Tab :: OnKeyDown , this );
2017-12-13 14:45:10 +01:00
2018-10-31 12:56:08 +01:00
m_presets_choice -> Bind ( wxEVT_COMBOBOX , ([ this ]( wxCommandEvent e ) {
2018-02-01 12:09:09 +01:00
//! Because of The MSW and GTK version of wxBitmapComboBox derived from wxComboBox,
//! but the OSX version derived from wxOwnerDrawnCombo, instead of:
2019-01-03 14:34:53 +01:00
//! select_preset(m_presets_choice->GetStringSelection().ToUTF8().data());
2018-02-01 12:09:09 +01:00
//! we doing next:
int selected_item = m_presets_choice -> GetSelection ();
2018-04-26 12:40:17 +02:00
if ( m_selected_preset_item == selected_item && ! m_presets -> current_is_dirty ())
2018-04-19 12:08:59 +02:00
return ;
2018-10-31 12:56:08 +01:00
if ( selected_item >= 0 ) {
2018-02-05 12:49:23 +01:00
std :: string selected_string = m_presets_choice -> GetString ( selected_item ). ToUTF8 (). data ();
2019-03-22 17:07:12 +01:00
if ( selected_string . find ( PresetCollection :: separator_head ()) == 0
2018-05-02 13:20:36 +02:00
/*selected_string == "------- System presets -------" ||
2018-10-31 12:56:08 +01:00
selected_string == "------- User presets -------"*/ ) {
2018-04-19 12:08:59 +02:00
m_presets_choice -> SetSelection ( m_selected_preset_item );
2019-03-22 17:07:12 +01:00
if ( wxString :: FromUTF8 ( selected_string . c_str ()) == PresetCollection :: separator ( L ( "Add a new printer" )))
2019-03-22 15:45:51 +01:00
wxTheApp -> CallAfter ([]() { Slic3r :: GUI :: config_wizard ( Slic3r :: GUI :: ConfigWizard :: RR_USER ); });
2018-04-19 12:08:59 +02:00
return ;
}
m_selected_preset_item = selected_item ;
2018-02-05 11:03:13 +01:00
select_preset ( selected_string );
2018-02-01 12:09:09 +01:00
}
2018-01-16 16:28:01 +01:00
}));
2018-10-31 12:56:08 +01:00
m_btn_save_preset -> Bind ( wxEVT_BUTTON , ([ this ]( wxCommandEvent e ) { save_preset (); }));
m_btn_delete_preset -> Bind ( wxEVT_BUTTON , ([ this ]( wxCommandEvent e ) { delete_preset (); }));
m_btn_hide_incompatible_presets -> Bind ( wxEVT_BUTTON , ([ this ]( wxCommandEvent e ) {
2018-01-18 11:45:25 +01:00
toggle_show_hide_incompatible ();
2018-01-16 16:28:01 +01:00
}));
2017-12-13 14:45:10 +01:00
2019-04-13 23:46:52 +02:00
// Fill cache for mode bitmaps
m_mode_bitmap_cache . reserve ( 3 );
2019-04-25 01:45:00 +02:00
m_mode_bitmap_cache . push_back ( ScalableBitmap ( this , "mode_simple_.png" ));
m_mode_bitmap_cache . push_back ( ScalableBitmap ( this , "mode_middle_.png" ));
m_mode_bitmap_cache . push_back ( ScalableBitmap ( this , "mode_expert_.png" ));
2019-04-13 23:46:52 +02:00
2017-12-05 15:54:01 +01:00
// Initialize the DynamicPrintConfig by default keys/values.
2017-12-13 14:45:10 +01:00
build ();
rebuild_page_tree ();
2019-03-07 16:36:39 +01:00
m_complited = true ;
2017-12-05 15:54:01 +01:00
}
2019-04-25 01:45:00 +02:00
void Tab :: add_scaled_button ( wxWindow * parent ,
ScalableButton ** btn ,
const std :: string & icon_name ,
2019-04-13 23:46:52 +02:00
const wxString & label /* = wxEmptyString*/ ,
long style /*= wxBU_EXACTFIT | wxNO_BORDER*/ )
{
2019-04-25 01:45:00 +02:00
* btn = new ScalableButton ( parent , wxID_ANY , icon_name , label , wxDefaultSize , wxDefaultPosition , style );
2019-04-13 23:46:52 +02:00
m_scaled_buttons . push_back ( * btn );
}
2019-04-25 01:45:00 +02:00
void Tab :: add_scaled_bitmap ( wxWindow * parent ,
ScalableBitmap & bmp ,
const std :: string & icon_name )
2019-04-13 23:46:52 +02:00
{
2019-04-25 01:45:00 +02:00
bmp = ScalableBitmap ( parent , icon_name );
2019-04-13 23:46:52 +02:00
m_scaled_bitmaps . push_back ( & bmp );
}
2018-03-16 12:56:03 +01:00
void Tab :: load_initial_data ()
{
m_config = & m_presets -> get_edited_preset (). config ;
2018-04-16 11:03:08 +02:00
m_bmp_non_system = m_presets -> get_selected_preset_parent () ? & m_bmp_value_unlock : & m_bmp_white_bullet ;
2018-04-24 14:11:23 +02:00
m_ttg_non_system = m_presets -> get_selected_preset_parent () ? & m_ttg_value_unlock : & m_ttg_white_bullet_ns ;
m_tt_non_system = m_presets -> get_selected_preset_parent () ? & m_tt_value_unlock : & m_ttg_white_bullet_ns ;
2018-03-16 12:56:03 +01:00
}
2018-08-03 14:34:52 +02:00
Slic3r :: GUI :: PageShp Tab :: add_options_page ( const wxString & title , const std :: string & icon , bool is_extruder_pages /*= false*/ )
2017-12-05 15:54:01 +01:00
{
2017-12-13 14:45:10 +01:00
// Index of icon in an icon list $self->{icons}.
auto icon_idx = 0 ;
2017-12-26 23:04:54 +01:00
if ( ! icon . empty ()) {
2018-02-28 15:39:20 +01:00
icon_idx = ( m_icon_index . find ( icon ) == m_icon_index . end ()) ? - 1 : m_icon_index . at ( icon );
2017-12-13 14:45:10 +01:00
if ( icon_idx == - 1 ) {
// Add a new icon to the icon list.
2019-04-25 01:45:00 +02:00
m_scaled_icons_list . push_back ( ScalableBitmap ( this , icon ));
2019-04-13 23:46:52 +02:00
m_icons -> Add ( m_scaled_icons_list . back (). bmp ());
2018-10-23 11:44:46 +02:00
icon_idx = ++ m_icon_count ;
2017-12-26 23:04:54 +01:00
m_icon_index [ icon ] = icon_idx ;
2017-12-13 14:45:10 +01:00
}
}
// Initialize the page.
2018-06-28 18:30:22 +02:00
#ifdef __WXOSX__
auto panel = m_tmp_panel ;
#else
auto panel = this ;
#endif
2019-04-13 23:46:52 +02:00
PageShp page ( new Page ( panel , title , icon_idx , m_mode_bitmap_cache ));
2019-03-18 12:48:39 +01:00
// page->SetBackgroundStyle(wxBG_STYLE_SYSTEM);
#ifdef __WINDOWS__
// page->SetDoubleBuffered(true);
#endif //__WINDOWS__
2018-12-18 13:22:22 +01:00
page -> SetScrollbars ( 1 , 20 , 1 , 2 );
2017-12-13 14:45:10 +01:00
page -> Hide ();
2017-12-26 23:04:54 +01:00
m_hsizer -> Add ( page . get (), 1 , wxEXPAND | wxLEFT , 5 );
2018-08-03 14:34:52 +02:00
2018-08-07 11:58:27 +02:00
if ( ! is_extruder_pages )
2018-01-02 12:50:27 +01:00
m_pages . push_back ( page );
2017-12-14 14:42:47 +01:00
2018-01-12 12:41:13 +01:00
page -> set_config ( m_config );
2017-12-13 14:45:10 +01:00
return page ;
}
2018-06-27 09:07:04 +02:00
void Tab :: OnActivate ()
{
#ifdef __WXOSX__
wxWindowUpdateLocker noUpdates ( this );
2018-06-28 18:30:22 +02:00
auto size = GetSizer () -> GetSize ();
m_tmp_panel -> GetSizer () -> SetMinSize ( size . x + m_size_move , size . y );
Fit ();
m_size_move *= - 1 ;
#endif // __WXOSX__
2018-06-27 09:07:04 +02:00
}
2018-04-30 14:20:33 +02:00
void Tab :: update_labels_colour ()
{
2019-03-18 12:48:39 +01:00
// Freeze();
2018-04-30 14:20:33 +02:00
//update options "decoration"
for ( const auto opt : m_options_list )
{
const wxColour * color = & m_sys_label_clr ;
// value isn't equal to system value
2018-10-31 12:56:08 +01:00
if (( opt . second & osSystemValue ) == 0 ) {
2018-04-30 14:20:33 +02:00
// value is equal to last saved
if (( opt . second & osInitValue ) != 0 )
color = & m_default_text_clr ;
// value is modified
else
color = & m_modified_label_clr ;
}
2018-12-04 17:56:49 +01:00
if ( opt . first == "bed_shape" || opt . first == "compatible_prints" || opt . first == "compatible_printers" ) {
2018-04-30 14:20:33 +02:00
if ( m_colored_Label != nullptr ) {
m_colored_Label -> SetForegroundColour ( * color );
m_colored_Label -> Refresh ( true );
}
continue ;
}
Field * field = get_field ( opt . first );
if ( field == nullptr ) continue ;
field -> set_label_colour_force ( color );
}
2019-03-18 12:48:39 +01:00
// Thaw();
2018-04-30 14:20:33 +02:00
auto cur_item = m_treectrl -> GetFirstVisibleItem ();
2018-10-31 12:56:08 +01:00
while ( cur_item ) {
2018-04-30 14:20:33 +02:00
auto title = m_treectrl -> GetItemText ( cur_item );
for ( auto page : m_pages )
{
if ( page -> title () != title )
continue ;
const wxColor * clr = ! page -> m_is_nonsys_values ? & m_sys_label_clr :
page -> m_is_modified_values ? & m_modified_label_clr :
& m_default_text_clr ;
m_treectrl -> SetItemTextColour ( cur_item , * clr );
break ;
}
cur_item = m_treectrl -> GetNextVisible ( cur_item );
}
}
2018-03-09 08:34:32 +01:00
// Update UI according to changes
void Tab :: update_changed_ui ()
{
2018-04-16 13:43:01 +02:00
if ( m_postpone_update_ui )
return ;
2018-03-07 15:05:41 +01:00
2019-03-22 12:11:23 +01:00
const bool deep_compare = ( m_type == Slic3r :: Preset :: TYPE_PRINTER || m_type == Slic3r :: Preset :: TYPE_SLA_MATERIAL );
2018-08-08 17:47:59 +02:00
auto dirty_options = m_presets -> current_dirty_options ( deep_compare );
auto nonsys_options = m_presets -> current_different_from_parent_options ( deep_compare );
2018-12-04 17:56:49 +01:00
if ( m_type == Slic3r :: Preset :: TYPE_PRINTER ) {
2018-03-08 11:58:06 +01:00
TabPrinter * tab = static_cast < TabPrinter *> ( this );
2018-03-19 17:21:37 +01:00
if ( tab -> m_initial_extruders_count != tab -> m_extruders_count )
2018-04-18 14:15:13 +02:00
dirty_options . emplace_back ( "extruders_count" );
2018-04-18 13:32:21 +02:00
if ( tab -> m_sys_extruders_count != tab -> m_extruders_count )
2018-04-18 14:15:13 +02:00
nonsys_options . emplace_back ( "extruders_count" );
2018-03-02 09:08:11 +01:00
}
2018-03-06 09:44:53 +01:00
2018-04-18 13:32:21 +02:00
for ( auto & it : m_options_list )
it . second = m_opt_status_value ;
2018-04-18 14:15:13 +02:00
for ( auto opt_key : dirty_options ) m_options_list [ opt_key ] &= ~ osInitValue ;
for ( auto opt_key : nonsys_options ) m_options_list [ opt_key ] &= ~ osSystemValue ;
2018-04-18 13:32:21 +02:00
2019-03-18 12:48:39 +01:00
// Freeze();
2018-03-23 17:27:43 +01:00
//update options "decoration"
2018-04-18 14:15:13 +02:00
for ( const auto opt : m_options_list )
2018-03-21 22:21:37 +01:00
{
2018-03-23 17:27:43 +01:00
bool is_nonsys_value = false ;
bool is_modified_value = true ;
2019-04-25 01:45:00 +02:00
const ScalableBitmap * sys_icon = & m_bmp_value_lock ;
const ScalableBitmap * icon = & m_bmp_value_revert ;
2018-04-18 13:32:21 +02:00
2018-04-24 14:11:23 +02:00
const wxColour * color = & m_sys_label_clr ;
const wxString * sys_tt = & m_tt_value_lock ;
const wxString * tt = & m_tt_value_revert ;
// value isn't equal to system value
2018-10-31 12:56:08 +01:00
if (( opt . second & osSystemValue ) == 0 ) {
2018-03-23 17:27:43 +01:00
is_nonsys_value = true ;
2018-04-18 13:32:21 +02:00
sys_icon = m_bmp_non_system ;
2018-04-24 14:11:23 +02:00
sys_tt = m_tt_non_system ;
// value is equal to last saved
2018-04-18 13:32:21 +02:00
if (( opt . second & osInitValue ) != 0 )
color = & m_default_text_clr ;
2018-04-24 14:11:23 +02:00
// value is modified
2018-03-22 09:37:42 +01:00
else
2018-04-18 13:32:21 +02:00
color = & m_modified_label_clr ;
2018-03-21 22:21:37 +01:00
}
2018-04-18 13:32:21 +02:00
if (( opt . second & osInitValue ) != 0 )
2018-03-23 17:27:43 +01:00
{
is_modified_value = false ;
2018-04-18 13:32:21 +02:00
icon = & m_bmp_white_bullet ;
2018-04-24 14:11:23 +02:00
tt = & m_tt_white_bullet ;
2018-03-23 17:27:43 +01:00
}
2018-12-04 17:56:49 +01:00
if ( opt . first == "bed_shape" || opt . first == "compatible_prints" || opt . first == "compatible_printers" ) {
2018-04-13 18:22:06 +02:00
if ( m_colored_Label != nullptr ) {
2018-04-18 13:32:21 +02:00
m_colored_Label -> SetForegroundColour ( * color );
2018-04-13 18:22:06 +02:00
m_colored_Label -> Refresh ( true );
}
continue ;
}
2018-04-18 13:32:21 +02:00
Field * field = get_field ( opt . first );
2018-03-23 17:27:43 +01:00
if ( field == nullptr ) continue ;
field -> m_is_nonsys_value = is_nonsys_value ;
field -> m_is_modified_value = is_modified_value ;
2018-04-18 13:32:21 +02:00
field -> set_undo_bitmap ( icon );
field -> set_undo_to_sys_bitmap ( sys_icon );
2018-04-24 14:11:23 +02:00
field -> set_undo_tooltip ( tt );
field -> set_undo_to_sys_tooltip ( sys_tt );
2018-04-18 13:32:21 +02:00
field -> set_label_colour ( color );
2018-03-16 12:56:03 +01:00
}
2019-03-18 12:48:39 +01:00
// Thaw();
2018-03-21 22:21:37 +01:00
wxTheApp -> CallAfter ([ this ]() {
2019-05-10 15:10:17 +02:00
if ( parent ()) //To avoid a crash, parent should be exist for a moment of a tree updating
update_changed_tree_ui ();
2018-03-21 22:21:37 +01:00
});
}
2018-04-18 13:32:21 +02:00
void Tab :: init_options_list ()
{
if ( ! m_options_list . empty ())
m_options_list . clear ();
for ( const auto opt_key : m_config -> keys ())
m_options_list . emplace ( opt_key , m_opt_status_value );
}
2018-03-21 22:21:37 +01:00
template < class T >
2018-08-08 17:47:59 +02:00
void add_correct_opts_to_options_list ( const std :: string & opt_key , std :: map < std :: string , int >& map , Tab * tab , const int & value )
2018-03-21 22:21:37 +01:00
{
T * opt_cur = static_cast < T *> ( tab -> m_config -> option ( opt_key ));
for ( int i = 0 ; i < opt_cur -> values . size (); i ++ )
2018-04-18 13:32:21 +02:00
map . emplace ( opt_key + "#" + std :: to_string ( i ), value );
2018-03-21 22:21:37 +01:00
}
2018-04-18 13:32:21 +02:00
void TabPrinter :: init_options_list ()
2018-03-21 22:21:37 +01:00
{
2018-04-18 13:32:21 +02:00
if ( ! m_options_list . empty ())
m_options_list . clear ();
2018-03-21 22:21:37 +01:00
for ( const auto opt_key : m_config -> keys ())
{
2018-10-31 12:56:08 +01:00
if ( opt_key == "bed_shape" ) {
2018-04-18 13:32:21 +02:00
m_options_list . emplace ( opt_key , m_opt_status_value );
2018-03-21 22:21:37 +01:00
continue ;
}
switch ( m_config -> option ( opt_key ) -> type ())
{
2018-04-18 13:32:21 +02:00
case coInts : add_correct_opts_to_options_list < ConfigOptionInts > ( opt_key , m_options_list , this , m_opt_status_value ); break ;
case coBools : add_correct_opts_to_options_list < ConfigOptionBools > ( opt_key , m_options_list , this , m_opt_status_value ); break ;
case coFloats : add_correct_opts_to_options_list < ConfigOptionFloats > ( opt_key , m_options_list , this , m_opt_status_value ); break ;
case coStrings : add_correct_opts_to_options_list < ConfigOptionStrings > ( opt_key , m_options_list , this , m_opt_status_value ); break ;
case coPercents : add_correct_opts_to_options_list < ConfigOptionPercents > ( opt_key , m_options_list , this , m_opt_status_value ); break ;
case coPoints : add_correct_opts_to_options_list < ConfigOptionPoints > ( opt_key , m_options_list , this , m_opt_status_value ); break ;
default : m_options_list . emplace ( opt_key , m_opt_status_value ); break ;
2018-03-21 22:21:37 +01:00
}
}
2018-04-18 13:32:21 +02:00
m_options_list . emplace ( "extruders_count" , m_opt_status_value );
2018-03-21 22:21:37 +01:00
}
2018-08-08 17:47:59 +02:00
void TabSLAMaterial :: init_options_list ()
{
if ( ! m_options_list . empty ())
m_options_list . clear ();
for ( const auto opt_key : m_config -> keys ())
{
2018-12-04 17:56:49 +01:00
if ( opt_key == "compatible_prints" || opt_key == "compatible_printers" ) {
2018-08-08 17:47:59 +02:00
m_options_list . emplace ( opt_key , m_opt_status_value );
continue ;
}
switch ( m_config -> option ( opt_key ) -> type ())
{
case coInts : add_correct_opts_to_options_list < ConfigOptionInts > ( opt_key , m_options_list , this , m_opt_status_value ); break ;
case coBools : add_correct_opts_to_options_list < ConfigOptionBools > ( opt_key , m_options_list , this , m_opt_status_value ); break ;
case coFloats : add_correct_opts_to_options_list < ConfigOptionFloats > ( opt_key , m_options_list , this , m_opt_status_value ); break ;
case coStrings : add_correct_opts_to_options_list < ConfigOptionStrings > ( opt_key , m_options_list , this , m_opt_status_value ); break ;
case coPercents : add_correct_opts_to_options_list < ConfigOptionPercents > ( opt_key , m_options_list , this , m_opt_status_value ); break ;
case coPoints : add_correct_opts_to_options_list < ConfigOptionPoints > ( opt_key , m_options_list , this , m_opt_status_value ); break ;
default : m_options_list . emplace ( opt_key , m_opt_status_value ); break ;
}
}
}
2018-04-13 18:22:06 +02:00
void Tab :: get_sys_and_mod_flags ( const std :: string & opt_key , bool & sys_page , bool & modified_page )
{
2018-04-18 13:32:21 +02:00
auto opt = m_options_list . find ( opt_key );
if ( sys_page ) sys_page = ( opt -> second & osSystemValue ) != 0 ;
2018-12-04 17:56:49 +01:00
modified_page |= ( opt -> second & osInitValue ) == 0 ;
2018-04-13 18:22:06 +02:00
}
2018-03-21 22:21:37 +01:00
void Tab :: update_changed_tree_ui ()
{
2019-02-04 12:57:39 +01:00
if ( m_options_list . empty ())
return ;
2018-03-21 22:21:37 +01:00
auto cur_item = m_treectrl -> GetFirstVisibleItem ();
2018-10-22 15:18:05 +02:00
if ( ! cur_item || ! m_treectrl -> IsVisible ( cur_item ))
2018-10-15 17:18:38 +02:00
return ;
2019-03-22 20:49:17 +01:00
auto selected_item = m_treectrl -> GetSelection ();
auto selection = selected_item ? m_treectrl -> GetItemText ( selected_item ) : "" ;
2018-10-31 12:56:08 +01:00
while ( cur_item ) {
2018-03-21 22:21:37 +01:00
auto title = m_treectrl -> GetItemText ( cur_item );
for ( auto page : m_pages )
{
2018-10-22 12:07:40 +02:00
if ( page -> title () != title )
2018-03-21 22:21:37 +01:00
continue ;
bool sys_page = true ;
bool modified_page = false ;
2018-10-31 12:56:08 +01:00
if ( title == _ ( "General" )) {
2018-03-23 17:27:43 +01:00
std :: initializer_list < const char *> optional_keys { "extruders_count" , "bed_shape" };
for ( auto & opt_key : optional_keys ) {
2018-04-13 18:22:06 +02:00
get_sys_and_mod_flags ( opt_key , sys_page , modified_page );
2018-03-23 17:27:43 +01:00
}
2018-03-21 22:21:37 +01:00
}
2018-10-31 12:56:08 +01:00
if ( title == _ ( "Dependencies" )) {
2018-12-04 17:56:49 +01:00
if ( m_type == Slic3r :: Preset :: TYPE_PRINTER ) {
sys_page = m_presets -> get_selected_preset_parent () != nullptr ;
2018-07-02 13:51:50 +02:00
modified_page = false ;
2018-12-04 17:56:49 +01:00
} else {
if ( m_type == Slic3r :: Preset :: TYPE_FILAMENT || m_type == Slic3r :: Preset :: TYPE_SLA_MATERIAL )
get_sys_and_mod_flags ( "compatible_prints" , sys_page , modified_page );
get_sys_and_mod_flags ( "compatible_printers" , sys_page , modified_page );
2018-07-02 13:51:50 +02:00
}
2018-04-13 18:22:06 +02:00
}
2018-03-21 22:21:37 +01:00
for ( auto group : page -> m_optgroups )
{
if ( ! sys_page && modified_page )
break ;
2018-04-13 18:22:06 +02:00
for ( t_opt_map :: iterator it = group -> m_opt_map . begin (); it != group -> m_opt_map . end (); ++ it ) {
const std :: string & opt_key = it -> first ;
get_sys_and_mod_flags ( opt_key , sys_page , modified_page );
}
2018-03-21 22:21:37 +01:00
}
2018-04-18 13:32:21 +02:00
const wxColor * clr = sys_page ? & m_sys_label_clr :
modified_page ? & m_modified_label_clr :
& m_default_text_clr ;
if ( page -> set_item_colour ( clr ))
m_treectrl -> SetItemTextColour ( cur_item , * clr );
2018-03-22 09:37:42 +01:00
page -> m_is_nonsys_values = ! sys_page ;
page -> m_is_modified_values = modified_page ;
2018-10-31 12:56:08 +01:00
if ( selection == title ) {
2018-03-22 09:37:42 +01:00
m_is_nonsys_values = page -> m_is_nonsys_values ;
m_is_modified_values = page -> m_is_modified_values ;
}
2018-03-21 22:21:37 +01:00
break ;
}
2018-09-21 01:33:41 +02:00
auto next_item = m_treectrl -> GetNextVisible ( cur_item );
2018-10-08 16:27:38 +02:00
cur_item = next_item ;
2018-03-21 22:21:37 +01:00
}
2018-03-22 09:37:42 +01:00
update_undo_buttons ();
}
void Tab :: update_undo_buttons ()
{
2019-04-13 23:46:52 +02:00
m_undo_btn -> SetBitmap_ ( m_is_modified_values ? m_bmp_value_revert : m_bmp_white_bullet );
m_undo_to_sys_btn -> SetBitmap_ ( m_is_nonsys_values ? * m_bmp_non_system : m_bmp_value_lock );
2018-03-22 09:37:42 +01:00
2018-04-24 14:11:23 +02:00
m_undo_btn -> SetToolTip ( m_is_modified_values ? m_ttg_value_revert : m_ttg_white_bullet );
m_undo_to_sys_btn -> SetToolTip ( m_is_nonsys_values ? * m_ttg_non_system : m_ttg_value_lock );
2018-01-05 15:11:33 +01:00
}
2018-04-18 13:32:21 +02:00
void Tab :: on_roll_back_value ( const bool to_sys /*= true*/ )
2018-03-22 10:56:57 +01:00
{
2018-04-18 13:32:21 +02:00
int os ;
if ( to_sys ) {
if ( ! m_is_nonsys_values ) return ;
os = osSystemValue ;
}
else {
if ( ! m_is_modified_values ) return ;
os = osInitValue ;
}
2018-03-22 10:56:57 +01:00
2018-04-16 13:43:01 +02:00
m_postpone_update_ui = true ;
2018-03-22 10:56:57 +01:00
auto selection = m_treectrl -> GetItemText ( m_treectrl -> GetSelection ());
for ( auto page : m_pages )
if ( page -> title () == selection ) {
2018-10-31 12:56:08 +01:00
for ( auto group : page -> m_optgroups ) {
if ( group -> title == _ ( "Capabilities" )) {
2018-04-18 13:32:21 +02:00
if (( m_options_list [ "extruders_count" ] & os ) == 0 )
to_sys ? group -> back_to_sys_value ( "extruders_count" ) : group -> back_to_initial_value ( "extruders_count" );
2018-03-22 10:56:57 +01:00
}
2018-10-31 12:56:08 +01:00
if ( group -> title == _ ( "Size and coordinates" )) {
if (( m_options_list [ "bed_shape" ] & os ) == 0 ) {
2018-04-18 13:32:21 +02:00
to_sys ? group -> back_to_sys_value ( "bed_shape" ) : group -> back_to_initial_value ( "bed_shape" );
2018-04-16 13:43:01 +02:00
load_key_value ( "bed_shape" , true /*some value*/ , true );
}
2018-04-13 18:22:06 +02:00
2018-03-23 17:27:43 +01:00
}
2018-12-04 17:56:49 +01:00
if ( group -> title == _ ( "Profile dependencies" )) {
if ( m_type != Slic3r :: Preset :: TYPE_PRINTER && ( m_options_list [ "compatible_printers" ] & os ) == 0 ) {
2018-04-18 13:32:21 +02:00
to_sys ? group -> back_to_sys_value ( "compatible_printers" ) : group -> back_to_initial_value ( "compatible_printers" );
2018-04-16 13:43:01 +02:00
load_key_value ( "compatible_printers" , true /*some value*/ , true );
2018-04-13 18:22:06 +02:00
2018-04-16 13:43:01 +02:00
bool is_empty = m_config -> option < ConfigOptionStrings > ( "compatible_printers" ) -> values . empty ();
2018-12-04 17:56:49 +01:00
m_compatible_printers . checkbox -> SetValue ( is_empty );
is_empty ? m_compatible_printers . btn -> Disable () : m_compatible_printers . btn -> Enable ();
}
if (( m_type == Slic3r :: Preset :: TYPE_PRINT || m_type == Slic3r :: Preset :: TYPE_SLA_PRINT ) && ( m_options_list [ "compatible_prints" ] & os ) == 0 ) {
to_sys ? group -> back_to_sys_value ( "compatible_prints" ) : group -> back_to_initial_value ( "compatible_prints" );
load_key_value ( "compatible_prints" , true /*some value*/ , true );
bool is_empty = m_config -> option < ConfigOptionStrings > ( "compatible_prints" ) -> values . empty ();
m_compatible_prints . checkbox -> SetValue ( is_empty );
is_empty ? m_compatible_prints . btn -> Disable () : m_compatible_prints . btn -> Enable ();
2018-04-16 13:43:01 +02:00
}
2018-04-13 18:22:06 +02:00
}
2018-12-04 17:56:49 +01:00
for ( auto kvp : group -> m_opt_map ) {
const std :: string & opt_key = kvp . first ;
2018-04-18 13:32:21 +02:00
if (( m_options_list [ opt_key ] & os ) == 0 )
to_sys ? group -> back_to_sys_value ( opt_key ) : group -> back_to_initial_value ( opt_key );
2018-03-22 10:56:57 +01:00
}
}
break ;
}
2018-04-16 13:43:01 +02:00
m_postpone_update_ui = false ;
2018-03-23 17:27:43 +01:00
update_changed_ui ();
2018-03-22 10:56:57 +01:00
}
2018-03-09 08:34:32 +01:00
// Update the combo box label of the selected preset based on its "dirty" state,
// comparing the selected preset config with $self->{config}.
2018-10-31 12:56:08 +01:00
void Tab :: update_dirty ()
{
2018-03-09 08:34:32 +01:00
m_presets -> update_dirty_ui ( m_presets_choice );
on_presets_changed ();
update_changed_ui ();
}
2018-01-16 16:28:01 +01:00
void Tab :: update_tab_ui ()
{
2019-04-23 16:33:06 +02:00
m_selected_preset_item = m_presets -> update_tab_ui ( m_presets_choice , m_show_incompatible_presets , m_em_unit );
2018-01-16 16:28:01 +01:00
}
2018-01-05 15:11:33 +01:00
// Load a provied DynamicConfig into the tab, modifying the active preset.
// This could be used for example by setting a Wipe Tower position by interactive manipulation in the 3D view.
2018-04-13 12:35:04 +02:00
void Tab :: load_config ( const DynamicPrintConfig & config )
2018-01-05 15:11:33 +01:00
{
bool modified = 0 ;
2018-01-12 12:41:13 +01:00
for ( auto opt_key : m_config -> diff ( config )) {
2018-03-12 16:52:21 +01:00
m_config -> set_key_value ( opt_key , config . option ( opt_key ) -> clone ());
2018-01-05 15:11:33 +01:00
modified = 1 ;
}
if ( modified ) {
2018-01-07 18:41:40 +01:00
update_dirty ();
2018-01-05 15:11:33 +01:00
//# Initialize UI components with the config values.
2018-01-09 09:41:07 +01:00
reload_config ();
2018-01-05 15:11:33 +01:00
update ();
}
}
2018-01-09 09:41:07 +01:00
// Reload current $self->{config} (aka $self->{presets}->edited_preset->config) into the UI fields.
2018-10-31 16:22:36 +01:00
void Tab :: reload_config ()
{
2019-03-18 12:48:39 +01:00
// Freeze();
2018-01-09 09:41:07 +01:00
for ( auto page : m_pages )
page -> reload_config ();
2019-03-18 12:48:39 +01:00
// Thaw();
2018-01-09 09:41:07 +01:00
}
2019-03-20 16:22:01 +01:00
void Tab :: update_mode ()
2018-10-19 13:55:29 +02:00
{
2019-03-20 16:22:01 +01:00
m_mode = wxGetApp (). get_mode ();
2018-10-21 23:09:24 +02:00
2019-01-11 12:47:40 +01:00
// update mode for ModeSizer
2019-03-20 16:22:01 +01:00
m_mode_sizer -> SetMode ( m_mode );
update_visibility ();
}
void Tab :: update_visibility ()
{
Freeze (); // There is needed Freeze/Thaw to avoid a flashing after Show/Layout
for ( auto page : m_pages )
page -> update_visibility ( m_mode );
update_page_tree_visibility ();
2018-10-21 23:09:24 +02:00
2019-01-11 12:47:40 +01:00
Layout ();
2019-03-21 10:46:40 +01:00
Thaw ();
2018-10-22 12:07:40 +02:00
2019-03-20 16:22:01 +01:00
update_changed_tree_ui ();
2018-10-19 13:55:29 +02:00
}
2019-04-25 01:45:00 +02:00
void Tab :: msw_rescale ()
2019-04-10 09:56:32 +02:00
{
m_em_unit = wxGetApp (). em_unit ();
2019-04-25 01:45:00 +02:00
m_mode_sizer -> msw_rescale ();
2019-04-13 23:46:52 +02:00
2019-04-16 10:05:45 +02:00
m_presets_choice -> SetSize ( 35 * m_em_unit , - 1 );
2019-04-13 23:46:52 +02:00
m_treectrl -> SetMinSize ( wxSize ( 20 * m_em_unit , - 1 ));
2019-04-10 09:56:32 +02:00
update_tab_ui ();
2019-04-13 23:46:52 +02:00
// rescale buttons and cached bitmaps
for ( const auto btn : m_scaled_buttons )
2019-04-25 01:45:00 +02:00
btn -> msw_rescale ();
2019-04-13 23:46:52 +02:00
for ( const auto bmp : m_scaled_bitmaps )
2019-04-25 01:45:00 +02:00
bmp -> msw_rescale ();
for ( ScalableBitmap & bmp : m_mode_bitmap_cache )
bmp . msw_rescale ();
2019-04-13 23:46:52 +02:00
// rescale icons for tree_ctrl
2019-04-25 01:45:00 +02:00
for ( ScalableBitmap & bmp : m_scaled_icons_list )
bmp . msw_rescale ();
2019-04-13 23:46:52 +02:00
// recreate and set new ImageList for tree_ctrl
m_icons -> RemoveAll ();
m_icons = new wxImageList ( m_scaled_icons_list . front (). bmp (). GetWidth (), m_scaled_icons_list . front (). bmp (). GetHeight ());
2019-04-25 01:45:00 +02:00
for ( ScalableBitmap & bmp : m_scaled_icons_list )
2019-04-13 23:46:52 +02:00
m_icons -> Add ( bmp . bmp ());
m_treectrl -> AssignImageList ( m_icons );
// rescale options_groups
for ( auto page : m_pages )
2019-04-25 01:45:00 +02:00
page -> msw_rescale ();
2019-04-13 23:46:52 +02:00
Layout ();
2019-04-10 09:56:32 +02:00
}
2018-04-13 12:35:04 +02:00
Field * Tab :: get_field ( const t_config_option_key & opt_key , int opt_index /* = -1*/ ) const
2018-01-11 10:33:17 +01:00
{
Field * field = nullptr ;
2018-10-31 12:56:08 +01:00
for ( auto page : m_pages ) {
2018-01-12 17:16:59 +01:00
field = page -> get_field ( opt_key , opt_index );
2018-01-11 10:33:17 +01:00
if ( field != nullptr )
return field ;
}
return field ;
}
2018-01-16 16:28:01 +01:00
// Set a key/value pair on this page. Return true if the value has been modified.
// Currently used for distributing extruders_count over preset pages of Slic3r::GUI::Tab::Printer
// after a preset is loaded.
2018-10-31 12:56:08 +01:00
bool Tab :: set_value ( const t_config_option_key & opt_key , const boost :: any & value ) {
2018-01-16 16:28:01 +01:00
bool changed = false ;
for ( auto page : m_pages ) {
if ( page -> set_value ( opt_key , value ))
changed = true ;
}
return changed ;
}
2018-01-12 12:41:13 +01:00
// To be called by custom widgets, load a value into a config,
// update the preset selection boxes (the dirty flags)
2018-04-16 13:43:01 +02:00
// If value is saved before calling this function, put saved_value = true,
// and value can be some random value because in this case it will not been used
void Tab :: load_key_value ( const std :: string & opt_key , const boost :: any & value , bool saved_value /*= false*/ )
2017-12-22 11:50:28 +01:00
{
2018-04-16 13:43:01 +02:00
if ( ! saved_value ) change_opt_value ( * m_config , opt_key , value );
2018-01-12 12:41:13 +01:00
// Mark the print & filament enabled if they are compatible with the currently selected preset.
2018-12-04 17:56:49 +01:00
if ( opt_key == "compatible_printers" || opt_key == "compatible_prints" ) {
2018-04-13 14:49:33 +02:00
// Don't select another profile if this profile happens to become incompatible.
2018-12-04 17:56:49 +01:00
m_preset_bundle -> update_compatible ( false );
}
2018-01-12 12:41:13 +01:00
m_presets -> update_dirty_ui ( m_presets_choice );
on_presets_changed ();
update ();
}
2019-05-03 18:01:39 +02:00
static wxString support_combo_value_for_config ( const DynamicPrintConfig & config , bool is_fff )
{
const std :: string support = is_fff ? "support_material" : "supports_enable" ;
const std :: string buildplate_only = is_fff ? "support_material_buildplate_only" : "support_buildplate_only" ;
return
! config . opt_bool ( support ) ?
_ ( "None" ) :
( is_fff && ! config . opt_bool ( "support_material_auto" )) ?
_ ( "For support enforcers only" ) :
( config . opt_bool ( buildplate_only ) ? _ ( "Support on build plate only" ) :
_ ( "Everywhere" ));
}
2018-04-13 12:35:04 +02:00
void Tab :: on_value_change ( const std :: string & opt_key , const boost :: any & value )
2018-01-21 23:35:00 +01:00
{
2019-03-11 13:59:58 +01:00
if ( wxGetApp (). plater () == nullptr ) {
return ;
}
2019-03-11 16:00:13 +01:00
const bool is_fff = supports_printer_technology ( ptFFF );
2019-05-03 18:01:39 +02:00
ConfigOptionsGroup * og_freq_chng_params = wxGetApp (). sidebar (). og_freq_chng_params ( is_fff );
2019-03-11 16:00:13 +01:00
if ( opt_key == "fill_density" || opt_key == "pad_enable" )
2018-03-12 16:52:21 +01:00
{
2018-10-05 23:29:15 +02:00
boost :: any val = og_freq_chng_params -> get_config_value ( * m_config , opt_key );
og_freq_chng_params -> set_value ( opt_key , val );
2018-03-12 16:52:21 +01:00
}
2019-03-11 16:00:13 +01:00
2019-05-03 18:01:39 +02:00
if ( is_fff ?
( opt_key == "support_material" || opt_key == "support_material_auto" || opt_key == "support_material_buildplate_only" ) :
( opt_key == "supports_enable" || opt_key == "support_buildplate_only" ))
og_freq_chng_params -> set_value ( "support" , support_combo_value_for_config ( * m_config , is_fff ));
2019-03-11 16:00:13 +01:00
2018-03-12 16:52:21 +01:00
if ( opt_key == "brim_width" )
{
bool val = m_config -> opt_float ( "brim_width" ) > 0.0 ? true : false ;
2018-10-05 23:29:15 +02:00
og_freq_chng_params -> set_value ( "brim" , val );
2018-03-12 16:52:21 +01:00
}
2018-04-05 10:44:31 +02:00
if ( opt_key == "wipe_tower" || opt_key == "single_extruder_multi_material" || opt_key == "extruders_count" )
update_wiping_button_visibility ();
2019-02-22 09:38:56 +01:00
if ( opt_key == "extruders_count" )
wxGetApp (). plater () -> on_extruders_change ( boost :: any_cast < size_t > ( value ));
2018-01-21 23:35:00 +01:00
update ();
2018-01-25 13:46:04 +01:00
}
2018-01-21 23:35:00 +01:00
2018-04-05 10:44:31 +02:00
// Show/hide the 'purging volumes' button
void Tab :: update_wiping_button_visibility () {
2018-10-04 16:43:10 +02:00
if ( m_preset_bundle -> printers . get_selected_preset (). printer_technology () == ptSLA )
2018-08-06 17:01:41 +02:00
return ; // ys_FIXME
2018-04-05 10:44:31 +02:00
bool wipe_tower_enabled = dynamic_cast < ConfigOptionBool *> ( ( m_preset_bundle -> prints . get_edited_preset (). config ). option ( "wipe_tower" )) -> value ;
bool multiple_extruders = dynamic_cast < ConfigOptionFloats *> (( m_preset_bundle -> printers . get_edited_preset (). config ). option ( "nozzle_diameter" )) -> values . size () > 1 ;
bool single_extruder_mm = dynamic_cast < ConfigOptionBool *> ( ( m_preset_bundle -> printers . get_edited_preset (). config ). option ( "single_extruder_multi_material" )) -> value ;
2018-10-24 12:57:23 +02:00
auto wiping_dialog_button = wxGetApp (). sidebar (). get_wiping_dialog_button ();
2018-10-03 15:14:52 +02:00
if ( wiping_dialog_button ) {
wiping_dialog_button -> Show ( wipe_tower_enabled && multiple_extruders && single_extruder_mm );
wiping_dialog_button -> GetParent () -> Layout ();
2018-09-21 01:33:41 +02:00
}
2018-04-05 10:44:31 +02:00
}
2018-01-16 16:28:01 +01:00
// Call a callback to update the selection of presets on the platter:
// To update the content of the selection boxes,
// to update the filament colors of the selection boxes,
// to update the "dirty" flags of the selection boxes,
2019-03-13 13:13:18 +01:00
// to update number of "filament" selection boxes when the number of extruders change.
2018-02-08 10:58:13 +01:00
void Tab :: on_presets_changed ()
2018-01-21 23:35:00 +01:00
{
2019-03-13 17:38:41 +01:00
if ( wxGetApp (). plater () == nullptr ) {
return ;
}
2019-03-13 13:13:18 +01:00
// Instead of PostEvent (EVT_TAB_PRESETS_CHANGED) just call update_presets
wxGetApp (). plater () -> sidebar (). update_presets ( m_type );
update_preset_description_line ();
2018-12-04 17:56:49 +01:00
// Printer selected at the Printer tab, update "compatible" marks at the print and filament selectors.
for ( auto t : m_dependent_tabs )
{
// If the printer tells us that the print or filament/sla_material preset has been switched or invalidated,
// refresh the print or filament/sla_material tab page.
wxGetApp (). get_tab ( t ) -> load_current_preset ();
2018-11-16 11:14:56 +01:00
}
2019-02-22 11:59:40 +01:00
// clear m_dependent_tabs after first update from select_preset()
// to avoid needless preset loading from update() function
m_dependent_tabs . clear ();
2018-04-26 12:40:17 +02:00
}
2018-03-23 09:41:04 +01:00
2018-04-26 12:40:17 +02:00
void Tab :: update_preset_description_line ()
{
2018-03-23 09:41:04 +01:00
const Preset * parent = m_presets -> get_selected_preset_parent ();
2018-04-26 12:40:17 +02:00
const Preset & preset = m_presets -> get_edited_preset ();
wxString description_line = preset . is_default ?
_ ( L ( "It's a default preset." )) : preset . is_system ?
_ ( L ( "It's a system preset." )) :
2019-05-11 23:29:25 +02:00
wxString :: Format ( _ ( L ( "Current preset is inherited from %s" )), ( parent == nullptr ?
_ ( L ( "default preset" )) + "." :
": \n\t " + parent -> name ));
2018-04-26 12:40:17 +02:00
if ( preset . is_default || preset . is_system )
2019-05-11 23:29:25 +02:00
description_line += " \n\t " + _ ( L ( "It can't be deleted or modified." )) +
" \n\t " + _ ( L ( "Any modifications should be saved as a new preset inherited from this one." )) +
2018-04-26 12:40:17 +02:00
" \n\t " + _ ( L ( "To do that please specify a new name for the preset." ));
if ( parent && parent -> vendor )
{
description_line += " \n\n " + _ ( L ( "Additional information:" )) + " \n " ;
2018-12-04 17:56:49 +01:00
description_line += " \t " + _ ( L ( "vendor" )) + ": " + ( m_type == Slic3r :: Preset :: TYPE_PRINTER ? " \n\t\t " : "" ) + parent -> vendor -> name +
2018-04-26 12:40:17 +02:00
", ver: " + parent -> vendor -> config_version . to_string ();
2018-12-04 17:56:49 +01:00
if ( m_type == Slic3r :: Preset :: TYPE_PRINTER ) {
2018-10-31 18:05:25 +01:00
const std :: string & printer_model = preset . config . opt_string ( "printer_model" );
if ( ! printer_model . empty ())
2018-04-26 12:40:17 +02:00
description_line += " \n\n\t " + _ ( L ( "printer model" )) + ": \n\t\t " + printer_model ;
2018-10-31 18:05:25 +01:00
switch ( preset . printer_technology ()) {
case ptFFF :
2018-04-26 12:40:17 +02:00
{
2018-10-31 18:05:25 +01:00
//FIXME add prefered_sla_material_profile for SLA
const std :: string & default_print_profile = preset . config . opt_string ( "default_print_profile" );
const std :: vector < std :: string > & default_filament_profiles = preset . config . option < ConfigOptionStrings > ( "default_filament_profile" ) -> values ;
if ( ! default_print_profile . empty ())
description_line += " \n\n\t " + _ ( L ( "default print profile" )) + ": \n\t\t " + default_print_profile ;
if ( ! default_filament_profiles . empty ())
{
description_line += " \n\n\t " + _ ( L ( "default filament profile" )) + ": \n\t\t " ;
for ( auto & profile : default_filament_profiles ) {
if ( & profile != &* default_filament_profiles . begin ())
description_line += ", " ;
description_line += profile ;
}
2018-04-26 12:40:17 +02:00
}
2018-10-31 18:05:25 +01:00
break ;
}
case ptSLA :
{
//FIXME add prefered_sla_material_profile for SLA
const std :: string & default_sla_material_profile = preset . config . opt_string ( "default_sla_material_profile" );
if ( ! default_sla_material_profile . empty ())
description_line += " \n\n\t " + _ ( L ( "default SLA material profile" )) + ": \n\t\t " + default_sla_material_profile ;
2018-11-16 17:36:23 +01:00
const std :: string & default_sla_print_profile = preset . config . opt_string ( "default_sla_print_profile" );
if ( ! default_sla_print_profile . empty ())
description_line += " \n\n\t " + _ ( L ( "default SLA print profile" )) + ": \n\t\t " + default_sla_print_profile ;
2018-10-31 18:05:25 +01:00
break ;
}
2018-04-26 12:40:17 +02:00
}
}
}
m_parent_preset_description_line -> SetText ( description_line , false );
2018-01-16 16:28:01 +01:00
}
2018-03-13 16:14:36 +01:00
void Tab :: update_frequently_changed_parameters ()
{
2019-05-03 18:01:39 +02:00
const bool is_fff = supports_printer_technology ( ptFFF );
auto og_freq_chng_params = wxGetApp (). sidebar (). og_freq_chng_params ( is_fff );
2018-10-05 23:29:15 +02:00
if ( ! og_freq_chng_params ) return ;
2019-01-15 09:31:53 +01:00
2019-05-03 18:01:39 +02:00
og_freq_chng_params -> set_value ( "support" , support_combo_value_for_config ( * m_config , is_fff ));
2018-03-13 16:14:36 +01:00
2019-03-27 16:59:34 +01:00
const std :: string updated_value_key = is_fff ? "fill_density" : "pad_enable" ;
2018-04-04 11:13:28 +02:00
2019-03-27 16:59:34 +01:00
const boost :: any val = og_freq_chng_params -> get_config_value ( * m_config , updated_value_key );
og_freq_chng_params -> set_value ( updated_value_key , val );
if ( is_fff )
{
og_freq_chng_params -> set_value ( "brim" , bool ( m_config -> opt_float ( "brim_width" ) > 0.0 ));
update_wiping_button_visibility ();
}
2018-03-13 16:14:36 +01:00
}
2018-01-05 15:11:33 +01:00
void TabPrint :: build ()
2017-12-13 14:45:10 +01:00
{
2018-01-05 15:11:33 +01:00
m_presets = & m_preset_bundle -> prints ;
2018-03-16 12:56:03 +01:00
load_initial_data ();
2017-12-13 14:45:10 +01:00
2019-04-08 09:37:23 +02:00
auto page = add_options_page ( _ ( L ( "Layers and perimeters" )), "layers" );
2018-02-23 09:16:35 +01:00
auto optgroup = page -> new_optgroup ( _ ( L ( "Layer height" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "layer_height" );
optgroup -> append_single_option_line ( "first_layer_height" );
2017-12-14 14:42:47 +01:00
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Vertical shells" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "perimeters" );
optgroup -> append_single_option_line ( "spiral_vase" );
2017-12-14 14:42:47 +01:00
2018-01-15 12:13:05 +01:00
Line line { "" , "" };
line . full_width = 1 ;
line . widget = [ this ]( wxWindow * parent ) {
return description_line_widget ( parent , & m_recommended_thin_wall_thickness_description_line );
};
optgroup -> append_line ( line );
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Horizontal shells" )));
line = { _ ( L ( "Solid layers" )), "" };
2018-01-07 18:41:40 +01:00
line . append_option ( optgroup -> get_option ( "top_solid_layers" ));
line . append_option ( optgroup -> get_option ( "bottom_solid_layers" ));
2017-12-14 14:42:47 +01:00
optgroup -> append_line ( line );
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Quality (slower slicing)" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "extra_perimeters" );
optgroup -> append_single_option_line ( "ensure_vertical_shell_thickness" );
optgroup -> append_single_option_line ( "avoid_crossing_perimeters" );
optgroup -> append_single_option_line ( "thin_walls" );
optgroup -> append_single_option_line ( "overhangs" );
2017-12-14 14:42:47 +01:00
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Advanced" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "seam_position" );
optgroup -> append_single_option_line ( "external_perimeters_first" );
2017-12-13 14:45:10 +01:00
2019-04-08 09:37:23 +02:00
page = add_options_page ( _ ( L ( "Infill" )), "infill" );
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Infill" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "fill_density" );
optgroup -> append_single_option_line ( "fill_pattern" );
2019-02-22 15:25:35 +01:00
optgroup -> append_single_option_line ( "top_fill_pattern" );
optgroup -> append_single_option_line ( "bottom_fill_pattern" );
2017-12-14 14:42:47 +01:00
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Reducing printing time" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "infill_every_layers" );
optgroup -> append_single_option_line ( "infill_only_where_needed" );
2017-12-14 14:42:47 +01:00
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Advanced" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "solid_infill_every_layers" );
optgroup -> append_single_option_line ( "fill_angle" );
optgroup -> append_single_option_line ( "solid_infill_below_area" );
optgroup -> append_single_option_line ( "bridge_angle" );
optgroup -> append_single_option_line ( "only_retract_when_crossing_perimeters" );
optgroup -> append_single_option_line ( "infill_first" );
2017-12-14 14:42:47 +01:00
2019-04-08 09:37:23 +02:00
page = add_options_page ( _ ( L ( "Skirt and brim" )), "skirt+brim" );
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Skirt" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "skirts" );
optgroup -> append_single_option_line ( "skirt_distance" );
optgroup -> append_single_option_line ( "skirt_height" );
optgroup -> append_single_option_line ( "min_skirt_length" );
2017-12-14 14:42:47 +01:00
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Brim" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "brim_width" );
2017-12-13 14:45:10 +01:00
2019-04-08 09:37:23 +02:00
page = add_options_page ( _ ( L ( "Support material" )), "support" );
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Support material" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "support_material" );
2018-09-17 15:12:13 +02:00
optgroup -> append_single_option_line ( "support_material_auto" );
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "support_material_threshold" );
optgroup -> append_single_option_line ( "support_material_enforce_layers" );
2017-12-14 14:42:47 +01:00
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Raft" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "raft_layers" );
// # optgroup->append_single_option_line(get_option_("raft_contact_distance");
2017-12-14 14:42:47 +01:00
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Options for support material and raft" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "support_material_contact_distance" );
optgroup -> append_single_option_line ( "support_material_pattern" );
optgroup -> append_single_option_line ( "support_material_with_sheath" );
optgroup -> append_single_option_line ( "support_material_spacing" );
optgroup -> append_single_option_line ( "support_material_angle" );
optgroup -> append_single_option_line ( "support_material_interface_layers" );
optgroup -> append_single_option_line ( "support_material_interface_spacing" );
optgroup -> append_single_option_line ( "support_material_interface_contact_loops" );
optgroup -> append_single_option_line ( "support_material_buildplate_only" );
optgroup -> append_single_option_line ( "support_material_xy_spacing" );
optgroup -> append_single_option_line ( "dont_support_bridges" );
optgroup -> append_single_option_line ( "support_material_synchronize_layers" );
2017-12-13 14:45:10 +01:00
2019-04-08 09:37:23 +02:00
page = add_options_page ( _ ( L ( "Speed" )), "time" );
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Speed for print moves" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "perimeter_speed" );
optgroup -> append_single_option_line ( "small_perimeter_speed" );
optgroup -> append_single_option_line ( "external_perimeter_speed" );
optgroup -> append_single_option_line ( "infill_speed" );
optgroup -> append_single_option_line ( "solid_infill_speed" );
optgroup -> append_single_option_line ( "top_solid_infill_speed" );
optgroup -> append_single_option_line ( "support_material_speed" );
optgroup -> append_single_option_line ( "support_material_interface_speed" );
optgroup -> append_single_option_line ( "bridge_speed" );
optgroup -> append_single_option_line ( "gap_fill_speed" );
2017-12-14 14:42:47 +01:00
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Speed for non-print moves" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "travel_speed" );
2017-12-14 14:42:47 +01:00
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Modifiers" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "first_layer_speed" );
2017-12-14 14:42:47 +01:00
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Acceleration control (advanced)" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "perimeter_acceleration" );
optgroup -> append_single_option_line ( "infill_acceleration" );
optgroup -> append_single_option_line ( "bridge_acceleration" );
optgroup -> append_single_option_line ( "first_layer_acceleration" );
optgroup -> append_single_option_line ( "default_acceleration" );
2017-12-14 14:42:47 +01:00
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Autospeed (advanced)" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "max_print_speed" );
optgroup -> append_single_option_line ( "max_volumetric_speed" );
2019-01-29 18:07:45 +01:00
#ifdef HAS_PRESSURE_EQUALIZER
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "max_volumetric_extrusion_rate_slope_positive" );
optgroup -> append_single_option_line ( "max_volumetric_extrusion_rate_slope_negative" );
2019-01-29 18:07:45 +01:00
#endif /* HAS_PRESSURE_EQUALIZER */
2017-12-13 14:45:10 +01:00
2019-04-08 09:37:23 +02:00
page = add_options_page ( _ ( L ( "Multiple Extruders" )), "funnel" );
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Extruders" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "perimeter_extruder" );
optgroup -> append_single_option_line ( "infill_extruder" );
optgroup -> append_single_option_line ( "solid_infill_extruder" );
optgroup -> append_single_option_line ( "support_material_extruder" );
optgroup -> append_single_option_line ( "support_material_interface_extruder" );
2017-12-14 14:42:47 +01:00
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Ooze prevention" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "ooze_prevention" );
optgroup -> append_single_option_line ( "standby_temperature_delta" );
2017-12-14 14:42:47 +01:00
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Wipe tower" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "wipe_tower" );
optgroup -> append_single_option_line ( "wipe_tower_x" );
optgroup -> append_single_option_line ( "wipe_tower_y" );
optgroup -> append_single_option_line ( "wipe_tower_width" );
2018-02-27 08:56:11 +01:00
optgroup -> append_single_option_line ( "wipe_tower_rotation_angle" );
2018-03-12 15:41:25 +01:00
optgroup -> append_single_option_line ( "wipe_tower_bridging" );
2018-07-27 22:19:46 +02:00
optgroup -> append_single_option_line ( "single_extruder_multi_material_priming" );
2017-12-14 14:42:47 +01:00
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Advanced" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "interface_shells" );
2017-12-13 14:45:10 +01:00
2019-04-12 12:08:52 +02:00
page = add_options_page ( _ ( L ( "Advanced" )), "wrench" );
2018-03-22 14:12:29 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Extrusion width" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "extrusion_width" );
optgroup -> append_single_option_line ( "first_layer_extrusion_width" );
optgroup -> append_single_option_line ( "perimeter_extrusion_width" );
optgroup -> append_single_option_line ( "external_perimeter_extrusion_width" );
optgroup -> append_single_option_line ( "infill_extrusion_width" );
optgroup -> append_single_option_line ( "solid_infill_extrusion_width" );
optgroup -> append_single_option_line ( "top_infill_extrusion_width" );
optgroup -> append_single_option_line ( "support_material_extrusion_width" );
2017-12-14 14:42:47 +01:00
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Overlap" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "infill_overlap" );
2017-12-14 14:42:47 +01:00
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Flow" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "bridge_flow_ratio" );
2017-12-14 14:42:47 +01:00
2019-03-01 17:53:02 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Slicing" )));
optgroup -> append_single_option_line ( "slice_closing_radius" );
optgroup -> append_single_option_line ( "resolution" );
optgroup -> append_single_option_line ( "xy_size_compensation" );
optgroup -> append_single_option_line ( "elefant_foot_compensation" );
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Other" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "clip_multipart_objects" );
2017-12-13 14:45:10 +01:00
2019-04-08 09:37:23 +02:00
page = add_options_page ( _ ( L ( "Output options" )), "output+page_white" );
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Sequential printing" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "complete_objects" );
2018-02-23 09:16:35 +01:00
line = { _ ( L ( "Extruder clearance (mm)" )), "" };
2018-01-07 18:41:40 +01:00
Option option = optgroup -> get_option ( "extruder_clearance_radius" );
2019-04-13 23:46:52 +02:00
option . opt . width = 6 ;
2017-12-14 14:42:47 +01:00
line . append_option ( option );
2018-01-07 18:41:40 +01:00
option = optgroup -> get_option ( "extruder_clearance_height" );
2019-04-13 23:46:52 +02:00
option . opt . width = 6 ;
2017-12-14 14:42:47 +01:00
line . append_option ( option );
optgroup -> append_line ( line );
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Output file" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "gcode_comments" );
2019-01-31 15:09:16 +01:00
optgroup -> append_single_option_line ( "gcode_label_objects" );
2018-01-07 18:41:40 +01:00
option = optgroup -> get_option ( "output_filename_format" );
2017-12-18 13:58:51 +01:00
option . opt . full_width = true ;
2017-12-14 14:42:47 +01:00
optgroup -> append_single_option_line ( option );
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Post-processing scripts" )), 0 );
2018-01-07 18:41:40 +01:00
option = optgroup -> get_option ( "post_process" );
2017-12-18 13:58:51 +01:00
option . opt . full_width = true ;
2019-04-13 23:46:52 +02:00
option . opt . height = 5 ; //50;
2017-12-14 14:42:47 +01:00
optgroup -> append_single_option_line ( option );
2017-12-13 14:45:10 +01:00
2018-02-23 09:16:35 +01:00
page = add_options_page ( _ ( L ( "Notes" )), "note.png" );
optgroup = page -> new_optgroup ( _ ( L ( "Notes" )), 0 );
2018-01-07 18:41:40 +01:00
option = optgroup -> get_option ( "notes" );
2017-12-18 13:58:51 +01:00
option . opt . full_width = true ;
2019-04-13 23:46:52 +02:00
option . opt . height = 25 ; //250;
2017-12-14 14:42:47 +01:00
optgroup -> append_single_option_line ( option );
2017-12-13 14:45:10 +01:00
2018-02-23 09:16:35 +01:00
page = add_options_page ( _ ( L ( "Dependencies" )), "wrench.png" );
optgroup = page -> new_optgroup ( _ ( L ( "Profile dependencies" )));
2018-12-04 17:56:49 +01:00
line = optgroup -> create_single_option_line ( "compatible_printers" );
line . widget = [ this ]( wxWindow * parent ) {
return compatible_widget_create ( parent , m_compatible_printers );
2017-12-26 23:04:54 +01:00
};
2018-04-13 18:22:06 +02:00
optgroup -> append_line ( line , & m_colored_Label );
2018-01-11 10:33:17 +01:00
option = optgroup -> get_option ( "compatible_printers_condition" );
option . opt . full_width = true ;
optgroup -> append_single_option_line ( option );
2018-03-22 11:46:15 +01:00
line = Line { "" , "" };
line . full_width = 1 ;
line . widget = [ this ]( wxWindow * parent ) {
return description_line_widget ( parent , & m_parent_preset_description_line );
};
optgroup -> append_line ( line );
2017-12-13 14:45:10 +01:00
}
2018-01-12 12:41:13 +01:00
// Reload current config (aka presets->edited_preset->config) into the UI fields.
2018-10-31 12:56:08 +01:00
void TabPrint :: reload_config ()
{
2018-12-04 17:56:49 +01:00
this -> compatible_widget_reload ( m_compatible_printers );
2018-01-12 12:41:13 +01:00
Tab :: reload_config ();
}
2018-01-05 15:11:33 +01:00
void TabPrint :: update ()
{
2018-10-04 16:43:10 +02:00
if ( m_preset_bundle -> printers . get_selected_preset (). printer_technology () == ptSLA )
2018-08-06 17:01:41 +02:00
return ; // ys_FIXME
2019-02-22 09:38:56 +01:00
// #ys_FIXME_to_delete
2019-01-14 15:38:54 +01:00
//! Temporary workaround for the correct updates of the SpinCtrl (like "perimeters"):
// KillFocus() for the wxSpinCtrl use CallAfter function. So,
// to except the duplicate call of the update() after dialog->ShowModal(),
// let check if this process is already started.
2019-02-20 16:09:18 +01:00
// if (is_msg_dlg_already_exist) // ! It looks like a fixed problem after start to using of a m_dirty_options
// return; // ! TODO Let delete this part of code after a common aplication testing
2019-01-14 15:38:54 +01:00
2019-02-22 09:38:56 +01:00
m_update_cnt ++ ;
2019-03-18 12:48:39 +01:00
// Freeze();
2018-01-05 15:11:33 +01:00
2018-03-16 17:25:11 +01:00
double fill_density = m_config -> option < ConfigOptionPercent > ( "fill_density" ) -> value ;
2018-02-23 09:16:35 +01:00
if ( m_config -> opt_bool ( "spiral_vase" ) &&
2018-01-26 01:44:34 +01:00
! ( m_config -> opt_int ( "perimeters" ) == 1 && m_config -> opt_int ( "top_solid_layers" ) == 0 &&
2018-03-16 17:25:11 +01:00
fill_density == 0 )) {
2018-02-23 09:16:35 +01:00
wxString msg_text = _ ( L ( "The Spiral Vase mode requires: \n "
2018-01-05 15:11:33 +01:00
"- one perimeter \n "
2018-02-23 09:16:35 +01:00
"- no top solid layers \n "
"- 0% fill density \n "
"- no support material \n "
"- no ensure_vertical_shell_thickness \n "
" \n Shall I adjust those settings in order to enable Spiral Vase?" ));
auto dialog = new wxMessageDialog ( parent (), msg_text , _ ( L ( "Spiral Vase" )), wxICON_WARNING | wxYES | wxNO );
2019-02-20 16:09:18 +01:00
// is_msg_dlg_already_exist = true;
2018-01-26 01:44:34 +01:00
DynamicPrintConfig new_conf = * m_config ;
2018-02-23 09:16:35 +01:00
if ( dialog -> ShowModal () == wxID_YES ) {
2018-01-05 15:11:33 +01:00
new_conf . set_key_value ( "perimeters" , new ConfigOptionInt ( 1 ));
new_conf . set_key_value ( "top_solid_layers" , new ConfigOptionInt ( 0 ));
new_conf . set_key_value ( "fill_density" , new ConfigOptionPercent ( 0 ));
new_conf . set_key_value ( "support_material" , new ConfigOptionBool ( false ));
2018-02-22 11:34:41 +01:00
new_conf . set_key_value ( "support_material_enforce_layers" , new ConfigOptionInt ( 0 ));
2018-01-05 15:11:33 +01:00
new_conf . set_key_value ( "ensure_vertical_shell_thickness" , new ConfigOptionBool ( false ));
2018-03-16 17:25:11 +01:00
fill_density = 0 ;
2018-01-05 15:11:33 +01:00
}
else {
new_conf . set_key_value ( "spiral_vase" , new ConfigOptionBool ( false ));
}
2018-02-23 09:16:35 +01:00
load_config ( new_conf );
2018-03-16 17:25:11 +01:00
on_value_change ( "fill_density" , fill_density );
2019-02-20 16:09:18 +01:00
// is_msg_dlg_already_exist = false;
2018-01-05 15:11:33 +01:00
}
2018-02-23 09:16:35 +01:00
if ( m_config -> opt_bool ( "wipe_tower" ) && m_config -> opt_bool ( "support_material" ) &&
2018-01-12 12:41:13 +01:00
m_config -> opt_float ( "support_material_contact_distance" ) > 0. &&
( m_config -> opt_int ( "support_material_extruder" ) != 0 || m_config -> opt_int ( "support_material_interface_extruder" ) != 0 )) {
2018-02-23 09:16:35 +01:00
wxString msg_text = _ ( L ( "The Wipe Tower currently supports the non-soluble supports only \n "
2018-01-11 10:33:17 +01:00
"if they are printed with the current extruder without triggering a tool change. \n "
"(both support_material_extruder and support_material_interface_extruder need to be set to 0). \n "
2018-02-23 09:16:35 +01:00
" \n Shall I adjust those settings in order to enable the Wipe Tower?" ));
auto dialog = new wxMessageDialog ( parent (), msg_text , _ ( L ( "Wipe Tower" )), wxICON_WARNING | wxYES | wxNO );
2018-01-12 12:41:13 +01:00
DynamicPrintConfig new_conf = * m_config ;
2018-01-11 10:33:17 +01:00
if ( dialog -> ShowModal () == wxID_YES ) {
new_conf . set_key_value ( "support_material_extruder" , new ConfigOptionInt ( 0 ));
new_conf . set_key_value ( "support_material_interface_extruder" , new ConfigOptionInt ( 0 ));
}
2018-02-23 09:16:35 +01:00
else
2018-01-11 10:33:17 +01:00
new_conf . set_key_value ( "wipe_tower" , new ConfigOptionBool ( false ));
load_config ( new_conf );
}
2018-02-23 09:16:35 +01:00
if ( m_config -> opt_bool ( "wipe_tower" ) && m_config -> opt_bool ( "support_material" ) &&
2018-01-12 12:41:13 +01:00
m_config -> opt_float ( "support_material_contact_distance" ) == 0 &&
! m_config -> opt_bool ( "support_material_synchronize_layers" )) {
2018-02-23 09:16:35 +01:00
wxString msg_text = _ ( L ( "For the Wipe Tower to work with the soluble supports, the support layers \n "
2018-01-11 10:33:17 +01:00
"need to be synchronized with the object layers. \n "
2018-02-23 09:16:35 +01:00
" \n Shall I synchronize support layers in order to enable the Wipe Tower?" ));
auto dialog = new wxMessageDialog ( parent (), msg_text , _ ( L ( "Wipe Tower" )), wxICON_WARNING | wxYES | wxNO );
2018-01-12 12:41:13 +01:00
DynamicPrintConfig new_conf = * m_config ;
2018-01-11 10:33:17 +01:00
if ( dialog -> ShowModal () == wxID_YES ) {
new_conf . set_key_value ( "support_material_synchronize_layers" , new ConfigOptionBool ( true ));
}
else
new_conf . set_key_value ( "wipe_tower" , new ConfigOptionBool ( false ));
load_config ( new_conf );
}
2018-01-12 12:41:13 +01:00
if ( m_config -> opt_bool ( "support_material" )) {
2018-01-11 10:33:17 +01:00
// Ask only once.
if ( ! m_support_material_overhangs_queried ) {
m_support_material_overhangs_queried = true ;
2018-01-12 12:41:13 +01:00
if ( ! m_config -> opt_bool ( "overhangs" ) /* != 1*/ ) {
2018-02-23 09:16:35 +01:00
wxString msg_text = _ ( L ( "Supports work better, if the following feature is enabled: \n "
2018-01-11 10:33:17 +01:00
"- Detect bridging perimeters \n "
2018-02-23 09:16:35 +01:00
" \n Shall I adjust those settings for supports?" ));
auto dialog = new wxMessageDialog ( parent (), msg_text , _ ( L ( "Support Generator" )), wxICON_WARNING | wxYES | wxNO | wxCANCEL );
2018-01-12 12:41:13 +01:00
DynamicPrintConfig new_conf = * m_config ;
2018-01-11 10:33:17 +01:00
auto answer = dialog -> ShowModal ();
if ( answer == wxID_YES ) {
// Enable "detect bridging perimeters".
new_conf . set_key_value ( "overhangs" , new ConfigOptionBool ( true ));
2018-02-23 09:16:35 +01:00
} else if ( answer == wxID_NO ) {
2018-01-11 10:33:17 +01:00
// Do nothing, leave supports on and "detect bridging perimeters" off.
2018-02-23 09:16:35 +01:00
} else if ( answer == wxID_CANCEL ) {
2018-01-11 10:33:17 +01:00
// Disable supports.
new_conf . set_key_value ( "support_material" , new ConfigOptionBool ( false ));
m_support_material_overhangs_queried = false ;
}
load_config ( new_conf );
}
}
}
else {
m_support_material_overhangs_queried = false ;
}
2018-01-12 12:41:13 +01:00
if ( m_config -> option < ConfigOptionPercent > ( "fill_density" ) -> value == 100 ) {
auto fill_pattern = m_config -> option < ConfigOptionEnum < InfillPattern >> ( "fill_pattern" ) -> value ;
2018-01-11 10:33:17 +01:00
std :: string str_fill_pattern = "" ;
2018-01-12 12:41:13 +01:00
t_config_enum_values map_names = m_config -> option < ConfigOptionEnum < InfillPattern >> ( "fill_pattern" ) -> get_enum_values ();
2018-02-23 09:16:35 +01:00
for ( auto it : map_names ) {
2018-01-11 10:33:17 +01:00
if ( fill_pattern == it . second ) {
str_fill_pattern = it . first ;
break ;
}
}
2018-10-31 12:56:08 +01:00
if ( ! str_fill_pattern . empty ()) {
2019-02-22 15:25:35 +01:00
const std :: vector < std :: string > & external_fill_pattern = m_config -> def () -> get ( "top_fill_pattern" ) -> enum_values ;
2018-01-11 10:33:17 +01:00
bool correct_100p_fill = false ;
2018-12-04 17:56:49 +01:00
for ( const std :: string & fill : external_fill_pattern )
2018-01-11 10:33:17 +01:00
{
2018-12-04 17:56:49 +01:00
if ( str_fill_pattern == fill )
2018-01-11 10:33:17 +01:00
correct_100p_fill = true ;
}
// get fill_pattern name from enum_labels for using this one at dialog_msg
2019-05-11 23:29:25 +02:00
str_fill_pattern = _utf8 ( m_config -> def () -> get ( "fill_pattern" ) -> enum_labels [ fill_pattern ]);
2018-10-31 12:56:08 +01:00
if ( ! correct_100p_fill ) {
2019-05-11 23:29:25 +02:00
wxString msg_text = GUI :: from_u8 (( boost :: format ( _utf8 ( L ( "The %1% infill pattern is not supposed to work at 100%% density. \n\n "
"Shall I switch to rectilinear fill pattern?" ))) % str_fill_pattern ). str ());
2018-02-23 09:16:35 +01:00
auto dialog = new wxMessageDialog ( parent (), msg_text , _ ( L ( "Infill" )), wxICON_WARNING | wxYES | wxNO );
2018-01-12 12:41:13 +01:00
DynamicPrintConfig new_conf = * m_config ;
2018-01-11 10:33:17 +01:00
if ( dialog -> ShowModal () == wxID_YES ) {
new_conf . set_key_value ( "fill_pattern" , new ConfigOptionEnum < InfillPattern > ( ipRectilinear ));
2018-03-14 11:45:31 +01:00
fill_density = 100 ;
2018-01-11 10:33:17 +01:00
}
else
2018-03-14 15:10:16 +01:00
fill_density = m_presets -> get_selected_preset (). config . option < ConfigOptionPercent > ( "fill_density" ) -> value ;
2018-03-14 11:45:31 +01:00
new_conf . set_key_value ( "fill_density" , new ConfigOptionPercent ( fill_density ));
2018-01-11 10:33:17 +01:00
load_config ( new_conf );
2018-03-14 11:45:31 +01:00
on_value_change ( "fill_density" , fill_density );
2018-01-11 10:33:17 +01:00
}
}
}
2018-01-12 12:41:13 +01:00
bool have_perimeters = m_config -> opt_int ( "perimeters" ) > 0 ;
2018-04-04 10:18:26 +02:00
for ( auto el : { "extra_perimeters" , "ensure_vertical_shell_thickness" , "thin_walls" , "overhangs" ,
"seam_position" , "external_perimeters_first" , "external_perimeter_extrusion_width" ,
"perimeter_speed" , "small_perimeter_speed" , "external_perimeter_speed" })
2018-01-11 10:33:17 +01:00
get_field ( el ) -> toggle ( have_perimeters );
2018-01-12 12:41:13 +01:00
bool have_infill = m_config -> option < ConfigOptionPercent > ( "fill_density" ) -> value > 0 ;
2018-01-11 10:33:17 +01:00
// infill_extruder uses the same logic as in Print::extruders()
2018-04-04 10:18:26 +02:00
for ( auto el : { "fill_pattern" , "infill_every_layers" , "infill_only_where_needed" ,
"solid_infill_every_layers" , "solid_infill_below_area" , "infill_extruder" })
2018-01-11 10:33:17 +01:00
get_field ( el ) -> toggle ( have_infill );
2018-01-12 12:41:13 +01:00
bool have_solid_infill = m_config -> opt_int ( "top_solid_layers" ) > 0 || m_config -> opt_int ( "bottom_solid_layers" ) > 0 ;
2018-01-11 10:33:17 +01:00
// solid_infill_extruder uses the same logic as in Print::extruders()
2019-02-22 15:25:35 +01:00
for ( auto el : { "top_fill_pattern" , "bottom_fill_pattern" , "infill_first" , "solid_infill_extruder" ,
2018-04-04 10:18:26 +02:00
"solid_infill_extrusion_width" , "solid_infill_speed" })
2018-01-11 10:33:17 +01:00
get_field ( el ) -> toggle ( have_solid_infill );
2018-04-04 10:18:26 +02:00
for ( auto el : { "fill_angle" , "bridge_angle" , "infill_extrusion_width" ,
"infill_speed" , "bridge_speed" })
2018-01-11 10:33:17 +01:00
get_field ( el ) -> toggle ( have_infill || have_solid_infill );
get_field ( "gap_fill_speed" ) -> toggle ( have_perimeters && have_infill );
2018-01-12 12:41:13 +01:00
bool have_top_solid_infill = m_config -> opt_int ( "top_solid_layers" ) > 0 ;
2018-04-04 10:18:26 +02:00
for ( auto el : { "top_infill_extrusion_width" , "top_solid_infill_speed" })
2018-01-11 10:33:17 +01:00
get_field ( el ) -> toggle ( have_top_solid_infill );
2018-01-12 12:41:13 +01:00
bool have_default_acceleration = m_config -> opt_float ( "default_acceleration" ) > 0 ;
2018-04-04 10:18:26 +02:00
for ( auto el : { "perimeter_acceleration" , "infill_acceleration" ,
"bridge_acceleration" , "first_layer_acceleration" })
2018-01-11 10:33:17 +01:00
get_field ( el ) -> toggle ( have_default_acceleration );
2018-01-12 12:41:13 +01:00
bool have_skirt = m_config -> opt_int ( "skirts" ) > 0 || m_config -> opt_float ( "min_skirt_length" ) > 0 ;
2018-04-04 10:18:26 +02:00
for ( auto el : { "skirt_distance" , "skirt_height" })
2018-01-11 10:33:17 +01:00
get_field ( el ) -> toggle ( have_skirt );
2018-01-12 12:41:13 +01:00
bool have_brim = m_config -> opt_float ( "brim_width" ) > 0 ;
2018-01-11 10:33:17 +01:00
// perimeter_extruder uses the same logic as in Print::extruders()
get_field ( "perimeter_extruder" ) -> toggle ( have_perimeters || have_brim );
2018-01-12 12:41:13 +01:00
bool have_raft = m_config -> opt_int ( "raft_layers" ) > 0 ;
bool have_support_material = m_config -> opt_bool ( "support_material" ) || have_raft ;
2018-09-17 15:12:13 +02:00
bool have_support_material_auto = have_support_material && m_config -> opt_bool ( "support_material_auto" );
2018-01-12 12:41:13 +01:00
bool have_support_interface = m_config -> opt_int ( "support_material_interface_layers" ) > 0 ;
bool have_support_soluble = have_support_material && m_config -> opt_float ( "support_material_contact_distance" ) == 0 ;
2018-09-17 15:12:13 +02:00
for ( auto el : { "support_material_pattern" , "support_material_with_sheath" ,
2018-02-23 09:16:35 +01:00
"support_material_spacing" , "support_material_angle" , "support_material_interface_layers" ,
"dont_support_bridges" , "support_material_extrusion_width" , "support_material_contact_distance" ,
2018-04-04 10:18:26 +02:00
"support_material_xy_spacing" })
2018-01-11 10:33:17 +01:00
get_field ( el ) -> toggle ( have_support_material );
2018-09-17 15:12:13 +02:00
get_field ( "support_material_threshold" ) -> toggle ( have_support_material_auto );
2018-01-11 10:33:17 +01:00
2018-04-04 10:18:26 +02:00
for ( auto el : { "support_material_interface_spacing" , "support_material_interface_extruder" ,
"support_material_interface_speed" , "support_material_interface_contact_loops" })
2018-01-11 10:33:17 +01:00
get_field ( el ) -> toggle ( have_support_material && have_support_interface );
get_field ( "support_material_synchronize_layers" ) -> toggle ( have_support_soluble );
get_field ( "perimeter_extrusion_width" ) -> toggle ( have_perimeters || have_skirt || have_brim );
get_field ( "support_material_extruder" ) -> toggle ( have_support_material || have_skirt );
get_field ( "support_material_speed" ) -> toggle ( have_support_material || have_brim || have_skirt );
2018-01-12 12:41:13 +01:00
bool have_sequential_printing = m_config -> opt_bool ( "complete_objects" );
2018-04-04 10:18:26 +02:00
for ( auto el : { "extruder_clearance_radius" , "extruder_clearance_height" })
2018-01-11 10:33:17 +01:00
get_field ( el ) -> toggle ( have_sequential_printing );
2018-01-12 12:41:13 +01:00
bool have_ooze_prevention = m_config -> opt_bool ( "ooze_prevention" );
2018-01-11 10:33:17 +01:00
get_field ( "standby_temperature_delta" ) -> toggle ( have_ooze_prevention );
2018-01-12 12:41:13 +01:00
bool have_wipe_tower = m_config -> opt_bool ( "wipe_tower" );
2018-04-04 10:18:26 +02:00
for ( auto el : { "wipe_tower_x" , "wipe_tower_y" , "wipe_tower_width" , "wipe_tower_rotation_angle" , "wipe_tower_bridging" })
2018-01-11 10:33:17 +01:00
get_field ( el ) -> toggle ( have_wipe_tower );
2018-01-05 15:11:33 +01:00
2018-01-15 12:13:05 +01:00
m_recommended_thin_wall_thickness_description_line -> SetText (
2018-02-26 13:57:36 +01:00
from_u8 ( PresetHints :: recommended_thin_wall_thickness ( * m_preset_bundle )));
2019-05-11 23:29:25 +02:00
Layout ();
2018-01-15 12:13:05 +01:00
2019-03-18 12:48:39 +01:00
// Thaw();
2019-02-22 09:38:56 +01:00
m_update_cnt -- ;
if ( m_update_cnt == 0 )
wxGetApp (). mainframe -> on_config_changed ( m_config );
2018-01-05 15:11:33 +01:00
}
2018-01-15 12:13:05 +01:00
void TabPrint :: OnActivate ()
{
2018-02-26 13:57:36 +01:00
m_recommended_thin_wall_thickness_description_line -> SetText (
from_u8 ( PresetHints :: recommended_thin_wall_thickness ( * m_preset_bundle )));
2018-06-28 18:30:22 +02:00
Tab :: OnActivate ();
2018-01-15 12:13:05 +01:00
}
2018-01-05 15:11:33 +01:00
void TabFilament :: build ()
2017-12-22 11:50:28 +01:00
{
2018-01-12 12:41:13 +01:00
m_presets = & m_preset_bundle -> filaments ;
2018-03-16 12:56:03 +01:00
load_initial_data ();
2017-12-22 11:50:28 +01:00
2018-02-23 09:16:35 +01:00
auto page = add_options_page ( _ ( L ( "Filament" )), "spool.png" );
auto optgroup = page -> new_optgroup ( _ ( L ( "Filament" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "filament_colour" );
optgroup -> append_single_option_line ( "filament_diameter" );
optgroup -> append_single_option_line ( "extrusion_multiplier" );
optgroup -> append_single_option_line ( "filament_density" );
optgroup -> append_single_option_line ( "filament_cost" );
2017-12-22 11:50:28 +01:00
2019-05-11 23:29:25 +02:00
optgroup = page -> new_optgroup ( _ ( L ( "Temperature" )) + wxString ( " °C" , wxConvUTF8 ));
2018-02-23 09:16:35 +01:00
Line line = { _ ( L ( "Extruder" )), "" };
2018-01-07 18:41:40 +01:00
line . append_option ( optgroup -> get_option ( "first_layer_temperature" ));
line . append_option ( optgroup -> get_option ( "temperature" ));
2017-12-22 11:50:28 +01:00
optgroup -> append_line ( line );
2018-02-23 09:16:35 +01:00
line = { _ ( L ( "Bed" )), "" };
2018-01-07 18:41:40 +01:00
line . append_option ( optgroup -> get_option ( "first_layer_bed_temperature" ));
line . append_option ( optgroup -> get_option ( "bed_temperature" ));
2017-12-22 11:50:28 +01:00
optgroup -> append_line ( line );
2019-04-04 09:20:11 +02:00
page = add_options_page ( _ ( L ( "Cooling" )), "cooling" );
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Enable" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "fan_always_on" );
optgroup -> append_single_option_line ( "cooling" );
2017-12-22 11:50:28 +01:00
2018-02-23 09:16:35 +01:00
line = { "" , "" };
2017-12-22 11:50:28 +01:00
line . full_width = 1 ;
2017-12-26 23:04:54 +01:00
line . widget = [ this ]( wxWindow * parent ) {
2018-01-15 12:13:05 +01:00
return description_line_widget ( parent , & m_cooling_description_line );
2017-12-26 23:04:54 +01:00
};
2017-12-22 11:50:28 +01:00
optgroup -> append_line ( line );
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Fan settings" )));
line = { _ ( L ( "Fan speed" )), "" };
2018-01-07 18:41:40 +01:00
line . append_option ( optgroup -> get_option ( "min_fan_speed" ));
line . append_option ( optgroup -> get_option ( "max_fan_speed" ));
2017-12-22 11:50:28 +01:00
optgroup -> append_line ( line );
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "bridge_fan_speed" );
optgroup -> append_single_option_line ( "disable_fan_first_layers" );
2017-12-22 11:50:28 +01:00
2019-04-13 23:46:52 +02:00
optgroup = page -> new_optgroup ( _ ( L ( "Cooling thresholds" )), 25 );
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "fan_below_layer_time" );
optgroup -> append_single_option_line ( "slowdown_below_layer_time" );
optgroup -> append_single_option_line ( "min_print_speed" );
2017-12-22 11:50:28 +01:00
2019-04-12 12:08:52 +02:00
page = add_options_page ( _ ( L ( "Advanced" )), "wrench" );
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Filament properties" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "filament_type" );
optgroup -> append_single_option_line ( "filament_soluble" );
2017-12-22 11:50:28 +01:00
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Print speed override" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "filament_max_volumetric_speed" );
2017-12-22 11:50:28 +01:00
2018-02-23 09:16:35 +01:00
line = { "" , "" };
2017-12-22 11:50:28 +01:00
line . full_width = 1 ;
2017-12-26 23:04:54 +01:00
line . widget = [ this ]( wxWindow * parent ) {
2018-01-15 12:13:05 +01:00
return description_line_widget ( parent , & m_volumetric_speed_description_line );
2017-12-26 23:04:54 +01:00
};
2017-12-22 11:50:28 +01:00
optgroup -> append_line ( line );
2018-05-02 10:52:17 +02:00
optgroup = page -> new_optgroup ( _ ( L ( "Toolchange parameters with single extruder MM printers" )));
2018-08-21 14:36:24 +02:00
optgroup -> append_single_option_line ( "filament_loading_speed_start" );
optgroup -> append_single_option_line ( "filament_loading_speed" );
2018-08-14 16:23:23 +02:00
optgroup -> append_single_option_line ( "filament_unloading_speed_start" );
2018-03-02 15:52:16 +01:00
optgroup -> append_single_option_line ( "filament_unloading_speed" );
2018-07-31 09:44:29 +02:00
optgroup -> append_single_option_line ( "filament_load_time" );
optgroup -> append_single_option_line ( "filament_unload_time" );
2018-03-02 15:52:16 +01:00
optgroup -> append_single_option_line ( "filament_toolchange_delay" );
2018-04-24 13:02:08 +02:00
optgroup -> append_single_option_line ( "filament_cooling_moves" );
optgroup -> append_single_option_line ( "filament_cooling_initial_speed" );
optgroup -> append_single_option_line ( "filament_cooling_final_speed" );
2018-08-02 15:14:12 +02:00
optgroup -> append_single_option_line ( "filament_minimal_purge_on_wipe_tower" );
2018-04-24 13:10:33 +02:00
2018-10-19 13:55:29 +02:00
line = optgroup -> create_single_option_line ( "filament_ramming_parameters" ); // { _(L("Ramming")), "" };
2018-10-31 12:56:08 +01:00
line . widget = [ this ]( wxWindow * parent ) {
2018-06-07 22:10:23 +02:00
auto ramming_dialog_btn = new wxButton ( parent , wxID_ANY , _ ( L ( "Ramming settings" )) + dots , wxDefaultPosition , wxDefaultSize , wxBU_EXACTFIT );
2019-03-18 20:54:01 +01:00
ramming_dialog_btn -> SetFont ( Slic3r :: GUI :: wxGetApp (). normal_font ());
2018-03-13 15:54:29 +01:00
auto sizer = new wxBoxSizer ( wxHORIZONTAL );
sizer -> Add ( ramming_dialog_btn );
ramming_dialog_btn -> Bind ( wxEVT_BUTTON , ([ this ]( wxCommandEvent & e )
2018-03-12 15:41:25 +01:00
{
2018-03-15 14:04:12 +01:00
RammingDialog dlg ( this ,( m_config -> option < ConfigOptionStrings > ( "filament_ramming_parameters" )) -> get_at ( 0 ));
2018-03-28 15:37:10 +02:00
if ( dlg . ShowModal () == wxID_OK )
( m_config -> option < ConfigOptionStrings > ( "filament_ramming_parameters" )) -> get_at ( 0 ) = dlg . get_parameters ();
2018-03-13 15:54:29 +01:00
}));
2018-03-12 15:41:25 +01:00
return sizer ;
};
optgroup -> append_line ( line );
2019-04-13 23:46:52 +02:00
const int gcode_field_height = 15 ; // 150
const int notes_field_height = 25 ; // 250
2018-03-02 15:52:16 +01:00
2019-04-08 09:37:23 +02:00
page = add_options_page ( _ ( L ( "Custom G-code" )), "cog" );
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Start G-code" )), 0 );
2018-01-07 18:41:40 +01:00
Option option = optgroup -> get_option ( "start_filament_gcode" );
2017-12-22 11:50:28 +01:00
option . opt . full_width = true ;
2019-02-04 12:07:15 +01:00
option . opt . height = gcode_field_height ; // 150;
2017-12-22 11:50:28 +01:00
optgroup -> append_single_option_line ( option );
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "End G-code" )), 0 );
2018-01-07 18:41:40 +01:00
option = optgroup -> get_option ( "end_filament_gcode" );
2017-12-22 11:50:28 +01:00
option . opt . full_width = true ;
2019-02-04 12:07:15 +01:00
option . opt . height = gcode_field_height ; // 150;
2017-12-22 11:50:28 +01:00
optgroup -> append_single_option_line ( option );
2018-02-23 09:16:35 +01:00
page = add_options_page ( _ ( L ( "Notes" )), "note.png" );
optgroup = page -> new_optgroup ( _ ( L ( "Notes" )), 0 );
2017-12-22 11:50:28 +01:00
optgroup -> label_width = 0 ;
2018-01-07 18:41:40 +01:00
option = optgroup -> get_option ( "filament_notes" );
2017-12-22 11:50:28 +01:00
option . opt . full_width = true ;
2019-02-04 12:07:15 +01:00
option . opt . height = notes_field_height ; // 250;
2017-12-26 23:04:54 +01:00
optgroup -> append_single_option_line ( option );
2017-12-22 11:50:28 +01:00
2018-02-23 09:16:35 +01:00
page = add_options_page ( _ ( L ( "Dependencies" )), "wrench.png" );
optgroup = page -> new_optgroup ( _ ( L ( "Profile dependencies" )));
2018-12-04 17:56:49 +01:00
line = optgroup -> create_single_option_line ( "compatible_printers" );
line . widget = [ this ]( wxWindow * parent ) {
return compatible_widget_create ( parent , m_compatible_printers );
2017-12-26 23:04:54 +01:00
};
2018-04-13 18:22:06 +02:00
optgroup -> append_line ( line , & m_colored_Label );
2018-01-12 12:41:13 +01:00
option = optgroup -> get_option ( "compatible_printers_condition" );
option . opt . full_width = true ;
optgroup -> append_single_option_line ( option );
2018-03-22 11:46:15 +01:00
2018-12-04 17:56:49 +01:00
line = optgroup -> create_single_option_line ( "compatible_prints" );
line . widget = [ this ]( wxWindow * parent ) {
return compatible_widget_create ( parent , m_compatible_prints );
};
optgroup -> append_line ( line , & m_colored_Label );
option = optgroup -> get_option ( "compatible_prints_condition" );
option . opt . full_width = true ;
optgroup -> append_single_option_line ( option );
2018-03-22 11:46:15 +01:00
line = Line { "" , "" };
line . full_width = 1 ;
line . widget = [ this ]( wxWindow * parent ) {
return description_line_widget ( parent , & m_parent_preset_description_line );
};
optgroup -> append_line ( line );
2018-01-12 12:41:13 +01:00
}
// Reload current config (aka presets->edited_preset->config) into the UI fields.
2018-10-31 12:56:08 +01:00
void TabFilament :: reload_config ()
{
2018-12-04 17:56:49 +01:00
this -> compatible_widget_reload ( m_compatible_printers );
this -> compatible_widget_reload ( m_compatible_prints );
2018-01-12 12:41:13 +01:00
Tab :: reload_config ();
}
void TabFilament :: update ()
{
2018-10-04 16:43:10 +02:00
if ( m_preset_bundle -> printers . get_selected_preset (). printer_technology () == ptSLA )
2018-08-06 17:01:41 +02:00
return ; // ys_FIXME
2019-02-22 09:38:56 +01:00
m_update_cnt ++ ;
2019-03-18 12:48:39 +01:00
// Freeze();
2018-02-22 11:34:41 +01:00
wxString text = from_u8 ( PresetHints :: cooling_description ( m_presets -> get_edited_preset ()));
2018-01-15 12:13:05 +01:00
m_cooling_description_line -> SetText ( text );
2018-02-22 11:34:41 +01:00
text = from_u8 ( PresetHints :: maximum_volumetric_flow_description ( * m_preset_bundle ));
2018-01-15 12:13:05 +01:00
m_volumetric_speed_description_line -> SetText ( text );
2019-05-11 23:29:25 +02:00
Layout ();
2018-01-12 12:41:13 +01:00
bool cooling = m_config -> opt_bool ( "cooling" , 0 );
bool fan_always_on = cooling || m_config -> opt_bool ( "fan_always_on" , 0 );
2018-04-04 10:18:26 +02:00
for ( auto el : { "max_fan_speed" , "fan_below_layer_time" , "slowdown_below_layer_time" , "min_print_speed" })
2018-01-12 12:41:13 +01:00
get_field ( el ) -> toggle ( cooling );
2018-04-04 10:18:26 +02:00
for ( auto el : { "min_fan_speed" , "disable_fan_first_layers" })
2018-01-12 12:41:13 +01:00
get_field ( el ) -> toggle ( fan_always_on );
2019-03-18 12:48:39 +01:00
// Thaw();
2019-02-22 09:38:56 +01:00
m_update_cnt -- ;
if ( m_update_cnt == 0 )
wxGetApp (). mainframe -> on_config_changed ( m_config );
2018-01-12 12:41:13 +01:00
}
void TabFilament :: OnActivate ()
{
2018-02-22 11:34:41 +01:00
m_volumetric_speed_description_line -> SetText ( from_u8 ( PresetHints :: maximum_volumetric_flow_description ( * m_preset_bundle )));
2018-06-28 18:30:22 +02:00
Tab :: OnActivate ();
2017-12-22 11:50:28 +01:00
}
2018-01-15 12:13:05 +01:00
wxSizer * Tab :: description_line_widget ( wxWindow * parent , ogStaticText * * StaticText )
2017-12-22 11:50:28 +01:00
{
2018-01-15 12:13:05 +01:00
* StaticText = new ogStaticText ( parent , "" );
2019-04-13 23:46:52 +02:00
// auto font = (new wxSystemSettings)->GetFont(wxSYS_DEFAULT_GUI_FONT);
( * StaticText ) -> SetFont ( wxGetApp (). normal_font ());
2017-12-22 11:50:28 +01:00
auto sizer = new wxBoxSizer ( wxHORIZONTAL );
2018-04-26 12:40:17 +02:00
sizer -> Add ( * StaticText , 1 , wxEXPAND | wxALL , 0 );
2017-12-22 11:50:28 +01:00
return sizer ;
}
2018-01-25 13:46:04 +01:00
bool Tab :: current_preset_is_dirty ()
{
return m_presets -> current_is_dirty ();
}
2018-12-18 14:34:16 +01:00
void TabPrinter :: build_printhost ( ConfigOptionsGroup * optgroup )
{
2019-03-12 17:41:43 +01:00
const PrinterTechnology tech = m_presets -> get_selected_preset (). printer_technology ();
2018-12-18 14:34:16 +01:00
// Only offer the host type selection for FFF, for SLA it's always the SL1 printer (at the moment)
2019-03-12 17:41:43 +01:00
if ( tech == ptFFF ) {
2018-12-18 14:34:16 +01:00
optgroup -> append_single_option_line ( "host_type" );
}
2019-03-12 17:41:43 +01:00
auto printhost_browse = [ = ]( wxWindow * parent ) {
2019-05-04 02:07:07 +02:00
add_scaled_button ( parent , & m_printhost_browse_btn , "browse" , _ ( L ( "Browse" )) + " " + dots , wxBU_LEFT | wxBU_EXACTFIT );
2019-04-25 01:45:00 +02:00
ScalableButton * btn = m_printhost_browse_btn ;
2019-03-18 20:54:01 +01:00
btn -> SetFont ( Slic3r :: GUI :: wxGetApp (). normal_font ());
2019-04-14 13:49:22 +02:00
2018-12-18 14:34:16 +01:00
auto sizer = new wxBoxSizer ( wxHORIZONTAL );
sizer -> Add ( btn );
2019-03-12 17:41:43 +01:00
btn -> Bind ( wxEVT_BUTTON , [ = ]( wxCommandEvent & e ) {
BonjourDialog dialog ( parent , tech );
2018-12-18 14:34:16 +01:00
if ( dialog . show_and_lookup ()) {
optgroup -> set_value ( "print_host" , std :: move ( dialog . get_selected ()), true );
2019-01-29 15:57:22 +01:00
optgroup -> get_field ( "print_host" ) -> field_changed ();
2018-12-18 14:34:16 +01:00
}
});
return sizer ;
};
auto print_host_test = [ this ]( wxWindow * parent ) {
2019-04-14 13:57:15 +02:00
add_scaled_button ( parent , & m_print_host_test_btn , "test" , _ ( L ( "Test" )), wxBU_LEFT | wxBU_EXACTFIT );
2019-04-25 01:45:00 +02:00
ScalableButton * btn = m_print_host_test_btn ;
2019-04-13 23:46:52 +02:00
btn -> SetFont ( Slic3r :: GUI :: wxGetApp (). normal_font ());
2018-12-18 14:34:16 +01:00
auto sizer = new wxBoxSizer ( wxHORIZONTAL );
sizer -> Add ( btn );
2019-01-29 15:57:22 +01:00
btn -> Bind ( wxEVT_BUTTON , [ this ]( wxCommandEvent & e ) {
2018-12-18 14:34:16 +01:00
std :: unique_ptr < PrintHost > host ( PrintHost :: get_print_host ( m_config ));
if ( ! host ) {
const auto text = wxString :: Format ( "%s" ,
_ ( L ( "Could not get a valid Printer Host reference" )));
show_error ( this , text );
return ;
}
wxString msg ;
if ( host -> test ( msg )) {
show_info ( this , host -> get_test_ok_msg (), _ ( L ( "Success!" )));
} else {
show_error ( this , host -> get_test_failed_msg ( msg ));
}
});
return sizer ;
};
Line host_line = optgroup -> create_single_option_line ( "print_host" );
host_line . append_widget ( printhost_browse );
host_line . append_widget ( print_host_test );
optgroup -> append_line ( host_line );
optgroup -> append_single_option_line ( "printhost_apikey" );
2018-12-20 18:48:49 +01:00
const auto ca_file_hint = _ ( L ( "HTTPS CA file is optional. It is only needed if you use HTTPS with a self-signed certificate." ));
2018-12-18 14:34:16 +01:00
2018-12-20 18:48:49 +01:00
if ( Http :: ca_file_supported ()) {
2018-12-18 14:34:16 +01:00
Line cafile_line = optgroup -> create_single_option_line ( "printhost_cafile" );
auto printhost_cafile_browse = [ this , optgroup ] ( wxWindow * parent ) {
2019-05-11 23:29:25 +02:00
auto btn = new wxButton ( parent , wxID_ANY , " " + _ ( L ( "Browse" )) + " " + dots , wxDefaultPosition , wxDefaultSize , wxBU_LEFT );
2019-03-18 20:54:01 +01:00
btn -> SetFont ( Slic3r :: GUI :: wxGetApp (). normal_font ());
2019-04-12 17:10:04 +02:00
btn -> SetBitmap ( create_scaled_bitmap ( this , "browse" ));
2018-12-18 14:34:16 +01:00
auto sizer = new wxBoxSizer ( wxHORIZONTAL );
sizer -> Add ( btn );
btn -> Bind ( wxEVT_BUTTON , [ this , optgroup ] ( wxCommandEvent e ) {
static const auto filemasks = _ ( L ( "Certificate files (*.crt, *.pem)|*.crt;*.pem|All files|*.*" ));
wxFileDialog openFileDialog ( this , _ ( L ( "Open CA certificate file" )), "" , "" , filemasks , wxFD_OPEN | wxFD_FILE_MUST_EXIST );
if ( openFileDialog . ShowModal () != wxID_CANCEL ) {
optgroup -> set_value ( "printhost_cafile" , std :: move ( openFileDialog . GetPath ()), true );
2019-01-29 15:57:22 +01:00
optgroup -> get_field ( "printhost_cafile" ) -> field_changed ();
2018-12-18 14:34:16 +01:00
}
});
return sizer ;
};
cafile_line . append_widget ( printhost_cafile_browse );
optgroup -> append_line ( cafile_line );
2018-12-20 18:48:49 +01:00
Line cafile_hint { "" , "" };
cafile_hint . full_width = 1 ;
cafile_hint . widget = [ this , ca_file_hint ]( wxWindow * parent ) {
auto txt = new wxStaticText ( parent , wxID_ANY , ca_file_hint );
auto sizer = new wxBoxSizer ( wxHORIZONTAL );
sizer -> Add ( txt );
return sizer ;
};
optgroup -> append_line ( cafile_hint );
} else {
Line line { "" , "" };
line . full_width = 1 ;
line . widget = [ this , ca_file_hint ] ( wxWindow * parent ) {
auto txt = new wxStaticText ( parent , wxID_ANY , wxString :: Format ( "%s \n\n\t %s" ,
2019-04-26 10:52:38 +02:00
wxString :: Format ( _ ( L ( "HTTPS CA File: \n \
\t On this system, %s uses HTTPS certificates from the system Certificate Store or Keychain. \n \
\t To use a custom CA file, please import your CA file into Certificate Store / Keychain." )), SLIC3R_APP_NAME ),
2018-12-20 18:48:49 +01:00
ca_file_hint ));
2019-03-18 20:54:01 +01:00
txt -> SetFont ( Slic3r :: GUI :: wxGetApp (). normal_font ());
2018-12-18 14:34:16 +01:00
auto sizer = new wxBoxSizer ( wxHORIZONTAL );
sizer -> Add ( txt );
return sizer ;
};
2018-12-20 18:48:49 +01:00
optgroup -> append_line ( line );
2018-12-18 14:34:16 +01:00
}
}
2018-01-05 15:11:33 +01:00
void TabPrinter :: build ()
2017-12-22 11:50:28 +01:00
{
2018-01-12 12:41:13 +01:00
m_presets = & m_preset_bundle -> printers ;
2018-03-16 12:56:03 +01:00
load_initial_data ();
2017-12-22 11:50:28 +01:00
2018-08-07 11:58:27 +02:00
m_printer_technology = m_presets -> get_selected_preset (). printer_technology ();
2018-08-06 17:01:41 +02:00
2018-08-07 11:58:27 +02:00
m_presets -> get_selected_preset (). printer_technology () == ptSLA ? build_sla () : build_fff ();
}
2018-08-03 14:34:52 +02:00
2018-08-07 11:58:27 +02:00
void TabPrinter :: build_fff ()
{
if ( ! m_pages . empty ())
m_pages . resize ( 0 );
2018-04-23 11:52:03 +02:00
// to avoid redundant memory allocation / deallocation during extruders count changing
2018-04-23 15:09:01 +02:00
m_pages . reserve ( 30 );
2018-04-23 11:52:03 +02:00
2018-01-12 12:41:13 +01:00
auto * nozzle_diameter = dynamic_cast < const ConfigOptionFloats *> ( m_config -> option ( "nozzle_diameter" ));
2018-03-07 15:05:41 +01:00
m_initial_extruders_count = m_extruders_count = nozzle_diameter -> values . size ();
2019-04-22 01:51:10 +02:00
wxGetApp (). sidebar (). update_objects_list_extruder_column ( m_initial_extruders_count );
2018-03-21 22:21:37 +01:00
const Preset * parent_preset = m_presets -> get_selected_preset_parent ();
m_sys_extruders_count = parent_preset == nullptr ? 0 :
static_cast < const ConfigOptionFloats *> ( parent_preset -> config . option ( "nozzle_diameter" )) -> values . size ();
2017-12-22 11:50:28 +01:00
2019-04-08 09:37:23 +02:00
auto page = add_options_page ( _ ( L ( "General" )), "printer" );
2018-02-23 09:16:35 +01:00
auto optgroup = page -> new_optgroup ( _ ( L ( "Size and coordinates" )));
2017-12-22 11:50:28 +01:00
2018-10-19 13:55:29 +02:00
Line line = optgroup -> create_single_option_line ( "bed_shape" ); //{ _(L("Bed shape")), "" };
2018-10-31 12:56:08 +01:00
line . widget = [ this ]( wxWindow * parent ) {
2019-04-25 01:45:00 +02:00
ScalableButton * btn ;
2019-05-11 23:29:25 +02:00
add_scaled_button ( parent , & btn , "printer_white" , " " + _ ( L ( "Set" )) + " " + dots , wxBU_LEFT | wxBU_EXACTFIT );
2019-04-13 23:46:52 +02:00
btn -> SetFont ( wxGetApp (). normal_font ());
2017-12-26 23:04:54 +01:00
auto sizer = new wxBoxSizer ( wxHORIZONTAL );
sizer -> Add ( btn );
2018-01-25 13:46:04 +01:00
btn -> Bind ( wxEVT_BUTTON , ([ this ]( wxCommandEvent e )
2017-12-26 23:04:54 +01:00
{
2018-01-25 13:46:04 +01:00
auto dlg = new BedShapeDialog ( this );
dlg -> build_dialog ( m_config -> option < ConfigOptionPoints > ( "bed_shape" ));
2018-10-31 12:56:08 +01:00
if ( dlg -> ShowModal () == wxID_OK ) {
2018-01-30 12:10:12 +01:00
load_key_value ( "bed_shape" , dlg -> GetValue ());
2018-03-23 17:27:43 +01:00
update_changed_ui ();
}
2017-12-26 23:04:54 +01:00
}));
return sizer ;
};
2018-04-13 18:22:06 +02:00
optgroup -> append_line ( line , & m_colored_Label );
2018-03-09 10:40:42 +01:00
optgroup -> append_single_option_line ( "max_print_height" );
optgroup -> append_single_option_line ( "z_offset" );
2017-12-22 11:50:28 +01:00
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Capabilities" )));
2017-12-22 11:50:28 +01:00
ConfigOptionDef def ;
def . type = coInt ,
2019-05-03 18:01:39 +02:00
def . set_default_value ( new ConfigOptionInt ( 1 ));
2018-02-23 09:16:35 +01:00
def . label = L ( "Extruders" );
def . tooltip = L ( "Number of extruders of the printer." );
2017-12-22 11:50:28 +01:00
def . min = 1 ;
2018-10-19 13:55:29 +02:00
def . mode = comExpert ;
2017-12-22 11:50:28 +01:00
Option option ( def , "extruders_count" );
optgroup -> append_single_option_line ( option );
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "single_extruder_multi_material" );
2017-12-22 11:50:28 +01:00
2018-10-31 12:56:08 +01:00
optgroup -> m_on_change = [ this , optgroup ]( t_config_option_key opt_key , boost :: any value ) {
2018-01-12 17:16:59 +01:00
size_t extruders_count = boost :: any_cast < int > ( optgroup -> get_value ( "extruders_count" ));
2018-10-31 12:56:08 +01:00
wxTheApp -> CallAfter ([ this , opt_key , value , extruders_count ]() {
2018-12-04 17:56:49 +01:00
if ( opt_key == "extruders_count" || opt_key == "single_extruder_multi_material" ) {
2018-01-12 17:16:59 +01:00
extruders_count_changed ( extruders_count );
2018-12-21 12:58:03 +01:00
init_options_list (); // m_options_list should be updated before UI updating
2018-01-12 17:16:59 +01:00
update_dirty ();
2018-12-04 17:56:49 +01:00
if ( opt_key == "single_extruder_multi_material" ) // the single_extruder_multimaterial was added to force pages
2018-04-05 10:44:31 +02:00
on_value_change ( opt_key , value ); // rebuild - let's make sure the on_value_change is not skipped
2018-01-12 17:16:59 +01:00
}
else {
update_dirty ();
on_value_change ( opt_key , value );
}
});
};
2017-12-22 11:50:28 +01:00
2018-03-22 16:13:41 +01:00
2018-09-17 12:01:02 +02:00
#if 0
2018-01-12 17:16:59 +01:00
if (!m_no_controller)
2018-01-03 10:12:42 +01:00
{
2018-02-23 09:16:35 +01:00
optgroup = page->new_optgroup(_(L("USB/Serial connection")));
line = {_(L("Serial port")), ""};
2018-01-07 18:41:40 +01:00
Option serial_port = optgroup->get_option("serial_port");
2018-10-31 12:56:08 +01:00
serial_port.side_widget = ([this](wxWindow* parent) {
2018-02-22 11:34:41 +01:00
auto btn = new wxBitmapButton(parent, wxID_ANY, wxBitmap(from_u8(Slic3r::var("arrow_rotate_clockwise.png")), wxBITMAP_TYPE_PNG),
2017-12-22 11:50:28 +01:00
wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
2018-02-23 09:16:35 +01:00
btn->SetToolTip(_(L("Rescan serial ports")));
2017-12-22 11:50:28 +01:00
auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(btn);
2018-01-12 17:16:59 +01:00
btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent e) {update_serial_ports(); });
2017-12-22 11:50:28 +01:00
return sizer;
});
2018-10-31 12:56:08 +01:00
auto serial_test = [this](wxWindow* parent) {
2018-01-12 17:16:59 +01:00
auto btn = m_serial_test_btn = new wxButton(parent, wxID_ANY,
2018-02-23 09:16:35 +01:00
_(L("Test")), wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
2018-05-24 16:57:35 +02:00
btn->SetFont(Slic3r::GUI::small_font());
2018-02-22 11:34:41 +01:00
btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("wrench.png")), wxBITMAP_TYPE_PNG));
2017-12-22 11:50:28 +01:00
auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(btn);
2018-10-31 12:56:08 +01:00
btn->Bind(wxEVT_BUTTON, [this, parent](wxCommandEvent e) {
2018-07-02 17:18:09 +02:00
auto sender = Slic3r::make_unique<GCodeSender>();
2018-01-03 10:12:42 +01:00
auto res = sender->connect(
2018-01-12 17:16:59 +01:00
m_config->opt_string("serial_port"),
m_config->opt_int("serial_speed")
2018-01-03 10:12:42 +01:00
);
if (res && sender->wait_connected()) {
2018-02-23 09:16:35 +01:00
show_info(parent, _(L("Connection to printer works correctly.")), _(L("Success!")));
2018-01-03 10:12:42 +01:00
}
else {
2018-02-23 09:16:35 +01:00
show_error(parent, _(L("Connection failed.")));
2018-01-03 10:12:42 +01:00
}
2017-12-26 23:04:54 +01:00
});
2017-12-22 11:50:28 +01:00
return sizer;
2017-12-26 23:04:54 +01:00
};
2017-12-22 11:50:28 +01:00
line.append_option(serial_port);
2018-01-26 01:44:34 +01:00
line.append_option(optgroup->get_option("serial_speed"));
2017-12-22 11:50:28 +01:00
line.append_widget(serial_test);
optgroup->append_line(line);
2018-01-03 10:12:42 +01:00
}
2018-09-17 12:01:02 +02:00
#endif
2018-01-03 10:12:42 +01:00
2018-12-18 14:34:16 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Print Host upload" )));
build_printhost ( optgroup . get ());
2018-03-15 18:06:26 +01:00
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Firmware" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "gcode_flavor" );
2018-06-20 14:20:48 +02:00
optgroup -> append_single_option_line ( "silent_mode" );
2018-08-04 17:38:25 +02:00
optgroup -> append_single_option_line ( "remaining_times" );
2018-06-20 14:20:48 +02:00
2018-10-31 12:56:08 +01:00
optgroup -> m_on_change = [ this , optgroup ]( t_config_option_key opt_key , boost :: any value ) {
wxTheApp -> CallAfter ([ this , opt_key , value ]() {
2018-12-04 17:56:49 +01:00
if ( opt_key == "silent_mode" ) {
2018-06-22 13:01:41 +02:00
bool val = boost :: any_cast < bool > ( value );
if ( m_use_silent_mode != val ) {
2018-06-25 16:03:43 +02:00
m_rebuild_kinematics_page = true ;
2018-06-22 13:01:41 +02:00
m_use_silent_mode = val ;
}
}
2019-04-21 23:12:39 +02:00
build_unregular_pages ();
2018-06-20 14:20:48 +02:00
update_dirty ();
on_value_change ( opt_key , value );
});
};
2017-12-22 11:50:28 +01:00
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Advanced" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "use_relative_e_distances" );
optgroup -> append_single_option_line ( "use_firmware_retraction" );
optgroup -> append_single_option_line ( "use_volumetric_e" );
optgroup -> append_single_option_line ( "variable_layer_height" );
2017-12-22 11:50:28 +01:00
2019-04-13 23:46:52 +02:00
const int gcode_field_height = 15 ; // 150
const int notes_field_height = 25 ; // 250
2019-04-08 09:37:23 +02:00
page = add_options_page ( _ ( L ( "Custom G-code" )), "cog" );
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Start G-code" )), 0 );
2018-01-07 18:41:40 +01:00
option = optgroup -> get_option ( "start_gcode" );
2017-12-22 11:50:28 +01:00
option . opt . full_width = true ;
2019-02-04 12:07:15 +01:00
option . opt . height = gcode_field_height ; //150;
2017-12-22 11:50:28 +01:00
optgroup -> append_single_option_line ( option );
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "End G-code" )), 0 );
2018-01-07 18:41:40 +01:00
option = optgroup -> get_option ( "end_gcode" );
2017-12-22 11:50:28 +01:00
option . opt . full_width = true ;
2019-02-04 12:07:15 +01:00
option . opt . height = gcode_field_height ; //150;
2017-12-22 11:50:28 +01:00
optgroup -> append_single_option_line ( option );
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Before layer change G-code" )), 0 );
2018-01-07 18:41:40 +01:00
option = optgroup -> get_option ( "before_layer_gcode" );
2017-12-22 11:50:28 +01:00
option . opt . full_width = true ;
2019-02-04 12:07:15 +01:00
option . opt . height = gcode_field_height ; //150;
2017-12-22 11:50:28 +01:00
optgroup -> append_single_option_line ( option );
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "After layer change G-code" )), 0 );
2018-01-07 18:41:40 +01:00
option = optgroup -> get_option ( "layer_gcode" );
2017-12-22 11:50:28 +01:00
option . opt . full_width = true ;
2019-02-04 12:07:15 +01:00
option . opt . height = gcode_field_height ; //150;
2017-12-22 11:50:28 +01:00
optgroup -> append_single_option_line ( option );
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Tool change G-code" )), 0 );
2018-01-07 18:41:40 +01:00
option = optgroup -> get_option ( "toolchange_gcode" );
2017-12-22 11:50:28 +01:00
option . opt . full_width = true ;
2019-02-04 12:07:15 +01:00
option . opt . height = gcode_field_height ; //150;
2017-12-22 11:50:28 +01:00
optgroup -> append_single_option_line ( option );
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Between objects G-code (for sequential printing)" )), 0 );
2018-01-07 18:41:40 +01:00
option = optgroup -> get_option ( "between_objects_gcode" );
2017-12-22 11:50:28 +01:00
option . opt . full_width = true ;
2019-02-04 12:07:15 +01:00
option . opt . height = gcode_field_height ; //150;
2017-12-22 11:50:28 +01:00
optgroup -> append_single_option_line ( option );
2018-02-23 09:16:35 +01:00
page = add_options_page ( _ ( L ( "Notes" )), "note.png" );
optgroup = page -> new_optgroup ( _ ( L ( "Notes" )), 0 );
2018-01-07 18:41:40 +01:00
option = optgroup -> get_option ( "printer_notes" );
2017-12-22 11:50:28 +01:00
option . opt . full_width = true ;
2019-02-04 12:07:15 +01:00
option . opt . height = notes_field_height ; //250;
2017-12-22 11:50:28 +01:00
optgroup -> append_single_option_line ( option );
2018-03-22 11:46:15 +01:00
page = add_options_page ( _ ( L ( "Dependencies" )), "wrench.png" );
optgroup = page -> new_optgroup ( _ ( L ( "Profile dependencies" )));
line = Line { "" , "" };
line . full_width = 1 ;
line . widget = [ this ]( wxWindow * parent ) {
return description_line_widget ( parent , & m_parent_preset_description_line );
};
optgroup -> append_line ( line );
2019-04-21 23:12:39 +02:00
build_unregular_pages ();
2017-12-22 11:50:28 +01:00
2018-09-17 12:01:02 +02:00
#if 0
2018-01-12 17:16:59 +01:00
if (!m_no_controller)
update_serial_ports();
2018-09-17 12:01:02 +02:00
#endif
2018-01-12 17:16:59 +01:00
}
2018-08-03 14:34:52 +02:00
void TabPrinter :: build_sla ()
{
2018-08-07 11:58:27 +02:00
if ( ! m_pages . empty ())
m_pages . resize ( 0 );
2019-04-08 09:37:23 +02:00
auto page = add_options_page ( _ ( L ( "General" )), "printer" );
2018-08-03 14:34:52 +02:00
auto optgroup = page -> new_optgroup ( _ ( L ( "Size and coordinates" )));
2018-10-22 12:07:40 +02:00
Line line = optgroup -> create_single_option_line ( "bed_shape" ); //{ _(L("Bed shape")), "" };
2018-10-31 12:56:08 +01:00
line . widget = [ this ]( wxWindow * parent ) {
2019-04-25 01:45:00 +02:00
ScalableButton * btn ;
2019-05-11 23:29:25 +02:00
add_scaled_button ( parent , & btn , "printer_white" , " " + _ ( L ( "Set" )) + " " + dots , wxBU_LEFT | wxBU_EXACTFIT );
2019-04-13 23:46:52 +02:00
btn -> SetFont ( wxGetApp (). normal_font ());
2018-08-03 14:34:52 +02:00
auto sizer = new wxBoxSizer ( wxHORIZONTAL );
sizer -> Add ( btn );
btn -> Bind ( wxEVT_BUTTON , ([ this ]( wxCommandEvent e )
{
auto dlg = new BedShapeDialog ( this );
dlg -> build_dialog ( m_config -> option < ConfigOptionPoints > ( "bed_shape" ));
2018-10-31 12:56:08 +01:00
if ( dlg -> ShowModal () == wxID_OK ) {
2018-08-03 14:34:52 +02:00
load_key_value ( "bed_shape" , dlg -> GetValue ());
update_changed_ui ();
}
}));
return sizer ;
};
optgroup -> append_line ( line , & m_colored_Label );
optgroup -> append_single_option_line ( "max_print_height" );
optgroup = page -> new_optgroup ( _ ( L ( "Display" )));
optgroup -> append_single_option_line ( "display_width" );
optgroup -> append_single_option_line ( "display_height" );
2018-08-08 17:47:59 +02:00
auto option = optgroup -> get_option ( "display_pixels_x" );
line = { _ ( option . opt . full_label ), "" };
line . append_option ( option );
2018-08-03 14:34:52 +02:00
line . append_option ( optgroup -> get_option ( "display_pixels_y" ));
optgroup -> append_line ( line );
2018-12-13 12:42:45 +01:00
optgroup -> append_single_option_line ( "display_orientation" );
2018-08-03 14:34:52 +02:00
2019-02-18 16:04:55 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Tilt" )));
line = { _ ( L ( "Tilt time" )), "" };
line . append_option ( optgroup -> get_option ( "fast_tilt_time" ));
line . append_option ( optgroup -> get_option ( "slow_tilt_time" ));
optgroup -> append_line ( line );
optgroup -> append_single_option_line ( "area_fill" );
2018-08-03 14:34:52 +02:00
optgroup = page -> new_optgroup ( _ ( L ( "Corrections" )));
2019-05-04 02:07:07 +02:00
line = Line { _ ( m_config -> def () -> get ( "relative_correction" ) -> full_label ), "" };
2019-04-09 18:15:25 +02:00
// std::vector<std::string> axes{ "X", "Y", "Z" };
std :: vector < std :: string > axes { "XY" , "Z" };
2018-08-03 16:20:39 +02:00
int id = 0 ;
for ( auto & axis : axes ) {
2019-04-09 13:42:32 +02:00
auto opt = optgroup -> get_option ( "relative_correction" , id );
2018-08-03 16:20:39 +02:00
opt . opt . label = axis ;
line . append_option ( opt );
++ id ;
}
optgroup -> append_line ( line );
2019-04-09 13:42:32 +02:00
optgroup -> append_single_option_line ( "absolute_correction" );
optgroup -> append_single_option_line ( "gamma_correction" );
2018-08-03 14:34:52 +02:00
2018-12-18 14:34:16 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Print Host upload" )));
build_printhost ( optgroup . get ());
2019-04-13 23:46:52 +02:00
const int notes_field_height = 25 ; // 250
2019-02-04 12:07:15 +01:00
2018-08-03 14:34:52 +02:00
page = add_options_page ( _ ( L ( "Notes" )), "note.png" );
optgroup = page -> new_optgroup ( _ ( L ( "Notes" )), 0 );
2018-08-08 17:47:59 +02:00
option = optgroup -> get_option ( "printer_notes" );
2018-08-03 14:34:52 +02:00
option . opt . full_width = true ;
2019-02-04 12:07:15 +01:00
option . opt . height = notes_field_height ; //250;
2018-08-03 14:34:52 +02:00
optgroup -> append_single_option_line ( option );
page = add_options_page ( _ ( L ( "Dependencies" )), "wrench.png" );
optgroup = page -> new_optgroup ( _ ( L ( "Profile dependencies" )));
line = Line { "" , "" };
line . full_width = 1 ;
line . widget = [ this ]( wxWindow * parent ) {
return description_line_widget ( parent , & m_parent_preset_description_line );
};
optgroup -> append_line ( line );
2018-01-12 17:16:59 +01:00
}
2018-10-31 12:56:08 +01:00
void TabPrinter :: update_serial_ports ()
{
2018-01-12 17:16:59 +01:00
Field * field = get_field ( "serial_port" );
Choice * choice = static_cast < Choice *> ( field );
2018-05-21 16:14:20 +02:00
choice -> set_values ( Utils :: scan_serial_ports ());
2018-01-12 17:16:59 +01:00
}
2018-10-31 12:56:08 +01:00
void TabPrinter :: extruders_count_changed ( size_t extruders_count )
{
2019-04-21 23:12:39 +02:00
bool is_count_changed = false ;
if ( m_extruders_count != extruders_count ) {
m_extruders_count = extruders_count ;
m_preset_bundle -> printers . get_edited_preset (). set_num_extruders ( extruders_count );
m_preset_bundle -> update_multi_material_filament_presets ();
is_count_changed = true ;
}
/* This function should be call in any case because of correct updating/rebuilding
* of unregular pages of a Printer Settings
*/
build_unregular_pages ();
if ( is_count_changed ) {
on_value_change ( "extruders_count" , extruders_count );
wxGetApp (). sidebar (). update_objects_list_extruder_column ( extruders_count );
}
2017-12-22 11:50:28 +01:00
}
2018-06-22 13:01:41 +02:00
void TabPrinter :: append_option_line ( ConfigOptionsGroupShp optgroup , const std :: string opt_key )
2018-06-21 16:15:56 +02:00
{
auto option = optgroup -> get_option ( opt_key , 0 );
2019-05-09 15:37:52 +02:00
auto line = Line { _ ( option . opt . full_label ), "" };
2018-06-21 16:15:56 +02:00
line . append_option ( option );
2018-06-22 13:01:41 +02:00
if ( m_use_silent_mode )
line . append_option ( optgroup -> get_option ( opt_key , 1 ));
2018-06-21 16:15:56 +02:00
optgroup -> append_line ( line );
}
2018-06-22 16:13:34 +02:00
PageShp TabPrinter :: build_kinematics_page ()
2018-06-20 14:20:48 +02:00
{
2019-04-08 09:37:23 +02:00
auto page = add_options_page ( _ ( L ( "Machine limits" )), "cog" , true );
2018-06-21 16:15:56 +02:00
2018-06-22 13:01:41 +02:00
if ( m_use_silent_mode ) {
// Legend for OptionsGroups
2019-01-21 12:34:28 +01:00
auto optgroup = page -> new_optgroup ( "" );
2018-06-22 13:01:41 +02:00
optgroup -> set_show_modified_btns_val ( false );
2019-04-13 23:46:52 +02:00
optgroup -> label_width = 23 ; // 230;
2018-06-22 13:01:41 +02:00
auto line = Line { "" , "" };
2018-06-21 16:15:56 +02:00
2018-06-22 13:01:41 +02:00
ConfigOptionDef def ;
def . type = coString ;
2019-04-13 23:46:52 +02:00
def . width = 15 ;
2018-06-22 13:01:41 +02:00
def . gui_type = "legend" ;
2018-12-21 09:19:00 +01:00
def . mode = comAdvanced ;
2019-05-09 15:39:15 +02:00
def . tooltip = L ( "Values in this column are for Normal mode" );
def . set_default_value ( new ConfigOptionString { _ ( L ( "Normal" )). ToUTF8 (). data () });
2018-06-21 16:15:56 +02:00
2018-06-22 13:01:41 +02:00
auto option = Option ( def , "full_power_legend" );
line . append_option ( option );
2018-06-21 16:15:56 +02:00
2019-05-09 15:39:15 +02:00
def . tooltip = L ( "Values in this column are for Stealth mode" );
def . set_default_value ( new ConfigOptionString { _ ( L ( "Stealth" )). ToUTF8 (). data () });
2018-06-22 13:01:41 +02:00
option = Option ( def , "silent_legend" );
line . append_option ( option );
2018-06-21 16:15:56 +02:00
2018-06-22 13:01:41 +02:00
optgroup -> append_line ( line );
}
2018-06-21 16:15:56 +02:00
std :: vector < std :: string > axes { "x" , "y" , "z" , "e" };
2018-07-18 15:08:55 +02:00
auto optgroup = page -> new_optgroup ( _ ( L ( "Maximum feedrates" )));
2018-06-21 16:15:56 +02:00
for ( const std :: string & axis : axes ) {
append_option_line ( optgroup , "machine_max_feedrate_" + axis );
}
2018-06-20 14:20:48 +02:00
2018-07-18 15:08:55 +02:00
optgroup = page -> new_optgroup ( _ ( L ( "Maximum accelerations" )));
for ( const std :: string & axis : axes ) {
append_option_line ( optgroup , "machine_max_acceleration_" + axis );
}
2018-06-21 16:15:56 +02:00
append_option_line ( optgroup , "machine_max_acceleration_extruding" );
append_option_line ( optgroup , "machine_max_acceleration_retracting" );
2018-06-20 14:20:48 +02:00
2018-07-18 15:08:55 +02:00
optgroup = page -> new_optgroup ( _ ( L ( "Jerk limits" )));
2018-06-21 16:15:56 +02:00
for ( const std :: string & axis : axes ) {
append_option_line ( optgroup , "machine_max_jerk_" + axis );
}
2018-06-20 14:20:48 +02:00
2018-07-18 15:08:55 +02:00
optgroup = page -> new_optgroup ( _ ( L ( "Minimum feedrates" )));
append_option_line ( optgroup , "machine_min_extruding_rate" );
append_option_line ( optgroup , "machine_min_travel_rate" );
2018-06-20 14:20:48 +02:00
return page ;
}
2019-04-21 23:12:39 +02:00
/* Previous name build_extruder_pages().
*
* This function was renamed because of now it implements not just an extruder pages building,
* but "Machine limits" and "Single extruder MM setup" too
* (These pages can changes according to the another values of a current preset)
* */
void TabPrinter :: build_unregular_pages ()
2018-06-20 14:20:48 +02:00
{
2018-04-23 15:39:55 +02:00
size_t n_before_extruders = 2 ; // Count of pages before Extruder pages
2018-06-20 14:20:48 +02:00
bool is_marlin_flavor = m_config -> option < ConfigOptionEnum < GCodeFlavor >> ( "gcode_flavor" ) -> value == gcfMarlin ;
2019-04-22 00:17:56 +02:00
/* ! Freeze/Thaw in this function is needed to avoid call OnPaint() for erased pages
* and be cause of application crash, when try to change Preset in moment,
* when one of unregular pages is selected.
* */
Freeze ();
2018-06-20 14:20:48 +02:00
// Add/delete Kinematics page according to is_marlin_flavor
size_t existed_page = 0 ;
for ( int i = n_before_extruders ; i < m_pages . size (); ++ i ) // first make sure it's not there already
2018-06-20 16:30:55 +02:00
if ( m_pages [ i ] -> title (). find ( _ ( L ( "Machine limits" ))) != std :: string :: npos ) {
2018-06-25 16:03:43 +02:00
if ( ! is_marlin_flavor || m_rebuild_kinematics_page )
2018-06-20 14:20:48 +02:00
m_pages . erase ( m_pages . begin () + i );
else
existed_page = i ;
break ;
}
2018-10-31 12:56:08 +01:00
if ( existed_page < n_before_extruders && is_marlin_flavor ) {
2018-06-22 16:13:34 +02:00
auto page = build_kinematics_page ();
2018-06-20 14:20:48 +02:00
m_pages . insert ( m_pages . begin () + n_before_extruders , page );
}
if ( is_marlin_flavor )
n_before_extruders ++ ;
2018-04-23 15:39:55 +02:00
size_t n_after_single_extruder_MM = 2 ; // Count of pages after single_extruder_multi_material page
2018-05-21 14:36:09 +02:00
if ( m_extruders_count_old == m_extruders_count ||
( m_has_single_extruder_MM_page && m_extruders_count == 1 ))
2018-04-18 13:32:21 +02:00
{
// if we have a single extruder MM setup, add a page with configuration options:
for ( int i = 0 ; i < m_pages . size (); ++ i ) // first make sure it's not there already
if ( m_pages [ i ] -> title (). find ( _ ( L ( "Single extruder MM setup" ))) != std :: string :: npos ) {
m_pages . erase ( m_pages . begin () + i );
break ;
}
2018-05-21 14:36:09 +02:00
m_has_single_extruder_MM_page = false ;
2018-04-18 13:32:21 +02:00
}
2018-05-21 14:36:09 +02:00
if ( m_extruders_count > 1 && m_config -> opt_bool ( "single_extruder_multi_material" ) && ! m_has_single_extruder_MM_page ) {
// create a page, but pretend it's an extruder page, so we can add it to m_pages ourselves
2019-04-08 09:37:23 +02:00
auto page = add_options_page ( _ ( L ( "Single extruder MM setup" )), "printer" , true );
2018-05-21 14:36:09 +02:00
auto optgroup = page -> new_optgroup ( _ ( L ( "Single extruder multimaterial parameters" )));
optgroup -> append_single_option_line ( "cooling_tube_retraction" );
optgroup -> append_single_option_line ( "cooling_tube_length" );
optgroup -> append_single_option_line ( "parking_pos_retraction" );
2018-05-23 19:34:33 +02:00
optgroup -> append_single_option_line ( "extra_loading_move" );
2018-12-14 20:09:10 +01:00
optgroup -> append_single_option_line ( "high_current_on_filament_swap" );
2018-05-21 14:36:09 +02:00
m_pages . insert ( m_pages . end () - n_after_single_extruder_MM , page );
m_has_single_extruder_MM_page = true ;
}
2019-04-21 23:12:39 +02:00
// Build missed extruder pages
2018-10-31 12:56:08 +01:00
for ( auto extruder_idx = m_extruders_count_old ; extruder_idx < m_extruders_count ; ++ extruder_idx ) {
2017-12-22 11:50:28 +01:00
//# build page
2019-04-22 00:17:56 +02:00
const wxString & page_name = wxString :: Format ( _ ( L ( "Extruder %d" )), int ( extruder_idx + 1 ));
auto page = add_options_page ( page_name , "funnel" , true );
2018-04-23 15:39:55 +02:00
m_pages . insert ( m_pages . begin () + n_before_extruders + extruder_idx , page );
2018-01-02 12:50:27 +01:00
2018-02-23 09:16:35 +01:00
auto optgroup = page -> new_optgroup ( _ ( L ( "Size" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "nozzle_diameter" , extruder_idx );
2017-12-22 11:50:28 +01:00
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Layer height limits" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "min_layer_height" , extruder_idx );
optgroup -> append_single_option_line ( "max_layer_height" , extruder_idx );
2017-12-22 11:50:28 +01:00
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Position (for multi-extruder printers)" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "extruder_offset" , extruder_idx );
2017-12-22 11:50:28 +01:00
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Retraction" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "retract_length" , extruder_idx );
optgroup -> append_single_option_line ( "retract_lift" , extruder_idx );
2018-02-23 09:16:35 +01:00
Line line = { _ ( L ( "Only lift Z" )), "" };
2018-01-07 18:41:40 +01:00
line . append_option ( optgroup -> get_option ( "retract_lift_above" , extruder_idx ));
line . append_option ( optgroup -> get_option ( "retract_lift_below" , extruder_idx ));
2017-12-22 11:50:28 +01:00
optgroup -> append_line ( line );
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "retract_speed" , extruder_idx );
optgroup -> append_single_option_line ( "deretract_speed" , extruder_idx );
optgroup -> append_single_option_line ( "retract_restart_extra" , extruder_idx );
optgroup -> append_single_option_line ( "retract_before_travel" , extruder_idx );
optgroup -> append_single_option_line ( "retract_layer_change" , extruder_idx );
optgroup -> append_single_option_line ( "wipe" , extruder_idx );
optgroup -> append_single_option_line ( "retract_before_wipe" , extruder_idx );
2017-12-22 11:50:28 +01:00
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Retraction when tool is disabled (advanced settings for multi-extruder setups)" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "retract_length_toolchange" , extruder_idx );
optgroup -> append_single_option_line ( "retract_restart_extra_toolchange" , extruder_idx );
2017-12-22 11:50:28 +01:00
2018-02-23 09:16:35 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Preview" )));
2018-01-07 18:41:40 +01:00
optgroup -> append_single_option_line ( "extruder_colour" , extruder_idx );
2018-01-02 12:50:27 +01:00
}
// # remove extra pages
2018-04-18 13:32:21 +02:00
if ( m_extruders_count < m_extruders_count_old )
2018-04-23 15:39:55 +02:00
m_pages . erase ( m_pages . begin () + n_before_extruders + m_extruders_count ,
m_pages . begin () + n_before_extruders + m_extruders_count_old );
2018-01-02 12:50:27 +01:00
2019-04-22 00:17:56 +02:00
Thaw ();
2018-04-18 13:32:21 +02:00
m_extruders_count_old = m_extruders_count ;
2018-01-02 12:50:27 +01:00
rebuild_page_tree ();
2019-04-21 23:12:39 +02:00
// Reload preset pages with current configuration values
reload_config ();
2017-12-22 11:50:28 +01:00
}
2018-01-16 16:28:01 +01:00
// this gets executed after preset is loaded and before GUI fields are updated
void TabPrinter :: on_preset_loaded ()
{
// update the extruders count field
auto * nozzle_diameter = dynamic_cast < const ConfigOptionFloats *> ( m_config -> option ( "nozzle_diameter" ));
int extruders_count = nozzle_diameter -> values . size ();
set_value ( "extruders_count" , extruders_count );
// update the GUI field according to the number of nozzle diameters supplied
extruders_count_changed ( extruders_count );
}
2018-08-07 11:58:27 +02:00
void TabPrinter :: update_pages ()
{
// update m_pages ONLY if printer technology is changed
2018-10-31 16:22:36 +01:00
const PrinterTechnology new_printer_technology = m_presets -> get_edited_preset (). printer_technology ();
if ( new_printer_technology == m_printer_technology )
2018-08-07 11:58:27 +02:00
return ;
// hide all old pages
for ( auto & el : m_pages )
el . get () -> Hide ();
// set m_pages to m_pages_(technology before changing)
m_printer_technology == ptFFF ? m_pages . swap ( m_pages_fff ) : m_pages . swap ( m_pages_sla );
// build Tab according to the technology, if it's not exist jet OR
// set m_pages_(technology after changing) to m_pages
2018-10-31 16:22:36 +01:00
// m_printer_technology will be set by Tab::load_current_preset()
if ( new_printer_technology == ptFFF )
2019-05-10 11:05:54 +02:00
{
if ( m_pages_fff . empty ())
{
build_fff ();
if ( m_extruders_count > 1 )
{
m_preset_bundle -> update_multi_material_filament_presets ();
on_value_change ( "extruders_count" , m_extruders_count );
wxGetApp (). sidebar (). update_objects_list_extruder_column ( m_extruders_count );
}
}
else
m_pages . swap ( m_pages_fff );
}
2018-08-07 11:58:27 +02:00
else
m_pages_sla . empty () ? build_sla () : m_pages . swap ( m_pages_sla );
2019-03-20 16:22:01 +01:00
rebuild_page_tree ();
2018-08-07 11:58:27 +02:00
}
void TabPrinter :: update ()
{
2019-02-22 09:38:56 +01:00
m_update_cnt ++ ;
2018-08-07 11:58:27 +02:00
m_presets -> get_edited_preset (). printer_technology () == ptFFF ? update_fff () : update_sla ();
2019-02-22 09:38:56 +01:00
m_update_cnt -- ;
if ( m_update_cnt == 0 )
wxGetApp (). mainframe -> on_config_changed ( m_config );
2018-08-07 11:58:27 +02:00
}
void TabPrinter :: update_fff ()
{
2019-03-18 12:48:39 +01:00
// Freeze();
2018-01-12 17:16:59 +01:00
bool en ;
auto serial_speed = get_field ( "serial_speed" );
if ( serial_speed != nullptr ) {
en = ! m_config -> opt_string ( "serial_port" ). empty ();
get_field ( "serial_speed" ) -> toggle ( en );
if ( m_config -> opt_int ( "serial_speed" ) != 0 && en )
m_serial_test_btn -> Enable ();
else
m_serial_test_btn -> Disable ();
}
2018-08-21 11:10:32 +02:00
{
std :: unique_ptr < PrintHost > host ( PrintHost :: get_print_host ( m_config ));
m_print_host_test_btn -> Enable ( ! m_config -> opt_string ( "print_host" ). empty () && host -> can_test ());
m_printhost_browse_btn -> Enable ( host -> has_auto_discovery ());
}
2018-01-12 17:16:59 +01:00
bool have_multiple_extruders = m_extruders_count > 1 ;
get_field ( "toolchange_gcode" ) -> toggle ( have_multiple_extruders );
get_field ( "single_extruder_multi_material" ) -> toggle ( have_multiple_extruders );
2018-06-20 14:20:48 +02:00
bool is_marlin_flavor = m_config -> option < ConfigOptionEnum < GCodeFlavor >> ( "gcode_flavor" ) -> value == gcfMarlin ;
2018-06-28 12:40:27 +02:00
2018-07-17 19:37:24 +02:00
{
Field * sm = get_field ( "silent_mode" );
if ( ! is_marlin_flavor )
// Disable silent mode for non-marlin firmwares.
get_field ( "silent_mode" ) -> toggle ( false );
if ( is_marlin_flavor )
sm -> enable ();
else
sm -> disable ();
}
2018-06-28 12:40:27 +02:00
2018-07-17 19:37:24 +02:00
if ( m_use_silent_mode != m_config -> opt_bool ( "silent_mode" )) {
2018-06-25 16:03:43 +02:00
m_rebuild_kinematics_page = true ;
m_use_silent_mode = m_config -> opt_bool ( "silent_mode" );
}
2018-06-20 14:20:48 +02:00
2018-01-12 17:16:59 +01:00
for ( size_t i = 0 ; i < m_extruders_count ; ++ i ) {
bool have_retract_length = m_config -> opt_float ( "retract_length" , i ) > 0 ;
// when using firmware retraction, firmware decides retraction length
bool use_firmware_retraction = m_config -> opt_bool ( "use_firmware_retraction" );
get_field ( "retract_length" , i ) -> toggle ( ! use_firmware_retraction );
// user can customize travel length if we have retraction length or we"re using
// firmware retraction
get_field ( "retract_before_travel" , i ) -> toggle ( have_retract_length || use_firmware_retraction );
// user can customize other retraction options if retraction is enabled
bool retraction = ( have_retract_length || use_firmware_retraction );
std :: vector < std :: string > vec = { "retract_lift" , "retract_layer_change" };
for ( auto el : vec )
get_field ( el , i ) -> toggle ( retraction );
// retract lift above / below only applies if using retract lift
vec . resize ( 0 );
vec = { "retract_lift_above" , "retract_lift_below" };
for ( auto el : vec )
get_field ( el , i ) -> toggle ( retraction && m_config -> opt_float ( "retract_lift" , i ) > 0 );
// some options only apply when not using firmware retraction
vec . resize ( 0 );
vec = { "retract_speed" , "deretract_speed" , "retract_before_wipe" , "retract_restart_extra" , "wipe" };
for ( auto el : vec )
get_field ( el , i ) -> toggle ( retraction && ! use_firmware_retraction );
bool wipe = m_config -> opt_bool ( "wipe" , i );
get_field ( "retract_before_wipe" , i ) -> toggle ( wipe );
if ( use_firmware_retraction && wipe ) {
auto dialog = new wxMessageDialog ( parent (),
2018-02-23 09:16:35 +01:00
_ ( L ( "The Wipe option is not available when using the Firmware Retraction mode. \n "
" \n Shall I disable it in order to enable Firmware Retraction?" )),
_ ( L ( "Firmware Retraction" )), wxICON_WARNING | wxYES | wxNO );
2018-01-12 17:16:59 +01:00
DynamicPrintConfig new_conf = * m_config ;
if ( dialog -> ShowModal () == wxID_YES ) {
2018-03-09 17:17:51 +01:00
auto wipe = static_cast < ConfigOptionBools *> ( m_config -> option ( "wipe" ) -> clone ());
2018-03-12 16:52:21 +01:00
for ( int w = 0 ; w < wipe -> values . size (); w ++ )
wipe -> values [ w ] = false ;
2018-01-12 17:16:59 +01:00
new_conf . set_key_value ( "wipe" , wipe );
}
else {
new_conf . set_key_value ( "use_firmware_retraction" , new ConfigOptionBool ( false ));
}
load_config ( new_conf );
}
get_field ( "retract_length_toolchange" , i ) -> toggle ( have_multiple_extruders );
bool toolchange_retraction = m_config -> opt_float ( "retract_length_toolchange" , i ) > 0 ;
get_field ( "retract_restart_extra_toolchange" , i ) -> toggle
( have_multiple_extruders && toolchange_retraction );
}
2019-03-18 12:48:39 +01:00
// Thaw();
2018-01-12 17:16:59 +01:00
}
2018-10-31 12:56:08 +01:00
void TabPrinter :: update_sla ()
{ ; }
2018-08-07 11:58:27 +02:00
2018-01-16 16:28:01 +01:00
// Initialize the UI from the current preset
2018-01-05 15:11:33 +01:00
void Tab :: load_current_preset ()
{
2019-01-09 10:43:17 +01:00
const Preset & preset = m_presets -> get_edited_preset ();
2018-03-16 17:25:11 +01:00
2018-04-26 12:40:17 +02:00
( preset . is_default || preset . is_system ) ? m_btn_delete_preset -> Disable () : m_btn_delete_preset -> Enable ( true );
2018-08-06 17:01:41 +02:00
2018-08-07 11:58:27 +02:00
update ();
2019-03-22 12:11:23 +01:00
if ( m_type == Slic3r :: Preset :: TYPE_PRINTER ) {
2019-01-10 18:08:38 +01:00
// For the printer profile, generate the extruder pages.
if ( preset . printer_technology () == ptFFF )
on_preset_loaded ();
else
wxGetApp (). sidebar (). update_objects_list_extruder_column ( 1 );
}
2018-08-07 11:58:27 +02:00
// Reload preset pages with the new configuration values.
reload_config ();
2018-08-06 17:01:41 +02:00
2018-04-16 11:03:08 +02:00
m_bmp_non_system = m_presets -> get_selected_preset_parent () ? & m_bmp_value_unlock : & m_bmp_white_bullet ;
2018-04-24 14:11:23 +02:00
m_ttg_non_system = m_presets -> get_selected_preset_parent () ? & m_ttg_value_unlock : & m_ttg_white_bullet_ns ;
2018-08-07 17:23:48 +02:00
m_tt_non_system = m_presets -> get_selected_preset_parent () ? & m_tt_value_unlock : & m_ttg_white_bullet_ns ;
2018-03-13 16:14:36 +01:00
2018-07-02 13:51:50 +02:00
m_undo_to_sys_btn -> Enable ( ! preset . is_default );
2019-01-09 10:43:17 +01:00
#if 0
2018-01-16 16:28:01 +01:00
// use CallAfter because some field triggers schedule on_change calls using CallAfter,
// and we don't want them to be called after this update_dirty() as they would mark the
// preset dirty again
// (not sure this is true anymore now that update_dirty is idempotent)
2019-01-09 10:43:17 +01:00
wxTheApp->CallAfter([this]
#endif
{
2018-02-09 11:04:34 +01:00
// checking out if this Tab exists till this moment
2018-10-01 15:09:31 +02:00
if ( ! wxGetApp (). checked_tab ( this ))
2018-02-09 11:04:34 +01:00
return ;
2018-01-16 16:28:01 +01:00
update_tab_ui ();
2018-08-06 17:01:41 +02:00
// update show/hide tabs
2019-03-22 12:11:23 +01:00
if ( m_type == Slic3r :: Preset :: TYPE_PRINTER ) {
2019-01-10 18:08:38 +01:00
const PrinterTechnology printer_technology = m_presets -> get_edited_preset (). printer_technology ();
2018-08-07 11:58:27 +02:00
if ( printer_technology != static_cast < TabPrinter *> ( this ) -> m_printer_technology )
2018-08-06 17:01:41 +02:00
{
2018-11-19 13:17:14 +01:00
for ( auto tab : wxGetApp (). tabs_list ) {
if ( tab -> type () == Preset :: TYPE_PRINTER ) // Printer tab is shown every time
continue ;
if ( tab -> supports_printer_technology ( printer_technology ))
2019-01-01 16:08:46 -05:00
{
2018-11-19 13:17:14 +01:00
wxGetApp (). tab_panel () -> InsertPage ( wxGetApp (). tab_panel () -> FindPage ( this ), tab , tab -> title ());
2019-01-01 16:08:46 -05:00
#ifdef __linux__ // the tabs apparently need to be explicitly shown on Linux (pull request #1563)
int page_id = wxGetApp (). tab_panel () -> FindPage ( tab );
wxGetApp (). tab_panel () -> GetPage ( page_id ) -> Show ( true );
#endif // __linux__
}
2018-11-19 13:17:14 +01:00
else {
int page_id = wxGetApp (). tab_panel () -> FindPage ( tab );
2018-09-21 01:33:41 +02:00
wxGetApp (). tab_panel () -> GetPage ( page_id ) -> Show ( false );
wxGetApp (). tab_panel () -> RemovePage ( page_id );
2018-11-19 13:17:14 +01:00
}
2018-08-06 17:01:41 +02:00
}
2018-08-08 16:22:56 +02:00
static_cast < TabPrinter *> ( this ) -> m_printer_technology = printer_technology ;
2018-08-06 17:01:41 +02:00
}
2018-10-31 16:22:36 +01:00
on_presets_changed ();
if ( printer_technology == ptFFF ) {
static_cast < TabPrinter *> ( this ) -> m_initial_extruders_count = static_cast < TabPrinter *> ( this ) -> m_extruders_count ;
const Preset * parent_preset = m_presets -> get_selected_preset_parent ();
static_cast < TabPrinter *> ( this ) -> m_sys_extruders_count = parent_preset == nullptr ? 0 :
static_cast < const ConfigOptionFloats *> ( parent_preset -> config . option ( "nozzle_diameter" )) -> values . size ();
}
2018-03-21 22:21:37 +01:00
}
2018-10-31 16:22:36 +01:00
else {
on_presets_changed ();
2019-03-22 12:11:23 +01:00
if ( m_type == Preset :: TYPE_SLA_PRINT || m_type == Preset :: TYPE_PRINT )
2018-10-31 16:22:36 +01:00
update_frequently_changed_parameters ();
}
2018-04-18 13:32:21 +02:00
m_opt_status_value = ( m_presets -> get_selected_preset_parent () ? osSystemValue : 0 ) | osInitValue ;
init_options_list ();
2018-12-21 12:58:03 +01:00
update_visibility ();
2018-03-14 15:38:54 +01:00
update_changed_ui ();
2019-01-09 10:43:17 +01:00
}
#if 0
);
#endif
2018-01-05 15:11:33 +01:00
}
2017-12-13 14:45:10 +01:00
//Regerenerate content of the page tree.
2019-03-20 16:22:01 +01:00
void Tab :: rebuild_page_tree ()
2017-12-13 14:45:10 +01:00
{
// get label of the currently selected item
2018-09-21 01:33:41 +02:00
const auto sel_item = m_treectrl -> GetSelection ();
const auto selected = sel_item ? m_treectrl -> GetItemText ( sel_item ) : "" ;
const auto rootItem = m_treectrl -> GetRootItem ();
2018-04-23 15:09:01 +02:00
2017-12-13 14:45:10 +01:00
auto have_selection = 0 ;
2018-04-23 15:39:55 +02:00
m_treectrl -> DeleteChildren ( rootItem );
2017-12-26 23:04:54 +01:00
for ( auto p : m_pages )
2017-12-13 14:45:10 +01:00
{
2017-12-26 23:04:54 +01:00
auto itemId = m_treectrl -> AppendItem ( rootItem , p -> title (), p -> iconID ());
2018-04-23 15:39:55 +02:00
m_treectrl -> SetItemTextColour ( itemId , p -> get_item_colour ());
2017-12-13 14:45:10 +01:00
if ( p -> title () == selected ) {
2017-12-26 23:04:54 +01:00
m_treectrl -> SelectItem ( itemId );
2017-12-13 14:45:10 +01:00
have_selection = 1 ;
}
}
2018-04-23 15:39:55 +02:00
2017-12-13 14:45:10 +01:00
if ( ! have_selection ) {
// this is triggered on first load, so we don't disable the sel change event
2019-03-22 20:49:17 +01:00
auto item = m_treectrl -> GetFirstVisibleItem ();
if ( item ) {
2019-03-22 23:08:13 +01:00
m_treectrl -> SelectItem ( item );
2019-03-22 20:49:17 +01:00
}
2017-12-13 14:45:10 +01:00
}
}
2018-10-21 23:09:24 +02:00
void Tab :: update_page_tree_visibility ()
{
const auto sel_item = m_treectrl -> GetSelection ();
const auto selected = sel_item ? m_treectrl -> GetItemText ( sel_item ) : "" ;
const auto rootItem = m_treectrl -> GetRootItem ();
auto have_selection = 0 ;
m_treectrl -> DeleteChildren ( rootItem );
for ( auto p : m_pages )
{
if ( ! p -> get_show ())
continue ;
auto itemId = m_treectrl -> AppendItem ( rootItem , p -> title (), p -> iconID ());
m_treectrl -> SetItemTextColour ( itemId , p -> get_item_colour ());
if ( p -> title () == selected ) {
m_treectrl -> SelectItem ( itemId );
have_selection = 1 ;
}
}
if ( ! have_selection ) {
// this is triggered on first load, so we don't disable the sel change event
2019-03-22 20:49:17 +01:00
auto item = m_treectrl -> GetFirstVisibleItem ();
if ( item ) {
m_treectrl -> SelectItem ( item );
}
2018-10-21 23:09:24 +02:00
}
}
2019-03-22 12:11:23 +01:00
// Called by the UI combo box when the user switches profiles, and also to delete the current profile.
2018-01-16 16:28:01 +01:00
// Select a preset by a name.If !defined(name), then the default preset is selected.
// If the current profile is modified, user is asked to save the changes.
2019-03-22 12:11:23 +01:00
void Tab :: select_preset ( std :: string preset_name , bool delete_current )
2018-01-16 16:28:01 +01:00
{
2019-03-22 12:11:23 +01:00
if ( preset_name . empty ()) {
if ( delete_current ) {
// Find an alternate preset to be selected after the current preset is deleted.
const std :: deque < Preset > & presets = this -> m_presets -> get_presets ();
size_t idx_current = this -> m_presets -> get_idx_selected ();
// Find the next visible preset.
size_t idx_new = idx_current + 1 ;
if ( idx_new < presets . size ())
for (; idx_new < presets . size () && ! presets [ idx_new ]. is_visible ; ++ idx_new ) ;
if ( idx_new == presets . size ())
for ( idx_new = idx_current - 1 ; idx_new > 0 && ! presets [ idx_new ]. is_visible ; -- idx_new );
preset_name = presets [ idx_new ]. name ;
} else {
// If no name is provided, select the "-- default --" preset.
preset_name = m_presets -> default_preset (). name ;
}
}
assert ( ! delete_current || ( m_presets -> get_edited_preset (). name != preset_name && m_presets -> get_edited_preset (). is_user ()));
bool current_dirty = ! delete_current && m_presets -> current_is_dirty ();
2018-12-04 17:56:49 +01:00
bool print_tab = m_presets -> type () == Preset :: TYPE_PRINT || m_presets -> type () == Preset :: TYPE_SLA_PRINT ;
bool printer_tab = m_presets -> type () == Preset :: TYPE_PRINTER ;
bool canceled = false ;
2018-11-16 11:14:56 +01:00
m_dependent_tabs = {};
2019-03-22 12:11:23 +01:00
if ( current_dirty && ! may_discard_current_dirty_preset ()) {
2018-01-16 16:28:01 +01:00
canceled = true ;
2018-12-04 17:56:49 +01:00
} else if ( print_tab ) {
// Before switching the print profile to a new one, verify, whether the currently active filament or SLA material
// are compatible with the new print.
// If it is not compatible and the current filament or SLA material are dirty, let user decide
// whether to discard the changes or keep the current print selection.
PrinterTechnology printer_technology = m_preset_bundle -> printers . get_edited_preset (). printer_technology ();
PresetCollection & dependent = ( printer_technology == ptFFF ) ? m_preset_bundle -> filaments : m_preset_bundle -> sla_materials ;
bool old_preset_dirty = dependent . current_is_dirty ();
bool new_preset_compatible = dependent . get_edited_preset (). is_compatible_with_print ( * m_presets -> find_preset ( preset_name , true ));
if ( ! canceled )
canceled = old_preset_dirty && ! new_preset_compatible && ! may_discard_current_dirty_preset ( & dependent , preset_name );
if ( ! canceled ) {
// The preset will be switched to a different, compatible preset, or the '-- default --'.
m_dependent_tabs . emplace_back (( printer_technology == ptFFF ) ? Preset :: Type :: TYPE_FILAMENT : Preset :: Type :: TYPE_SLA_MATERIAL );
if ( old_preset_dirty )
dependent . discard_current_changes ();
}
2018-08-01 11:09:51 +02:00
} else if ( printer_tab ) {
2018-01-16 16:28:01 +01:00
// Before switching the printer to a new one, verify, whether the currently active print and filament
// are compatible with the new printer.
// If they are not compatible and the current print or filament are dirty, let user decide
// whether to discard the changes or keep the current printer selection.
2018-08-01 11:09:51 +02:00
//
// With the introduction of the SLA printer types, we need to support switching between
// the FFF and SLA printers.
const Preset & new_printer_preset = * m_presets -> find_preset ( preset_name , true );
PrinterTechnology old_printer_technology = m_presets -> get_edited_preset (). printer_technology ();
PrinterTechnology new_printer_technology = new_printer_preset . printer_technology ();
2018-11-29 12:33:04 +01:00
if ( new_printer_technology == ptSLA && old_printer_technology == ptFFF && ! may_switch_to_SLA_preset ())
canceled = true ;
else {
struct PresetUpdate {
Preset :: Type tab_type ;
PresetCollection * presets ;
PrinterTechnology technology ;
bool old_preset_dirty ;
bool new_preset_compatible ;
};
std :: vector < PresetUpdate > updates = {
{ Preset :: Type :: TYPE_PRINT , & m_preset_bundle -> prints , ptFFF },
{ Preset :: Type :: TYPE_SLA_PRINT , & m_preset_bundle -> sla_prints , ptSLA },
{ Preset :: Type :: TYPE_FILAMENT , & m_preset_bundle -> filaments , ptFFF },
{ Preset :: Type :: TYPE_SLA_MATERIAL , & m_preset_bundle -> sla_materials , ptSLA }
};
for ( PresetUpdate & pu : updates ) {
pu . old_preset_dirty = ( old_printer_technology == pu . technology ) && pu . presets -> current_is_dirty ();
pu . new_preset_compatible = ( new_printer_technology == pu . technology ) && pu . presets -> get_edited_preset (). is_compatible_with_printer ( new_printer_preset );
if ( ! canceled )
canceled = pu . old_preset_dirty && ! pu . new_preset_compatible && ! may_discard_current_dirty_preset ( pu . presets , preset_name );
}
if ( ! canceled ) {
for ( PresetUpdate & pu : updates ) {
// The preset will be switched to a different, compatible preset, or the '-- default --'.
if ( pu . technology == new_printer_technology )
m_dependent_tabs . emplace_back ( pu . tab_type );
2019-03-04 12:52:30 +01:00
if ( pu . old_preset_dirty && ! pu . new_preset_compatible )
2018-11-29 12:33:04 +01:00
pu . presets -> discard_current_changes ();
}
}
}
2018-01-16 16:28:01 +01:00
}
2019-03-22 12:11:23 +01:00
if ( ! canceled && delete_current ) {
// Delete the file and select some other reasonable preset.
// It does not matter which preset will be made active as the preset will be re-selected from the preset_name variable.
// The 'external' presets will only be removed from the preset list, their files will not be deleted.
try {
m_presets -> delete_current_preset ();
} catch ( const std :: exception & /* e */ ) {
//FIXME add some error reporting!
canceled = true ;
}
}
2018-01-16 16:28:01 +01:00
if ( canceled ) {
update_tab_ui ();
// Trigger the on_presets_changed event so that we also restore the previous value in the plater selector,
// if this action was initiated from the platter.
on_presets_changed ();
2018-08-01 11:09:51 +02:00
} else {
if ( current_dirty )
2018-12-04 17:56:49 +01:00
m_presets -> discard_current_changes ();
2019-03-22 12:11:23 +01:00
const bool is_selected = m_presets -> select_preset_by_name ( preset_name , false ) || delete_current ;
assert ( m_presets -> get_edited_preset (). name == preset_name || ! is_selected );
2018-01-16 16:28:01 +01:00
// Mark the print & filament enabled if they are compatible with the currently selected preset.
// The following method should not discard changes of current print or filament presets on change of a printer profile,
// if they are compatible with the current printer.
2019-03-22 12:11:23 +01:00
if ( current_dirty || delete_current || print_tab || printer_tab )
2018-12-04 17:56:49 +01:00
m_preset_bundle -> update_compatible ( true );
2018-01-16 16:28:01 +01:00
// Initialize the UI from the current preset.
2018-08-07 11:58:27 +02:00
if ( printer_tab )
static_cast < TabPrinter *> ( this ) -> update_pages ();
2019-03-15 14:21:32 +01:00
2019-03-22 12:11:23 +01:00
if ( ! is_selected && printer_tab )
2019-03-15 14:21:32 +01:00
{
/* There is a case, when :
* after Config Wizard applying we try to select previously selected preset, but
* in a current configuration this one:
* 1. doesn't exist now,
* 2. have another printer_technology
* So, it is necessary to update list of dependent tabs
* to the corresponding printer_technology
*/
const PrinterTechnology printer_technology = m_presets -> get_edited_preset (). printer_technology ();
2019-03-22 12:11:23 +01:00
if ( printer_technology == ptFFF && m_dependent_tabs . front () != Preset :: Type :: TYPE_PRINT )
m_dependent_tabs = { Preset :: Type :: TYPE_PRINT , Preset :: Type :: TYPE_FILAMENT };
else if ( printer_technology == ptSLA && m_dependent_tabs . front () != Preset :: Type :: TYPE_SLA_PRINT )
m_dependent_tabs = { Preset :: Type :: TYPE_SLA_PRINT , Preset :: Type :: TYPE_SLA_MATERIAL };
2019-03-15 14:21:32 +01:00
}
2018-01-26 01:44:34 +01:00
load_current_preset ();
2018-01-16 16:28:01 +01:00
}
}
// If the current preset is dirty, the user is asked whether the changes may be discarded.
// if the current preset was not dirty, or the user agreed to discard the changes, 1 is returned.
2018-04-13 12:35:04 +02:00
bool Tab :: may_discard_current_dirty_preset ( PresetCollection * presets /*= nullptr*/ , const std :: string & new_printer_name /*= ""*/ )
2018-01-16 16:28:01 +01:00
{
if ( presets == nullptr ) presets = m_presets ;
// Display a dialog showing the dirty options in a human readable form.
2018-12-04 19:10:31 +01:00
const Preset & old_preset = presets -> get_edited_preset ();
std :: string type_name = presets -> name ();
wxString tab = " " ;
wxString name = old_preset . is_default ?
2019-05-11 23:29:25 +02:00
wxString :: Format ( _ ( L ( "Default preset (%s)" )), _ ( type_name )) :
wxString :: Format ( _ ( L ( "Preset (%s)" )), _ ( type_name )) + " \n " + tab + old_preset . name ;
2019-01-21 12:34:28 +01:00
2018-01-16 16:28:01 +01:00
// Collect descriptions of the dirty options.
2018-12-04 19:10:31 +01:00
wxString changes ;
for ( const std :: string & opt_key : presets -> current_dirty_options ()) {
const ConfigOptionDef & opt = m_config -> def () -> options . at ( opt_key );
2019-01-21 12:34:28 +01:00
/*std::string*/ wxString name = "" ;
2018-12-04 19:10:31 +01:00
if ( ! opt . category . empty ())
2019-01-21 12:34:28 +01:00
name += _ ( opt . category ) + " > " ;
2018-01-16 16:28:01 +01:00
name += ! opt . full_label . empty () ?
2019-01-21 12:34:28 +01:00
_ ( opt . full_label ) :
_ ( opt . label );
changes += tab + /*from_u8*/ ( name ) + " \n " ;
2018-01-16 16:28:01 +01:00
}
// Show a confirmation dialog with the list of dirty options.
2018-12-04 19:10:31 +01:00
wxString message = name + " \n\n " ;
2018-12-04 17:56:49 +01:00
if ( new_printer_name . empty ())
message += _ ( L ( "has the following unsaved changes:" ));
else {
message += ( m_type == Slic3r :: Preset :: TYPE_PRINTER ) ?
_ ( L ( "is not compatible with printer" )) :
_ ( L ( "is not compatible with print profile" ));
2018-12-04 19:21:53 +01:00
message += wxString ( " \n " ) + tab + from_u8 ( new_printer_name ) + " \n\n " ;
2018-12-04 17:56:49 +01:00
message += _ ( L ( "and it has the following unsaved changes:" ));
}
2018-01-16 16:28:01 +01:00
auto confirm = new wxMessageDialog ( parent (),
2019-01-21 12:34:28 +01:00
message + " \n " + changes + " \n\n " + _ ( L ( "Discard changes and continue anyway?" )),
2018-02-23 09:16:35 +01:00
_ ( L ( "Unsaved Changes" )), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION );
2018-01-16 16:28:01 +01:00
return confirm -> ShowModal () == wxID_YES ;
}
2018-11-29 12:33:04 +01:00
// If we are switching from the FFF-preset to the SLA, we should to control the printed objects if they have a part(s).
// Because of we can't to print the multi-part objects with SLA technology.
bool Tab :: may_switch_to_SLA_preset ()
{
if ( wxGetApp (). obj_list () -> has_multi_part_objects ())
{
show_info ( parent (),
2019-01-21 12:34:28 +01:00
_ ( L ( "It's impossible to print multi-part object(s) with SLA technology." )) + " \n\n " +
_ ( L ( "Please check your object list before preset changing." )),
2018-11-29 12:33:04 +01:00
_ ( L ( "Attention!" )) );
return false ;
}
return true ;
}
2018-01-05 15:11:33 +01:00
void Tab :: OnTreeSelChange ( wxTreeEvent & event )
2017-12-13 14:45:10 +01:00
{
2019-04-22 00:17:56 +02:00
if ( m_disable_tree_sel_changed_event )
return ;
2018-06-11 16:56:35 +02:00
// There is a bug related to Ubuntu overlay scrollbars, see https://github.com/prusa3d/Slic3r/issues/898 and https://github.com/prusa3d/Slic3r/issues/952.
// The issue apparently manifests when Show()ing a window with overlay scrollbars while the UI is frozen. For this reason,
// we will Thaw the UI prematurely on Linux. This means destroing the no_updates object prematurely.
#ifdef __linux__
std :: unique_ptr < wxWindowUpdateLocker > no_updates ( new wxWindowUpdateLocker ( this ));
#else
2019-03-18 12:48:39 +01:00
// wxWindowUpdateLocker noUpdates(this);
2018-06-11 16:56:35 +02:00
#endif
2018-04-17 10:15:48 +02:00
2018-10-23 09:48:01 +02:00
if ( m_pages . empty ())
return ;
2018-01-05 15:11:33 +01:00
Page * page = nullptr ;
2018-09-21 01:33:41 +02:00
const auto sel_item = m_treectrl -> GetSelection ();
const auto selection = sel_item ? m_treectrl -> GetItemText ( sel_item ) : "" ;
2018-10-23 09:48:01 +02:00
for ( auto p : m_pages )
2017-12-13 14:45:10 +01:00
if ( p -> title () == selection )
2017-12-05 15:54:01 +01:00
{
2017-12-13 14:45:10 +01:00
page = p . get ();
2018-03-22 09:37:42 +01:00
m_is_nonsys_values = page -> m_is_nonsys_values ;
m_is_modified_values = page -> m_is_modified_values ;
2017-12-05 15:54:01 +01:00
break ;
}
if ( page == nullptr ) return ;
2017-12-26 23:04:54 +01:00
for ( auto & el : m_pages )
2019-03-18 12:48:39 +01:00
// if (el.get()->IsShown()) {
el . get () -> Hide ();
// break;
// }
2018-06-11 16:56:35 +02:00
2019-03-18 12:48:39 +01:00
#ifdef __linux__
no_updates . reset ( nullptr );
#endif
2018-03-22 09:37:42 +01:00
update_undo_buttons ();
2019-03-18 12:48:39 +01:00
page -> Show ();
// if (! page->layout_valid) {
page -> layout_valid = true ;
m_hsizer -> Layout ();
Refresh ();
// }
2017-12-13 14:45:10 +01:00
}
2017-12-05 15:54:01 +01:00
2018-01-05 15:11:33 +01:00
void Tab :: OnKeyDown ( wxKeyEvent & event )
2017-12-05 15:54:01 +01:00
{
2018-01-21 21:56:20 +01:00
if ( event . GetKeyCode () == WXK_TAB )
m_treectrl -> Navigate ( event . ShiftDown () ? wxNavigationKeyEvent :: IsBackward : wxNavigationKeyEvent :: IsForward );
else
2017-12-05 15:54:01 +01:00
event . Skip ();
2018-01-16 16:28:01 +01:00
}
2017-12-05 15:54:01 +01:00
2018-01-16 16:28:01 +01:00
// Save the current preset into file.
// This removes the "dirty" flag of the preset, possibly creates a new preset under a new name,
// and activates the new preset.
// Wizard calls save_preset with a name "My Settings", otherwise no name is provided and this method
// opens a Slic3r::GUI::SavePresetWindow dialog.
void Tab :: save_preset ( std :: string name /*= ""*/ )
{
// since buttons(and choices too) don't get focus on Mac, we set focus manually
// to the treectrl so that the EVT_* events are fired for the input field having
// focus currently.is there anything better than this ?
//! m_treectrl->OnSetFocus();
2017-12-05 15:54:01 +01:00
2018-01-16 16:28:01 +01:00
if ( name . empty ()) {
2019-03-22 12:11:23 +01:00
const Preset & preset = m_presets -> get_selected_preset ();
2019-05-11 23:29:25 +02:00
auto default_name = preset . is_default ? "Untitled" :
preset . is_system ? ( boost :: format ( _utf8 ( L ( "%1% - Copy" ))) % preset . name ). str () :
preset . name ;
2018-01-18 11:45:25 +01:00
bool have_extention = boost :: iends_with ( default_name , ".ini" );
2019-03-22 12:11:23 +01:00
if ( have_extention ) {
2018-01-18 11:45:25 +01:00
size_t len = default_name . length () - 4 ;
default_name . resize ( len );
}
//[map $_->name, grep !$_->default && !$_->external, @{$self->{presets}}],
std :: vector < std :: string > values ;
for ( size_t i = 0 ; i < m_presets -> size (); ++ i ) {
const Preset & preset = m_presets -> preset ( i );
2018-03-09 16:37:33 +01:00
if ( preset . is_default || preset . is_system || preset . is_external )
2018-01-18 11:45:25 +01:00
continue ;
values . push_back ( preset . name );
}
auto dlg = new SavePresetWindow ( parent ());
dlg -> build ( title (), default_name , values );
if ( dlg -> ShowModal () != wxID_OK )
return ;
name = dlg -> get_name ();
2018-10-31 12:56:08 +01:00
if ( name == "" ) {
2018-02-23 09:16:35 +01:00
show_error ( this , _ ( L ( "The supplied name is empty. It can't be saved." )));
2018-01-18 11:45:25 +01:00
return ;
}
2018-03-09 16:37:33 +01:00
const Preset * existing = m_presets -> find_preset ( name , false );
if ( existing && ( existing -> is_default || existing -> is_system )) {
show_error ( this , _ ( L ( "Cannot overwrite a system profile." )));
return ;
}
if ( existing && ( existing -> is_external )) {
2018-05-14 12:59:19 +02:00
show_error ( this , _ ( L ( "Cannot overwrite an external profile." )));
2018-03-09 16:37:33 +01:00
return ;
}
2018-01-16 16:28:01 +01:00
}
2018-02-16 15:41:33 +01:00
// Save the preset into Slic3r::data_dir / presets / section_name / preset_name.ini
m_presets -> save_current_preset ( name );
2018-01-16 16:28:01 +01:00
// Mark the print & filament enabled if they are compatible with the currently selected preset.
2018-12-04 17:56:49 +01:00
m_preset_bundle -> update_compatible ( false );
2018-01-16 16:28:01 +01:00
// Add the new item into the UI component, remove dirty flags and activate the saved item.
update_tab_ui ();
// Update the selection boxes at the platter.
on_presets_changed ();
2018-07-03 12:19:34 +02:00
// If current profile is saved, "delete preset" button have to be enabled
m_btn_delete_preset -> Enable ( true );
2018-03-16 12:56:03 +01:00
2019-03-22 12:11:23 +01:00
if ( m_type == Preset :: TYPE_PRINTER )
2018-03-19 17:21:37 +01:00
static_cast < TabPrinter *> ( this ) -> m_initial_extruders_count = static_cast < TabPrinter *> ( this ) -> m_extruders_count ;
2018-03-16 12:56:03 +01:00
update_changed_ui ();
2018-01-16 16:28:01 +01:00
}
// Called for a currently selected preset.
2018-01-18 11:45:25 +01:00
void Tab :: delete_preset ()
2018-01-16 16:28:01 +01:00
{
auto current_preset = m_presets -> get_selected_preset ();
// Don't let the user delete the ' - default - ' configuration.
2019-05-11 23:29:25 +02:00
std :: string action = current_preset . is_external ? _utf8 ( L ( "remove" )) : _utf8 ( L ( "delete" ));
// TRN remove/delete
const wxString msg = from_u8 (( boost :: format ( _utf8 ( L ( "Are you sure you want to %1% the selected preset?" ))) % action ). str ());
action = current_preset . is_external ? _utf8 ( L ( "Remove" )) : _utf8 ( L ( "Delete" ));
// TRN Remove/Delete
wxString title = from_u8 (( boost :: format ( _utf8 ( L ( "%1% Preset" ))) % action ). str ()); //action + _(L(" Preset"));
2018-01-16 16:28:01 +01:00
if ( current_preset . is_default ||
2018-02-13 16:05:53 +01:00
wxID_YES != wxMessageDialog ( parent (), msg , title , wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION ). ShowModal ())
2018-01-16 16:28:01 +01:00
return ;
2019-03-22 12:11:23 +01:00
// Select will handle of the preset dependencies, of saving & closing the depending profiles, and
// finally of deleting the preset.
this -> select_preset ( "" , true );
2018-01-16 16:28:01 +01:00
}
2018-01-18 11:45:25 +01:00
void Tab :: toggle_show_hide_incompatible ()
2018-01-16 16:28:01 +01:00
{
m_show_incompatible_presets = ! m_show_incompatible_presets ;
update_show_hide_incompatible_button ();
update_tab_ui ();
}
void Tab :: update_show_hide_incompatible_button ()
{
2019-04-13 23:46:52 +02:00
m_btn_hide_incompatible_presets -> SetBitmap_ ( m_show_incompatible_presets ?
2018-04-16 11:03:08 +02:00
m_bmp_show_incompatible_presets : m_bmp_hide_incompatible_presets );
2018-01-16 16:28:01 +01:00
m_btn_hide_incompatible_presets -> SetToolTip ( m_show_incompatible_presets ?
"Both compatible an incompatible presets are shown. Click to hide presets not compatible with the current printer." :
"Only compatible presets are shown. Click to show both the presets compatible and not compatible with the current printer." );
}
void Tab :: update_ui_from_settings ()
{
// Show the 'show / hide presets' button only for the print and filament tabs, and only if enabled
// in application preferences.
2018-09-21 01:33:41 +02:00
m_show_btn_incompatible_presets = wxGetApp (). app_config -> get ( "show_incompatible_presets" )[ 0 ] == '1' ? true : false ;
2018-12-04 17:56:49 +01:00
bool show = m_show_btn_incompatible_presets && m_type != Slic3r :: Preset :: TYPE_PRINTER ;
2018-11-16 11:14:56 +01:00
Layout ();
2018-01-16 16:28:01 +01:00
show ? m_btn_hide_incompatible_presets -> Show () : m_btn_hide_incompatible_presets -> Hide ();
// If the 'show / hide presets' button is hidden, hide the incompatible presets.
if ( show ) {
update_show_hide_incompatible_button ();
}
else {
if ( m_show_incompatible_presets ) {
m_show_incompatible_presets = false ;
update_tab_ui ();
}
}
}
// Return a callback to create a Tab widget to mark the preferences as compatible / incompatible to the current printer.
2018-12-04 17:56:49 +01:00
wxSizer * Tab :: compatible_widget_create ( wxWindow * parent , PresetDependencies & deps )
2017-12-19 11:59:42 +01:00
{
2018-12-04 17:56:49 +01:00
deps . checkbox = new wxCheckBox ( parent , wxID_ANY , _ ( L ( "All" )));
2019-03-18 20:54:01 +01:00
deps . checkbox -> SetFont ( Slic3r :: GUI :: wxGetApp (). normal_font ());
2019-05-11 23:29:25 +02:00
add_scaled_button ( parent , & deps . btn , "printer_white" , wxString :: Format ( " %s %s" , _ ( L ( "Set" )), dots ), wxBU_LEFT | wxBU_EXACTFIT );
2019-04-13 23:46:52 +02:00
deps . btn -> SetFont ( Slic3r :: GUI :: wxGetApp (). normal_font ());
2018-01-15 12:13:05 +01:00
2017-12-19 11:59:42 +01:00
auto sizer = new wxBoxSizer ( wxHORIZONTAL );
2018-12-04 17:56:49 +01:00
sizer -> Add (( deps . checkbox ), 0 , wxALIGN_CENTER_VERTICAL );
sizer -> Add (( deps . btn ), 0 , wxALIGN_CENTER_VERTICAL );
2017-12-19 11:59:42 +01:00
2018-12-04 17:56:49 +01:00
deps . checkbox -> Bind ( wxEVT_CHECKBOX , ([ this , & deps ]( wxCommandEvent e )
2017-12-19 11:59:42 +01:00
{
2018-12-04 17:56:49 +01:00
deps . btn -> Enable ( ! deps . checkbox -> GetValue ());
2018-01-12 12:41:13 +01:00
// All printers have been made compatible with this preset.
2018-12-04 17:56:49 +01:00
if ( deps . checkbox -> GetValue ())
this -> load_key_value ( deps . key_list , std :: vector < std :: string > {});
this -> get_field ( deps . key_condition ) -> toggle ( deps . checkbox -> GetValue ());
this -> update_changed_ui ();
2017-12-19 11:59:42 +01:00
}) );
2018-12-04 17:56:49 +01:00
deps . btn -> Bind ( wxEVT_BUTTON , ([ this , parent , & deps ]( wxCommandEvent e )
2017-12-19 11:59:42 +01:00
{
2018-12-04 17:56:49 +01:00
// Collect names of non-default non-external profiles.
PrinterTechnology printer_technology = m_preset_bundle -> printers . get_edited_preset (). printer_technology ();
PresetCollection & depending_presets = ( deps . type == Preset :: TYPE_PRINTER ) ? m_preset_bundle -> printers :
( printer_technology == ptFFF ) ? m_preset_bundle -> prints : m_preset_bundle -> sla_prints ;
2017-12-19 11:59:42 +01:00
wxArrayString presets ;
2018-12-04 17:56:49 +01:00
for ( size_t idx = 0 ; idx < depending_presets . size (); ++ idx )
2017-12-19 11:59:42 +01:00
{
2018-12-04 17:56:49 +01:00
Preset & preset = depending_presets . preset ( idx );
bool add = ! preset . is_default && ! preset . is_external ;
if ( add && deps . type == Preset :: TYPE_PRINTER )
// Only add printers with the same technology as the active printer.
add &= preset . printer_technology () == printer_technology ;
if ( add )
presets . Add ( from_u8 ( preset . name ));
2017-12-19 11:59:42 +01:00
}
2018-12-04 17:56:49 +01:00
wxMultiChoiceDialog dlg ( parent , deps . dialog_title , deps . dialog_label , presets );
// Collect and set indices of depending_presets marked as compatible.
2017-12-19 11:59:42 +01:00
wxArrayInt selections ;
2018-12-04 17:56:49 +01:00
auto * compatible_printers = dynamic_cast < const ConfigOptionStrings *> ( m_config -> option ( deps . key_list ));
2017-12-19 11:59:42 +01:00
if ( compatible_printers != nullptr || ! compatible_printers -> values . empty ())
for ( auto preset_name : compatible_printers -> values )
for ( size_t idx = 0 ; idx < presets . GetCount (); ++ idx )
2018-12-04 17:56:49 +01:00
if ( presets [ idx ] == preset_name ) {
2017-12-19 11:59:42 +01:00
selections . Add ( idx );
break ;
}
2018-04-11 12:21:15 +02:00
dlg . SetSelections ( selections );
2018-01-12 12:41:13 +01:00
std :: vector < std :: string > value ;
// Show the dialog.
2018-04-11 12:21:15 +02:00
if ( dlg . ShowModal () == wxID_OK ) {
2017-12-19 11:59:42 +01:00
selections . Clear ();
2018-04-11 12:21:15 +02:00
selections = dlg . GetSelections ();
2017-12-19 11:59:42 +01:00
for ( auto idx : selections )
2019-01-03 14:34:53 +01:00
value . push_back ( presets [ idx ]. ToUTF8 (). data ());
2018-01-12 12:41:13 +01:00
if ( value . empty ()) {
2018-12-04 17:56:49 +01:00
deps . checkbox -> SetValue ( 1 );
deps . btn -> Disable ();
2017-12-19 11:59:42 +01:00
}
2018-12-04 17:56:49 +01:00
// All depending_presets have been made compatible with this preset.
this -> load_key_value ( deps . key_list , value );
this -> update_changed_ui ();
2017-12-19 11:59:42 +01:00
}
}));
2018-12-04 17:56:49 +01:00
return sizer ;
}
void Tab :: compatible_widget_reload ( PresetDependencies & deps )
{
bool has_any = ! m_config -> option < ConfigOptionStrings > ( deps . key_list ) -> values . empty ();
has_any ? deps . btn -> Enable () : deps . btn -> Disable ();
deps . checkbox -> SetValue ( ! has_any );
this -> get_field ( deps . key_condition ) -> toggle ( ! has_any );
2017-12-19 11:59:42 +01:00
}
2018-04-20 12:58:07 +02:00
void Tab :: fill_icon_descriptions ()
{
2019-05-09 19:24:21 +02:00
m_icon_descriptions . emplace_back ( & m_bmp_value_lock , L ( "LOCKED LOCK" ),
2019-05-09 16:14:45 +02:00
// TRN Description for "LOCKED LOCK"
2019-05-09 19:24:21 +02:00
L ( "indicates that the settings are the same as the system values for the current option group" ));
2018-04-20 12:58:07 +02:00
2019-05-09 19:24:21 +02:00
m_icon_descriptions . emplace_back ( & m_bmp_value_unlock , L ( "UNLOCKED LOCK" ),
2019-05-09 16:14:45 +02:00
// TRN Description for "UNLOCKED LOCK"
L ( "indicates that some settings were changed and are not equal to the system values for "
2018-04-24 08:49:37 +02:00
"the current option group. \n "
"Click the UNLOCKED LOCK icon to reset all settings for current option group to "
2019-05-09 19:24:21 +02:00
"the system values." ));
2018-04-20 12:58:07 +02:00
2019-05-09 19:24:21 +02:00
m_icon_descriptions . emplace_back ( & m_bmp_white_bullet , L ( "WHITE BULLET" ),
2019-05-09 16:14:45 +02:00
// TRN Description for "WHITE BULLET"
L ( "for the left button: \t indicates a non-system preset, \n "
2019-05-09 19:24:21 +02:00
"for the right button: \t indicates that the settings hasn't been modified." ));
2018-04-20 12:58:07 +02:00
2019-05-09 19:24:21 +02:00
m_icon_descriptions . emplace_back ( & m_bmp_value_revert , L ( "BACK ARROW" ),
2019-05-09 16:14:45 +02:00
// TRN Description for "BACK ARROW"
L ( "indicates that the settings were changed and are not equal to the last saved preset for "
2018-04-24 08:49:37 +02:00
"the current option group. \n "
"Click the BACK ARROW icon to reset all settings for the current option group to "
2019-05-09 19:24:21 +02:00
"the last saved preset." ));
2018-04-20 12:58:07 +02:00
}
2018-04-24 14:11:23 +02:00
void Tab :: set_tooltips_text ()
{
// m_undo_to_sys_btn->SetToolTip(_(L( "LOCKED LOCK icon indicates that the settings are the same as the system values "
// "for the current option group.\n"
// "UNLOCKED LOCK icon indicates that some settings were changed and are not equal "
// "to the system values for the current option group.\n"
// "WHITE BULLET icon indicates a non system preset.\n\n"
// "Click the UNLOCKED LOCK icon to reset all settings for current option group to "
// "the system values.")));
//
// m_undo_btn->SetToolTip(_(L( "WHITE BULLET icon indicates that the settings are the same as in the last saved"
// "preset for the current option group.\n"
// "BACK ARROW icon indicates that the settings were changed and are not equal to "
// "the last saved preset for the current option group.\n\n"
// "Click the BACK ARROW icon to reset all settings for the current option group to "
// "the last saved preset.")));
// --- Tooltip text for reset buttons (for whole options group)
// Text to be shown on the "Revert to system" aka "Lock to system" button next to each input field.
m_ttg_value_lock = _ ( L ( "LOCKED LOCK icon indicates that the settings are the same as the system values "
"for the current option group" ));
m_ttg_value_unlock = _ ( L ( "UNLOCKED LOCK icon indicates that some settings were changed and are not equal "
"to the system values for the current option group. \n "
"Click to reset all settings for current option group to the system values." ));
m_ttg_white_bullet_ns = _ ( L ( "WHITE BULLET icon indicates a non system preset." ));
m_ttg_non_system = & m_ttg_white_bullet_ns ;
// Text to be shown on the "Undo user changes" button next to each input field.
m_ttg_white_bullet = _ ( L ( "WHITE BULLET icon indicates that the settings are the same as in the last saved "
"preset for the current option group." ));
m_ttg_value_revert = _ ( L ( "BACK ARROW icon indicates that the settings were changed and are not equal to "
"the last saved preset for the current option group. \n "
"Click to reset all settings for the current option group to the last saved preset." ));
// --- Tooltip text for reset buttons (for each option in group)
// Text to be shown on the "Revert to system" aka "Lock to system" button next to each input field.
m_tt_value_lock = _ ( L ( "LOCKED LOCK icon indicates that the value is the same as the system value." ));
m_tt_value_unlock = _ ( L ( "UNLOCKED LOCK icon indicates that the value was changed and is not equal "
"to the system value. \n "
"Click to reset current value to the system value." ));
// m_tt_white_bullet_ns= _(L("WHITE BULLET icon indicates a non system preset."));
m_tt_non_system = & m_ttg_white_bullet_ns ;
// Text to be shown on the "Undo user changes" button next to each input field.
m_tt_white_bullet = _ ( L ( "WHITE BULLET icon indicates that the value is the same as in the last saved preset." ));
m_tt_value_revert = _ ( L ( "BACK ARROW icon indicates that the value was changed and is not equal to the last saved preset. \n "
"Click to reset current value to the last saved preset." ));
}
2018-01-11 10:33:17 +01:00
void Page :: reload_config ()
{
for ( auto group : m_optgroups )
group -> reload_config ();
}
2018-10-19 13:55:29 +02:00
void Page :: update_visibility ( ConfigOptionMode mode )
{
2018-10-21 23:09:24 +02:00
bool ret_val = false ;
for ( auto group : m_optgroups )
ret_val = group -> update_visibility ( mode ) || ret_val ;
m_show = ret_val ;
2018-10-19 13:55:29 +02:00
}
2019-04-25 01:45:00 +02:00
void Page :: msw_rescale ()
2019-04-13 23:46:52 +02:00
{
for ( auto group : m_optgroups )
2019-04-25 01:45:00 +02:00
group -> msw_rescale ();
2019-04-13 23:46:52 +02:00
}
2018-04-13 12:35:04 +02:00
Field * Page :: get_field ( const t_config_option_key & opt_key , int opt_index /*= -1*/ ) const
2018-01-11 10:33:17 +01:00
{
Field * field = nullptr ;
2018-10-31 12:56:08 +01:00
for ( auto opt : m_optgroups ) {
2018-01-11 10:33:17 +01:00
field = opt -> get_fieldc ( opt_key , opt_index );
if ( field != nullptr )
return field ;
}
return field ;
}
2018-10-31 12:56:08 +01:00
bool Page :: set_value ( const t_config_option_key & opt_key , const boost :: any & value ) {
2018-01-16 16:28:01 +01:00
bool changed = false ;
for ( auto optgroup : m_optgroups ) {
if ( optgroup -> set_value ( opt_key , value ))
changed = 1 ;
}
return changed ;
}
2017-12-13 14:45:10 +01:00
// package Slic3r::GUI::Tab::Page;
2018-04-13 12:35:04 +02:00
ConfigOptionsGroupShp Page :: new_optgroup ( const wxString & title , int noncommon_label_width /*= -1*/ )
2017-12-13 14:45:10 +01:00
{
2019-04-13 23:46:52 +02:00
auto extra_column = [ this ]( wxWindow * parent , const Line & line )
2018-10-19 13:55:29 +02:00
{
std :: string bmp_name ;
2018-12-21 09:19:00 +01:00
const std :: vector < Option >& options = line . get_options ();
2019-04-16 14:06:09 +02:00
int mode_id = int ( options [ 0 ]. opt . mode );
2019-04-13 23:46:52 +02:00
const wxBitmap & bitmap = options . size () == 0 || options [ 0 ]. opt . gui_type == "legend" ? wxNullBitmap :
2019-04-16 14:06:09 +02:00
m_mode_bitmap_cache [ mode_id ]. bmp ();
2019-04-13 23:46:52 +02:00
auto bmp = new wxStaticBitmap ( parent , wxID_ANY , bitmap );
2019-04-16 14:06:09 +02:00
bmp -> SetClientData (( void * ) & m_mode_bitmap_cache [ mode_id ]);
2019-04-13 23:46:52 +02:00
2019-03-18 12:48:39 +01:00
bmp -> SetBackgroundStyle ( wxBG_STYLE_PAINT );
2018-10-19 13:55:29 +02:00
return bmp ;
};
2017-12-13 14:45:10 +01:00
//! config_ have to be "right"
2018-10-19 13:55:29 +02:00
ConfigOptionsGroupShp optgroup = std :: make_shared < ConfigOptionsGroup > ( this , title , m_config , true , extra_column );
2017-12-22 11:50:28 +01:00
if ( noncommon_label_width >= 0 )
optgroup -> label_width = noncommon_label_width ;
2017-12-13 14:45:10 +01:00
2018-07-02 13:51:50 +02:00
#ifdef __WXOSX__
auto tab = GetParent () -> GetParent ();
#else
auto tab = GetParent ();
#endif
2018-10-31 12:56:08 +01:00
optgroup -> m_on_change = [ this , tab ]( t_config_option_key opt_key , boost :: any value ) {
2018-01-18 16:36:26 +01:00
//! This function will be called from OptionGroup.
//! Using of CallAfter is redundant.
2018-01-26 01:44:34 +01:00
//! And in some cases it causes update() function to be recalled again
2018-01-18 16:36:26 +01:00
//! wxTheApp->CallAfter([this, opt_key, value]() {
2018-07-02 13:51:50 +02:00
static_cast < Tab *> ( tab ) -> update_dirty ();
static_cast < Tab *> ( tab ) -> on_value_change ( opt_key , value );
2018-01-18 16:36:26 +01:00
//! });
};
2017-12-13 14:45:10 +01:00
2018-10-31 12:56:08 +01:00
optgroup -> m_get_initial_config = [ this , tab ]() {
2018-07-02 13:51:50 +02:00
DynamicPrintConfig config = static_cast < Tab *> ( tab ) -> m_presets -> get_selected_preset (). config ;
2018-03-06 12:34:20 +01:00
return config ;
};
2018-10-31 12:56:08 +01:00
optgroup -> m_get_sys_config = [ this , tab ]() {
2018-07-02 13:51:50 +02:00
DynamicPrintConfig config = static_cast < Tab *> ( tab ) -> m_presets -> get_selected_preset_parent () -> config ;
2018-03-16 17:25:11 +01:00
return config ;
};
2018-10-31 12:56:08 +01:00
optgroup -> have_sys_config = [ this , tab ]() {
2018-07-02 13:51:50 +02:00
return static_cast < Tab *> ( tab ) -> m_presets -> get_selected_preset_parent () != nullptr ;
2018-03-16 17:25:11 +01:00
};
2019-04-16 10:05:45 +02:00
optgroup -> rescale_extra_column_item = [ this ]( wxWindow * win ) {
2019-04-13 23:46:52 +02:00
auto * ctrl = dynamic_cast < wxStaticBitmap *> ( win );
if ( ctrl == nullptr )
return ;
2019-04-25 01:45:00 +02:00
ctrl -> SetBitmap ( reinterpret_cast < ScalableBitmap *> ( ctrl -> GetClientData ()) -> bmp ());
2019-04-13 23:46:52 +02:00
};
2017-12-13 14:45:10 +01:00
vsizer () -> Add ( optgroup -> sizer , 0 , wxEXPAND | wxALL , 10 );
2017-12-26 23:04:54 +01:00
m_optgroups . push_back ( optgroup );
2017-12-13 14:45:10 +01:00
return optgroup ;
}
2018-04-13 12:35:04 +02:00
void SavePresetWindow :: build ( const wxString & title , const std :: string & default_name , std :: vector < std :: string > & values )
2018-01-18 11:45:25 +01:00
{
2019-05-11 23:29:25 +02:00
// TRN Preset
auto text = new wxStaticText ( this , wxID_ANY , wxString :: Format ( _ ( L ( "Save %s as:" )), title ),
2018-02-08 10:58:13 +01:00
wxDefaultPosition , wxDefaultSize );
2018-02-22 11:34:41 +01:00
m_combo = new wxComboBox ( this , wxID_ANY , from_u8 ( default_name ),
2018-02-05 11:03:13 +01:00
wxDefaultPosition , wxDefaultSize , 0 , 0 , wxTE_PROCESS_ENTER );
2018-01-18 11:45:25 +01:00
for ( auto value : values )
2018-02-22 11:34:41 +01:00
m_combo -> Append ( from_u8 ( value ));
2018-01-18 11:45:25 +01:00
auto buttons = CreateStdDialogButtonSizer ( wxOK | wxCANCEL );
auto sizer = new wxBoxSizer ( wxVERTICAL );
sizer -> Add ( text , 0 , wxEXPAND | wxALL , 10 );
sizer -> Add ( m_combo , 0 , wxEXPAND | wxLEFT | wxRIGHT , 10 );
sizer -> Add ( buttons , 0 , wxALIGN_CENTER_HORIZONTAL | wxALL , 10 );
wxButton * btn = static_cast < wxButton *> ( FindWindowById ( wxID_OK , this ));
btn -> Bind ( wxEVT_BUTTON , [ this ]( wxCommandEvent & ) { accept (); });
m_combo -> Bind ( wxEVT_TEXT_ENTER , [ this ]( wxCommandEvent & ) { accept (); });
SetSizer ( sizer );
sizer -> SetSizeHints ( this );
}
void SavePresetWindow :: accept ()
{
2018-02-05 11:03:13 +01:00
m_chosen_name = normalize_utf8_nfc ( m_combo -> GetValue (). ToUTF8 ());
2018-01-18 11:45:25 +01:00
if ( ! m_chosen_name . empty ()) {
const char * unusable_symbols = "<>:/ \\ |?* \" " ;
bool is_unusable_symbol = false ;
2018-06-25 11:40:40 +02:00
bool is_unusable_postfix = false ;
2018-07-23 15:44:01 +02:00
const std :: string unusable_postfix = PresetCollection :: get_suffix_modified (); //"(modified)";
2018-10-31 12:56:08 +01:00
for ( size_t i = 0 ; i < std :: strlen ( unusable_symbols ); i ++ ) {
if ( m_chosen_name . find_first_of ( unusable_symbols [ i ]) != std :: string :: npos ) {
2018-01-18 11:45:25 +01:00
is_unusable_symbol = true ;
break ;
}
}
2018-06-25 11:40:40 +02:00
if ( m_chosen_name . find ( unusable_postfix ) != std :: string :: npos )
is_unusable_postfix = true ;
2018-01-18 11:45:25 +01:00
if ( is_unusable_symbol ) {
2018-06-25 11:40:40 +02:00
show_error ( this , _ ( L ( "The supplied name is not valid;" )) + " \n " +
_ ( L ( "the following characters are not allowed:" )) + " <>:/ \\ |?* \" " );
}
2018-10-31 12:56:08 +01:00
else if ( is_unusable_postfix ) {
2018-07-23 15:44:01 +02:00
show_error ( this , _ ( L ( "The supplied name is not valid;" )) + " \n " +
_ ( L ( "the following postfix are not allowed:" )) + " \n\t " + //unusable_postfix);
wxString :: FromUTF8 ( unusable_postfix . c_str ()));
2018-01-18 11:45:25 +01:00
}
2018-12-04 17:56:49 +01:00
else if ( m_chosen_name == "- default -" ) {
2018-02-23 09:16:35 +01:00
show_error ( this , _ ( L ( "The supplied name is not available." )));
2018-01-18 11:45:25 +01:00
}
else {
EndModal ( wxID_OK );
}
}
}
2018-08-03 13:04:41 +02:00
void TabSLAMaterial :: build ()
{
m_presets = & m_preset_bundle -> sla_materials ;
load_initial_data ();
2019-04-10 09:41:04 +02:00
auto page = add_options_page ( _ ( L ( "Material" )), "resin" );
2018-08-03 13:04:41 +02:00
auto optgroup = page -> new_optgroup ( _ ( L ( "Layers" )));
2018-11-16 17:36:23 +01:00
// optgroup->append_single_option_line("layer_height");
2018-08-03 13:04:41 +02:00
optgroup -> append_single_option_line ( "initial_layer_height" );
optgroup = page -> new_optgroup ( _ ( L ( "Exposure" )));
optgroup -> append_single_option_line ( "exposure_time" );
optgroup -> append_single_option_line ( "initial_exposure_time" );
optgroup = page -> new_optgroup ( _ ( L ( "Corrections" )));
2019-04-13 23:46:52 +02:00
optgroup -> label_width = 19 ; //190;
2019-04-03 17:34:46 +02:00
std :: vector < std :: string > corrections = { "material_correction" };
2019-04-11 17:07:41 +02:00
// std::vector<std::string> axes{ "X", "Y", "Z" };
std :: vector < std :: string > axes { "XY" , "Z" };
2018-10-31 12:56:08 +01:00
for ( auto & opt_key : corrections ) {
2019-05-04 02:07:07 +02:00
auto line = Line { _ ( m_config -> def () -> get ( opt_key ) -> full_label ), "" };
2018-08-03 16:20:39 +02:00
int id = 0 ;
for ( auto & axis : axes ) {
auto opt = optgroup -> get_option ( opt_key , id );
opt . opt . label = axis ;
2019-04-13 23:46:52 +02:00
opt . opt . width = 6 ;
2018-08-03 16:20:39 +02:00
line . append_option ( opt );
++ id ;
}
optgroup -> append_line ( line );
}
2018-08-03 13:04:41 +02:00
page = add_options_page ( _ ( L ( "Notes" )), "note.png" );
optgroup = page -> new_optgroup ( _ ( L ( "Notes" )), 0 );
optgroup -> label_width = 0 ;
Option option = optgroup -> get_option ( "material_notes" );
option . opt . full_width = true ;
2019-04-13 23:46:52 +02:00
option . opt . height = 25 ; //250;
2018-08-03 13:04:41 +02:00
optgroup -> append_single_option_line ( option );
page = add_options_page ( _ ( L ( "Dependencies" )), "wrench.png" );
optgroup = page -> new_optgroup ( _ ( L ( "Profile dependencies" )));
2018-12-04 17:56:49 +01:00
Line line = optgroup -> create_single_option_line ( "compatible_printers" );
2018-10-31 12:56:08 +01:00
line . widget = [ this ]( wxWindow * parent ) {
2018-12-04 17:56:49 +01:00
return compatible_widget_create ( parent , m_compatible_printers );
2018-08-03 13:04:41 +02:00
};
optgroup -> append_line ( line , & m_colored_Label );
option = optgroup -> get_option ( "compatible_printers_condition" );
option . opt . full_width = true ;
optgroup -> append_single_option_line ( option );
2018-12-04 17:56:49 +01:00
line = optgroup -> create_single_option_line ( "compatible_prints" );
line . widget = [ this ]( wxWindow * parent ) {
return compatible_widget_create ( parent , m_compatible_prints );
};
optgroup -> append_line ( line , & m_colored_Label );
option = optgroup -> get_option ( "compatible_prints_condition" );
option . opt . full_width = true ;
optgroup -> append_single_option_line ( option );
2018-08-03 13:04:41 +02:00
line = Line { "" , "" };
line . full_width = 1 ;
line . widget = [ this ]( wxWindow * parent ) {
return description_line_widget ( parent , & m_parent_preset_description_line );
};
optgroup -> append_line ( line );
}
2018-12-04 17:56:49 +01:00
// Reload current config (aka presets->edited_preset->config) into the UI fields.
void TabSLAMaterial :: reload_config ()
{
this -> compatible_widget_reload ( m_compatible_printers );
this -> compatible_widget_reload ( m_compatible_prints );
Tab :: reload_config ();
}
2018-08-03 13:04:41 +02:00
void TabSLAMaterial :: update ()
{
2018-10-04 16:43:10 +02:00
if ( m_preset_bundle -> printers . get_selected_preset (). printer_technology () == ptFFF )
2018-11-16 17:36:23 +01:00
return ; // #ys_FIXME
2019-02-22 09:38:56 +01:00
// #ys_FIXME
// m_update_cnt++;
// ! something to update
// m_update_cnt--;
//
// if (m_update_cnt == 0)
wxGetApp (). mainframe -> on_config_changed ( m_config );
2018-11-16 17:36:23 +01:00
}
void TabSLAPrint :: build ()
{
m_presets = & m_preset_bundle -> sla_prints ;
load_initial_data ();
2019-04-08 09:37:23 +02:00
auto page = add_options_page ( _ ( L ( "Layers and perimeters" )), "layers" );
2018-11-16 17:36:23 +01:00
auto optgroup = page -> new_optgroup ( _ ( L ( "Layers" )));
optgroup -> append_single_option_line ( "layer_height" );
2019-02-18 16:04:55 +01:00
optgroup -> append_single_option_line ( "faded_layers" );
2018-11-16 17:36:23 +01:00
2019-04-12 17:10:04 +02:00
page = add_options_page ( _ ( L ( "Supports" )), "support" /*"sla_supports"*/ );
2018-11-22 18:02:05 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Supports" )));
optgroup -> append_single_option_line ( "supports_enable" );
2018-11-19 09:15:53 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Support head" )));
2018-11-23 13:03:07 +01:00
optgroup -> append_single_option_line ( "support_head_front_diameter" );
2018-11-19 09:15:53 +01:00
optgroup -> append_single_option_line ( "support_head_penetration" );
optgroup -> append_single_option_line ( "support_head_width" );
optgroup = page -> new_optgroup ( _ ( L ( "Support pillar" )));
2018-11-23 13:03:07 +01:00
optgroup -> append_single_option_line ( "support_pillar_diameter" );
2019-01-09 12:21:43 +01:00
optgroup -> append_single_option_line ( "support_pillar_connection_mode" );
2019-02-05 11:16:03 +01:00
optgroup -> append_single_option_line ( "support_buildplate_only" );
2019-03-11 14:55:28 +01:00
// TODO: This parameter is not used at the moment.
// optgroup->append_single_option_line("support_pillar_widening_factor");
2018-11-23 13:03:07 +01:00
optgroup -> append_single_option_line ( "support_base_diameter" );
2018-11-19 09:15:53 +01:00
optgroup -> append_single_option_line ( "support_base_height" );
2018-11-19 17:58:08 +01:00
optgroup -> append_single_option_line ( "support_object_elevation" );
2018-11-19 09:15:53 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Connection of the support sticks and junctions" )));
optgroup -> append_single_option_line ( "support_critical_angle" );
optgroup -> append_single_option_line ( "support_max_bridge_length" );
2019-03-08 11:39:34 +01:00
optgroup -> append_single_option_line ( "support_max_pillar_link_distance" );
2018-11-19 09:15:53 +01:00
2018-12-07 14:10:16 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Automatic generation" )));
2019-02-19 16:34:52 +01:00
optgroup -> append_single_option_line ( "support_points_density_relative" );
optgroup -> append_single_option_line ( "support_points_minimal_distance" );
2018-12-07 14:10:16 +01:00
2019-04-12 17:10:04 +02:00
page = add_options_page ( _ ( L ( "Pad" )), "pad" );
2018-11-19 09:15:53 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Pad" )));
2018-11-20 16:12:04 +01:00
optgroup -> append_single_option_line ( "pad_enable" );
2018-11-19 09:15:53 +01:00
optgroup -> append_single_option_line ( "pad_wall_thickness" );
optgroup -> append_single_option_line ( "pad_wall_height" );
optgroup -> append_single_option_line ( "pad_max_merge_distance" );
2019-02-25 12:06:38 +01:00
// TODO: Disabling this parameter for the beta release
// optgroup->append_single_option_line("pad_edge_radius");
2019-02-25 16:04:46 +01:00
optgroup -> append_single_option_line ( "pad_wall_slope" );
2018-11-19 09:15:53 +01:00
2019-04-08 09:37:23 +02:00
page = add_options_page ( _ ( L ( "Advanced" )), "wrench" );
2019-03-01 17:53:02 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Slicing" )));
optgroup -> append_single_option_line ( "slice_closing_radius" );
2019-04-08 09:37:23 +02:00
page = add_options_page ( _ ( L ( "Output options" )), "output+page_white" );
2018-12-03 13:14:28 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Output file" )));
Option option = optgroup -> get_option ( "output_filename_format" );
option . opt . full_width = true ;
optgroup -> append_single_option_line ( option );
2019-04-08 09:37:23 +02:00
page = add_options_page ( _ ( L ( "Dependencies" )), "wrench" );
2018-11-16 17:36:23 +01:00
optgroup = page -> new_optgroup ( _ ( L ( "Profile dependencies" )));
Line line = optgroup -> create_single_option_line ( "compatible_printers" ); //Line { _(L("Compatible printers")), "" };
line . widget = [ this ]( wxWindow * parent ) {
2018-12-04 17:56:49 +01:00
return compatible_widget_create ( parent , m_compatible_printers );
2018-11-16 17:36:23 +01:00
};
optgroup -> append_line ( line , & m_colored_Label );
2018-12-03 13:14:28 +01:00
option = optgroup -> get_option ( "compatible_printers_condition" );
2018-11-16 17:36:23 +01:00
option . opt . full_width = true ;
optgroup -> append_single_option_line ( option );
line = Line { "" , "" };
line . full_width = 1 ;
line . widget = [ this ]( wxWindow * parent ) {
return description_line_widget ( parent , & m_parent_preset_description_line );
};
optgroup -> append_line ( line );
}
2018-12-04 17:56:49 +01:00
// Reload current config (aka presets->edited_preset->config) into the UI fields.
void TabSLAPrint :: reload_config ()
{
this -> compatible_widget_reload ( m_compatible_printers );
Tab :: reload_config ();
}
2018-11-16 17:36:23 +01:00
void TabSLAPrint :: update ()
{
if ( m_preset_bundle -> printers . get_selected_preset (). printer_technology () == ptFFF )
return ; // #ys_FIXME
2019-02-22 09:38:56 +01:00
// #ys_FIXME
2019-03-11 16:27:54 +01:00
m_update_cnt ++ ;
double head_penetration = m_config -> opt_float ( "support_head_penetration" );
double head_width = m_config -> opt_float ( "support_head_width" );
if ( head_penetration > head_width ) {
wxString msg_text = _ ( L ( "Head penetration should not be greater than the head width." ));
auto dialog = new wxMessageDialog ( parent (), msg_text , _ ( L ( "Invalid Head penetration" )), wxICON_WARNING | wxOK );
DynamicPrintConfig new_conf = * m_config ;
if ( dialog -> ShowModal () == wxID_OK ) {
new_conf . set_key_value ( "support_head_penetration" , new ConfigOptionFloat ( head_width ));
}
load_config ( new_conf );
}
double pinhead_d = m_config -> opt_float ( "support_head_front_diameter" );
double pillar_d = m_config -> opt_float ( "support_pillar_diameter" );
if ( pinhead_d > pillar_d ) {
wxString msg_text = _ ( L ( "Pinhead diameter should be smaller than the pillar diameter." ));
auto dialog = new wxMessageDialog ( parent (), msg_text , _ ( L ( "Invalid pinhead diameter" )), wxICON_WARNING | wxOK );
DynamicPrintConfig new_conf = * m_config ;
if ( dialog -> ShowModal () == wxID_OK ) {
new_conf . set_key_value ( "support_head_front_diameter" , new ConfigOptionFloat ( pillar_d / 2.0 ));
}
load_config ( new_conf );
}
m_update_cnt -- ;
if ( m_update_cnt == 0 )
2019-02-22 09:38:56 +01:00
wxGetApp (). mainframe -> on_config_changed ( m_config );
2018-08-03 13:04:41 +02:00
}
2017-12-05 15:54:01 +01:00
} // GUI
} // Slic3r