mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 20:21:12 -06:00 
			
		
		
		
	"on_change" function call correctly work now. Start adding of Tab::update().
It's need to think about config->set_key_value(...): at cpp side it's non-trivial.
This commit is contained in:
		
							parent
							
								
									f8a48f5c13
								
							
						
					
					
						commit
						e62c17bddf
					
				
					 9 changed files with 617 additions and 262 deletions
				
			
		|  | @ -158,7 +158,9 @@ sub _build_field { | |||
|      | ||||
|     my $opt_id = $opt->opt_id; | ||||
|     my $on_change = sub { | ||||
|         #! This function will be called from Field. | ||||
|         my ($opt_id, $value) = @_; | ||||
|         #! Call OptionGroup._on_change(...) | ||||
|         $self->_on_change($opt_id, $value) | ||||
|             unless $self->_disabled; | ||||
|     }; | ||||
|  | @ -213,6 +215,7 @@ sub _build_field { | |||
|     } | ||||
|     return undef if !$field; | ||||
|      | ||||
|     #! setting up a function that will be triggered when the field changes | ||||
|     $field->on_change($on_change); | ||||
|     $field->on_kill_focus($on_kill_focus); | ||||
|     $self->_fields->{$opt_id} = $field; | ||||
|  |  | |||
|  | @ -15,13 +15,13 @@ namespace Slic3r { namespace GUI { | |||
|         event.Skip(1); | ||||
| 
 | ||||
|         // call the registered function if it is available
 | ||||
| //!        if (on_kill_focus) 
 | ||||
| //!            on_kill_focus(opt_id);
 | ||||
|         if (on_kill_focus)  | ||||
|             on_kill_focus(m_opt_id); | ||||
|     } | ||||
|     void Field::_on_change(wxCommandEvent& event) { | ||||
|         std::cerr << "calling Field::_on_change \n"; | ||||
| //!        if (on_change != nullptr  && !disable_change_event)
 | ||||
| //!            on_change(opt_id, "A");
 | ||||
|     void Field::on_change_field(wxCommandEvent& event) { | ||||
| //        std::cerr << "calling Field::_on_change \n";
 | ||||
|         if (m_on_change != nullptr  && !m_disable_change_event) | ||||
|             m_on_change(m_opt_id, get_value()); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -33,32 +33,32 @@ namespace Slic3r { namespace GUI { | |||
| 
 | ||||
| 	void TextCtrl::BUILD() { | ||||
|         auto size = wxSize(wxDefaultSize); | ||||
|         if (opt.height >= 0) size.SetHeight(opt.height); | ||||
|         if (opt.width >= 0) size.SetWidth(opt.width); | ||||
|         if (m_opt.height >= 0) size.SetHeight(m_opt.height); | ||||
|         if (m_opt.width >= 0) size.SetWidth(m_opt.width); | ||||
| 
 | ||||
| 		wxString text_value = wxString("");  | ||||
| 
 | ||||
| 		switch (opt.type) { | ||||
| 		switch (m_opt.type) { | ||||
| 		case coFloatOrPercent: | ||||
| 		{ | ||||
| 			if (static_cast<const ConfigOptionFloatOrPercent*>(opt.default_value)->percent) | ||||
| 			if (static_cast<const ConfigOptionFloatOrPercent*>(m_opt.default_value)->percent) | ||||
| 			{ | ||||
| 				text_value = wxString::Format(_T("%i"), int(opt.default_value->getFloat())); | ||||
| 				text_value = wxString::Format(_T("%i"), int(m_opt.default_value->getFloat())); | ||||
| 				text_value += "%"; | ||||
| 			} | ||||
| 			else | ||||
| 				wxNumberFormatter::ToString(opt.default_value->getFloat(), 2); | ||||
| 				wxNumberFormatter::ToString(m_opt.default_value->getFloat(), 2); | ||||
| 			break; | ||||
| 		} | ||||
| 		case coPercent: | ||||
| 		{ | ||||
| 			text_value = wxString::Format(_T("%i"), int(opt.default_value->getFloat())); | ||||
| 			text_value = wxString::Format(_T("%i"), int(m_opt.default_value->getFloat())); | ||||
| 			text_value += "%"; | ||||
| 			break; | ||||
| 		}	 | ||||
| 		case coPercents: | ||||
| 		{ | ||||
| 			const ConfigOptionPercents *vec = static_cast<const ConfigOptionPercents*>(opt.default_value); | ||||
| 			const ConfigOptionPercents *vec = static_cast<const ConfigOptionPercents*>(m_opt.default_value); | ||||
| 			if (vec == nullptr || vec->empty()) break; | ||||
| 			if (vec->size() > 1) | ||||
| 				break; | ||||
|  | @ -68,13 +68,13 @@ namespace Slic3r { namespace GUI { | |||
| 		}			 | ||||
| 		case coFloat: | ||||
| 		{ | ||||
| 			double val = opt.default_value->getFloat(); | ||||
| 			double val = m_opt.default_value->getFloat(); | ||||
| 			text_value = (val - int(val)) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2); | ||||
| 			break; | ||||
| 		}			 | ||||
| 		case coFloats: | ||||
| 		{ | ||||
| 			const ConfigOptionFloats *vec = static_cast<const ConfigOptionFloats*>(opt.default_value); | ||||
| 			const ConfigOptionFloats *vec = static_cast<const ConfigOptionFloats*>(m_opt.default_value); | ||||
| 			if (vec == nullptr || vec->empty()) break; | ||||
| 			if (vec->size() > 1) | ||||
| 				break; | ||||
|  | @ -83,11 +83,11 @@ namespace Slic3r { namespace GUI { | |||
| 			break; | ||||
| 		} | ||||
| 		case coString:			 | ||||
| 			text_value = static_cast<const ConfigOptionString*>(opt.default_value)->value; | ||||
| 			text_value = static_cast<const ConfigOptionString*>(m_opt.default_value)->value; | ||||
| 			break; | ||||
| 		case coStrings: | ||||
| 		{ | ||||
| 			const ConfigOptionStrings *vec = static_cast<const ConfigOptionStrings*>(opt.default_value); | ||||
| 			const ConfigOptionStrings *vec = static_cast<const ConfigOptionStrings*>(m_opt.default_value); | ||||
| 			if (vec == nullptr || vec->empty()) break; | ||||
| 			if (vec->size() > 1) | ||||
| 				break; | ||||
|  | @ -98,11 +98,11 @@ namespace Slic3r { namespace GUI { | |||
| 			break;  | ||||
| 		} | ||||
| 
 | ||||
| 		auto temp = new wxTextCtrl(parent, wxID_ANY, text_value, wxDefaultPosition, size, (opt.multiline ? wxTE_MULTILINE : 0)); | ||||
| 		auto temp = new wxTextCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, (m_opt.multiline ? wxTE_MULTILINE : 0)); | ||||
| 
 | ||||
|         if (opt.tooltip.length() > 0) { temp->SetToolTip(opt.tooltip); } | ||||
|         if (m_opt.tooltip.length() > 0) { temp->SetToolTip(m_opt.tooltip); } | ||||
|          | ||||
|         temp->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { _on_change(e); }), temp->GetId()); | ||||
|         temp->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { on_change_field(e); }), temp->GetId()); | ||||
|         temp->Bind(wxEVT_KILL_FOCUS, ([this](wxFocusEvent e) { _on_kill_focus(e); }), temp->GetId()); | ||||
| 
 | ||||
|         // recast as a wxWindow to fit the calling convention
 | ||||
|  | @ -116,21 +116,21 @@ namespace Slic3r { namespace GUI { | |||
| 
 | ||||
| void CheckBox::BUILD() { | ||||
| 	auto size = wxSize(wxDefaultSize); | ||||
| 	if (opt.height >= 0) size.SetHeight(opt.height); | ||||
| 	if (opt.width >= 0) size.SetWidth(opt.width); | ||||
| 	if (m_opt.height >= 0) size.SetHeight(m_opt.height); | ||||
| 	if (m_opt.width >= 0) size.SetWidth(m_opt.width); | ||||
| 
 | ||||
| 	bool check_value =	opt.type == coBool ?  | ||||
| 						opt.default_value->getBool() : opt.type == coBools ?  | ||||
| 						static_cast<ConfigOptionBools*>(opt.default_value)->values.at(0) :  | ||||
| 	bool check_value =	m_opt.type == coBool ?  | ||||
| 						m_opt.default_value->getBool() : m_opt.type == coBools ?  | ||||
| 						static_cast<ConfigOptionBools*>(m_opt.default_value)->values.at(0) :  | ||||
|     					false; | ||||
| 
 | ||||
| 	auto temp = new wxCheckBox(parent, wxID_ANY, wxString(""), wxDefaultPosition, size);  | ||||
| 	auto temp = new wxCheckBox(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, size);  | ||||
| 	temp->SetValue(check_value); | ||||
| 	if (opt.readonly) temp->Disable(); | ||||
| 	if (m_opt.readonly) temp->Disable(); | ||||
| 
 | ||||
| 	temp->Bind(wxEVT_CHECKBOX, ([this](wxCommandEvent e) { _on_change(e); }), temp->GetId()); | ||||
| 	temp->Bind(wxEVT_CHECKBOX, ([this](wxCommandEvent e) { on_change_field(e); }), temp->GetId()); | ||||
| 
 | ||||
| 	if (opt.tooltip.length() > 0) { temp->SetToolTip(opt.tooltip); } | ||||
| 	if (m_opt.tooltip.length() > 0) { temp->SetToolTip(m_opt.tooltip); } | ||||
| 
 | ||||
| 	// recast as a wxWindow to fit the calling convention
 | ||||
| 	window = dynamic_cast<wxWindow*>(temp); | ||||
|  | @ -140,20 +140,20 @@ int undef_spin_val = -9999;		//! Probably, It's not necessary | |||
| 
 | ||||
| void SpinCtrl::BUILD() { | ||||
| 	auto size = wxSize(wxDefaultSize); | ||||
| 	if (opt.height >= 0) size.SetHeight(opt.height); | ||||
| 	if (opt.width >= 0) size.SetWidth(opt.width); | ||||
| 	if (m_opt.height >= 0) size.SetHeight(m_opt.height); | ||||
| 	if (m_opt.width >= 0) size.SetWidth(m_opt.width); | ||||
| 
 | ||||
| 	wxString	text_value = wxString(""); | ||||
| 	int			default_value = 0; | ||||
| 
 | ||||
| 	switch (opt.type) { | ||||
| 	switch (m_opt.type) { | ||||
| 	case coInt: | ||||
| 		default_value = opt.default_value->getInt(); | ||||
| 		default_value = m_opt.default_value->getInt(); | ||||
| 		text_value = wxString::Format(_T("%i"), default_value); | ||||
| 		break; | ||||
| 	case coInts: | ||||
| 	{ | ||||
| 		const ConfigOptionInts *vec = static_cast<const ConfigOptionInts*>(opt.default_value); | ||||
| 		const ConfigOptionInts *vec = static_cast<const ConfigOptionInts*>(m_opt.default_value); | ||||
| 		if (vec == nullptr || vec->empty()) break; | ||||
| 		for (size_t id = 0; id < vec->size(); ++id) | ||||
| 		{ | ||||
|  | @ -166,10 +166,10 @@ void SpinCtrl::BUILD() { | |||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	auto temp = new wxSpinCtrl(parent, wxID_ANY, text_value, wxDefaultPosition, size, | ||||
| 		0, opt.min >0 ? opt.min : 0, opt.max < 2147483647 ? opt.max : 2147483647, default_value); | ||||
| 	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); | ||||
| 
 | ||||
| 	temp->Bind(wxEVT_SPINCTRL, ([=](wxCommandEvent e) { tmp_value = undef_spin_val; _on_change(e); }), temp->GetId()); | ||||
| 	temp->Bind(wxEVT_SPINCTRL, ([=](wxCommandEvent e) { tmp_value = undef_spin_val; on_change_field(e); }), temp->GetId()); | ||||
| 	temp->Bind(wxEVT_KILL_FOCUS, ([this](wxFocusEvent e) { tmp_value = undef_spin_val; _on_kill_focus(e); }), temp->GetId()); | ||||
| 	temp->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) | ||||
| 	{ | ||||
|  | @ -181,14 +181,14 @@ void SpinCtrl::BUILD() { | |||
| 		std::string value = e.GetString(); | ||||
| 		if (is_matched(value, "^\d+$")) | ||||
| 			tmp_value = std::stoi(value); | ||||
| 		_on_change(e); | ||||
| 		on_change_field(e); | ||||
| // 		# We don't reset tmp_value here because _on_change might put callbacks
 | ||||
| // 		# in the CallAfter queue, and we want the tmp value to be available from
 | ||||
| // 		# them as well.
 | ||||
| 	}), temp->GetId()); | ||||
| 
 | ||||
| 
 | ||||
| 	if (opt.tooltip.length() > 0) { temp->SetToolTip(opt.tooltip); } | ||||
| 	if (m_opt.tooltip.length() > 0) { temp->SetToolTip(m_opt.tooltip); } | ||||
| 
 | ||||
| 	// recast as a wxWindow to fit the calling convention
 | ||||
| 	window = dynamic_cast<wxWindow*>(temp); | ||||
|  | @ -196,66 +196,66 @@ void SpinCtrl::BUILD() { | |||
| 
 | ||||
| void Choice::BUILD() { | ||||
| 	auto size = wxSize(wxDefaultSize); | ||||
| 	if (opt.height >= 0) size.SetHeight(opt.height); | ||||
| 	if (opt.width >= 0) size.SetWidth(opt.width); | ||||
| 	if (m_opt.height >= 0) size.SetHeight(m_opt.height); | ||||
| 	if (m_opt.width >= 0) size.SetWidth(m_opt.width); | ||||
| 
 | ||||
| 	auto temp = new wxComboBox(parent, wxID_ANY, wxString(""), wxDefaultPosition, size); | ||||
| 	if (opt.gui_type.compare("select_open") != 0) | ||||
| 	auto temp = new wxComboBox(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, size); | ||||
| 	if (m_opt.gui_type.compare("select_open") != 0) | ||||
| 		temp->SetExtraStyle(wxCB_READONLY); | ||||
| 
 | ||||
| 	// recast as a wxWindow to fit the calling convention
 | ||||
| 	window = dynamic_cast<wxWindow*>(temp); | ||||
| 
 | ||||
| 	if (opt.enum_labels.empty() && opt.enum_values.empty()){ | ||||
| 	if (m_opt.enum_labels.empty() && m_opt.enum_values.empty()){ | ||||
| 	} | ||||
| 	else{ | ||||
| 		for (auto el : opt.enum_labels.empty() ? opt.enum_values : opt.enum_labels) | ||||
| 		for (auto el : m_opt.enum_labels.empty() ? m_opt.enum_values : m_opt.enum_labels) | ||||
| 			temp->Append(wxString(el)); | ||||
| 		set_selection(); | ||||
| 	} | ||||
|  	temp->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { _on_change(e); }), temp->GetId()); | ||||
|  	temp->Bind(wxEVT_COMBOBOX, ([this](wxCommandEvent e) { _on_change(e); }), temp->GetId()); | ||||
|  	temp->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { on_change_field(e); }), temp->GetId()); | ||||
|  	temp->Bind(wxEVT_COMBOBOX, ([this](wxCommandEvent e) { on_change_field(e); }), temp->GetId()); | ||||
| 
 | ||||
| 	if (opt.tooltip.length() > 0) temp->SetToolTip(opt.tooltip); | ||||
| 	if (m_opt.tooltip.length() > 0) temp->SetToolTip(m_opt.tooltip); | ||||
| } | ||||
| 
 | ||||
| void Choice::set_selection() | ||||
| { | ||||
| 	wxString text_value = wxString(""); | ||||
| 	switch (opt.type){ | ||||
| 	switch (m_opt.type){ | ||||
| 	case coFloat: | ||||
| 	case coPercent:	{ | ||||
| 		double val = opt.default_value->getFloat(); | ||||
| 		double val = m_opt.default_value->getFloat(); | ||||
| 		text_value = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 1); | ||||
| 		auto idx = 0; | ||||
| 		for (auto el : opt.enum_values) | ||||
| 		for (auto el : m_opt.enum_values) | ||||
| 		{ | ||||
| 			if (el.compare(text_value) == 0) | ||||
| 				break; | ||||
| 			++idx; | ||||
| 		} | ||||
| 		if (opt.type == coPercent) text_value += "%"; | ||||
| 		idx == opt.enum_values.size() ? | ||||
| 		if (m_opt.type == coPercent) text_value += "%"; | ||||
| 		idx == m_opt.enum_values.size() ? | ||||
| 			dynamic_cast<wxComboBox*>(window)->SetValue(text_value) : | ||||
| 			dynamic_cast<wxComboBox*>(window)->SetSelection(idx); | ||||
| 		break; | ||||
| 	} | ||||
| 	case coEnum:{ | ||||
| 		int id_value = static_cast<const ConfigOptionEnum<SeamPosition>*>(opt.default_value)->value; //!!
 | ||||
| 		int id_value = static_cast<const ConfigOptionEnum<SeamPosition>*>(m_opt.default_value)->value; //!!
 | ||||
| 		dynamic_cast<wxComboBox*>(window)->SetSelection(id_value); | ||||
| 		break; | ||||
| 	} | ||||
| 	case coInt:{ | ||||
| 		int val = opt.default_value->getInt(); //!!
 | ||||
| 		int val = m_opt.default_value->getInt(); //!!
 | ||||
| 		text_value = wxString::Format(_T("%i"), int(val)); | ||||
| 		auto idx = 0; | ||||
| 		for (auto el : opt.enum_values) | ||||
| 		for (auto el : m_opt.enum_values) | ||||
| 		{ | ||||
| 			if (el.compare(text_value) == 0) | ||||
| 				break; | ||||
| 			++idx; | ||||
| 		} | ||||
| 		idx == opt.enum_values.size() ? | ||||
| 		idx == m_opt.enum_values.size() ? | ||||
| 			dynamic_cast<wxComboBox*>(window)->SetValue(text_value) : | ||||
| 			dynamic_cast<wxComboBox*>(window)->SetSelection(idx); | ||||
| 		break; | ||||
|  | @ -276,16 +276,16 @@ void Choice::set_selection() | |||
| // 		break;
 | ||||
| // 	}
 | ||||
| 	case coStrings:{ | ||||
| 		text_value = static_cast<const ConfigOptionStrings*>(opt.default_value)->values.at(0); | ||||
| 		text_value = static_cast<const ConfigOptionStrings*>(m_opt.default_value)->values.at(0); | ||||
| 
 | ||||
| 		auto idx = 0; | ||||
| 		for (auto el : opt.enum_values) | ||||
| 		for (auto el : m_opt.enum_values) | ||||
| 		{ | ||||
| 			if (el.compare(text_value) == 0) | ||||
| 				break; | ||||
| 			++idx; | ||||
| 		} | ||||
| 		idx == opt.enum_values.size() ? | ||||
| 		idx == m_opt.enum_values.size() ? | ||||
| 			dynamic_cast<wxComboBox*>(window)->SetValue(text_value) : | ||||
| 			dynamic_cast<wxComboBox*>(window)->SetSelection(idx); | ||||
| 		break; | ||||
|  | @ -295,27 +295,29 @@ void Choice::set_selection() | |||
| 
 | ||||
| void Choice::set_value(const std::string value)  //! Redundant?
 | ||||
| { | ||||
| 	disable_change_event = true; | ||||
| 	m_disable_change_event = true; | ||||
| 
 | ||||
| 	auto idx=0; | ||||
| 	for (auto el : opt.enum_values) | ||||
| 	for (auto el : m_opt.enum_values) | ||||
| 	{ | ||||
| 		if (el.compare(value) == 0) | ||||
| 			break; | ||||
| 		++idx; | ||||
| 	} | ||||
| 
 | ||||
| 	idx == opt.enum_values.size() ?  | ||||
| 	idx == m_opt.enum_values.size() ?  | ||||
| 		dynamic_cast<wxComboBox*>(window)->SetValue(value) : | ||||
| 		dynamic_cast<wxComboBox*>(window)->SetSelection(idx); | ||||
| 	 | ||||
| 	disable_change_event = false; | ||||
| 	m_disable_change_event = false; | ||||
| } | ||||
| 
 | ||||
| //! it's needed for _update_serial_ports()
 | ||||
| void Choice::set_values(const std::vector<std::string> values) | ||||
| { | ||||
| 	disable_change_event = true; | ||||
| 	if (values.empty()) | ||||
| 		return; | ||||
| 	m_disable_change_event = true; | ||||
| 
 | ||||
| // 	# it looks that Clear() also clears the text field in recent wxWidgets versions,
 | ||||
| // 	# but we want to preserve it
 | ||||
|  | @ -326,75 +328,75 @@ void Choice::set_values(const std::vector<std::string> values) | |||
| 		ww->Append(wxString(el)); | ||||
| 	ww->SetValue(value); | ||||
| 
 | ||||
| 	disable_change_event = false; | ||||
| 	m_disable_change_event = false; | ||||
| } | ||||
| 
 | ||||
| void ColourPicker::BUILD() | ||||
| { | ||||
| 	auto size = wxSize(wxDefaultSize); | ||||
| 	if (opt.height >= 0) size.SetHeight(opt.height); | ||||
| 	if (opt.width >= 0) size.SetWidth(opt.width); | ||||
| 	if (m_opt.height >= 0) size.SetHeight(m_opt.height); | ||||
| 	if (m_opt.width >= 0) size.SetWidth(m_opt.width); | ||||
| 
 | ||||
| 	wxString clr(static_cast<ConfigOptionStrings*>(opt.default_value)->values.at(0)); | ||||
| 	auto temp = new wxColourPickerCtrl(parent, wxID_ANY, clr, wxDefaultPosition, size); | ||||
| 	wxString clr(static_cast<ConfigOptionStrings*>(m_opt.default_value)->values.at(0)); | ||||
| 	auto temp = new wxColourPickerCtrl(m_parent, wxID_ANY, clr, wxDefaultPosition, size); | ||||
| 		 | ||||
| 	// 	// recast as a wxWindow to fit the calling convention
 | ||||
| 	window = dynamic_cast<wxWindow*>(temp); | ||||
| 
 | ||||
| 	temp->Bind(wxEVT_COLOURPICKER_CHANGED, ([=](wxCommandEvent e) { _on_change(e); }), temp->GetId()); | ||||
| 	temp->Bind(wxEVT_COLOURPICKER_CHANGED, ([=](wxCommandEvent e) { on_change_field(e); }), temp->GetId()); | ||||
| 
 | ||||
| 	if (opt.tooltip.length() > 0) temp->SetToolTip(opt.tooltip); | ||||
| 	if (m_opt.tooltip.length() > 0) temp->SetToolTip(m_opt.tooltip); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| void Point::BUILD() | ||||
| { | ||||
| 	auto size = wxSize(wxDefaultSize); | ||||
| 	if (opt.height >= 0) size.SetHeight(opt.height); | ||||
| 	if (opt.width >= 0) size.SetWidth(opt.width); | ||||
| 	if (m_opt.height >= 0) size.SetHeight(m_opt.height); | ||||
| 	if (m_opt.width >= 0) size.SetWidth(m_opt.width); | ||||
| 
 | ||||
| 	auto temp = new wxBoxSizer(wxHORIZONTAL); | ||||
| 	// 	$self->wxSizer($sizer);
 | ||||
| 	// 
 | ||||
| 	wxSize field_size(40, -1); | ||||
| 
 | ||||
| 	auto default_pt = static_cast<ConfigOptionPoints*>(opt.default_value)->values.at(0); | ||||
| 	auto default_pt = static_cast<ConfigOptionPoints*>(m_opt.default_value)->values.at(0); | ||||
| 	double val = default_pt.x; | ||||
| 	wxString X = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2); | ||||
| 	val = default_pt.y; | ||||
| 	wxString Y = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2); | ||||
| 
 | ||||
| 	x_textctrl = new wxTextCtrl(parent, wxID_ANY, X, wxDefaultPosition, field_size); | ||||
| 	y_textctrl = new wxTextCtrl(parent, wxID_ANY, Y, wxDefaultPosition, field_size); | ||||
| 	x_textctrl = new wxTextCtrl(m_parent, wxID_ANY, X, wxDefaultPosition, field_size); | ||||
| 	y_textctrl = new wxTextCtrl(m_parent, wxID_ANY, Y, wxDefaultPosition, field_size); | ||||
| 
 | ||||
| 	temp->Add(new wxStaticText(parent, wxID_ANY, "x:")/*, 0, wxALIGN_CENTER_VERTICAL, 0*/); | ||||
| 	temp->Add(new wxStaticText(m_parent, wxID_ANY, "x:")/*, 0, wxALIGN_CENTER_VERTICAL, 0*/); | ||||
| 	temp->Add(x_textctrl); | ||||
| 	temp->Add(new wxStaticText(parent, wxID_ANY, "y:")/*, 0, wxALIGN_CENTER_VERTICAL, 0*/); | ||||
| 	temp->Add(new wxStaticText(m_parent, wxID_ANY, "y:")/*, 0, wxALIGN_CENTER_VERTICAL, 0*/); | ||||
| 	temp->Add(y_textctrl); | ||||
| 
 | ||||
| 	x_textctrl->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { _on_change(e/*$self->option->opt_id*/); }), x_textctrl->GetId()); | ||||
| 	y_textctrl->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { _on_change(e/*$self->option->opt_id*/); }), x_textctrl->GetId()); | ||||
| 	x_textctrl->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { on_change_field(e/*$self->option->opt_id*/); }), x_textctrl->GetId()); | ||||
| 	y_textctrl->Bind(wxEVT_TEXT, ([=](wxCommandEvent e) { on_change_field(e/*$self->option->opt_id*/); }), x_textctrl->GetId()); | ||||
| 
 | ||||
| 	// 	// recast as a wxWindow to fit the calling convention
 | ||||
| 	sizer = dynamic_cast<wxSizer*>(temp); | ||||
| 
 | ||||
| 	if (opt.tooltip.length() > 0) | ||||
| 	if (m_opt.tooltip.length() > 0) | ||||
| 	{ | ||||
| 		x_textctrl->SetToolTip(opt.tooltip); | ||||
| 		y_textctrl->SetToolTip(opt.tooltip); | ||||
| 		x_textctrl->SetToolTip(m_opt.tooltip); | ||||
| 		y_textctrl->SetToolTip(m_opt.tooltip); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void Point::set_value(const Pointf value) | ||||
| { | ||||
| 	disable_change_event = true; | ||||
| 	m_disable_change_event = true; | ||||
| 
 | ||||
| 	double val = value.x; | ||||
| 	x_textctrl->SetValue(val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2)); | ||||
| 	val = value.y; | ||||
| 	y_textctrl->SetValue(val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2)); | ||||
| 
 | ||||
| 	disable_change_event = false; | ||||
| 	m_disable_change_event = false; | ||||
| } | ||||
| 
 | ||||
| boost::any Point::get_value() | ||||
|  |  | |||
|  | @ -23,6 +23,8 @@ namespace Slic3r { namespace GUI { | |||
| 
 | ||||
| class Field; | ||||
| using t_field = std::unique_ptr<Field>; | ||||
| using t_kill_focus = std::function<void(t_config_option_key)>; | ||||
| using t_change = std::function<void(t_config_option_key, boost::any)>; | ||||
| 
 | ||||
| class Field { | ||||
| protected: | ||||
|  | @ -35,47 +37,47 @@ protected: | |||
|     /// Call the attached on_kill_focus method. 
 | ||||
|     void _on_kill_focus(wxFocusEvent& event); | ||||
|     /// Call the attached on_change method. 
 | ||||
|     void _on_change(wxCommandEvent& event); | ||||
|     void on_change_field(wxCommandEvent& event); | ||||
| 
 | ||||
| public: | ||||
|     /// parent wx item, opportunity to refactor (probably not necessary - data duplication)
 | ||||
|     wxWindow* parent {nullptr}; | ||||
|     wxWindow*		m_parent {nullptr}; | ||||
| 
 | ||||
|     /// Function object to store callback passed in from owning object.
 | ||||
| //!    t_kill_focus on_kill_focus {nullptr};
 | ||||
| 	t_kill_focus	on_kill_focus {nullptr}; | ||||
| 
 | ||||
|     /// Function object to store callback passed in from owning object.
 | ||||
| //!    t_change on_change {nullptr};
 | ||||
| 	t_change		m_on_change {nullptr}; | ||||
| 
 | ||||
|     bool disable_change_event {false}; | ||||
|     bool			m_disable_change_event {false}; | ||||
| 
 | ||||
|     /// Copy of ConfigOption for deduction purposes
 | ||||
|     const ConfigOptionDef opt {ConfigOptionDef()}; | ||||
| 	const t_config_option_key opt_id;//! {""};
 | ||||
|     const ConfigOptionDef			m_opt {ConfigOptionDef()}; | ||||
| 	const t_config_option_key		m_opt_id;//! {""};
 | ||||
| 
 | ||||
|     /// Sets a value for this control.
 | ||||
|     /// subclasses should overload with a specific version
 | ||||
|     /// Postcondition: Method does not fire the on_change event.
 | ||||
|     virtual void set_value(boost::any value) = 0; | ||||
|     virtual void		set_value(boost::any value) = 0; | ||||
|      | ||||
|     /// Gets a boost::any representing this control.
 | ||||
|     /// subclasses should overload with a specific version
 | ||||
|     virtual boost::any get_value() = 0; | ||||
|     virtual boost::any	get_value() = 0; | ||||
| 
 | ||||
|     virtual void enable() = 0; | ||||
|     virtual void disable() = 0; | ||||
|     virtual void		enable() = 0; | ||||
|     virtual void		disable() = 0; | ||||
| 
 | ||||
|     /// Fires the enable or disable function, based on the input.
 | ||||
|     inline void toggle(bool en) { en ? enable() : disable(); } | ||||
|     inline void			toggle(bool en) { en ? enable() : disable(); } | ||||
| 
 | ||||
|     virtual void set_tooltip(const wxString& tip) = 0; | ||||
|     virtual void		set_tooltip(const wxString& tip) = 0; | ||||
| 
 | ||||
|     Field(const ConfigOptionDef& opt, const t_config_option_key& id) : opt(opt), opt_id(id) {}; | ||||
|     Field(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : parent(parent), opt(opt), opt_id(id) {}; | ||||
|     Field(const ConfigOptionDef& opt, const t_config_option_key& id) : m_opt(opt), m_opt_id(id) {}; | ||||
|     Field(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : m_parent(parent), m_opt(opt), m_opt_id(id) {}; | ||||
| 
 | ||||
|     /// If you don't know what you are getting back, check both methods for nullptr. 
 | ||||
|     virtual wxSizer*  getSizer()  { return nullptr; } | ||||
|     virtual wxWindow* getWindow() { return nullptr; } | ||||
|     virtual wxSizer*	getSizer()  { return nullptr; } | ||||
|     virtual wxWindow*	getWindow() { return nullptr; } | ||||
| 
 | ||||
| 	bool		is_matched(std::string string, std::string pattern); | ||||
| 
 | ||||
|  | @ -210,14 +212,14 @@ public: | |||
| 	wxWindow*		window{ nullptr }; | ||||
| 	void			BUILD()  override; | ||||
| 
 | ||||
| 	void			set_selection(); | ||||
| //	void			set_selection();
 | ||||
| 	void			set_value(const std::string value) { | ||||
| 	 		dynamic_cast<wxColourPickerCtrl*>(window)->SetColour(value); | ||||
| 	 	} | ||||
| 	void			set_value(boost::any value) { | ||||
| 		dynamic_cast<wxColourPickerCtrl*>(window)->SetColour(boost::any_cast<std::string>(value)); | ||||
| 	} | ||||
| 	void			set_values(const std::vector<std::string> values); | ||||
| //	void			set_values(const std::vector<std::string> values);
 | ||||
| 	boost::any		get_value() override	{ | ||||
| 		return boost::any(dynamic_cast<wxColourPickerCtrl*>(window)->GetColour()); | ||||
| 	} | ||||
|  |  | |||
|  | @ -32,11 +32,7 @@ | |||
| #include <wx/window.h> | ||||
| 
 | ||||
| #include "Tab.h" | ||||
| 
 | ||||
| //#include <wx/bmpcbox.h>
 | ||||
| //#include <wx/bmpbuttn.h>
 | ||||
| //#include <wx/treectrl.h>
 | ||||
| //#include <wx/imaglist.h>
 | ||||
| #include "AppConfig.hpp" | ||||
| 
 | ||||
| namespace Slic3r { namespace GUI { | ||||
| 
 | ||||
|  | @ -189,15 +185,53 @@ void add_debug_menu(wxMenuBar *menu) | |||
| } | ||||
| 
 | ||||
| void create_preset_tabs(PresetBundle *preset_bundle, AppConfig *app_config) | ||||
| { | ||||
| 	add_created_tab(new CTabPrint   (g_wxTabPanel, "Print"),    preset_bundle, app_config); | ||||
| 	add_created_tab(new CTabFilament(g_wxTabPanel, "Filament"), preset_bundle, app_config); | ||||
| 	add_created_tab(new CTabPrinter (g_wxTabPanel, "Printer"),  preset_bundle, app_config); | ||||
| {	 | ||||
| 	add_created_tab(new TabPrint   (g_wxTabPanel, "Print"),    preset_bundle, app_config); | ||||
| 	add_created_tab(new TabFilament(g_wxTabPanel, "Filament"), preset_bundle, app_config); | ||||
| 	add_created_tab(new TabPrinter (g_wxTabPanel, "Printer"),  preset_bundle, app_config); | ||||
| } | ||||
| 
 | ||||
| void add_created_tab(CTab* panel, PresetBundle *preset_bundle, AppConfig *app_config) | ||||
| void add_created_tab(Tab* panel, PresetBundle *preset_bundle, AppConfig *app_config) | ||||
| { | ||||
| 	panel->create_preset_tab(preset_bundle, app_config); | ||||
| 	panel->m_no_controller = app_config->get("no_controller").empty(); | ||||
| 	panel->create_preset_tab(preset_bundle); | ||||
| 	// Callback to be executed after any of the configuration fields(Perl class Slic3r::GUI::OptionsGroup::Field) change their value.
 | ||||
| 	panel->m_on_value_change = [/*this*/](std::string opt_key, boost::any value){ | ||||
| 	//! plater & loaded - variables of MainFrame
 | ||||
| // 		if (plater) {
 | ||||
| // 			plater->on_config_change(m_config); //# propagate config change events to the plater
 | ||||
| // 			if (opt_key.compare("extruders_count")	plater->on_extruders_change(value);
 | ||||
| // 		}
 | ||||
| 		// don't save while loading for the first time
 | ||||
| //		if (loaded && Slic3r::GUI::autosave) m_config->save(Slic3r::GUI::autosave) ;
 | ||||
| 	}; | ||||
| 
 | ||||
| // 	# Install a callback for the tab to update the platter and print controller presets, when
 | ||||
| // 	# a preset changes at Slic3r::GUI::Tab.
 | ||||
| // 	$tab->on_presets_changed(sub{
 | ||||
| // 		if ($self->{plater}) {
 | ||||
| // 			# Update preset combo boxes(Print settings, Filament, Printer) from their respective tabs.
 | ||||
| // 			$self->{plater}->update_presets($tab_name, @_);
 | ||||
| // 			if ($tab_name eq 'printer') {
 | ||||
| // 				# Printer selected at the Printer tab, update "compatible" marks at the print and filament selectors.
 | ||||
| // 				my($presets, $reload_dependent_tabs) = @_;
 | ||||
| // 				for my $tab_name_other(qw(print filament)) {
 | ||||
| // 					# If the printer tells us that the print or filament preset has been switched or invalidated,
 | ||||
| // 					# refresh the print or filament tab page.Otherwise just refresh the combo box.
 | ||||
| // 					my $update_action = ($reload_dependent_tabs && (first{ $_ eq $tab_name_other } (@{$reload_dependent_tabs})))
 | ||||
| // 						? 'load_current_preset' : 'update_tab_ui';
 | ||||
| // 					$self->{options_tabs}{$tab_name_other}->$update_action;
 | ||||
| // 				}
 | ||||
| // 				# Update the controller printers.
 | ||||
| // 				$self->{controller}->update_presets(@_) if $self->{controller};
 | ||||
| // 			}
 | ||||
| // 			$self->{plater}->on_config_change($tab->{presets}->get_current_preset->config);
 | ||||
| // 		}
 | ||||
| // 	});
 | ||||
| 
 | ||||
| 	//# Load the currently selected preset into the GUI, update the preset selection box.
 | ||||
| //	panel->load_current_preset;
 | ||||
| 
 | ||||
| 	g_wxTabPanel->AddPage(panel, panel->title()); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -13,11 +13,12 @@ class wxNotebook; | |||
| namespace Slic3r {  | ||||
| 
 | ||||
| class PresetBundle; | ||||
| class PresetCollection; | ||||
| class AppConfig; | ||||
| 
 | ||||
| namespace GUI { | ||||
| 
 | ||||
| class CTab; | ||||
| class Tab; | ||||
| 
 | ||||
| void disable_screensaver(); | ||||
| void enable_screensaver(); | ||||
|  | @ -34,7 +35,7 @@ void add_debug_menu(wxMenuBar *menu); | |||
| // Create a new preset tab (print, filament and printer),
 | ||||
| void create_preset_tabs(PresetBundle *preset_bundle, AppConfig *app_config); | ||||
| // add it at the end of the tab panel.
 | ||||
| void add_created_tab(CTab* panel, PresetBundle *preset_bundle, AppConfig *app_config); | ||||
| void add_created_tab(Tab* panel, PresetBundle *preset_bundle, AppConfig *app_config); | ||||
| 
 | ||||
| void show_error(wxWindow* parent, std::string message); | ||||
| void show_info(wxWindow* parent, std::string message, std::string title); | ||||
|  |  | |||
|  | @ -10,7 +10,7 @@ const t_field& OptionsGroup::build_field(const Option& opt) { | |||
|     return build_field(opt.opt_id, opt.opt); | ||||
| } | ||||
| const t_field& OptionsGroup::build_field(const t_config_option_key& id) { | ||||
| 	const ConfigOptionDef& opt = options.at(id); | ||||
| 	const ConfigOptionDef& opt = m_options_map.at(id); | ||||
|     return build_field(id, opt); | ||||
| } | ||||
| 
 | ||||
|  | @ -19,13 +19,13 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co | |||
|     // is the normal type.
 | ||||
|     if (opt.gui_type.compare("select") == 0) { | ||||
|     } else if (opt.gui_type.compare("select_open") == 0) { | ||||
| 		fields.emplace(id, STDMOVE(Choice::Create<Choice>(_parent, opt, id))); | ||||
| 		m_fields.emplace(id, STDMOVE(Choice::Create<Choice>(m_parent, opt, id))); | ||||
|     } else if (opt.gui_type.compare("color") == 0) { | ||||
| 		fields.emplace(id, STDMOVE(ColourPicker::Create<ColourPicker>(_parent, opt, id))); | ||||
| 		m_fields.emplace(id, STDMOVE(ColourPicker::Create<ColourPicker>(m_parent, opt, id))); | ||||
|     } else if (opt.gui_type.compare("f_enum_open") == 0 ||  | ||||
|                 opt.gui_type.compare("i_enum_open") == 0 || | ||||
|                 opt.gui_type.compare("i_enum_closed") == 0) { | ||||
| 		fields.emplace(id, STDMOVE(Choice::Create<Choice>(_parent, opt, id))); | ||||
| 		m_fields.emplace(id, STDMOVE(Choice::Create<Choice>(m_parent, opt, id))); | ||||
|     } else if (opt.gui_type.compare("slider") == 0) { | ||||
|     } else if (opt.gui_type.compare("i_spin") == 0) { // Spinctrl
 | ||||
|     } else {  | ||||
|  | @ -37,21 +37,21 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co | |||
| 			case coPercents: | ||||
| 			case coString: | ||||
| 			case coStrings: | ||||
| 				fields.emplace(id, STDMOVE(TextCtrl::Create<TextCtrl>(_parent, opt, id))); | ||||
| 				m_fields.emplace(id, STDMOVE(TextCtrl::Create<TextCtrl>(m_parent, opt, id))); | ||||
|                 break; | ||||
| 			case coBool: | ||||
| 			case coBools: | ||||
| 				fields.emplace(id, STDMOVE(CheckBox::Create<CheckBox>(_parent, opt, id))); | ||||
| 				m_fields.emplace(id, STDMOVE(CheckBox::Create<CheckBox>(m_parent, opt, id))); | ||||
| 				break; | ||||
| 			case coInt: | ||||
| 			case coInts: | ||||
| 				fields.emplace(id, STDMOVE(SpinCtrl::Create<SpinCtrl>(_parent, opt, id))); | ||||
| 				m_fields.emplace(id, STDMOVE(SpinCtrl::Create<SpinCtrl>(m_parent, opt, id))); | ||||
| 				break; | ||||
|             case coEnum: | ||||
| 				fields.emplace(id, STDMOVE(Choice::Create<Choice>(_parent, opt, id))); | ||||
| 				m_fields.emplace(id, STDMOVE(Choice::Create<Choice>(m_parent, opt, id))); | ||||
| 				break; | ||||
|             case coPoints: | ||||
| 				fields.emplace(id, STDMOVE(Point::Create<Point>(_parent, opt, id))); | ||||
| 				m_fields.emplace(id, STDMOVE(Point::Create<Point>(m_parent, opt, id))); | ||||
| 				break; | ||||
|             case coNone:   break; | ||||
|             default: | ||||
|  | @ -59,9 +59,14 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co | |||
|         } | ||||
|     } | ||||
|     // Grab a reference to fields for convenience
 | ||||
|     const t_field& field = fields[id]; | ||||
| //!        field->on_change = [this](std::string id, boost::any val) {   };
 | ||||
|     field->parent = parent(); | ||||
|     const t_field& field = m_fields[id]; | ||||
| 	field->m_on_change = [this](std::string opt_id, boost::any value){ | ||||
| 			//! This function will be called from Field.					
 | ||||
| 			//! Call OptionGroup._on_change(...)
 | ||||
| 			if (!this->m_disabled)  | ||||
| 				this->on_change_OG(opt_id, value); | ||||
| 	}; | ||||
|     field->m_parent = parent(); | ||||
|     // assign function objects for callbacks, etc.
 | ||||
|     return field; | ||||
| } | ||||
|  | @ -74,7 +79,7 @@ void OptionsGroup::append_line(const Line& line) { | |||
|             return; | ||||
|         } | ||||
|         if (line.widget != nullptr) { | ||||
|             sizer->Add(line.widget(_parent), 0, wxEXPAND | wxALL, wxOSX ? 0 : 15); | ||||
|             sizer->Add(line.widget(m_parent), 0, wxEXPAND | wxALL, wxOSX ? 0 : 15); | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
|  | @ -95,7 +100,7 @@ void OptionsGroup::append_line(const Line& line) { | |||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
|     auto grid_sizer = _grid_sizer; | ||||
|     auto grid_sizer = m_grid_sizer; | ||||
| 
 | ||||
|     // Build a label if we have it
 | ||||
|     if (label_width != 0) { | ||||
|  | @ -146,8 +151,6 @@ void OptionsGroup::append_line(const Line& line) { | |||
| 
 | ||||
| 		// add field
 | ||||
| 		const Option& opt_ref = opt; | ||||
| //!		auto field = build_field(opt_ref)->getWindow();		
 | ||||
| //!		sizer->Add(field, 0, wxALIGN_CENTER_VERTICAL, 0);
 | ||||
| 		auto& field = build_field(opt_ref); | ||||
| 		is_sizer_field(field) ?  | ||||
| 			sizer->Add(field->getSizer(), 0, wxALIGN_CENTER_VERTICAL, 0) : | ||||
|  | @ -184,14 +187,45 @@ Line OptionsGroup::create_single_option_line(const Option& option) const { | |||
|     return retval; | ||||
| } | ||||
| 
 | ||||
| //!    void OptionsGroup::_on_change(t_config_option_key id, config_value value) {
 | ||||
| //!        if (on_change != nullptr)
 | ||||
| //!            on_change(id, value);
 | ||||
| //!   }
 | ||||
| void OptionsGroup::on_change_OG(t_config_option_key id, /*config_value*/boost::any value) { | ||||
| 	if (m_on_change != nullptr) | ||||
| 		m_on_change(id, value); | ||||
| } | ||||
| 
 | ||||
| void OptionsGroup::_on_kill_focus (t_config_option_key id) {  | ||||
|     // do nothing.
 | ||||
| } | ||||
| 
 | ||||
| void ConfigOptionsGroup::on_change_OG(t_config_option_key opt_id, boost::any value) | ||||
| { | ||||
| // 	if (m_options_map.at(opt_id)/*exists $self->_opt_map->{$opt_id}*/) {
 | ||||
| // 		my($opt_key, $opt_index) = @{ $self->_opt_map->{$opt_id} };
 | ||||
| // 		auto option = m_options->{$opt_id};
 | ||||
| 
 | ||||
| }} | ||||
| 		// get value
 | ||||
| 		auto field_value = get_value(opt_id); | ||||
| // 		if ($option->gui_flags = ~/ \bserialized\b / ) {
 | ||||
| // 			die "Can't set serialized option indexed value" if $opt_index != -1;
 | ||||
| // 			# Split a string to multiple strings by a semi - colon.This is the old way of storing multi - string values.
 | ||||
| // 			# Currently used for the post_process config value only.
 | ||||
| // 			my @values = split / ; / , $field_value;
 | ||||
| // 			$self->config->set($opt_key, \@values);
 | ||||
| // 		}
 | ||||
| // 		else {
 | ||||
| // 			if ($opt_index == -1) {
 | ||||
| //				$self->config->set($opt_key, $field_value);
 | ||||
| //!		m_config->set_key_value(opt_id, new ConfigOption(value));
 | ||||
| // 			}
 | ||||
| // 			else {
 | ||||
| // 				my $value = $self->config->get($opt_key);
 | ||||
| // 				$value->[$opt_index] = $field_value;
 | ||||
| // 				$self->config->set($opt_key, $value);
 | ||||
| // 			}
 | ||||
| // 		}
 | ||||
| // 	}
 | ||||
| 
 | ||||
| 	OptionsGroup::on_change_OG(opt_id, value); | ||||
| } | ||||
| 
 | ||||
| } // GUI
 | ||||
| } // Slic3r
 | ||||
|  |  | |||
|  | @ -33,118 +33,119 @@ class StaticText; | |||
| 
 | ||||
| /// Wraps a ConfigOptionDef and adds function object for creating a side_widget.
 | ||||
| struct Option { | ||||
| 	ConfigOptionDef opt { ConfigOptionDef() }; | ||||
| 	t_config_option_key opt_id;//! {""};
 | ||||
|     widget_t side_widget {nullptr}; | ||||
|     bool readonly {false}; | ||||
| 	ConfigOptionDef			opt { ConfigOptionDef() }; | ||||
| 	t_config_option_key		opt_id;//! {""};
 | ||||
|     widget_t				side_widget {nullptr}; | ||||
|     bool					readonly {false}; | ||||
| 
 | ||||
|     Option(const ConfigOptionDef& _opt, t_config_option_key id) : opt(_opt), opt_id(id) {}; | ||||
|     Option(const ConfigOptionDef& _opt, t_config_option_key id) :  | ||||
| 		opt(_opt), opt_id(id) {} | ||||
| }; | ||||
| using t_option = std::unique_ptr<Option>;	//!
 | ||||
| 
 | ||||
| /// Represents option lines
 | ||||
| class Line { | ||||
| public: | ||||
|     wxString label {wxString("")}; | ||||
|     wxString label_tooltip {wxString("")}; | ||||
|     size_t full_width {0};  | ||||
|     wxSizer* sizer {nullptr}; | ||||
|     widget_t widget {nullptr}; | ||||
|     wxString	label {wxString("")}; | ||||
|     wxString	label_tooltip {wxString("")}; | ||||
|     size_t		full_width {0};  | ||||
|     wxSizer*	sizer {nullptr}; | ||||
|     widget_t	widget {nullptr}; | ||||
| 
 | ||||
|     void append_option(const Option& option) { | ||||
|         _options.push_back(option); | ||||
|         m_options.push_back(option); | ||||
|     } | ||||
| 	void append_widget(const widget_t widget) { | ||||
| 		_extra_widgets.push_back(widget); | ||||
| 		m_extra_widgets.push_back(widget); | ||||
|     } | ||||
|     Line(std::string label, std::string tooltip) : label(wxString(label)), label_tooltip(wxString(tooltip)) {} ; | ||||
|     Line(std::string label, std::string tooltip) :  | ||||
| 		label(wxString(label)), label_tooltip(wxString(tooltip)) {} | ||||
| 
 | ||||
|     const std::vector<widget_t>& get_extra_widgets() const {return _extra_widgets;} | ||||
|     const std::vector<Option>& get_options() const { return _options; } | ||||
|     const std::vector<widget_t>&	get_extra_widgets() const {return m_extra_widgets;} | ||||
|     const std::vector<Option>&		get_options() const { return m_options; } | ||||
| 
 | ||||
| private: | ||||
| 	std::vector<Option> _options;//! {std::vector<Option>()};
 | ||||
|     std::vector<widget_t> _extra_widgets;//! {std::vector<widget_t>()};
 | ||||
| 	std::vector<Option>		m_options;//! {std::vector<Option>()};
 | ||||
|     std::vector<widget_t>	m_extra_widgets;//! {std::vector<widget_t>()};
 | ||||
| }; | ||||
| 
 | ||||
| using t_optionfield_map = std::map<t_config_option_key, t_field>; | ||||
| 
 | ||||
| class OptionsGroup { | ||||
| public: | ||||
|     const bool		staticbox {true}; | ||||
|     const wxString	title {wxString("")}; | ||||
|     size_t			label_width {200}; | ||||
|     wxSizer*		sizer {nullptr}; | ||||
|     column_t		extra_column {nullptr}; | ||||
|     t_change		m_on_change {nullptr}; | ||||
| 
 | ||||
|     const bool staticbox {true}; | ||||
|     const wxString title {wxString("")}; | ||||
|     size_t label_width {200}; | ||||
|     wxSizer* sizer {nullptr}; | ||||
|     column_t extra_column {nullptr}; | ||||
| //    t_change on_change {nullptr};
 | ||||
|     wxFont			sidetext_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) }; | ||||
|     wxFont			label_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) }; | ||||
| 
 | ||||
|     /// Returns a copy of the pointer of the parent wxWindow.
 | ||||
|     /// Accessor function is because users are not allowed to change the parent
 | ||||
|     /// but defining it as const means a lot of const_casts to deal with wx functions.
 | ||||
|     inline wxWindow* parent() const { return _parent; } | ||||
|     inline wxWindow* parent() const { return m_parent; } | ||||
| 
 | ||||
|     wxFont sidetext_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) }; | ||||
|     wxFont label_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) }; | ||||
| 
 | ||||
| 
 | ||||
|     void append_line(const Line& line); | ||||
|     /*virtual*/ Line create_single_option_line(const Option& option) const; | ||||
|     inline void append_single_option_line(const Option& option) { append_line(create_single_option_line(option)); } | ||||
|     void			append_line(const Line& line); | ||||
|     Line			create_single_option_line(const Option& option) const; | ||||
|     inline void		append_single_option_line(const Option& option) { append_line(create_single_option_line(option)); } | ||||
| 
 | ||||
|     // return a non-owning pointer reference 
 | ||||
|     inline const Field* get_field(t_config_option_key id) const { try { return fields.at(id).get(); } catch (std::out_of_range e) { return nullptr; } } | ||||
|     inline /*const*/ Field* get_field(t_config_option_key id) const { try { return m_fields.at(id).get(); } catch (std::out_of_range e) { return nullptr; } } | ||||
| //!    inline const Option& get_option(t_config_option_key id) const { try { return options.at(id).get(); } catch (std::out_of_range e) { return nullptr; } }
 | ||||
|  //   }
 | ||||
| //!    inline void set_value(t_config_option_key id, boost::any value) { try { fields.at(id).set_value(value); } catch (std::out_of_range e) {;}  }
 | ||||
|     inline void		set_value(t_config_option_key id, boost::any value) { try { m_fields.at(id)->set_value(value); } catch (std::out_of_range e) {;}  } | ||||
| 	boost::any		get_value(t_config_option_key id) { try { return m_fields.at(id)->get_value(); } catch (std::out_of_range e) { ; } } | ||||
| 
 | ||||
|     inline void enable() { for (auto& field : fields) field.second->enable(); } | ||||
|     inline void disable() { for (auto& field : fields) field.second->disable(); } | ||||
| 	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, std::string title, const ConfigDef& configs) : options(configs.options), _parent(_parent), title(wxString(title)) { | ||||
|     OptionsGroup(wxWindow* _parent, std::string title, const ConfigDef& configs) :  | ||||
| 		m_options_map(configs.options), m_parent(_parent), title(wxString(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++; | ||||
|         if (extra_column != nullptr) num_columns++; | ||||
|         _grid_sizer = new wxFlexGridSizer(0, num_columns, 0,0); | ||||
|         static_cast<wxFlexGridSizer*>(_grid_sizer)->SetFlexibleDirection(wxHORIZONTAL); | ||||
|         static_cast<wxFlexGridSizer*>(_grid_sizer)->AddGrowableCol(label_width != 0); | ||||
|         m_grid_sizer = new wxFlexGridSizer(0, num_columns, 0,0); | ||||
|         static_cast<wxFlexGridSizer*>(m_grid_sizer)->SetFlexibleDirection(wxHORIZONTAL); | ||||
|         static_cast<wxFlexGridSizer*>(m_grid_sizer)->AddGrowableCol(label_width != 0); | ||||
| 
 | ||||
|         sizer->Add(_grid_sizer, 0, wxEXPAND | wxALL, wxOSX ? 0: 5); | ||||
|     }; | ||||
|         sizer->Add(m_grid_sizer, 0, wxEXPAND | wxALL, wxOSX ? 0: 5); | ||||
|     } | ||||
| 
 | ||||
| protected: | ||||
|     const t_optiondef_map& options;  | ||||
|     wxWindow* _parent {nullptr}; | ||||
|     const t_optiondef_map&	m_options_map;  | ||||
|     wxWindow*				m_parent {nullptr}; | ||||
| 
 | ||||
|     /// Field list, contains unique_ptrs of the derived type.
 | ||||
|     /// using types that need to know what it is beyond the public interface 
 | ||||
|     /// need to cast based on the related ConfigOptionDef.
 | ||||
|     t_optionfield_map fields; | ||||
|     bool _disabled {false}; | ||||
|     wxGridSizer* _grid_sizer {nullptr}; | ||||
|     t_optionfield_map		m_fields; | ||||
|     bool					m_disabled {false}; | ||||
|     wxGridSizer*			m_grid_sizer {nullptr}; | ||||
| 
 | ||||
|     /// 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); | ||||
| 
 | ||||
|     virtual void _on_kill_focus (t_config_option_key id); | ||||
| //!    virtual void _on_change(t_config_option_key id, config_value value);
 | ||||
| 
 | ||||
|     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); | ||||
| 
 | ||||
|     virtual void		_on_kill_focus (t_config_option_key id); | ||||
| 	virtual void		on_change_OG(t_config_option_key opt_id, boost::any value); | ||||
| }; | ||||
| 
 | ||||
| class ConfigOptionsGroup: public OptionsGroup { | ||||
| public: | ||||
|     /// reference to libslic3r config, non-owning pointer (?).
 | ||||
|     const DynamicPrintConfig* config {nullptr}; | ||||
|     bool full_labels {0}; | ||||
| 	ConfigOptionsGroup(wxWindow* parent, std::string title, DynamicPrintConfig* _config) : OptionsGroup(parent, title, *(_config->def())), config(_config) {} | ||||
|     const DynamicPrintConfig*	m_config {nullptr}; | ||||
|     bool						m_full_labels {0}; | ||||
| 	ConfigOptionsGroup(wxWindow* parent, std::string title, DynamicPrintConfig* _config) :  | ||||
| 		OptionsGroup(parent, title, *(_config->def())), m_config(_config) {} | ||||
| 
 | ||||
| 	void		on_change_OG(t_config_option_key opt_id, boost::any value) override; | ||||
| }; | ||||
| 
 | ||||
| }} | ||||
|  |  | |||
|  | @ -21,12 +21,12 @@ namespace Slic3r { | |||
| namespace GUI { | ||||
| 
 | ||||
| // sub new
 | ||||
| void CTab::create_preset_tab(PresetBundle *preset_bundle, AppConfig *app_config) | ||||
| void Tab::create_preset_tab(PresetBundle *preset_bundle) | ||||
| { | ||||
| 	m_preset_bundle = preset_bundle; | ||||
| 	m_app_config = app_config; | ||||
| 
 | ||||
| 	// Vertical sizer to hold the choice menu and the rest of the page.
 | ||||
| 	CTab *panel = this; | ||||
| 	Tab *panel = this; | ||||
| 	auto  *sizer = new wxBoxSizer(wxVERTICAL); | ||||
| 	sizer->SetSizeHints(panel); | ||||
| 	panel->SetSizer(sizer); | ||||
|  | @ -93,13 +93,13 @@ void CTab::create_preset_tab(PresetBundle *preset_bundle, AppConfig *app_config) | |||
| 	m_treectrl->SetIndent(0); | ||||
| 	m_disable_tree_sel_changed_event = 0; | ||||
| 
 | ||||
| 	m_treectrl->Bind(wxEVT_TREE_SEL_CHANGED, &CTab::OnTreeSelChange, this); | ||||
| 	m_treectrl->Bind(wxEVT_KEY_DOWN, &CTab::OnKeyDown, this); | ||||
| 	m_treectrl->Bind(wxEVT_COMBOBOX, &CTab::OnComboBox, this);  | ||||
| 	m_treectrl->Bind(wxEVT_TREE_SEL_CHANGED, &Tab::OnTreeSelChange, this); | ||||
| 	m_treectrl->Bind(wxEVT_KEY_DOWN, &Tab::OnKeyDown, this); | ||||
| 	m_treectrl->Bind(wxEVT_COMBOBOX, &Tab::OnComboBox, this);  | ||||
| 
 | ||||
| 	m_btn_save_preset->Bind(wxEVT_BUTTON, &CTab::save_preset, this); | ||||
| 	m_btn_delete_preset->Bind(wxEVT_BUTTON, &CTab::delete_preset, this); | ||||
| 	m_btn_hide_incompatible_presets->Bind(wxEVT_BUTTON, &CTab::toggle_show_hide_incompatible, this); | ||||
| 	m_btn_save_preset->Bind(wxEVT_BUTTON, &Tab::save_preset, this); | ||||
| 	m_btn_delete_preset->Bind(wxEVT_BUTTON, &Tab::delete_preset, this); | ||||
| 	m_btn_hide_incompatible_presets->Bind(wxEVT_BUTTON, &Tab::toggle_show_hide_incompatible, this); | ||||
| 
 | ||||
| 	// Initialize the DynamicPrintConfig by default keys/values.
 | ||||
| 	// Possible %params keys: no_controller
 | ||||
|  | @ -108,7 +108,7 @@ void CTab::create_preset_tab(PresetBundle *preset_bundle, AppConfig *app_config) | |||
| //	_update();
 | ||||
| } | ||||
| 
 | ||||
| CPageShp CTab::add_options_page(wxString title, std::string icon, bool is_extruder_pages/* = false*/) | ||||
| PageShp Tab::add_options_page(wxString title, std::string icon, bool is_extruder_pages/* = false*/) | ||||
| { | ||||
| 	// Index of icon in an icon list $self->{icons}.
 | ||||
| 	auto icon_idx = 0; | ||||
|  | @ -124,7 +124,7 @@ CPageShp CTab::add_options_page(wxString title, std::string icon, bool is_extrud | |||
| 		} | ||||
| 	} | ||||
| 	// Initialize the page.
 | ||||
| 	CPageShp page(new CPage(this, title, icon_idx)); | ||||
| 	PageShp page(new Page(this, title, icon_idx)); | ||||
| 	page->SetScrollbars(1, 1, 1, 1); | ||||
| 	page->Hide(); | ||||
| 	m_hsizer->Add(page.get(), 1, wxEXPAND | wxLEFT, 5); | ||||
|  | @ -135,7 +135,64 @@ CPageShp CTab::add_options_page(wxString title, std::string icon, bool is_extrud | |||
| 	return page; | ||||
| } | ||||
| 
 | ||||
| void CTab::load_key_value(std::string opt_key, std::vector<std::string> value) | ||||
| // 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;
 | ||||
| } | ||||
| 
 | ||||
| // 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; | ||||
| 	for(auto opt_key : m_config.diff(config)) { | ||||
| 		ConfigOption* opt; | ||||
| 		switch ( config.def()->get(opt_key)->type ){ | ||||
| //		case coFloatOrPercent:
 | ||||
| 		case coPercent: | ||||
| //		case coPercents:			
 | ||||
| 		case coFloat: | ||||
| 			opt = new ConfigOptionFloat(config.opt_float(opt_key)); | ||||
| 			break; | ||||
| //		case coFloats:
 | ||||
| 		case coString: | ||||
| 			opt = new ConfigOptionString(config.opt_string(opt_key)); | ||||
| 			break; | ||||
| 		case coStrings: | ||||
| 			break; | ||||
| 		case coBool: | ||||
| 			opt = new ConfigOptionBool(config.opt_bool(opt_key)); | ||||
| 			break; | ||||
| 		case coBools: | ||||
| //			opt = new ConfigOptionBools(0, config.opt_bool(opt_key)); //! 0?
 | ||||
| 			break; | ||||
| 		case coInt: | ||||
| 			opt = new ConfigOptionInt(config.opt_int(opt_key)); | ||||
| 			break; | ||||
| 		case coInts: | ||||
| 			break; | ||||
| 		case coEnum: | ||||
| 			break; | ||||
| 		case coPoints: | ||||
| 			break; | ||||
| 		case coNone:   break; | ||||
| 		default: | ||||
| 			break; | ||||
| 		} | ||||
| 		m_config.set_key_value(opt_key, opt); | ||||
| 		modified = 1; | ||||
| 	} | ||||
| 	if (modified) { | ||||
| //		update_dirty();
 | ||||
| 		//# Initialize UI components with the config values.
 | ||||
| //		_reload_config();
 | ||||
| 		update(); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void Tab::load_key_value(std::string opt_key, std::vector<std::string> value) | ||||
| { | ||||
| 	// # To be called by custom widgets, load a value into a config,
 | ||||
| 	// # update the preset selection boxes (the dirty flags)
 | ||||
|  | @ -151,9 +208,10 @@ void CTab::load_key_value(std::string opt_key, std::vector<std::string> value) | |||
| 	// $self->_update;
 | ||||
| } | ||||
| 
 | ||||
| void CTabPrint::build() | ||||
| void TabPrint::build() | ||||
| { | ||||
| 	m_config = m_preset_bundle->prints.get_edited_preset().config; | ||||
| 	m_presets = &m_preset_bundle->prints; | ||||
| 	m_config = m_presets->get_edited_preset().config; | ||||
| 	m_config_def = m_config.def(); | ||||
| 
 | ||||
| 	auto page = add_options_page("Layers and perimeters", "layers.png"); | ||||
|  | @ -352,7 +410,211 @@ void CTabPrint::build() | |||
| 		optgroup->append_line(line); | ||||
| } | ||||
| 
 | ||||
| void CTabFilament::build() | ||||
| void TabPrint::update() | ||||
| { | ||||
| 	Freeze(); | ||||
| 
 | ||||
| 	if ( m_config.opt_bool("spiral_vase") &&  | ||||
| 		!(m_config.opt_int("perimeters") == 1 && m_config.opt_int("top_solid_layers") == 0 && m_config.opt_float("fill_density") == 0)) { | ||||
| 		std::string msg_text = "The Spiral Vase mode requires:\n" | ||||
| 			"- one perimeter\n" | ||||
|  			"- no top solid layers\n" | ||||
|  			"- 0% fill density\n" | ||||
|  			"- no support material\n" | ||||
|  			"- no ensure_vertical_shell_thickness\n" | ||||
|   			"\nShall I adjust those settings in order to enable Spiral Vase?"; | ||||
| 		auto dialog = new wxMessageDialog(parent(), msg_text, wxT("Spiral Vase"), wxICON_WARNING | wxYES | wxNO); | ||||
| 		DynamicPrintConfig new_conf = m_config;//new DynamicPrintConfig;
 | ||||
| 		if (dialog->ShowModal() == wxID_YES) { | ||||
| 			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)); | ||||
| 			new_conf.set_key_value("ensure_vertical_shell_thickness", new ConfigOptionBool(false)); | ||||
| 		} | ||||
| 		else { | ||||
| 			new_conf.set_key_value("spiral_vase", new ConfigOptionBool(false)); | ||||
| 		} | ||||
|  		load_config(new_conf); | ||||
| 	} | ||||
| 
 | ||||
| // 	if ($config->wipe_tower &&
 | ||||
| // 		($config->first_layer_height != 0.2 || $config->layer_height < 0.15 || $config->layer_height > 0.35)) {
 | ||||
| // 		my $dialog = Wx::MessageDialog->new($self,
 | ||||
| // 			"The Wipe Tower currently supports only:\n"
 | ||||
| // 			. "- first layer height 0.2mm\n"
 | ||||
| // 			. "- layer height from 0.15mm to 0.35mm\n"
 | ||||
| // 			. "\nShall I adjust those settings in order to enable the Wipe Tower?",
 | ||||
| // 			'Wipe Tower', wxICON_WARNING | wxYES | wxNO);
 | ||||
| // 		my $new_conf = Slic3r::Config->new;
 | ||||
| // 		if ($dialog->ShowModal() == wxID_YES) {
 | ||||
| // 			$new_conf->set("first_layer_height", 0.2);
 | ||||
| // 			$new_conf->set("layer_height", 0.15) if  $config->layer_height < 0.15;
 | ||||
| // 			$new_conf->set("layer_height", 0.35) if  $config->layer_height > 0.35;
 | ||||
| // 		}
 | ||||
| // 		else {
 | ||||
| // 			$new_conf->set("wipe_tower", 0);
 | ||||
| // 		}
 | ||||
| // 		$self->load_config($new_conf);
 | ||||
| // 	}
 | ||||
| // 
 | ||||
| // 	if ($config->wipe_tower && $config->support_material && $config->support_material_contact_distance > 0. &&
 | ||||
| // 		($config->support_material_extruder != 0 || $config->support_material_interface_extruder != 0)) {
 | ||||
| // 		my $dialog = Wx::MessageDialog->new($self,
 | ||||
| // 			"The Wipe Tower currently supports the non-soluble supports only\n"
 | ||||
| // 			. "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"
 | ||||
| // 			. "\nShall I adjust those settings in order to enable the Wipe Tower?",
 | ||||
| // 			'Wipe Tower', wxICON_WARNING | wxYES | wxNO);
 | ||||
| // 		my $new_conf = Slic3r::Config->new;
 | ||||
| // 		if ($dialog->ShowModal() == wxID_YES) {
 | ||||
| // 			$new_conf->set("support_material_extruder", 0);
 | ||||
| // 			$new_conf->set("support_material_interface_extruder", 0);
 | ||||
| // 		}
 | ||||
| // 		else {
 | ||||
| // 			$new_conf->set("wipe_tower", 0);
 | ||||
| // 		}
 | ||||
| // 		$self->load_config($new_conf);
 | ||||
| // 	}
 | ||||
| // 
 | ||||
| // 	if ($config->wipe_tower && $config->support_material && $config->support_material_contact_distance == 0 &&
 | ||||
| // 		!$config->support_material_synchronize_layers) {
 | ||||
| // 		my $dialog = Wx::MessageDialog->new($self,
 | ||||
| // 			"For the Wipe Tower to work with the soluble supports, the support layers\n"
 | ||||
| // 			. "need to be synchronized with the object layers.\n"
 | ||||
| // 			. "\nShall I synchronize support layers in order to enable the Wipe Tower?",
 | ||||
| // 			'Wipe Tower', wxICON_WARNING | wxYES | wxNO);
 | ||||
| // 		my $new_conf = Slic3r::Config->new;
 | ||||
| // 		if ($dialog->ShowModal() == wxID_YES) {
 | ||||
| // 			$new_conf->set("support_material_synchronize_layers", 1);
 | ||||
| // 		}
 | ||||
| // 		else {
 | ||||
| // 			$new_conf->set("wipe_tower", 0);
 | ||||
| // 		}
 | ||||
| // 		$self->load_config($new_conf);
 | ||||
| // 	}
 | ||||
| // 
 | ||||
| // 	if ($config->support_material) {
 | ||||
| // 		# Ask only once.
 | ||||
| // 		if (!$self->{support_material_overhangs_queried}) {
 | ||||
| // 			$self->{support_material_overhangs_queried} = 1;
 | ||||
| // 			if ($config->overhangs != 1) {
 | ||||
| // 				my $dialog = Wx::MessageDialog->new($self,
 | ||||
| // 					"Supports work better, if the following feature is enabled:\n"
 | ||||
| // 					. "- Detect bridging perimeters\n"
 | ||||
| // 					. "\nShall I adjust those settings for supports?",
 | ||||
| // 					'Support Generator', wxICON_WARNING | wxYES | wxNO | wxCANCEL);
 | ||||
| // 				my $answer = $dialog->ShowModal();
 | ||||
| // 				my $new_conf = Slic3r::Config->new;
 | ||||
| // 				if ($answer == wxID_YES) {
 | ||||
| // 					# Enable "detect bridging perimeters".
 | ||||
| // 					$new_conf->set("overhangs", 1);
 | ||||
| // 				} elsif($answer == wxID_NO) {
 | ||||
| // 					# Do nothing, leave supports on and "detect bridging perimeters" off.
 | ||||
| // 				} elsif($answer == wxID_CANCEL) {
 | ||||
| // 					# Disable supports.
 | ||||
| // 					$new_conf->set("support_material", 0);
 | ||||
| // 					$self->{support_material_overhangs_queried} = 0;
 | ||||
| // 				}
 | ||||
| // 				$self->load_config($new_conf);
 | ||||
| // 			}
 | ||||
| // 		}
 | ||||
| // 	}
 | ||||
| // 	else {
 | ||||
| // 		$self->{support_material_overhangs_queried} = 0;
 | ||||
| // 	}
 | ||||
| // 
 | ||||
| // 	if ($config->fill_density == 100
 | ||||
| // 		&& !first{ $_ eq $config->fill_pattern } @{$Slic3r::Config::Options->{external_fill_pattern}{values}}) {
 | ||||
| // 		my $dialog = Wx::MessageDialog->new($self,
 | ||||
| // 			"The ".$config->fill_pattern . " infill pattern is not supposed to work at 100% density.\n"
 | ||||
| // 			. "\nShall I switch to rectilinear fill pattern?",
 | ||||
| // 			'Infill', wxICON_WARNING | wxYES | wxNO);
 | ||||
| // 
 | ||||
| // 		my $new_conf = Slic3r::Config->new;
 | ||||
| // 		if ($dialog->ShowModal() == wxID_YES) {
 | ||||
| // 			$new_conf->set("fill_pattern", 'rectilinear');
 | ||||
| // 			$new_conf->set("fill_density", 100);
 | ||||
| // 		}
 | ||||
| // 		else {
 | ||||
| // 			$new_conf->set("fill_density", 40);
 | ||||
| // 		}
 | ||||
| // 		$self->load_config($new_conf);
 | ||||
| // 	}
 | ||||
| // 
 | ||||
| // 	my $have_perimeters = $config->perimeters > 0;
 | ||||
| // 	$self->get_field($_)->toggle($have_perimeters)
 | ||||
| // 		for qw(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);
 | ||||
| // 
 | ||||
| // 	my $have_infill = $config->fill_density > 0;
 | ||||
| // 	# infill_extruder uses the same logic as in Print::extruders()
 | ||||
| // 	$self->get_field($_)->toggle($have_infill)
 | ||||
| // 		for qw(fill_pattern infill_every_layers infill_only_where_needed solid_infill_every_layers
 | ||||
| // 			solid_infill_below_area infill_extruder);
 | ||||
| // 
 | ||||
| // 			my $have_solid_infill = ($config->top_solid_layers > 0) || ($config->bottom_solid_layers > 0);
 | ||||
| // 	# solid_infill_extruder uses the same logic as in Print::extruders()
 | ||||
| // 	$self->get_field($_)->toggle($have_solid_infill)
 | ||||
| // 		for qw(external_fill_pattern infill_first solid_infill_extruder solid_infill_extrusion_width
 | ||||
| // 			solid_infill_speed);
 | ||||
| // 
 | ||||
| // 			$self->get_field($_)->toggle($have_infill || $have_solid_infill)
 | ||||
| // 			for qw(fill_angle bridge_angle infill_extrusion_width infill_speed bridge_speed);
 | ||||
| // 
 | ||||
| // 	$self->get_field('gap_fill_speed')->toggle($have_perimeters && $have_infill);
 | ||||
| // 
 | ||||
| // 	my $have_top_solid_infill = $config->top_solid_layers > 0;
 | ||||
| // 	$self->get_field($_)->toggle($have_top_solid_infill)
 | ||||
| // 		for qw(top_infill_extrusion_width top_solid_infill_speed);
 | ||||
| // 
 | ||||
| // 	my $have_default_acceleration = $config->default_acceleration > 0;
 | ||||
| // 	$self->get_field($_)->toggle($have_default_acceleration)
 | ||||
| // 		for qw(perimeter_acceleration infill_acceleration bridge_acceleration first_layer_acceleration);
 | ||||
| // 
 | ||||
| // 	my $have_skirt = $config->skirts > 0 || $config->min_skirt_length > 0;
 | ||||
| // 	$self->get_field($_)->toggle($have_skirt)
 | ||||
| // 		for qw(skirt_distance skirt_height);
 | ||||
| // 
 | ||||
| // 	my $have_brim = $config->brim_width > 0;
 | ||||
| // 	# perimeter_extruder uses the same logic as in Print::extruders()
 | ||||
| // 	$self->get_field('perimeter_extruder')->toggle($have_perimeters || $have_brim);
 | ||||
| // 
 | ||||
| // 	my $have_raft = $config->raft_layers > 0;
 | ||||
| // 	my $have_support_material = $config->support_material || $have_raft;
 | ||||
| // 	my $have_support_interface = $config->support_material_interface_layers > 0;
 | ||||
| // 	my $have_support_soluble = $have_support_material && $config->support_material_contact_distance == 0;
 | ||||
| // 	$self->get_field($_)->toggle($have_support_material)
 | ||||
| // 		for qw(support_material_threshold support_material_pattern support_material_with_sheath
 | ||||
| // 			support_material_spacing support_material_angle
 | ||||
| // 			support_material_interface_layers dont_support_bridges
 | ||||
| // 			support_material_extrusion_width support_material_contact_distance support_material_xy_spacing);
 | ||||
| // 	$self->get_field($_)->toggle($have_support_material && $have_support_interface)
 | ||||
| // 		for qw(support_material_interface_spacing support_material_interface_extruder
 | ||||
| // 			support_material_interface_speed support_material_interface_contact_loops);
 | ||||
| // 			$self->get_field('support_material_synchronize_layers')->toggle($have_support_soluble);
 | ||||
| // 
 | ||||
| // 	$self->get_field('perimeter_extrusion_width')->toggle($have_perimeters || $have_skirt || $have_brim);
 | ||||
| // 	$self->get_field('support_material_extruder')->toggle($have_support_material || $have_skirt);
 | ||||
| // 	$self->get_field('support_material_speed')->toggle($have_support_material || $have_brim || $have_skirt);
 | ||||
| // 
 | ||||
| // 	my $have_sequential_printing = $config->complete_objects;
 | ||||
| // 	$self->get_field($_)->toggle($have_sequential_printing)
 | ||||
| // 		for qw(extruder_clearance_radius extruder_clearance_height);
 | ||||
| // 
 | ||||
| // 	my $have_ooze_prevention = $config->ooze_prevention;
 | ||||
| // 	$self->get_field($_)->toggle($have_ooze_prevention)
 | ||||
| // 		for qw(standby_temperature_delta);
 | ||||
| // 
 | ||||
| // 	my $have_wipe_tower = $config->wipe_tower;
 | ||||
| // 	$self->get_field($_)->toggle($have_wipe_tower)
 | ||||
| // 		for qw(wipe_tower_x wipe_tower_y wipe_tower_width wipe_tower_per_color_wipe);
 | ||||
| 
 | ||||
| 	Thaw(); | ||||
| } | ||||
| 
 | ||||
| void TabFilament::build() | ||||
| { | ||||
| 	m_config = m_preset_bundle->filaments.get_edited_preset().config; | ||||
| 	m_config_def = m_config.def(); | ||||
|  | @ -447,7 +709,7 @@ void CTabFilament::build() | |||
| 		optgroup->append_line(line); | ||||
| } | ||||
| 
 | ||||
| wxSizer* CTabFilament::description_line_widget(wxWindow* parent, wxStaticText* StaticText) | ||||
| wxSizer* TabFilament::description_line_widget(wxWindow* parent, wxStaticText* StaticText) | ||||
| { | ||||
| 	StaticText = new wxStaticText(parent, wxID_ANY, "gfghjkkl;\n fgdsufhsreotklg\n iesrftorsikgyfkh\nauiwrhfidj", wxDefaultPosition, wxDefaultSize); | ||||
| 	auto font = (new wxSystemSettings)->GetFont(wxSYS_DEFAULT_GUI_FONT); | ||||
|  | @ -460,7 +722,7 @@ wxSizer* CTabFilament::description_line_widget(wxWindow* parent, wxStaticText* S | |||
| 	return sizer; | ||||
| } | ||||
| 
 | ||||
| void CTabPrinter::build() | ||||
| void TabPrinter::build() | ||||
| { | ||||
| 	m_config = m_preset_bundle->printers.get_edited_preset().config; | ||||
| 	m_config_def = m_config.def();		// It will be used in get_option_(const std::string title)
 | ||||
|  | @ -520,7 +782,7 @@ void CTabPrinter::build() | |||
| // 		});
 | ||||
| 
 | ||||
| 		//if (!$params{ no_controller })
 | ||||
| 		if (m_app_config->get("no_controller").empty()) | ||||
| 		if (!m_no_controller/*m_app_config->get("no_controller").empty()*/) | ||||
| 		{ | ||||
| 		optgroup = page->new_optgroup("USB/Serial connection"); | ||||
| 			line = {"Serial port", ""}; | ||||
|  | @ -692,17 +954,17 @@ void CTabPrinter::build() | |||
| 	build_extruder_pages(); | ||||
| 
 | ||||
| // 	$self->_update_serial_ports if (!$params{ no_controller });
 | ||||
| 	if (m_app_config->get("no_controller").empty()){ | ||||
| 	if (!m_no_controller/*m_app_config->get("no_controller").empty()*/){ | ||||
| 		Field *field = optgroup->get_field("serial_port"); | ||||
| 		Choice *choice = static_cast<Choice *>(field); | ||||
| 		choice->set_values(scan_serial_ports()); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void CTabPrinter::build_extruder_pages(){ | ||||
| void TabPrinter::build_extruder_pages(){ | ||||
| //	auto default_config = m_preset_bundle->full_config();
 | ||||
| 
 | ||||
| 	std::vector<CPageShp>	extruder_pages;	 | ||||
| 	std::vector<PageShp>	extruder_pages;	 | ||||
| 
 | ||||
| 	for (auto extruder_idx = 0; extruder_idx < m_extruders_count; ++extruder_idx){ | ||||
| 		//# build page
 | ||||
|  | @ -750,7 +1012,7 @@ void CTabPrinter::build_extruder_pages(){ | |||
| 	} | ||||
| 
 | ||||
| 	// # rebuild page list
 | ||||
| 	CPageShp page_note = m_pages.back(); | ||||
| 	PageShp page_note = m_pages.back(); | ||||
| 	m_pages.pop_back(); | ||||
| 	for (auto page_extruder : extruder_pages) | ||||
| 		m_pages.push_back(page_extruder); | ||||
|  | @ -759,8 +1021,13 @@ void CTabPrinter::build_extruder_pages(){ | |||
| 	rebuild_page_tree(); | ||||
| } | ||||
| 
 | ||||
| void Tab::load_current_preset() | ||||
| { | ||||
| 	; | ||||
| } | ||||
| 
 | ||||
| //Regerenerate content of the page tree.
 | ||||
| void CTab::rebuild_page_tree() | ||||
| void Tab::rebuild_page_tree() | ||||
| { | ||||
| 	Freeze(); | ||||
| 	// get label of the currently selected item
 | ||||
|  | @ -786,10 +1053,10 @@ void CTab::rebuild_page_tree() | |||
| 	Thaw(); | ||||
| } | ||||
| 
 | ||||
| void CTab::OnTreeSelChange(wxTreeEvent& event) | ||||
| void Tab::OnTreeSelChange(wxTreeEvent& event) | ||||
| { | ||||
| 	if (m_disable_tree_sel_changed_event) return; | ||||
| 	CPage* page = nullptr; | ||||
| 	Page* page = nullptr; | ||||
| 	auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection()); | ||||
| 	for (auto p : m_pages) | ||||
| 		if (p->title() == selection) | ||||
|  | @ -806,19 +1073,19 @@ void CTab::OnTreeSelChange(wxTreeEvent& event) | |||
| 	Refresh(); | ||||
| } | ||||
| 
 | ||||
| void CTab::OnKeyDown(wxKeyEvent& event) | ||||
| void Tab::OnKeyDown(wxKeyEvent& event) | ||||
| { | ||||
| 	event.GetKeyCode() == WXK_TAB ? | ||||
| 		m_treectrl->Navigate(event.ShiftDown() ? wxNavigationKeyEvent::IsBackward : wxNavigationKeyEvent::IsForward) : | ||||
| 		event.Skip(); | ||||
| }; | ||||
| 
 | ||||
| void CTab::save_preset(wxCommandEvent &event){}; | ||||
| void CTab::delete_preset(wxCommandEvent &event){}; | ||||
| void CTab::toggle_show_hide_incompatible(wxCommandEvent &event){}; | ||||
| void Tab::save_preset(wxCommandEvent &event){}; | ||||
| void Tab::delete_preset(wxCommandEvent &event){}; | ||||
| void Tab::toggle_show_hide_incompatible(wxCommandEvent &event){}; | ||||
| 
 | ||||
| //	# Return a callback to create a Tab widget to mark the preferences as compatible / incompatible to the current printer.
 | ||||
| wxSizer* CTab::compatible_printers_widget(wxWindow* parent, wxCheckBox* checkbox, wxButton* btn) | ||||
| wxSizer* Tab::compatible_printers_widget(wxWindow* parent, wxCheckBox* checkbox, wxButton* btn) | ||||
| { | ||||
| 	checkbox = new wxCheckBox(parent, wxID_ANY, "All"); | ||||
| 
 | ||||
|  | @ -890,20 +1157,20 @@ wxSizer* CTab::compatible_printers_widget(wxWindow* parent, wxCheckBox* checkbox | |||
| } | ||||
| 
 | ||||
| // package Slic3r::GUI::Tab::Page;
 | ||||
| ConfigOptionsGroupShp CPage::new_optgroup(std::string title, int noncommon_label_width /*= -1*/) | ||||
| ConfigOptionsGroupShp Page::new_optgroup(std::string title, int noncommon_label_width /*= -1*/) | ||||
| { | ||||
| 	//! config_ have to be "right"
 | ||||
| 	ConfigOptionsGroupShp optgroup = std::make_shared<ConfigOptionsGroup>(this, title, m_config); | ||||
| 	if (noncommon_label_width >= 0) | ||||
| 		optgroup->label_width = noncommon_label_width; | ||||
| 
 | ||||
| //         on_change       => sub {
 | ||||
| //             my ($opt_key, $value) = @_;
 | ||||
| //             wxTheApp->CallAfter(sub {
 | ||||
| //                 $self->GetParent->update_dirty;
 | ||||
| //                 $self->GetParent->_on_value_change($opt_key, $value);
 | ||||
| //             });
 | ||||
| //         },
 | ||||
| 	optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){ | ||||
| 		//! This function will be called from OptionGroup.					
 | ||||
|         wxTheApp->CallAfter([this, opt_key, value]() { | ||||
| 			static_cast<Tab*>(GetParent())->update_dirty(); | ||||
| 			static_cast<Tab*>(GetParent())->on_value_change(opt_key, value); | ||||
|         }); | ||||
|     }, | ||||
| 
 | ||||
| 	vsizer()->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 10); | ||||
| 	m_optgroups.push_back(optgroup); | ||||
|  |  | |||
|  | @ -36,14 +36,14 @@ namespace GUI { | |||
| // Single Tab page containing a{ vsizer } of{ optgroups }
 | ||||
| // package Slic3r::GUI::Tab::Page;
 | ||||
| using ConfigOptionsGroupShp = std::shared_ptr<ConfigOptionsGroup>; | ||||
| class CPage : public wxScrolledWindow | ||||
| class Page : public wxScrolledWindow | ||||
| { | ||||
| 	wxWindow*		m_parent; | ||||
| 	wxString		m_title; | ||||
| 	size_t			m_iconID; | ||||
| 	wxBoxSizer*		m_vsizer; | ||||
| public: | ||||
| 	CPage(wxWindow* parent, const wxString title, const int iconID) : | ||||
| 	Page(wxWindow* parent, const wxString title, const int iconID) : | ||||
| 			m_parent(parent), | ||||
| 			m_title(title), | ||||
| 			m_iconID(iconID) | ||||
|  | @ -52,7 +52,7 @@ public: | |||
| 		m_vsizer = new wxBoxSizer(wxVERTICAL); | ||||
| 		SetSizer(m_vsizer); | ||||
| 	} | ||||
| 	~CPage(){} | ||||
| 	~Page(){} | ||||
| 
 | ||||
| public: | ||||
| 	std::vector <ConfigOptionsGroupShp> m_optgroups;  // $self->{optgroups} = [];
 | ||||
|  | @ -69,8 +69,8 @@ public: | |||
| 
 | ||||
| // Slic3r::GUI::Tab;
 | ||||
| 
 | ||||
| using CPageShp = std::shared_ptr<CPage>; | ||||
| class CTab: public wxPanel | ||||
| using PageShp = std::shared_ptr<Page>; | ||||
| class Tab: public wxPanel | ||||
| { | ||||
| 	wxNotebook*			m_parent; | ||||
| protected: | ||||
|  | @ -90,26 +90,35 @@ protected: | |||
| 
 | ||||
| 	int					m_icon_count; | ||||
| 	std::map<std::string, size_t>	m_icon_index;		// Map from an icon file name to its index in $self->{icons}.
 | ||||
| 	std::vector<CPageShp>			m_pages;	// $self->{pages} = [];
 | ||||
| 	std::vector<PageShp>			m_pages;	// $self->{pages} = [];
 | ||||
| 	bool				m_disable_tree_sel_changed_event; | ||||
| 
 | ||||
| public: | ||||
| 	PresetBundle*		m_preset_bundle; | ||||
| 	AppConfig*			m_app_config; | ||||
| 	bool				m_no_controller; | ||||
| 	PresetCollection*	m_presets; | ||||
| 	DynamicPrintConfig	m_config;		//! tmp_val
 | ||||
| 	const ConfigDef*	m_config_def;	// It will be used in get_option_(const std::string title)
 | ||||
| 	t_change			m_on_value_change{ nullptr }; | ||||
| 
 | ||||
| public: | ||||
| 	CTab() {} | ||||
| 	CTab(wxNotebook* parent, const char *title) : m_parent(parent), m_title(title) { | ||||
| 	Tab() {} | ||||
| 	Tab(wxNotebook* parent, const char *title) : m_parent(parent), m_title(title) { | ||||
| 		Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL); | ||||
| 	} | ||||
| 	~CTab(){} | ||||
| 	~Tab(){} | ||||
| 
 | ||||
| 	wxWindow*	parent() const { return m_parent; } | ||||
| 	wxString	title()	 const { return m_title; } | ||||
| 	 | ||||
| 	void		create_preset_tab(PresetBundle *preset_bundle, AppConfig *app_config); | ||||
| 	void		create_preset_tab(PresetBundle *preset_bundle); | ||||
| 	void		on_value_change(std::string opt_key, boost::any value){ | ||||
| 		if (m_on_value_change != nullptr) | ||||
| 			m_on_value_change(opt_key, value); | ||||
| 		update(); | ||||
| 	}; | ||||
| 	void		on_presets_changed(){}; | ||||
| 	void		load_current_preset(); | ||||
| 	void		rebuild_page_tree(); | ||||
| 	void		select_preset(wxString preset_name){}; | ||||
| 
 | ||||
|  | @ -124,37 +133,39 @@ public: | |||
| 	void		delete_preset(wxCommandEvent &event); | ||||
| 	void		toggle_show_hide_incompatible(wxCommandEvent &event); | ||||
| 
 | ||||
| 	CPageShp	add_options_page(wxString title, std::string icon, bool is_extruder_pages = false); | ||||
| 	PageShp		add_options_page(wxString title, std::string icon, bool is_extruder_pages = false); | ||||
| 
 | ||||
| 	virtual void	build() = 0; | ||||
| 	virtual void	update() = 0; | ||||
| 	void			update_dirty(); | ||||
| 	void			load_config(DynamicPrintConfig config); | ||||
| 
 | ||||
| 	Option get_option(const std::string title, int idx = -1){ | ||||
| 	Option		get_option(const std::string title, int idx = -1){ | ||||
| 		return Option(*m_config_def->get(title), idx == -1 ? title : title + std::to_string(idx)); | ||||
| 	}	 | ||||
| }; | ||||
| 
 | ||||
| //Slic3r::GUI::Tab::Print;
 | ||||
| class CTabPrint : public CTab | ||||
| class TabPrint : public Tab | ||||
| { | ||||
| public: | ||||
| 	CTabPrint() {} | ||||
| 	CTabPrint(wxNotebook* parent, const char *title) : CTab(parent, title) {} | ||||
| 	~CTabPrint(){} | ||||
| 	TabPrint() {} | ||||
| 	TabPrint(wxNotebook* parent, const char *title) : Tab(parent, title) {} | ||||
| 	~TabPrint(){} | ||||
| 
 | ||||
| 	void		build() override; | ||||
| 	void		update() override{}; | ||||
| 	void		update() override; | ||||
| }; | ||||
| 
 | ||||
| //Slic3r::GUI::Tab::Filament;
 | ||||
| class CTabFilament : public CTab | ||||
| class TabFilament : public Tab | ||||
| { | ||||
| 	wxStaticText*	m_cooling_description_line; | ||||
| 	wxStaticText*	m_volumetric_speed_description_line; | ||||
| public: | ||||
| 	CTabFilament() {} | ||||
| 	CTabFilament(wxNotebook* parent, const char *title) : CTab(parent, title) {} | ||||
| 	~CTabFilament(){} | ||||
| 	TabFilament() {} | ||||
| 	TabFilament(wxNotebook* parent, const char *title) : Tab(parent, title) {} | ||||
| 	~TabFilament(){} | ||||
| 
 | ||||
| 	wxSizer*		description_line_widget(wxWindow* parent, wxStaticText* StaticText); | ||||
| 
 | ||||
|  | @ -163,7 +174,7 @@ public: | |||
| }; | ||||
| 
 | ||||
| //Slic3r::GUI::Tab::Printer;
 | ||||
| class CTabPrinter : public CTab | ||||
| class TabPrinter : public Tab | ||||
| { | ||||
| public: | ||||
| 	wxButton*	serial_test_btn; | ||||
|  | @ -172,9 +183,9 @@ public: | |||
| 	size_t		m_extruders_count; | ||||
| 
 | ||||
| public: | ||||
| 	CTabPrinter() {} | ||||
| 	CTabPrinter(wxNotebook* parent, const char *title) : CTab(parent, title) {} | ||||
| 	~CTabPrinter(){} | ||||
| 	TabPrinter() {} | ||||
| 	TabPrinter(wxNotebook* parent, const char *title) : Tab(parent, title) {} | ||||
| 	~TabPrinter(){} | ||||
| 
 | ||||
| 	void		build() override; | ||||
| 	void		update() override{}; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 YuSanka
						YuSanka