mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 12:41:20 -06:00 
			
		
		
		
	Merge branch 'gui_improvements'
This commit is contained in:
		
						commit
						56c2267d19
					
				
					 18 changed files with 502 additions and 173 deletions
				
			
		|  | @ -117,6 +117,8 @@ sub OnInit { | |||
|     } | ||||
|     eval { $self->{preset_bundle}->load_selections($self->{app_config}) }; | ||||
|     $run_wizard = 1 if $self->{preset_bundle}->has_defauls_only; | ||||
| 
 | ||||
|     Slic3r::GUI::set_preset_bundle($self->{preset_bundle}); | ||||
|      | ||||
|     # application frame | ||||
|     Wx::Image::FindHandlerType(wxBITMAP_TYPE_PNG) || Wx::Image::AddHandler(Wx::PNGHandler->new); | ||||
|  |  | |||
|  | @ -400,6 +400,10 @@ sub mouse_event { | |||
|             $self->Refresh; | ||||
|             $self->Update; | ||||
|         } else { | ||||
|             # The mouse_to_3d gets the Z coordinate from the Z buffer at the screen coordinate $pos->x,y, | ||||
|             # an converts the screen space coordinate to unscaled object space. | ||||
|             my $pos3d = ($volume_idx == -1) ? undef : $self->mouse_to_3d(@$pos); | ||||
| 
 | ||||
|             # Select volume in this 3D canvas. | ||||
|             # Don't deselect a volume if layer editing is enabled. We want the object to stay selected | ||||
|             # during the scene manipulation. | ||||
|  | @ -427,9 +431,6 @@ sub mouse_event { | |||
|              | ||||
|             if ($volume_idx != -1) { | ||||
|                 if ($e->LeftDown && $self->enable_moving) { | ||||
|                     # The mouse_to_3d gets the Z coordinate from the Z buffer at the screen coordinate $pos->x,y, | ||||
|                     # an converts the screen space coordinate to unscaled object space. | ||||
|                     my $pos3d = $self->mouse_to_3d(@$pos); | ||||
|                     # Only accept the initial position, if it is inside the volume bounding box. | ||||
|                     my $volume_bbox = $self->volumes->[$volume_idx]->transformed_bounding_box; | ||||
|                     $volume_bbox->offset(1.); | ||||
|  | @ -948,6 +949,9 @@ sub mulquats { | |||
| sub mouse_to_3d { | ||||
|     my ($self, $x, $y, $z) = @_; | ||||
| 
 | ||||
|     return unless $self->GetContext; | ||||
|     $self->SetCurrent($self->GetContext); | ||||
| 
 | ||||
|     my @viewport    = glGetIntegerv_p(GL_VIEWPORT);             # 4 items | ||||
|     my @mview       = glGetDoublev_p(GL_MODELVIEW_MATRIX);      # 16 items | ||||
|     my @proj        = glGetDoublev_p(GL_PROJECTION_MATRIX);     # 16 items | ||||
|  |  | |||
|  | @ -217,7 +217,7 @@ sub _init_tabpanel { | |||
|     $self->{is_disabled_button_browse} = (!eval "use Net::Bonjour; 1") ? 1 : 0 ; | ||||
|     # A variable to inform C++ Tab implementation about user_agent | ||||
|     $self->{is_user_agent} = (eval "use LWP::UserAgent; 1") ? 1 : 0 ;     | ||||
|     Slic3r::GUI::create_preset_tabs(wxTheApp->{preset_bundle}, $self->{no_controller}, | ||||
|     Slic3r::GUI::create_preset_tabs($self->{no_controller}, | ||||
|                                     $self->{is_disabled_button_browse}, | ||||
|                                     $self->{is_user_agent}, | ||||
|                                     $VALUE_CHANGE_EVENT, $PRESETS_CHANGED_EVENT, | ||||
|  |  | |||
|  | @ -389,9 +389,12 @@ sub new { | |||
|                     }); | ||||
|                 }); | ||||
|                 $presets->Add($text, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxRIGHT, 4); | ||||
|                 $presets->Add($choice, 1, wxALIGN_CENTER_VERTICAL | wxEXPAND | wxBOTTOM, 0); | ||||
|                 $presets->Add($choice, 1, wxALIGN_CENTER_VERTICAL | wxEXPAND | wxBOTTOM, 1); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         my $frequently_changed_parameters_sizer = Wx::BoxSizer->new(wxHORIZONTAL); | ||||
|         Slic3r::GUI::add_frequently_changed_parameters($self, $frequently_changed_parameters_sizer, $presets); | ||||
|          | ||||
|         my $object_info_sizer; | ||||
|         { | ||||
|  | @ -473,6 +476,7 @@ sub new { | |||
|          | ||||
|         my $right_sizer = Wx::BoxSizer->new(wxVERTICAL); | ||||
|         $right_sizer->Add($presets, 0, wxEXPAND | wxTOP, 10) if defined $presets; | ||||
|         $right_sizer->Add($frequently_changed_parameters_sizer, 0, wxEXPAND | wxTOP, 10) if defined $frequently_changed_parameters_sizer; | ||||
|         $right_sizer->Add($buttons_sizer, 0, wxEXPAND | wxBOTTOM, 5); | ||||
|         $right_sizer->Add($self->{list}, 1, wxEXPAND, 5); | ||||
|         $right_sizer->Add($object_info_sizer, 0, wxEXPAND, 0); | ||||
|  |  | |||
							
								
								
									
										
											BIN
										
									
								
								resources/icons/action_undo.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								resources/icons/action_undo.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 616 B | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/arrow_undo.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								resources/icons/arrow_undo.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 631 B | 
							
								
								
									
										
											BIN
										
									
								
								resources/localization/uk/Slic3rPE_.mo
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								resources/localization/uk/Slic3rPE_.mo
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							|  | @ -12,7 +12,7 @@ BEGIN { | |||
| use File::Basename qw(basename); | ||||
| use Getopt::Long qw(:config no_auto_abbrev); | ||||
| use List::Util qw(first); | ||||
| use POSIX qw(setlocale LC_NUMERIC); | ||||
| #use POSIX qw(setlocale LC_NUMERIC); | ||||
| use Slic3r; | ||||
| use Slic3r::Geometry qw(deg2rad); | ||||
| use Time::HiRes qw(gettimeofday tv_interval); | ||||
|  | @ -112,7 +112,7 @@ if ((!@ARGV || $opt{gui}) && !$opt{no_gui} && !$opt{save} && eval "require Slic3 | |||
|         $Slic3r::GUI::autosave      = $opt{autosave}; | ||||
|     } | ||||
|     $gui = Slic3r::GUI->new; | ||||
|     setlocale(LC_NUMERIC, 'C'); | ||||
|     #setlocale(LC_NUMERIC, 'C'); | ||||
|     $gui->{mainframe}->load_config_file($_) for @{$opt{load}}; | ||||
|     $gui->{mainframe}->load_config($cli_config); | ||||
|     my @input_files = @ARGV; | ||||
|  |  | |||
|  | @ -18,6 +18,17 @@ namespace Slic3r { namespace GUI { | |||
| 			wxNumberFormatter::ToString(value, precision, wxNumberFormatter::Style_None); | ||||
| 	} | ||||
| 
 | ||||
| 	void Field::PostInitialize(){ | ||||
| 		m_Undo_btn = new wxButton(m_parent, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER); | ||||
| 		// use bouth of temporary_icons till don't have "undo_icon" 
 | ||||
| 		auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); | ||||
| 		if (wxMSW) m_Undo_btn->SetBackgroundColour(color); | ||||
| 		m_Undo_btn->SetBitmap(wxBitmap(from_u8(var("bullet_white.png")), wxBITMAP_TYPE_PNG)); | ||||
| 		m_Undo_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ on_back_to_initial_value(); })); | ||||
| 
 | ||||
| 		BUILD(); | ||||
| 	} | ||||
| 
 | ||||
| 	void Field::on_kill_focus(wxEvent& event) { | ||||
|         // Without this, there will be nasty focus bugs on Windows.
 | ||||
|         // Also, docs for wxEvent::Skip() say "In general, it is recommended to skip all 
 | ||||
|  | @ -34,6 +45,12 @@ namespace Slic3r { namespace GUI { | |||
|             m_on_change(m_opt_id, get_value()); | ||||
|     } | ||||
| 
 | ||||
| 	void Field::on_back_to_initial_value() | ||||
| 	{ | ||||
| 		if (m_back_to_initial_value != nullptr && m_is_modified_value) | ||||
| 			m_back_to_initial_value(m_opt_id); | ||||
| 	} | ||||
| 
 | ||||
| 	wxString Field::get_tooltip_text(const wxString& default_string) | ||||
| 	{ | ||||
| 		wxString tooltip_text(""); | ||||
|  | @ -187,6 +204,17 @@ void CheckBox::BUILD() { | |||
| 	window = dynamic_cast<wxWindow*>(temp); | ||||
| } | ||||
| 
 | ||||
| boost::any CheckBox::get_value() | ||||
| { | ||||
| 	boost::any ret_val; | ||||
| 	bool value = dynamic_cast<wxCheckBox*>(window)->GetValue(); | ||||
| 	if (m_opt.type == coBool) | ||||
| 		ret_val = static_cast<bool>(value); | ||||
| 	else | ||||
| 		ret_val = static_cast<unsigned char>(value); | ||||
|  	return ret_val; | ||||
| } | ||||
| 
 | ||||
| int undef_spin_val = -9999;		//! Probably, It's not necessary
 | ||||
| 
 | ||||
| void SpinCtrl::BUILD() { | ||||
|  | @ -217,8 +245,13 @@ void SpinCtrl::BUILD() { | |||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	const int min_val = m_opt_id == "standby_temperature_delta" ?  | ||||
| 						-500 : m_opt.min > 0 ?  | ||||
| 						m_opt.min : 0; | ||||
| 	const int max_val = m_opt.max < 2147483647 ? m_opt.max : 2147483647; | ||||
| 
 | ||||
| 	auto temp = new wxSpinCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, | ||||
| 		0, m_opt.min >0 ? m_opt.min : 0, m_opt.max < 2147483647 ? m_opt.max : 2147483647, default_value); | ||||
| 		0, min_val, max_val, default_value); | ||||
| 
 | ||||
| 	temp->Bind(wxEVT_SPINCTRL, ([this](wxCommandEvent e) { tmp_value = undef_spin_val; on_change_field(); }), temp->GetId()); | ||||
| 	temp->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) { tmp_value = undef_spin_val; on_kill_focus(e); }), temp->GetId()); | ||||
|  | @ -261,8 +294,10 @@ void Choice::BUILD() { | |||
| 	if (m_opt.enum_labels.empty() && m_opt.enum_values.empty()){ | ||||
| 	} | ||||
| 	else{ | ||||
| 		for (auto el : m_opt.enum_labels.empty() ? m_opt.enum_values : m_opt.enum_labels) | ||||
| 			temp->Append(wxString(el)); | ||||
| 		for (auto el : m_opt.enum_labels.empty() ? m_opt.enum_values : m_opt.enum_labels){ | ||||
| 			const wxString& str = m_opt_id == "support" ? L_str(el) : el; | ||||
| 			temp->Append(str); | ||||
| 		} | ||||
| 		set_selection(); | ||||
| 	} | ||||
|  	temp->Bind(wxEVT_TEXT, ([this](wxCommandEvent e) { on_change_field(); }), temp->GetId()); | ||||
|  | @ -411,6 +446,9 @@ boost::any Choice::get_value() | |||
| 	boost::any ret_val; | ||||
| 	wxString ret_str = static_cast<wxComboBox*>(window)->GetValue();	 | ||||
| 
 | ||||
| 	if (m_opt_id == "support") | ||||
| 		return ret_str; | ||||
| 
 | ||||
| 	if (m_opt.type != coEnum) | ||||
| 		ret_val = get_value_by_opt_type(ret_str); | ||||
| 	else | ||||
|  |  | |||
|  | @ -18,6 +18,13 @@ | |||
| 
 | ||||
| //#include "slic3r_gui.hpp"
 | ||||
| #include "GUI.hpp" | ||||
| #include "Utils.hpp" | ||||
| 
 | ||||
| #ifdef __WXMSW__ | ||||
| #define wxMSW true | ||||
| #else | ||||
| #define wxMSW false | ||||
| #endif | ||||
| 
 | ||||
| namespace Slic3r { namespace GUI { | ||||
| 
 | ||||
|  | @ -25,13 +32,14 @@ class Field; | |||
| using t_field = std::unique_ptr<Field>; | ||||
| using t_kill_focus = std::function<void()>; | ||||
| using t_change = std::function<void(t_config_option_key, boost::any)>; | ||||
| using t_back_to_init = std::function<void(std::string)>; | ||||
| 
 | ||||
| wxString double_to_string(double const value); | ||||
| 
 | ||||
| class Field { | ||||
| protected: | ||||
|     // factory function to defer and enforce creation of derived type. 
 | ||||
|     virtual void	PostInitialize() { BUILD(); } | ||||
| 	virtual void	PostInitialize(); | ||||
|      | ||||
|     /// Finish constructing the Field's wxWidget-related properties, including setting its own sizer, etc.
 | ||||
|     virtual void	BUILD() = 0; | ||||
|  | @ -42,6 +50,8 @@ protected: | |||
| 	void			on_kill_focus(wxEvent& event); | ||||
|     /// Call the attached on_change method. 
 | ||||
|     void			on_change_field(); | ||||
|     /// Call the attached m_back_to_initial_value method. 
 | ||||
| 	void			on_back_to_initial_value(); | ||||
| 
 | ||||
| public: | ||||
|     /// parent wx item, opportunity to refactor (probably not necessary - data duplication)
 | ||||
|  | @ -53,8 +63,13 @@ public: | |||
|     /// Function object to store callback passed in from owning object.
 | ||||
| 	t_change		m_on_change {nullptr}; | ||||
| 
 | ||||
|     /// Function object to store callback passed in from owning object.
 | ||||
| 	t_back_to_init	m_back_to_initial_value{ nullptr }; | ||||
| 
 | ||||
| 	// This is used to avoid recursive invocation of the field change/update by wxWidgets.
 | ||||
|     bool			m_disable_change_event {false}; | ||||
| 	// This is used to avoid recursive invocation of the field change/update by wxWidgets.
 | ||||
|     bool			m_is_modified_value {false}; | ||||
| 
 | ||||
|     /// Copy of ConfigOption for deduction purposes
 | ||||
|     const ConfigOptionDef			m_opt {ConfigOptionDef()}; | ||||
|  | @ -72,6 +87,9 @@ public: | |||
|     virtual void		enable() = 0; | ||||
|     virtual void		disable() = 0; | ||||
| 
 | ||||
| 	wxStaticText*		m_Label = nullptr; | ||||
| 	wxButton*			m_Undo_btn = nullptr; | ||||
| 
 | ||||
|     /// Fires the enable or disable function, based on the input.
 | ||||
|     inline void			toggle(bool en) { en ? enable() : disable(); } | ||||
| 
 | ||||
|  | @ -85,7 +103,7 @@ public: | |||
|     virtual wxWindow*	getWindow() { return nullptr; } | ||||
| 
 | ||||
| 	bool		is_matched(std::string string, std::string pattern); | ||||
| 	boost::any get_value_by_opt_type(wxString str); | ||||
| 	boost::any	get_value_by_opt_type(wxString str); | ||||
| 
 | ||||
|     /// Factory method for generating new derived classes.
 | ||||
|     template<class T> | ||||
|  | @ -153,9 +171,7 @@ public: | |||
| 		dynamic_cast<wxCheckBox*>(window)->SetValue(boost::any_cast<bool>(value)); | ||||
| 		m_disable_change_event = false; | ||||
| 	} | ||||
| 	boost::any		get_value() override { | ||||
| 		return boost::any(dynamic_cast<wxCheckBox*>(window)->GetValue()); | ||||
| 	} | ||||
| 	boost::any		get_value() override; | ||||
| 
 | ||||
| 	void			enable() override { dynamic_cast<wxCheckBox*>(window)->Enable(); } | ||||
| 	void			disable() override { dynamic_cast<wxCheckBox*>(window)->Disable(); } | ||||
|  |  | |||
|  | @ -45,6 +45,7 @@ | |||
| #include "AppConfig.hpp" | ||||
| #include "Utils.hpp" | ||||
| #include "Preferences.hpp" | ||||
| #include "PresetBundle.hpp" | ||||
| 
 | ||||
| namespace Slic3r { namespace GUI { | ||||
| 
 | ||||
|  | @ -172,11 +173,15 @@ wxApp       *g_wxApp        = nullptr; | |||
| wxFrame     *g_wxMainFrame  = nullptr; | ||||
| wxNotebook  *g_wxTabPanel   = nullptr; | ||||
| AppConfig	*g_AppConfig	= nullptr; | ||||
| PresetBundle *g_PresetBundle= nullptr; | ||||
| 
 | ||||
| std::vector<Tab *> g_tabs_list; | ||||
| 
 | ||||
| wxLocale*	g_wxLocale; | ||||
| 
 | ||||
| std::shared_ptr<ConfigOptionsGroup>	m_optgroup; | ||||
| double m_brim_width = 0.0; | ||||
| 
 | ||||
| void set_wxapp(wxApp *app) | ||||
| { | ||||
|     g_wxApp = app; | ||||
|  | @ -197,6 +202,11 @@ void set_app_config(AppConfig *app_config) | |||
| 	g_AppConfig = app_config; | ||||
| } | ||||
| 
 | ||||
| void set_preset_bundle(PresetBundle *preset_bundle) | ||||
| { | ||||
| 	g_PresetBundle = preset_bundle; | ||||
| } | ||||
| 
 | ||||
| std::vector<Tab *>& get_tabs_list() | ||||
| { | ||||
| 	return g_tabs_list; | ||||
|  | @ -240,6 +250,7 @@ bool select_language(wxArrayString & names, | |||
| 		g_wxLocale->Init(identifiers[index]); | ||||
| 		g_wxLocale->AddCatalogLookupPathPrefix(wxPathOnly(localization_dir())); | ||||
| 		g_wxLocale->AddCatalog(g_wxApp->GetAppName()); | ||||
| 		wxSetlocale(LC_NUMERIC, "C"); | ||||
| 		return true; | ||||
| 	} | ||||
| 	return false; | ||||
|  | @ -268,6 +279,7 @@ bool load_language() | |||
| 			g_wxLocale->Init(identifiers[i]); | ||||
| 			g_wxLocale->AddCatalogLookupPathPrefix(wxPathOnly(localization_dir())); | ||||
| 			g_wxLocale->AddCatalog(g_wxApp->GetAppName()); | ||||
| 			wxSetlocale(LC_NUMERIC, "C"); | ||||
| 			return true; | ||||
| 		} | ||||
| 	} | ||||
|  | @ -346,15 +358,13 @@ void open_preferences_dialog(int event_preferences) | |||
| 	dlg->ShowModal(); | ||||
| } | ||||
| 
 | ||||
| void create_preset_tabs(PresetBundle *preset_bundle, | ||||
| 						bool no_controller, bool is_disabled_button_browse, bool is_user_agent, | ||||
| void create_preset_tabs(bool no_controller, bool is_disabled_button_browse, bool is_user_agent, | ||||
| 						int event_value_change, int event_presets_changed, | ||||
| 						int event_button_browse, int event_button_test) | ||||
| {	 | ||||
| 	add_created_tab(new TabPrint	(g_wxTabPanel, no_controller), preset_bundle); | ||||
| 	add_created_tab(new TabFilament	(g_wxTabPanel, no_controller), preset_bundle); | ||||
| 	add_created_tab(new TabPrinter	(g_wxTabPanel, no_controller, is_disabled_button_browse, is_user_agent),  | ||||
| 					preset_bundle); | ||||
| 	add_created_tab(new TabPrint	(g_wxTabPanel, no_controller)); | ||||
| 	add_created_tab(new TabFilament	(g_wxTabPanel, no_controller)); | ||||
| 	add_created_tab(new TabPrinter	(g_wxTabPanel, no_controller, is_disabled_button_browse, is_user_agent)); | ||||
| 	for (size_t i = 0; i < g_wxTabPanel->GetPageCount(); ++ i) { | ||||
| 		Tab *tab = dynamic_cast<Tab*>(g_wxTabPanel->GetPage(i)); | ||||
| 		if (! tab) | ||||
|  | @ -419,9 +429,13 @@ void change_opt_value(DynamicPrintConfig& config, t_config_option_key opt_key, b | |||
| 			config.set_key_value(opt_key, new ConfigOptionString(boost::any_cast<std::string>(value))); | ||||
| 			break; | ||||
| 		case coStrings:{ | ||||
| 			if (opt_key.compare("compatible_printers") == 0){ | ||||
| 			if (opt_key.compare("compatible_printers") == 0 || | ||||
| 				config.def()->get(opt_key)->gui_flags.compare("serialized") == 0){ | ||||
| 				config.option<ConfigOptionStrings>(opt_key)->values.resize(0); | ||||
| 				for (auto el : boost::any_cast<std::vector<std::string>>(value)) | ||||
| 				std::vector<std::string> values = boost::any_cast<std::vector<std::string>>(value); | ||||
| 				if (values.size() == 1 && values[0] == "") | ||||
| 					break; | ||||
| 				for (auto el : values) | ||||
| 					config.option<ConfigOptionStrings>(opt_key)->values.push_back(el); | ||||
| 			} | ||||
| 			else{ | ||||
|  | @ -434,7 +448,7 @@ void change_opt_value(DynamicPrintConfig& config, t_config_option_key opt_key, b | |||
| 			config.set_key_value(opt_key, new ConfigOptionBool(boost::any_cast<bool>(value))); | ||||
| 			break; | ||||
| 		case coBools:{ | ||||
| 			ConfigOptionBools* vec_new = new ConfigOptionBools{ boost::any_cast<bool>(value) }; | ||||
| 			ConfigOptionBools* vec_new = new ConfigOptionBools{ (bool)boost::any_cast<unsigned char>(value) }; | ||||
| 			config.option<ConfigOptionBools>(opt_key)->set_at(vec_new, opt_index, 0); | ||||
| 			break;} | ||||
| 		case coInt: | ||||
|  | @ -458,9 +472,8 @@ void change_opt_value(DynamicPrintConfig& config, t_config_option_key opt_key, b | |||
| 			} | ||||
| 			break; | ||||
| 		case coPoints:{ | ||||
| 			ConfigOptionPoints points; | ||||
| 			points.values = boost::any_cast<std::vector<Pointf>>(value); | ||||
| 			config.set_key_value(opt_key, new ConfigOptionPoints(points)); | ||||
| 			ConfigOptionPoints* vec_new = new ConfigOptionPoints{ boost::any_cast<Pointf>(value) }; | ||||
| 			config.option<ConfigOptionPoints>(opt_key)->set_at(vec_new, opt_index, 0); | ||||
| 			} | ||||
| 			break; | ||||
| 		case coNone: | ||||
|  | @ -475,9 +488,9 @@ void change_opt_value(DynamicPrintConfig& config, t_config_option_key opt_key, b | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| void add_created_tab(Tab* panel, PresetBundle *preset_bundle) | ||||
| void add_created_tab(Tab* panel) | ||||
| { | ||||
| 	panel->create_preset_tab(preset_bundle); | ||||
| 	panel->create_preset_tab(g_PresetBundle); | ||||
| 
 | ||||
| 	// Load the currently selected preset into the GUI, update the preset selection box.
 | ||||
| 	panel->load_current_preset(); | ||||
|  | @ -505,6 +518,11 @@ wxApp* get_app(){ | |||
| 	return g_wxApp; | ||||
| } | ||||
| 
 | ||||
| wxColour* get_modified_label_clr() | ||||
| { | ||||
| 	return new wxColour(253, 88, 0); | ||||
| } | ||||
| 
 | ||||
| void create_combochecklist(wxComboCtrl* comboCtrl, std::string text, std::string items, bool initial_value) | ||||
| { | ||||
|     if (comboCtrl == nullptr) | ||||
|  | @ -562,13 +580,13 @@ AppConfig* get_app_config() | |||
| 	return g_AppConfig; | ||||
| } | ||||
| 
 | ||||
| wxString L_str(std::string str) | ||||
| wxString L_str(const std::string &str) | ||||
| { | ||||
| 	//! Explicitly specify that the source string is already in UTF-8 encoding
 | ||||
| 	return wxGetTranslation(wxString(str.c_str(), wxConvUTF8)); | ||||
| } | ||||
| 
 | ||||
| wxString from_u8(std::string str) | ||||
| wxString from_u8(const std::string &str) | ||||
| { | ||||
| 	return wxString::FromUTF8(str.c_str()); | ||||
| } | ||||
|  | @ -587,4 +605,105 @@ wxWindow *get_widget_by_id(int id) | |||
|     return window; | ||||
| } | ||||
| 
 | ||||
| void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFlexGridSizer* preset_sizer) | ||||
| { | ||||
| 	DynamicPrintConfig*	config = &g_PresetBundle->prints.get_edited_preset().config; | ||||
| 	m_optgroup = std::make_shared<ConfigOptionsGroup>(parent, "", config); | ||||
| 	const wxArrayInt& ar = preset_sizer->GetColWidths(); | ||||
| 	m_optgroup->label_width = ar.IsEmpty() ? 100 : ar.front(); | ||||
| 	m_optgroup->m_on_change = [config](t_config_option_key opt_key, boost::any value){ | ||||
| 		TabPrint* tab_print = nullptr; | ||||
| 		for (size_t i = 0; i < g_wxTabPanel->GetPageCount(); ++i) { | ||||
| 			Tab *tab = dynamic_cast<Tab*>(g_wxTabPanel->GetPage(i)); | ||||
| 			if (!tab) | ||||
| 				continue; | ||||
| 			if (tab->name() == "print"){ | ||||
| 				tab_print = static_cast<TabPrint*>(tab); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		if (tab_print == nullptr) | ||||
| 			return; | ||||
| 
 | ||||
| 		if (opt_key == "fill_density"){ | ||||
| 			value = m_optgroup->get_config_value(*config, opt_key); | ||||
| 			tab_print->set_value(opt_key, value); | ||||
| 			tab_print->update(); | ||||
| 		} | ||||
| 		else{ | ||||
| 			DynamicPrintConfig new_conf = *config; | ||||
| 			if (opt_key == "brim"){ | ||||
| 				double new_val; | ||||
| 				double brim_width = config->opt_float("brim_width"); | ||||
| 				if (boost::any_cast<bool>(value) == true) | ||||
| 				{ | ||||
| 					new_val = m_brim_width == 0.0 ? 10 : | ||||
| 						m_brim_width < 0.0 ? m_brim_width * (-1) : | ||||
| 						m_brim_width; | ||||
| 				} | ||||
| 				else{ | ||||
| 					m_brim_width = brim_width * (-1); | ||||
| 					new_val = 0; | ||||
| 				} | ||||
| 				new_conf.set_key_value("brim_width", new ConfigOptionFloat(new_val)); | ||||
| 			} | ||||
| 			else{ //(opt_key == "support")
 | ||||
| 				const wxString& selection = boost::any_cast<wxString>(value); | ||||
| 				 | ||||
| 				auto support_material = selection == _("None") ? false : true; | ||||
| 				new_conf.set_key_value("support_material", new ConfigOptionBool(support_material)); | ||||
| 
 | ||||
| 				if (selection == _("Everywhere")) | ||||
| 					new_conf.set_key_value("support_material_buildplate_only", new ConfigOptionBool(false)); | ||||
| 				else if (selection == _("Support on build plate only")) | ||||
| 					new_conf.set_key_value("support_material_buildplate_only", new ConfigOptionBool(true));				 | ||||
| 			} | ||||
| 			tab_print->load_config(new_conf); | ||||
| 		} | ||||
| 
 | ||||
| 		tab_print->update_dirty(); | ||||
| 	}; | ||||
| 
 | ||||
| 	const int width = 250; | ||||
| 	Option option = m_optgroup->get_option("fill_density"); | ||||
| 	option.opt.sidetext = ""; | ||||
| 	option.opt.width = width; | ||||
| 	m_optgroup->append_single_option_line(option); | ||||
| 
 | ||||
| 	ConfigOptionDef def; | ||||
| 
 | ||||
| 	def.label = L("Support"); | ||||
| 	def.type = coStrings; | ||||
| 	def.gui_type = "select_open"; | ||||
| 	def.tooltip = L("Select what kind of support do you need"); | ||||
| 	def.enum_labels.push_back(L("None")); | ||||
| 	def.enum_labels.push_back(L("Support on build plate only")); | ||||
| 	def.enum_labels.push_back(L("Everywhere")); | ||||
| 	std::string selection = !config->opt_bool("support_material") ? | ||||
| 		"None" : | ||||
| 		config->opt_bool("support_material_buildplate_only") ? | ||||
| 		"Support on build plate only" : | ||||
| 		"Everywhere"; | ||||
| 	def.default_value = new ConfigOptionStrings { selection }; | ||||
| 	option = Option(def, "support"); | ||||
| 	option.opt.width = width; | ||||
| 	m_optgroup->append_single_option_line(option); | ||||
| 
 | ||||
| 	m_brim_width = config->opt_float("brim_width"); | ||||
| 	def.label = L("Brim"); | ||||
| 	def.type = coBool; | ||||
| 	def.tooltip = L("This flag enables the brim that will be printed around each object on the first layer."); | ||||
| 	def.gui_type = ""; | ||||
| 	def.default_value = new ConfigOptionBool{ m_brim_width > 0.0 ? true : false }; | ||||
| 	option = Option(def, "brim"); | ||||
| 	m_optgroup->append_single_option_line(option); | ||||
| 
 | ||||
| 	sizer->Add(m_optgroup->sizer, 0, wxEXPAND | wxBOTTOM | wxBottom, 1); | ||||
| } | ||||
| 
 | ||||
| ConfigOptionsGroup* get_optgroup() | ||||
| { | ||||
| 	return m_optgroup.get(); | ||||
| } | ||||
| 
 | ||||
| } } | ||||
|  |  | |||
|  | @ -15,6 +15,9 @@ class wxComboCtrl; | |||
| class wxString; | ||||
| class wxArrayString; | ||||
| class wxArrayLong; | ||||
| class wxColour; | ||||
| class wxBoxSizer; | ||||
| class wxFlexGridSizer; | ||||
| 
 | ||||
| namespace Slic3r {  | ||||
| 
 | ||||
|  | @ -36,11 +39,12 @@ class TabIface; | |||
| #define _CHB(s) wxGetTranslation(wxString(s, wxConvUTF8)).utf8_str() | ||||
| 
 | ||||
| // Minimal buffer length for translated string (char buf[MIN_BUF_LENGTH_FOR_L])
 | ||||
| #define MIN_BUF_LENGTH_FOR_L	128 | ||||
| #define MIN_BUF_LENGTH_FOR_L	512 | ||||
| 
 | ||||
| namespace GUI { | ||||
| 
 | ||||
| class Tab; | ||||
| class ConfigOptionsGroup; | ||||
| // Map from an file_type name to full file wildcard name.
 | ||||
| typedef std::map<std::string, std::string> t_file_wild_card; | ||||
| inline t_file_wild_card& get_file_wild_card() { | ||||
|  | @ -70,9 +74,11 @@ void set_wxapp(wxApp *app); | |||
| void set_main_frame(wxFrame *main_frame); | ||||
| void set_tab_panel(wxNotebook *tab_panel); | ||||
| void set_app_config(AppConfig *app_config); | ||||
| void set_preset_bundle(PresetBundle *preset_bundle); | ||||
| 
 | ||||
| AppConfig*	get_app_config(); | ||||
| wxApp*		get_app(); | ||||
| wxColour*	get_modified_label_clr(); | ||||
| 
 | ||||
| void add_debug_menu(wxMenuBar *menu, int event_language_change); | ||||
| 
 | ||||
|  | @ -80,14 +86,13 @@ void add_debug_menu(wxMenuBar *menu, int event_language_change); | |||
| void open_preferences_dialog(int event_preferences); | ||||
| 
 | ||||
| // Create a new preset tab (print, filament and printer),
 | ||||
| void create_preset_tabs(PresetBundle *preset_bundle,  | ||||
| 						bool no_controller, bool is_disabled_button_browse,	bool is_user_agent, | ||||
| void create_preset_tabs(bool no_controller, bool is_disabled_button_browse,	bool is_user_agent, | ||||
| 						int event_value_change, int event_presets_changed, | ||||
| 						int event_button_browse, int event_button_test); | ||||
| TabIface* get_preset_tab_iface(char *name); | ||||
| 
 | ||||
| // add it at the end of the tab panel.
 | ||||
| void add_created_tab(Tab* panel, PresetBundle *preset_bundle); | ||||
| void add_created_tab(Tab* panel); | ||||
| // Change option value in config
 | ||||
| void change_opt_value(DynamicPrintConfig& config, t_config_option_key opt_key, boost::any value, int opt_index = 0); | ||||
| 
 | ||||
|  | @ -118,12 +123,16 @@ void create_combochecklist(wxComboCtrl* comboCtrl, std::string text, std::string | |||
| int combochecklist_get_flags(wxComboCtrl* comboCtrl); | ||||
| 
 | ||||
| // Return translated std::string as a wxString
 | ||||
| wxString	L_str(std::string str); | ||||
| wxString	L_str(const std::string &str); | ||||
| // Return wxString from std::string in UTF8
 | ||||
| wxString	from_u8(std::string str); | ||||
| wxString	from_u8(const std::string &str); | ||||
| 
 | ||||
| wxWindow *get_widget_by_id(int id); | ||||
| 
 | ||||
| void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFlexGridSizer* preset_sizer); | ||||
| 
 | ||||
| ConfigOptionsGroup* get_optgroup(); | ||||
| 
 | ||||
| } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,18 +3,21 @@ | |||
| 
 | ||||
| #include <utility> | ||||
| #include <wx/numformatter.h> | ||||
| #include <boost/algorithm/string/split.hpp> | ||||
| #include <boost/algorithm/string/classification.hpp> | ||||
| #include "Utils.hpp" | ||||
| 
 | ||||
| namespace Slic3r { namespace GUI { | ||||
| 
 | ||||
| const t_field& OptionsGroup::build_field(const Option& opt) { | ||||
|     return build_field(opt.opt_id, opt.opt); | ||||
| const t_field& OptionsGroup::build_field(const Option& opt, wxStaticText* label/* = nullptr*/) { | ||||
|     return build_field(opt.opt_id, opt.opt, label); | ||||
| } | ||||
| const t_field& OptionsGroup::build_field(const t_config_option_key& id) { | ||||
| const t_field& OptionsGroup::build_field(const t_config_option_key& id, wxStaticText* label/* = nullptr*/) { | ||||
| 	const ConfigOptionDef& opt = m_options.at(id).opt; | ||||
|     return build_field(id, opt); | ||||
|     return build_field(id, opt, label); | ||||
| } | ||||
| 
 | ||||
| const t_field& OptionsGroup::build_field(const t_config_option_key& id, const ConfigOptionDef& opt) { | ||||
| const t_field& OptionsGroup::build_field(const t_config_option_key& id, const ConfigOptionDef& opt, wxStaticText* label/* = nullptr*/) { | ||||
|     // Check the gui_type field first, fall through
 | ||||
|     // is the normal type.
 | ||||
|     if (opt.gui_type.compare("select") == 0) { | ||||
|  | @ -72,7 +75,16 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co | |||
| 				this->on_kill_focus(); | ||||
| 	}; | ||||
|     field->m_parent = parent(); | ||||
|     // assign function objects for callbacks, etc.
 | ||||
| 	 | ||||
| 	//! Label to change background color, when option is modified
 | ||||
| 	field->m_Label = label; | ||||
| 	field->m_back_to_initial_value = [this](std::string opt_id){ | ||||
| 		if (!this->m_disabled) | ||||
| 			this->back_to_initial_value(opt_id); | ||||
| 	}; | ||||
| 	if (!m_is_tab_opt) field->m_Undo_btn->Hide(); | ||||
|      | ||||
| 	// assign function objects for callbacks, etc.
 | ||||
|     return field; | ||||
| } | ||||
| 
 | ||||
|  | @ -100,6 +112,7 @@ void OptionsGroup::append_line(const Line& line) { | |||
| 		const auto& option = option_set.front(); | ||||
| 		const auto& field = build_field(option); | ||||
| 
 | ||||
| 		sizer->Add(field->m_Undo_btn); | ||||
| 		if (is_window_field(field)) | ||||
| 			sizer->Add(field->getWindow(), 0, wxEXPAND | wxALL, wxOSX ? 0 : 5); | ||||
| 		if (is_sizer_field(field)) | ||||
|  | @ -110,8 +123,9 @@ void OptionsGroup::append_line(const Line& line) { | |||
|     auto grid_sizer = m_grid_sizer; | ||||
| 
 | ||||
|     // Build a label if we have it
 | ||||
| 	wxStaticText* label=nullptr; | ||||
|     if (label_width != 0) { | ||||
| 		auto label = new wxStaticText(parent(), wxID_ANY, line.label + (line.label.IsEmpty() ? "" : ":"),  | ||||
| 		label = new wxStaticText(parent(), wxID_ANY, line.label + (line.label.IsEmpty() ? "" : ":"),  | ||||
| 							wxDefaultPosition, wxSize(label_width, -1)); | ||||
|         label->SetFont(label_font); | ||||
|         label->Wrap(label_width); // avoid a Linux/GTK bug
 | ||||
|  | @ -128,25 +142,24 @@ void OptionsGroup::append_line(const Line& line) { | |||
| 	} | ||||
| 	 | ||||
| 	// if we have a single option with no sidetext just add it directly to the grid sizer
 | ||||
|     if (option_set.size() == 1 && option_set.front().opt.sidetext.size() == 0 && | ||||
|         option_set.front().side_widget == nullptr && line.get_extra_widgets().size() == 0) { | ||||
|         const auto& option = option_set.front(); | ||||
|         const auto& field = build_field(option); | ||||
| //!         std::cerr << "single option, no sidetext.\n";
 | ||||
| //!         std::cerr << "field parent is not null?: " << (field->parent != nullptr) << "\n";
 | ||||
| 	auto sizer = new wxBoxSizer(wxHORIZONTAL); | ||||
| 	grid_sizer->Add(sizer, 0, wxEXPAND | wxALL, 0); | ||||
| 	if (option_set.size() == 1 && option_set.front().opt.sidetext.size() == 0 && | ||||
| 		option_set.front().side_widget == nullptr && line.get_extra_widgets().size() == 0) { | ||||
| 		const auto& option = option_set.front(); | ||||
| 		const auto& field = build_field(option, label); | ||||
| 
 | ||||
|         if (is_window_field(field))  | ||||
| 			grid_sizer->Add(field->getWindow(), 0, (option.opt.full_width ? wxEXPAND : 0) | | ||||
| 		sizer->Add(field->m_Undo_btn, 0, wxALIGN_CENTER_VERTICAL); | ||||
| 		if (is_window_field(field))  | ||||
| 			sizer->Add(field->getWindow(), 0, (option.opt.full_width ? wxEXPAND : 0) | | ||||
| 							wxBOTTOM | wxTOP | wxALIGN_CENTER_VERTICAL, wxOSX ? 0 : 2); | ||||
|         if (is_sizer_field(field))  | ||||
|             grid_sizer->Add(field->getSizer(), 0, (option.opt.full_width ? wxEXPAND : 0) | wxALIGN_CENTER_VERTICAL, 0); | ||||
|         return; | ||||
|     } | ||||
| 		if (is_sizer_field(field))  | ||||
| 			sizer->Add(field->getSizer(), 0, (option.opt.full_width ? wxEXPAND : 0) | wxALIGN_CENTER_VERTICAL, 0); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
|     // if we're here, we have more than one option or a single option with sidetext
 | ||||
|     // so we need a horizontal sizer to arrange these things
 | ||||
|     auto sizer = new wxBoxSizer(wxHORIZONTAL); | ||||
| 	grid_sizer->Add(sizer, 0, wxEXPAND | wxALL, 0); | ||||
| 	for (auto opt : option_set) { | ||||
| 		ConfigOptionDef option = opt.opt; | ||||
| 		// add label if any
 | ||||
|  | @ -156,14 +169,15 @@ void OptionsGroup::append_line(const Line& line) { | |||
| // 			wxString str_label = (option.label == "Top" || option.label == "Bottom") ?
 | ||||
| // 								wxGETTEXT_IN_CONTEXT("Layers", wxString(option.label.c_str()):
 | ||||
| // 								L_str(option.label);
 | ||||
| 			auto field_label = new wxStaticText(parent(), wxID_ANY, str_label + ":", wxDefaultPosition, wxDefaultSize); | ||||
| 			field_label->SetFont(label_font); | ||||
| 			sizer->Add(field_label, 0, wxALIGN_CENTER_VERTICAL, 0); | ||||
| 			label = new wxStaticText(parent(), wxID_ANY, str_label + ":", wxDefaultPosition, wxDefaultSize); | ||||
| 			label->SetFont(label_font); | ||||
| 			sizer->Add(label, 0, wxALIGN_CENTER_VERTICAL, 0); | ||||
| 		} | ||||
| 
 | ||||
| 		// add field
 | ||||
| 		const Option& opt_ref = opt; | ||||
| 		auto& field = build_field(opt_ref); | ||||
| 		auto& field = build_field(opt_ref, label); | ||||
| 		sizer->Add(field->m_Undo_btn, 0, wxALIGN_CENTER_VERTICAL, 0); | ||||
| 		is_sizer_field(field) ?  | ||||
| 			sizer->Add(field->getSizer(), 0, wxALIGN_CENTER_VERTICAL, 0) : | ||||
| 			sizer->Add(field->getWindow(), 0, wxALIGN_CENTER_VERTICAL, 0); | ||||
|  | @ -244,6 +258,12 @@ void ConfigOptionsGroup::on_change_OG(t_config_option_key opt_id, boost::any val | |||
| 			// 		# Currently used for the post_process config value only.
 | ||||
| 			// 		my @values = split / ; / , $field_value;
 | ||||
| 			// 		$self->config->set($opt_key, \@values);
 | ||||
| 			std::string str = boost::any_cast<std::string>(value); | ||||
| 			if (str.back() == ';') | ||||
| 				str.pop_back(); | ||||
| 			std::vector<std::string> values; | ||||
| 			boost::split(values, str, boost::is_any_of(";")); | ||||
| 			change_opt_value(*m_config, opt_key, values); | ||||
| 		} | ||||
| 		else { | ||||
| 			if (opt_index == -1) { | ||||
|  | @ -263,6 +283,30 @@ void ConfigOptionsGroup::on_change_OG(t_config_option_key opt_id, boost::any val | |||
| 	OptionsGroup::on_change_OG(opt_id, value); //!? Why doing this
 | ||||
| } | ||||
| 
 | ||||
| void ConfigOptionsGroup::back_to_initial_value(const std::string opt_key) | ||||
| { | ||||
| 	if (m_get_initial_config == nullptr) | ||||
| 		return; | ||||
| 	DynamicPrintConfig config = m_get_initial_config(); | ||||
| 	boost::any value; | ||||
| 	if (opt_key == "extruders_count"){ | ||||
| 		auto   *nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(config.option("nozzle_diameter")); | ||||
| 		value = int(nozzle_diameter->values.size()); | ||||
| 	} | ||||
| 	else if (m_opt_map.find(opt_key) != m_opt_map.end()) | ||||
| 	{ | ||||
| 		auto opt_id = m_opt_map.find(opt_key)->first; | ||||
| 		std::string opt_short_key = m_opt_map.at(opt_id).first; | ||||
| 		int opt_index = m_opt_map.at(opt_id).second; | ||||
| 		value = get_config_value(config, opt_short_key, opt_index); | ||||
| 	} | ||||
| 	else | ||||
| 		value = get_config_value(config, opt_key); | ||||
| 
 | ||||
| 	set_value(opt_key, value); | ||||
| 	on_change_OG(opt_key, get_value(opt_key)); | ||||
| } | ||||
| 
 | ||||
| void ConfigOptionsGroup::reload_config(){ | ||||
| 	for (std::map< std::string, std::pair<std::string, int> >::iterator it = m_opt_map.begin(); it != m_opt_map.end(); ++it) { | ||||
| 		auto opt_id = it->first; | ||||
|  | @ -323,7 +367,7 @@ boost::any ConfigOptionsGroup::get_config_value(DynamicPrintConfig& config, std: | |||
| 		double val = opt->type == coFloats ? | ||||
| 					config.opt_float(opt_key, idx) : | ||||
| 						opt->type == coFloat ? config.opt_float(opt_key) : | ||||
| 						config.option<ConfigOptionPercents>(opt_key)->values.at(idx); | ||||
| 						config.option<ConfigOptionPercents>(opt_key)->get_at(idx); | ||||
| 		ret = double_to_string(val); | ||||
| 		} | ||||
| 		break; | ||||
|  | @ -333,6 +377,12 @@ boost::any ConfigOptionsGroup::get_config_value(DynamicPrintConfig& config, std: | |||
| 	case coStrings: | ||||
| 		if (config.option<ConfigOptionStrings>(opt_key)->values.empty()) | ||||
| 			ret = text_value; | ||||
| 		else if (opt->gui_flags.compare("serialized") == 0){ | ||||
| 			std::vector<std::string> values = config.option<ConfigOptionStrings>(opt_key)->values; | ||||
| 			for (auto el : values) | ||||
| 				text_value += el + ";"; | ||||
| 			ret = text_value; | ||||
| 		} | ||||
| 		else | ||||
| 			ret = static_cast<wxString>(config.opt_string(opt_key, static_cast<unsigned int>(idx))); | ||||
| 		break; | ||||
|  | @ -363,10 +413,8 @@ boost::any ConfigOptionsGroup::get_config_value(DynamicPrintConfig& config, std: | |||
| 			ret = static_cast<int>(config.option<ConfigOptionEnum<SeamPosition>>(opt_key)->value); | ||||
| 	} | ||||
| 		break; | ||||
| 	case coPoints:{ | ||||
| 		const auto &value = *config.option<ConfigOptionPoints>(opt_key); | ||||
| 		ret = value.values.at(idx); | ||||
| 		} | ||||
| 	case coPoints: | ||||
| 		ret = config.option<ConfigOptionPoints>(opt_key)->get_at(idx); | ||||
| 		break; | ||||
| 	case coNone: | ||||
| 	default: | ||||
|  | @ -376,6 +424,9 @@ boost::any ConfigOptionsGroup::get_config_value(DynamicPrintConfig& config, std: | |||
| } | ||||
| 
 | ||||
| Field* ConfigOptionsGroup::get_fieldc(t_config_option_key opt_key, int opt_index){ | ||||
| 	Field* field = get_field(opt_key); | ||||
| 	if (field != nullptr) | ||||
| 		return field; | ||||
| 	std::string opt_id = ""; | ||||
| 	for (std::map< std::string, std::pair<std::string, int> >::iterator it = m_opt_map.begin(); it != m_opt_map.end(); ++it) { | ||||
| 		if (opt_key == m_opt_map.at(it->first).first && opt_index == m_opt_map.at(it->first).second){ | ||||
|  |  | |||
|  | @ -27,6 +27,9 @@ namespace Slic3r { namespace GUI { | |||
| using widget_t = std::function<wxSizer*(wxWindow*)>;//!std::function<wxWindow*(wxWindow*)>;
 | ||||
| using column_t = std::function<wxSizer*(const Line&)>; | ||||
| 
 | ||||
| //auto default_label_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT); //GetSystemColour
 | ||||
| //auto modified_label_clr = *new wxColour(254, 189, 101);
 | ||||
| 
 | ||||
| /// Wraps a ConfigOptionDef and adds function object for creating a side_widget.
 | ||||
| struct Option { | ||||
| 	ConfigOptionDef			opt { ConfigOptionDef() }; | ||||
|  | @ -75,6 +78,7 @@ public: | |||
|     wxSizer*		sizer {nullptr}; | ||||
|     column_t		extra_column {nullptr}; | ||||
|     t_change		m_on_change {nullptr}; | ||||
| 	std::function<DynamicPrintConfig()>	m_get_initial_config{ nullptr }; | ||||
| 
 | ||||
|     wxFont			sidetext_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) }; | ||||
|     wxFont			label_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) }; | ||||
|  | @ -109,8 +113,8 @@ public: | |||
| 	inline void		enable() { for (auto& field : m_fields) field.second->enable(); } | ||||
|     inline void		disable() { for (auto& field : m_fields) field.second->disable(); } | ||||
| 
 | ||||
|     OptionsGroup(wxWindow* _parent, wxString title) :  | ||||
| 		m_parent(_parent), title(title) { | ||||
|     OptionsGroup(wxWindow* _parent, wxString title, bool is_tab_opt=false) :  | ||||
| 		m_parent(_parent), title(title), m_is_tab_opt(is_tab_opt), staticbox(title!="") { | ||||
|         sizer = (staticbox ? new wxStaticBoxSizer(new wxStaticBox(_parent, wxID_ANY, title), wxVERTICAL) : new wxBoxSizer(wxVERTICAL)); | ||||
|         auto num_columns = 1U; | ||||
|         if (label_width != 0) num_columns++; | ||||
|  | @ -132,22 +136,25 @@ protected: | |||
|     t_optionfield_map		m_fields; | ||||
|     bool					m_disabled {false}; | ||||
|     wxGridSizer*			m_grid_sizer {nullptr}; | ||||
| 	// "true" if option is created in preset tabs
 | ||||
| 	bool					m_is_tab_opt{ false }; | ||||
| 
 | ||||
|     /// Generate a wxSizer or wxWindow from a configuration option
 | ||||
|     /// Precondition: opt resolves to a known ConfigOption
 | ||||
|     /// Postcondition: fields contains a wx gui object.
 | ||||
|     const t_field&		build_field(const t_config_option_key& id, const ConfigOptionDef& opt); | ||||
|     const t_field&		build_field(const t_config_option_key& id); | ||||
|     const t_field&		build_field(const Option& opt); | ||||
| 	const t_field&		build_field(const t_config_option_key& id, const ConfigOptionDef& opt, wxStaticText* label = nullptr); | ||||
| 	const t_field&		build_field(const t_config_option_key& id, wxStaticText* label = nullptr); | ||||
| 	const t_field&		build_field(const Option& opt, wxStaticText* label = nullptr); | ||||
| 
 | ||||
|     virtual void		on_kill_focus (){}; | ||||
| 	virtual void		on_change_OG(t_config_option_key opt_id, boost::any value); | ||||
| 	virtual void		back_to_initial_value(const std::string opt_key){}; | ||||
| }; | ||||
| 
 | ||||
| class ConfigOptionsGroup: public OptionsGroup { | ||||
| public: | ||||
| 	ConfigOptionsGroup(wxWindow* parent, wxString title, DynamicPrintConfig* _config = nullptr) :  | ||||
| 		OptionsGroup(parent, title), m_config(_config) {} | ||||
| 	ConfigOptionsGroup(wxWindow* parent, wxString title, DynamicPrintConfig* _config = nullptr, bool is_tab_opt = false) : | ||||
| 		OptionsGroup(parent, title, is_tab_opt), m_config(_config) {} | ||||
| 
 | ||||
|     /// reference to libslic3r config, non-owning pointer (?).
 | ||||
|     DynamicPrintConfig*		m_config {nullptr}; | ||||
|  | @ -169,10 +176,8 @@ public: | |||
| 	} | ||||
| 
 | ||||
| 	void		on_change_OG(t_config_option_key opt_id, boost::any value) override; | ||||
| 	void		on_kill_focus() override | ||||
| 	{ | ||||
| 		reload_config(); | ||||
| 	} | ||||
| 	void		back_to_initial_value(const std::string opt_key) override; | ||||
| 	void		on_kill_focus() override{ reload_config();} | ||||
| 	void		reload_config(); | ||||
| 	boost::any	config_value(std::string opt_key, int opt_index, bool deserialize); | ||||
| 	// return option value from config 
 | ||||
|  |  | |||
|  | @ -13,10 +13,11 @@ | |||
| 
 | ||||
| namespace Slic3r { | ||||
| 
 | ||||
| #define MIN_BUF_LENGTH	4096 | ||||
| std::string PresetHints::cooling_description(const Preset &preset) | ||||
| { | ||||
| 	std::string out; | ||||
| 	char buf[4096]; | ||||
| 	char buf[MIN_BUF_LENGTH/*4096*/]; | ||||
| 	if (preset.config.opt_bool("cooling", 0)) { | ||||
| 		int 	slowdown_below_layer_time 	= preset.config.opt_int("slowdown_below_layer_time", 0); | ||||
| 		int 	min_fan_speed 				= preset.config.opt_int("min_fan_speed", 0); | ||||
|  | @ -220,7 +221,7 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle | |||
|             + _CHB(L(" with a volumetric rate ")); | ||||
|         if (limited_by_max_volumetric_speed) | ||||
|             max_flow = max_volumetric_speed; | ||||
|         char buf[2048]; | ||||
| 		char buf[MIN_BUF_LENGTH/*2048*/]; | ||||
|         sprintf(buf, _CHB(L("%3.2f mm³/s")), max_flow); | ||||
|         out += buf; | ||||
|         sprintf(buf, _CHB(L(" at filament speed %3.2f mm/s.")), max_flow / filament_crossection); | ||||
|  | @ -258,7 +259,7 @@ std::string PresetHints::recommended_thin_wall_thickness(const PresetBundle &pre | |||
|      | ||||
|     if (num_perimeters > 0) { | ||||
|         int num_lines = std::min(num_perimeters * 2, 10); | ||||
|         char buf[256]; | ||||
| 		char buf[MIN_BUF_LENGTH/*256*/]; | ||||
|         sprintf(buf, _CHB(L("Recommended object thin wall thickness for layer height %.2f and ")), layer_height); | ||||
|         out += buf; | ||||
|         // Start with the width of two closely spaced 
 | ||||
|  |  | |||
|  | @ -33,19 +33,23 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle) | |||
| 
 | ||||
| 	// preset chooser
 | ||||
| 	m_presets_choice = new wxBitmapComboBox(panel, wxID_ANY, "", wxDefaultPosition, wxSize(270, -1), 0, 0,wxCB_READONLY); | ||||
| 	const wxBitmap* bmp = new wxBitmap(from_u8(Slic3r::var("flag-green-icon.png")), wxBITMAP_TYPE_PNG); | ||||
| 
 | ||||
| 	auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); | ||||
| 
 | ||||
| 	//buttons
 | ||||
| 	wxBitmap bmpMenu; | ||||
| 	bmpMenu = wxBitmap(from_u8(Slic3r::var("disk.png")), wxBITMAP_TYPE_PNG); | ||||
| 	m_btn_save_preset = new wxBitmapButton(panel, wxID_ANY, bmpMenu, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE); | ||||
| 	if (wxMSW) m_btn_save_preset->SetBackgroundColour(color); | ||||
| 	bmpMenu = wxBitmap(from_u8(Slic3r::var("delete.png")), wxBITMAP_TYPE_PNG); | ||||
| 	m_btn_delete_preset = new wxBitmapButton(panel, wxID_ANY, bmpMenu, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE); | ||||
| 	if (wxMSW) m_btn_delete_preset->SetBackgroundColour(color); | ||||
| 
 | ||||
| 	m_show_incompatible_presets = false; | ||||
| 	m_bmp_show_incompatible_presets = new wxBitmap(from_u8(Slic3r::var("flag-red-icon.png")), wxBITMAP_TYPE_PNG); | ||||
| 	m_bmp_hide_incompatible_presets = new wxBitmap(from_u8(Slic3r::var("flag-green-icon.png")), wxBITMAP_TYPE_PNG); | ||||
| 	m_btn_hide_incompatible_presets = new wxBitmapButton(panel, wxID_ANY, *m_bmp_hide_incompatible_presets, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE); | ||||
| 	if (wxMSW) m_btn_hide_incompatible_presets->SetBackgroundColour(color); | ||||
| 
 | ||||
| 	m_btn_save_preset->SetToolTip(_(L("Save current ")) + m_title); | ||||
| 	m_btn_delete_preset->SetToolTip(_(L("Delete this preset"))); | ||||
|  | @ -93,6 +97,7 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle) | |||
| 		if (selected_item >= 0){ | ||||
| 			std::string selected_string = m_presets_choice->GetString(selected_item).ToUTF8().data(); | ||||
| 			select_preset(selected_string); | ||||
| 			update_changed_ui(); | ||||
| 		} | ||||
| 	})); | ||||
| 
 | ||||
|  | @ -134,11 +139,93 @@ PageShp Tab::add_options_page(wxString title, std::string icon, bool is_extruder | |||
| 	return page; | ||||
| } | ||||
| 
 | ||||
| template<class T> | ||||
| void add_correct_opts_to_dirty_options(const std::string &opt_key, std::vector<std::string> *vec, TabPrinter *tab) | ||||
| { | ||||
| 	auto opt_init = static_cast<T*>(tab->m_presets->get_selected_preset().config.option(opt_key)); | ||||
| 	auto opt_cur = static_cast<T*>(tab->m_config->option(opt_key)); | ||||
| 	int opt_init_max_id = opt_init->values.size()-1; | ||||
| 	for (int i = 0; i < opt_cur->values.size(); i++) | ||||
| 	{ | ||||
| 		int init_id = i <= opt_init_max_id ? i : 0; | ||||
| 		if (opt_cur->values[i] != opt_init->values[init_id]) | ||||
| 			vec->emplace_back(opt_key + "#" + std::to_string(i)); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Update UI according to changes
 | ||||
| void Tab::update_changed_ui() | ||||
| { | ||||
| 	auto dirty_options = m_presets->current_dirty_options(); | ||||
| 
 | ||||
| 	if (name() == "printer"){ | ||||
| 		// Update dirty_options in case changes of Extruder's options 
 | ||||
| 		TabPrinter* tab = static_cast<TabPrinter*>(this); | ||||
| 		std::vector<std::string> new_dirty; | ||||
| 		for (auto opt_key : dirty_options) | ||||
| 		{ | ||||
| 			switch (m_config->option(opt_key)->type()) | ||||
| 			{ | ||||
| 			case coInts:	add_correct_opts_to_dirty_options<ConfigOptionInts		>(opt_key, &new_dirty, tab);	break; | ||||
| 			case coBools:	add_correct_opts_to_dirty_options<ConfigOptionBools		>(opt_key, &new_dirty, tab);	break; | ||||
| 			case coFloats:	add_correct_opts_to_dirty_options<ConfigOptionFloats	>(opt_key, &new_dirty, tab);	break; | ||||
| 			case coStrings:	add_correct_opts_to_dirty_options<ConfigOptionStrings	>(opt_key, &new_dirty, tab);	break; | ||||
| 			case coPercents:add_correct_opts_to_dirty_options<ConfigOptionPercents	>(opt_key, &new_dirty, tab);	break; | ||||
| 			case coPoints:	add_correct_opts_to_dirty_options<ConfigOptionPoints	>(opt_key, &new_dirty, tab);	break; | ||||
| 			default:		new_dirty.emplace_back(opt_key);		break; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		dirty_options.resize(0); | ||||
| 		dirty_options = new_dirty; | ||||
| 		if (tab->m_initial_extruders_count != tab->m_extruders_count){ | ||||
| 			dirty_options.emplace_back("extruders_count"); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// Add new dirty options to m_dirty_options
 | ||||
| 	for (auto opt_key : dirty_options){ | ||||
| 		Field* field = get_field(opt_key); | ||||
| 		if (field != nullptr && find(m_dirty_options.begin(), m_dirty_options.end(), opt_key) == m_dirty_options.end()){ | ||||
| 			if (field->m_Label != nullptr){ | ||||
| 				field->m_Label->SetForegroundColour(*get_modified_label_clr()); | ||||
| 				field->m_Label->Refresh(true); | ||||
| 			} | ||||
| 			field->m_Undo_btn->SetBitmap(wxBitmap(from_u8(wxMSW ? var("action_undo.png") : var("arrow_undo.png")), wxBITMAP_TYPE_PNG)); | ||||
| 			field->m_is_modified_value = true; | ||||
| 
 | ||||
| 			m_dirty_options.push_back(opt_key); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// Delete clear options from m_dirty_options
 | ||||
| 	for (auto i = 0; i < m_dirty_options.size(); ++i) | ||||
| 	{ | ||||
| 		const std::string &opt_key = m_dirty_options[i]; | ||||
| 		Field* field = get_field(opt_key); | ||||
| 		if (field != nullptr && find(dirty_options.begin(), dirty_options.end(), opt_key) == dirty_options.end()) | ||||
| 		{ | ||||
| 			field->m_Undo_btn->SetBitmap(wxBitmap(from_u8(var("bullet_white.png")), wxBITMAP_TYPE_PNG)); | ||||
| 			if (field->m_Label != nullptr){ | ||||
| 				field->m_Label->SetForegroundColour(wxSYS_COLOUR_WINDOWTEXT); | ||||
| 				field->m_Label->Refresh(true); | ||||
| 			} | ||||
| 			field->m_is_modified_value = false; | ||||
| 			std::vector<std::string>::iterator itr = find(m_dirty_options.begin(), m_dirty_options.end(), opt_key); | ||||
| 			if (itr != m_dirty_options.end()){ | ||||
| 				m_dirty_options.erase(itr); | ||||
| 				--i; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Update the combo box label of the selected preset based on its "dirty" state,
 | ||||
| // comparing the selected preset config with $self->{config}.
 | ||||
| void Tab::update_dirty(){ | ||||
| 	m_presets->update_dirty_ui(m_presets_choice); | ||||
| 	on_presets_changed(); | ||||
| 	on_presets_changed();	 | ||||
| 	update_changed_ui(); | ||||
| } | ||||
| 
 | ||||
| void Tab::update_tab_ui() | ||||
|  | @ -146,81 +233,13 @@ void Tab::update_tab_ui() | |||
| 	m_presets->update_tab_ui(m_presets_choice, m_show_incompatible_presets); | ||||
| } | ||||
| 
 | ||||
| template<class T> | ||||
| boost::any get_new_value(const DynamicPrintConfig &config_new, const DynamicPrintConfig &config_old, std::string opt_key, int &index) | ||||
| { | ||||
| 	for (int i = 0; i < config_new.option<T>(opt_key)->values.size(); i++) | ||||
| 		if (config_new.option<T>(opt_key)->values[i] != | ||||
| 			config_old.option<T>(opt_key)->values[i]){ | ||||
| 			index = i; | ||||
| 			break; | ||||
| 		} | ||||
| 	return config_new.option<T>(opt_key)->values[index]; | ||||
| } | ||||
| 
 | ||||
| // 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.
 | ||||
| void Tab::load_config(DynamicPrintConfig config) | ||||
| { | ||||
| 	bool modified = 0; | ||||
| 	boost::any value; | ||||
| 	int opt_index = 0; | ||||
| 	for(auto opt_key : m_config->diff(config)) { | ||||
| 		switch ( config.def()->get(opt_key)->type ){ | ||||
| 		case coFloatOrPercent: | ||||
| 			value = config.option<ConfigOptionFloatOrPercent>(opt_key)->value; | ||||
| 			break; | ||||
| 		case coPercent: | ||||
| 			value = config.option<ConfigOptionPercent>(opt_key)->value; | ||||
| 			break; | ||||
| 		case coFloat: | ||||
| 			value = config.opt_float(opt_key); | ||||
| 			break; | ||||
| 		case coString: | ||||
| 			value = config.opt_string(opt_key); | ||||
| 			break; | ||||
| 		case coPercents: | ||||
| 			value = get_new_value<ConfigOptionPercents>(config, *m_config, opt_key, opt_index); | ||||
| 			break; | ||||
| 		case coFloats: | ||||
| 			value = get_new_value<ConfigOptionFloats>(config, *m_config, opt_key, opt_index); | ||||
| 			break; | ||||
| 		case coStrings: | ||||
| 			value = config.option<ConfigOptionStrings>(opt_key)->values.empty() ? "" : | ||||
| 				get_new_value<ConfigOptionStrings>(config, *m_config, opt_key, opt_index); | ||||
| 			break; | ||||
| 		case coBool: | ||||
| 			value = config.opt_bool(opt_key); | ||||
| 			break; | ||||
| 		case coBools: | ||||
| 			value = get_new_value<ConfigOptionBools>(config, *m_config, opt_key, opt_index); | ||||
| 			break; | ||||
| 		case coInt: | ||||
| 			value = config.opt_int(opt_key); | ||||
| 			break; | ||||
| 		case coInts: | ||||
| 			value = get_new_value<ConfigOptionInts>(config, *m_config, opt_key, opt_index); | ||||
| 			break; | ||||
| 		case coEnum:{ | ||||
| 			if (opt_key.compare("external_fill_pattern") == 0 || | ||||
| 				opt_key.compare("fill_pattern") == 0) | ||||
| 				value = config.option<ConfigOptionEnum<InfillPattern>>(opt_key)->value; | ||||
| 			else if (opt_key.compare("gcode_flavor") == 0) | ||||
| 				value = config.option<ConfigOptionEnum<GCodeFlavor>>(opt_key)->value; | ||||
| 			else if (opt_key.compare("support_material_pattern") == 0) | ||||
| 				value = config.option<ConfigOptionEnum<SupportMaterialPattern>>(opt_key)->value; | ||||
| 			else if (opt_key.compare("seam_position") == 0) | ||||
| 				value = config.option<ConfigOptionEnum<SeamPosition>>(opt_key)->value; | ||||
| 		} | ||||
| 			break; | ||||
| 		case coPoints: | ||||
| 			break; | ||||
| 		case coNone: | ||||
| 			break; | ||||
| 		default: | ||||
| 			break; | ||||
| 		} | ||||
| 		change_opt_value(*m_config, opt_key, value, opt_index); | ||||
| 		m_config->set_key_value(opt_key, config.option(opt_key)->clone()); | ||||
| 		modified = 1; | ||||
| 	} | ||||
| 	if (modified) { | ||||
|  | @ -291,6 +310,27 @@ void Tab::on_value_change(std::string opt_key, boost::any value) | |||
| 		} | ||||
| 		g_wxMainFrame->ProcessWindowEvent(event); | ||||
| 	} | ||||
| 	if (opt_key == "fill_density") | ||||
| 	{ | ||||
| 		value = get_optgroup()->get_config_value(*m_config, opt_key); | ||||
| 		get_optgroup()->set_value(opt_key, value); | ||||
| 	} | ||||
| 	if (opt_key == "support_material" || opt_key == "support_material_buildplate_only") | ||||
| 	{ | ||||
| 		wxString new_selection = !m_config->opt_bool("support_material") ? | ||||
| 								_("None") : | ||||
| 								m_config->opt_bool("support_material_buildplate_only") ? | ||||
| 									_("Support on build plate only") : | ||||
| 									_("Everywhere"); | ||||
| 		get_optgroup()->set_value("support", new_selection); | ||||
| 	} | ||||
| 	if (opt_key == "brim_width") | ||||
| 	{ | ||||
| 		bool val = m_config->opt_float("brim_width") > 0.0 ? true : false; | ||||
| 		get_optgroup()->set_value("brim", val); | ||||
| 	} | ||||
| 
 | ||||
| 		 | ||||
| 	update(); | ||||
| } | ||||
| 
 | ||||
|  | @ -308,6 +348,22 @@ void Tab::on_presets_changed() | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| void Tab::update_frequently_changed_parameters() | ||||
| { | ||||
| 	boost::any value = get_optgroup()->get_config_value(*m_config, "fill_density"); | ||||
| 	get_optgroup()->set_value("fill_density", value); | ||||
| 
 | ||||
| 	wxString new_selection = !m_config->opt_bool("support_material") ? | ||||
| 							_("None") : | ||||
| 							m_config->opt_bool("support_material_buildplate_only") ? | ||||
| 								_("Support on build plate only") : | ||||
| 								_("Everywhere"); | ||||
| 	get_optgroup()->set_value("support", new_selection); | ||||
| 
 | ||||
| 	bool val = m_config->opt_float("brim_width") > 0.0 ? true : false; | ||||
| 	get_optgroup()->set_value("brim", val); | ||||
| } | ||||
| 
 | ||||
| void Tab::reload_compatible_printers_widget() | ||||
| { | ||||
| 	bool has_any = !m_config->option<ConfigOptionStrings>("compatible_printers")->values.empty(); | ||||
|  | @ -576,7 +632,8 @@ void TabPrint::update() | |||
| 		DynamicPrintConfig new_conf = *m_config; | ||||
| 		if (dialog->ShowModal() == wxID_YES) { | ||||
| 			const auto &val = *m_config->option<ConfigOptionFloatOrPercent>("first_layer_height"); | ||||
| 			new_conf.set_key_value("first_layer_height", new ConfigOptionFloatOrPercent(0.2, val.percent)); | ||||
| 			auto percent = val.percent; | ||||
| 			new_conf.set_key_value("first_layer_height", new ConfigOptionFloatOrPercent(0.2, percent)); | ||||
| 
 | ||||
| 			if (m_config->opt_float("layer_height") < 0.15) new_conf.set_key_value("layer_height", new ConfigOptionFloat(0.15)); | ||||
| 			if (m_config->opt_float("layer_height") > 0.35) new_conf.set_key_value("layer_height", new ConfigOptionFloat(0.35)); | ||||
|  | @ -674,13 +731,16 @@ void TabPrint::update() | |||
| 					"\nShall I switch to rectilinear fill pattern?")); | ||||
| 				auto dialog = new wxMessageDialog(parent(), msg_text, _(L("Infill")), wxICON_WARNING | wxYES | wxNO); | ||||
| 				DynamicPrintConfig new_conf = *m_config; | ||||
| 				double fill_density; | ||||
| 				if (dialog->ShowModal() == wxID_YES) { | ||||
| 					new_conf.set_key_value("fill_pattern", new ConfigOptionEnum<InfillPattern>(ipRectilinear)); | ||||
| 					new_conf.set_key_value("fill_density", new ConfigOptionPercent(100)); | ||||
| 					fill_density = 100; | ||||
| 				} | ||||
| 				else | ||||
| 					new_conf.set_key_value("fill_density", new ConfigOptionPercent(40)); | ||||
| 					fill_density = 40; | ||||
| 				new_conf.set_key_value("fill_density", new ConfigOptionPercent(fill_density)); | ||||
| 				load_config(new_conf); | ||||
| 				on_value_change("fill_density", fill_density); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | @ -943,14 +1003,14 @@ void TabPrinter::build() | |||
| 	auto default_config = m_preset_bundle->full_config(); | ||||
| 
 | ||||
| 	auto   *nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(m_config->option("nozzle_diameter")); | ||||
| 	m_extruders_count = nozzle_diameter->values.size(); | ||||
| 	m_initial_extruders_count = m_extruders_count = nozzle_diameter->values.size(); | ||||
| 
 | ||||
| 	auto page = add_options_page(_(L("General")), "printer_empty.png"); | ||||
| 		auto optgroup = page->new_optgroup(_(L("Size and coordinates"))); | ||||
| 
 | ||||
| 		Line line{ _(L("Bed shape")), "" }; | ||||
| 		line.widget = [this](wxWindow* parent){ | ||||
| 	auto btn = new wxButton(parent, wxID_ANY, _(L(" Set "))+"\u2026", wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); | ||||
| 			auto btn = new wxButton(parent, wxID_ANY, _(L(" Set "))+"\u2026", wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); | ||||
| 			//			btn->SetFont(Slic3r::GUI::small_font);
 | ||||
| 			btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("printer_empty.png")), wxBITMAP_TYPE_PNG)); | ||||
| 
 | ||||
|  | @ -1188,6 +1248,7 @@ void TabPrinter::extruders_count_changed(size_t extruders_count){ | |||
| 	m_preset_bundle->printers.get_edited_preset().set_num_extruders(extruders_count); | ||||
| 	m_preset_bundle->update_multi_material_filament_presets(); | ||||
| 	build_extruder_pages(); | ||||
| 	reload_config(); | ||||
| 	on_value_change("extruders_count", extruders_count); | ||||
| } | ||||
| 
 | ||||
|  | @ -1326,8 +1387,9 @@ void TabPrinter::update(){ | |||
| 
 | ||||
| 			DynamicPrintConfig new_conf = *m_config; | ||||
| 			if (dialog->ShowModal() == wxID_YES) { | ||||
| 				auto wipe = static_cast<ConfigOptionBools*>(m_config->option("wipe")); | ||||
| 				wipe->values[i] = 0; | ||||
| 				auto wipe = static_cast<ConfigOptionBools*>(m_config->option("wipe")->clone()); | ||||
| 				for (int w = 0; w < wipe->values.size(); w++) | ||||
| 					wipe->values[w] = false; | ||||
| 				new_conf.set_key_value("wipe", wipe); | ||||
| 			} | ||||
| 			else { | ||||
|  | @ -1350,15 +1412,13 @@ void TabPrinter::update(){ | |||
| void Tab::load_current_preset() | ||||
| { | ||||
| 	auto preset = m_presets->get_edited_preset(); | ||||
| //	try{
 | ||||
| //		local $SIG{ __WARN__ } = Slic3r::GUI::warning_catcher($self);
 | ||||
| 		preset.is_default ? m_btn_delete_preset->Disable() : m_btn_delete_preset->Enable(true); | ||||
| 		update(); | ||||
| 		// For the printer profile, generate the extruder pages.
 | ||||
| 		on_preset_loaded(); | ||||
| 		// Reload preset pages with the new configuration values.
 | ||||
| 		reload_config(); | ||||
| //	};
 | ||||
| 	preset.is_default ? m_btn_delete_preset->Disable() : m_btn_delete_preset->Enable(true); | ||||
| 	update(); | ||||
| 	// For the printer profile, generate the extruder pages.
 | ||||
| 	on_preset_loaded(); | ||||
| 	// Reload preset pages with the new configuration values.
 | ||||
| 	reload_config(); | ||||
| 
 | ||||
| 	// 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
 | ||||
|  | @ -1369,6 +1429,11 @@ void Tab::load_current_preset() | |||
| 			return; | ||||
| 		update_tab_ui(); | ||||
| 		on_presets_changed(); | ||||
| 
 | ||||
| 		if (name() == "print"){ | ||||
| 			update_frequently_changed_parameters(); | ||||
| 			update_changed_ui(); | ||||
| 		} | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
|  | @ -1737,7 +1802,7 @@ bool Page::set_value(t_config_option_key opt_key, boost::any value){ | |||
| ConfigOptionsGroupShp Page::new_optgroup(wxString title, int noncommon_label_width /*= -1*/) | ||||
| { | ||||
| 	//! config_ have to be "right"
 | ||||
| 	ConfigOptionsGroupShp optgroup = std::make_shared<ConfigOptionsGroup>(this, title, m_config); | ||||
| 	ConfigOptionsGroupShp optgroup = std::make_shared<ConfigOptionsGroup>(this, title, m_config, true); | ||||
| 	if (noncommon_label_width >= 0) | ||||
| 		optgroup->label_width = noncommon_label_width; | ||||
| 
 | ||||
|  | @ -1751,6 +1816,11 @@ ConfigOptionsGroupShp Page::new_optgroup(wxString title, int noncommon_label_wid | |||
| //!        });
 | ||||
| 	}; | ||||
| 
 | ||||
| 	optgroup->m_get_initial_config = [this](){ | ||||
| 		DynamicPrintConfig config = static_cast<Tab*>(GetParent())->m_presets->get_selected_preset().config; | ||||
| 		return config; | ||||
| 	}; | ||||
| 
 | ||||
| 	vsizer()->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 10); | ||||
| 	m_optgroups.push_back(optgroup); | ||||
| 
 | ||||
|  |  | |||
|  | @ -99,6 +99,7 @@ protected: | |||
| 	bool				m_no_controller; | ||||
| 
 | ||||
| 	std::vector<std::string>	m_reload_dependent_tabs = {}; | ||||
| 	std::vector<std::string>	m_dirty_options = {}; | ||||
| 
 | ||||
| 	// The two following two event IDs are generated at Plater.pm by calling Wx::NewEventType.
 | ||||
| 	wxEventType			m_event_value_change = 0; | ||||
|  | @ -145,6 +146,7 @@ public: | |||
| 	void		toggle_show_hide_incompatible(); | ||||
| 	void		update_show_hide_incompatible_button(); | ||||
| 	void		update_ui_from_settings(); | ||||
| 	void		update_changed_ui(); | ||||
| 	 | ||||
| 	PageShp		add_options_page(wxString title, std::string icon, bool is_extruder_pages = false); | ||||
| 
 | ||||
|  | @ -171,6 +173,7 @@ public: | |||
| 
 | ||||
| protected: | ||||
| 	void			on_presets_changed(); | ||||
| 	void			update_frequently_changed_parameters(); | ||||
| }; | ||||
| 
 | ||||
| //Slic3r::GUI::Tab::Print;
 | ||||
|  | @ -221,6 +224,7 @@ public: | |||
| 	wxButton*	m_octoprint_host_test_btn; | ||||
| 
 | ||||
| 	size_t		m_extruders_count; | ||||
| 	size_t		m_initial_extruders_count; | ||||
| 	std::vector<PageShp>	m_extruder_pages; | ||||
| 
 | ||||
| 	TabPrinter() {} | ||||
|  |  | |||
|  | @ -35,12 +35,10 @@ void set_tab_panel(SV *ui) | |||
| void add_debug_menu(SV *ui, int event_language_change) | ||||
|     %code%{ Slic3r::GUI::add_debug_menu((wxMenuBar*)wxPli_sv_2_object(aTHX_ ui, "Wx::MenuBar"), event_language_change); %}; | ||||
| 
 | ||||
| void create_preset_tabs(PresetBundle *preset_bundle, bool no_controller,  | ||||
|                         bool is_disabled_button_browse, bool is_user_agent, | ||||
| void create_preset_tabs(bool no_controller, bool is_disabled_button_browse, bool is_user_agent, | ||||
|                         int event_value_change, int event_presets_changed, | ||||
|                         int event_button_browse, int event_button_test) | ||||
|     %code%{ Slic3r::GUI::create_preset_tabs(preset_bundle, no_controller,  | ||||
|                                             is_disabled_button_browse, is_user_agent, | ||||
|     %code%{ Slic3r::GUI::create_preset_tabs(no_controller, is_disabled_button_browse, is_user_agent, | ||||
|                                             event_value_change, event_presets_changed,  | ||||
|                                             event_button_browse, event_button_test); %}; | ||||
| 
 | ||||
|  | @ -61,3 +59,11 @@ void set_app_config(AppConfig *app_config) | |||
| 
 | ||||
| void open_preferences_dialog(int preferences_event) | ||||
|     %code%{ Slic3r::GUI::open_preferences_dialog(preferences_event); %}; | ||||
| 
 | ||||
| void set_preset_bundle(PresetBundle *preset_bundle) | ||||
|     %code%{ Slic3r::GUI::set_preset_bundle(preset_bundle); %}; | ||||
| 
 | ||||
| void add_frequently_changed_parameters(SV *ui_parent, SV *ui_sizer, SV *ui_p_sizer) | ||||
|     %code%{ Slic3r::GUI::add_frequently_changed_parameters((wxWindow*)wxPli_sv_2_object(aTHX_ ui_parent, "Wx::Window"), | ||||
|                                                            (wxBoxSizer*)wxPli_sv_2_object(aTHX_ ui_sizer, "Wx::BoxSizer"), | ||||
|                                                            (wxFlexGridSizer*)wxPli_sv_2_object(aTHX_ ui_p_sizer, "Wx::FlexGridSizer")); %}; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 bubnikv
						bubnikv