From c18b28e27ca4acf68482f981620632d86b1ac356 Mon Sep 17 00:00:00 2001
From: bubnikv <bubnikv@gmail.com>
Date: Mon, 16 Apr 2018 11:03:08 +0200
Subject: [PATCH 01/20] Implemented caching of often rendered bitmaps on the
 Tab UI.

---
 xs/src/slic3r/GUI/Field.cpp        |  8 ++---
 xs/src/slic3r/GUI/Field.hpp        | 32 +++++++++++++++++--
 xs/src/slic3r/GUI/OptionsGroup.cpp |  4 +--
 xs/src/slic3r/GUI/OptionsGroup.hpp |  2 +-
 xs/src/slic3r/GUI/Tab.cpp          | 50 +++++++++++++++---------------
 xs/src/slic3r/GUI/Tab.hpp          | 19 +++++++++---
 6 files changed, 76 insertions(+), 39 deletions(-)

diff --git a/xs/src/slic3r/GUI/Field.cpp b/xs/src/slic3r/GUI/Field.cpp
index c68b2304c..a32943da0 100644
--- a/xs/src/slic3r/GUI/Field.cpp
+++ b/xs/src/slic3r/GUI/Field.cpp
@@ -26,16 +26,16 @@ namespace Slic3r { namespace GUI {
 			m_Undo_btn->SetBackgroundColour(color);
 			m_Undo_to_sys_btn->SetBackgroundColour(color);
 		}
-		m_Undo_btn->SetBitmap(wxBitmap(from_u8(var("bullet_white.png")), wxBITMAP_TYPE_PNG));
+//		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(); }));
 		m_Undo_to_sys_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ on_back_to_sys_value(); }));
 
 		BUILD();
 	}
 
-	void Field::set_nonsys_btn_icon(const std::string& icon){
-		m_Undo_to_sys_btn->SetBitmap(wxBitmap(from_u8(var(icon)), wxBITMAP_TYPE_PNG));
-	}
+//	void Field::set_nonsys_btn_icon(const wxBitmap& icon){
+//		m_Undo_to_sys_btn->SetBitmap(icon);
+//	}
 
 	void Field::on_kill_focus(wxEvent& event) {
         // Without this, there will be nasty focus bugs on Windows.
diff --git a/xs/src/slic3r/GUI/Field.hpp b/xs/src/slic3r/GUI/Field.hpp
index cdc7c0d81..2b2646b7c 100644
--- a/xs/src/slic3r/GUI/Field.hpp
+++ b/xs/src/slic3r/GUI/Field.hpp
@@ -91,8 +91,6 @@ public:
     virtual void		disable() = 0;
 
 	wxStaticText*		m_Label = nullptr;
-	wxButton*			m_Undo_btn = nullptr;
-	wxButton*			m_Undo_to_sys_btn = nullptr;
 
     /// Fires the enable or disable function, based on the input.
     inline void			toggle(bool en) { en ? enable() : disable(); }
@@ -100,7 +98,7 @@ public:
 	virtual wxString	get_tooltip_text(const wxString& default_string);
 
     // set icon to "UndoToSystemValue" button according to an inheritance of preset
-	void				set_nonsys_btn_icon(const std::string& icon);
+//	void				set_nonsys_btn_icon(const wxBitmap& icon);
 
     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) {};
@@ -120,6 +118,34 @@ public:
         p->PostInitialize();
 		return std::move(p); //!p;
     }
+
+    bool 	set_undo_bitmap(const wxBitmap *bmp) {
+    	if (m_undo_bitmap != bmp) {
+    		m_undo_bitmap = bmp;
+    		m_Undo_btn->SetBitmap(*bmp);
+    		return true;
+    	}
+    	return false;
+    }
+
+    bool 	set_undo_to_sys_bitmap(const wxBitmap *bmp) {
+    	if (m_undo_to_sys_bitmap != bmp) {
+    		m_undo_to_sys_bitmap = bmp;
+    		m_Undo_to_sys_btn->SetBitmap(*bmp);
+    		return true;
+    	}
+    	return false;
+    }
+
+protected:
+	wxButton*			m_Undo_btn = nullptr;
+	// Bitmap for m_Undo_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one.
+	const wxBitmap*		m_undo_bitmap = nullptr;
+	wxButton*			m_Undo_to_sys_btn = nullptr;
+	// Bitmap for m_Undo_to_sys_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one.
+	const wxBitmap*		m_undo_to_sys_bitmap = nullptr;
+
+	friend class OptionsGroup;
 };
 
 /// Convenience function, accepts a const reference to t_field and checks to see whether 
diff --git a/xs/src/slic3r/GUI/OptionsGroup.cpp b/xs/src/slic3r/GUI/OptionsGroup.cpp
index 168ffcdc9..c71dd5ba6 100644
--- a/xs/src/slic3r/GUI/OptionsGroup.cpp
+++ b/xs/src/slic3r/GUI/OptionsGroup.cpp
@@ -90,8 +90,8 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co
 		field->m_Undo_btn->Hide();
 		field->m_Undo_to_sys_btn->Hide();
 	}
-	if (nonsys_btn_icon != nullptr)
-		field->set_nonsys_btn_icon(nonsys_btn_icon());
+//	if (nonsys_btn_icon != nullptr)
+//		field->set_nonsys_btn_icon(*nonsys_btn_icon);
     
 	// assign function objects for callbacks, etc.
     return field;
diff --git a/xs/src/slic3r/GUI/OptionsGroup.hpp b/xs/src/slic3r/GUI/OptionsGroup.hpp
index dd6d48f46..92ebb4488 100644
--- a/xs/src/slic3r/GUI/OptionsGroup.hpp
+++ b/xs/src/slic3r/GUI/OptionsGroup.hpp
@@ -86,7 +86,7 @@ public:
     wxFont			sidetext_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) };
     wxFont			label_font {wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) };
 
-	std::function<std::string()>	nonsys_btn_icon{ nullptr };
+//	std::function<const wxBitmap&()>	nonsys_btn_icon{ nullptr };
 
     /// Returns a copy of the pointer of the parent wxWindow.
     /// Accessor function is because users are not allowed to change the parent
diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp
index cc4b18c7c..f2511708b 100644
--- a/xs/src/slic3r/GUI/Tab.cpp
+++ b/xs/src/slic3r/GUI/Tab.cpp
@@ -88,9 +88,9 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
 	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);
+	m_bmp_show_incompatible_presets.LoadFile(from_u8(Slic3r::var("flag-red-icon.png")), wxBITMAP_TYPE_PNG);
+	m_bmp_hide_incompatible_presets.LoadFile(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);
@@ -103,9 +103,16 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
 		m_undo_btn->SetBackgroundColour(color);
 		m_undo_to_sys_btn->SetBackgroundColour(color);
 	}
-	m_undo_btn->SetBitmap(wxBitmap(from_u8(var("bullet_white.png")), wxBITMAP_TYPE_PNG));
+	// Bitmaps to be shown on the "Revert to system" aka "Lock to system" button next to each input field.
+	m_bmp_value_lock  	  .LoadFile(from_u8(var("sys_lock.png")),     wxBITMAP_TYPE_PNG);
+	m_bmp_value_unlock	  .LoadFile(from_u8(var("sys_unlock.png")),   wxBITMAP_TYPE_PNG);
+	m_bmp_non_system = &m_bmp_white_bullet;
+	// Bitmaps to be shown on the "Undo user changes" button next to each input field.
+	m_bmp_value_revert	  .LoadFile(from_u8(var("action_undo.png")),  wxBITMAP_TYPE_PNG);
+	m_bmp_white_bullet	  .LoadFile(from_u8(var("bullet_white.png")), wxBITMAP_TYPE_PNG);
+	m_undo_btn->SetBitmap(m_bmp_white_bullet);
 	m_undo_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ on_back_to_initial_value(); }));
-	m_undo_to_sys_btn->SetBitmap(wxBitmap(from_u8(var("bullet_white.png")), wxBITMAP_TYPE_PNG));
+	m_undo_to_sys_btn->SetBitmap(m_bmp_white_bullet);
 	m_undo_to_sys_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ on_back_to_sys_value(); }));
 
 	m_hsizer = new wxBoxSizer(wxHORIZONTAL);
@@ -204,8 +211,7 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
 void Tab::load_initial_data()
 {
 	m_config = &m_presets->get_edited_preset().config;
-	m_nonsys_btn_icon = m_presets->get_selected_preset_parent() == nullptr ?
-						"bullet_white.png" : "sys_unlock.png";
+	m_bmp_non_system = m_presets->get_selected_preset_parent() ? &m_bmp_value_unlock : &m_bmp_white_bullet;
 }
 
 PageShp Tab::add_options_page(const wxString& title, const std::string& icon, bool is_extruder_pages/* = false*/)
@@ -334,12 +340,12 @@ void Tab::update_changed_ui()
 	{
 		bool is_nonsys_value = false;
 		bool is_modified_value = true;
-		std::string sys_icon = "sys_lock.png";
-		std::string icon = "action_undo.png";
+		const wxBitmap *sys_icon = &m_bmp_value_lock;
+		const wxBitmap *icon     = &m_bmp_value_revert;
 		wxColour color = get_sys_label_clr();
 		if (find(m_sys_options.begin(), m_sys_options.end(), opt_key) == m_sys_options.end()) {
 			is_nonsys_value = true;
-			sys_icon = m_nonsys_btn_icon;
+			sys_icon = m_bmp_non_system;
 			if(find(m_dirty_options.begin(), m_dirty_options.end(), opt_key) == m_dirty_options.end())
 				color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
 			else
@@ -348,7 +354,7 @@ void Tab::update_changed_ui()
 		if (find(m_dirty_options.begin(), m_dirty_options.end(), opt_key) == m_dirty_options.end())
 		{
 			is_modified_value = false;
-			icon = "bullet_white.png";
+			icon = &m_bmp_white_bullet;
 		}
 		if (opt_key == "bed_shape" || opt_key == "compatible_printers") {
 			if (m_colored_Label != nullptr)	{
@@ -362,8 +368,8 @@ void Tab::update_changed_ui()
 		if (field == nullptr) continue;
 		field->m_is_nonsys_value = is_nonsys_value;
 		field->m_is_modified_value = is_modified_value;
-		field->m_Undo_btn->SetBitmap(wxBitmap(from_u8(var(icon)), wxBITMAP_TYPE_PNG));
-		field->m_Undo_to_sys_btn->SetBitmap(wxBitmap(from_u8(var(sys_icon)), wxBITMAP_TYPE_PNG));
+		field->set_undo_bitmap(icon);
+		field->set_undo_to_sys_bitmap(sys_icon);
 		if (field->m_Label != nullptr){
 			field->m_Label->SetForegroundColour(color);
 			field->m_Label->Refresh(true);
@@ -420,7 +426,7 @@ void Tab::update_sys_ui_after_sel_preset()
 	for (const auto opt_key : m_full_options_list){
 		Field* field = get_field(opt_key);
 		if (field != nullptr){
-			field->m_Undo_to_sys_btn->SetBitmap(wxBitmap(from_u8(var(m_nonsys_btn_icon)), wxBITMAP_TYPE_PNG));
+			field->set_undo_to_sys_bitmap(m_bmp_non_system);
 			field->m_is_nonsys_value = true;
 			if (field->m_Label != nullptr){
 				field->m_Label->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
@@ -493,11 +499,8 @@ void Tab::update_changed_tree_ui()
 
 void Tab::update_undo_buttons()
 {
-	const std::string& undo_icon = !m_is_modified_values ? "bullet_white.png" : "action_undo.png";
-	const std::string& undo_to_sys_icon = m_is_nonsys_values ? m_nonsys_btn_icon : "sys_lock.png";
-
-	m_undo_btn->SetBitmap(wxBitmap(from_u8(var(undo_icon)), wxBITMAP_TYPE_PNG));
-	m_undo_to_sys_btn->SetBitmap(wxBitmap(from_u8(var(undo_to_sys_icon)), wxBITMAP_TYPE_PNG));
+	m_undo_btn->SetBitmap(m_is_modified_values ? m_bmp_value_revert : m_bmp_white_bullet);
+	m_undo_to_sys_btn->SetBitmap(m_is_nonsys_values ? *m_bmp_non_system : m_bmp_value_lock);
 }
 
 void Tab::on_back_to_initial_value()
@@ -1853,8 +1856,7 @@ void Tab::load_current_preset()
 	on_preset_loaded();
 	// Reload preset pages with the new configuration values.
 	reload_config();
-	const Preset* parent = m_presets->get_selected_preset_parent();
-	m_nonsys_btn_icon = parent == nullptr ? "bullet_white.png" : "sys_unlock.png";
+	m_bmp_non_system = m_presets->get_selected_preset_parent() ? &m_bmp_value_unlock : &m_bmp_white_bullet;
 
 	// 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 
@@ -2142,7 +2144,7 @@ void Tab::toggle_show_hide_incompatible()
 void Tab::update_show_hide_incompatible_button()
 {
 	m_btn_hide_incompatible_presets->SetBitmap(m_show_incompatible_presets ?
-		*m_bmp_show_incompatible_presets : *m_bmp_hide_incompatible_presets);
+		m_bmp_show_incompatible_presets : m_bmp_hide_incompatible_presets);
 	m_btn_hide_incompatible_presets->SetToolTip(m_show_incompatible_presets ?
 		"Both compatible an incompatible presets are shown. Click to hide presets not compatible with the current printer." :
 		"Only compatible presets are shown. Click to show both the presets compatible and not compatible with the current printer.");
@@ -2460,9 +2462,7 @@ ConfigOptionsGroupShp Page::new_optgroup(const wxString& title, int noncommon_la
 		return static_cast<Tab*>(GetParent())->m_presets->get_selected_preset_parent() != nullptr;
 	};
 
-	optgroup->nonsys_btn_icon = [this](){
-		return static_cast<Tab*>(GetParent())->m_nonsys_btn_icon;
-	};
+//	optgroup->nonsys_btn_icon = m_bmp_non_system;
 
 	vsizer()->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 10);
 	m_optgroups.push_back(optgroup);
diff --git a/xs/src/slic3r/GUI/Tab.hpp b/xs/src/slic3r/GUI/Tab.hpp
index f9ee4f363..cb622582f 100644
--- a/xs/src/slic3r/GUI/Tab.hpp
+++ b/xs/src/slic3r/GUI/Tab.hpp
@@ -85,8 +85,6 @@ protected:
 	wxBitmapComboBox*	m_presets_choice;
 	wxBitmapButton*		m_btn_save_preset;
 	wxBitmapButton*		m_btn_delete_preset;
-	wxBitmap*			m_bmp_show_incompatible_presets;
-	wxBitmap*			m_bmp_hide_incompatible_presets;
 	wxBitmapButton*		m_btn_hide_incompatible_presets;
 	wxBoxSizer*			m_hsizer;
 	wxBoxSizer*			m_left_sizer;
@@ -95,11 +93,25 @@ protected:
 	wxCheckBox*			m_compatible_printers_checkbox;
 	wxButton*			m_compatible_printers_btn;
 	wxButton*			m_undo_btn;
-	wxButton*			m_undo_to_sys_btn;
+	wxButton*			m_undo_to_sys_btn;	
 	wxComboCtrl*		m_cc_presets_choice;
 	wxDataViewTreeCtrl*	m_presetctrl;
 	wxImageList*		m_preset_icons;
 
+	// Cached bitmaps.
+	// A "flag" icon to be displayned next to the preset name in the Tab's combo box.
+	wxBitmap			m_bmp_show_incompatible_presets;
+	wxBitmap			m_bmp_hide_incompatible_presets;
+	// Bitmaps to be shown on the "Revert to system" aka "Lock to system" button next to each input field.
+	wxBitmap 			m_bmp_value_lock;
+	wxBitmap 			m_bmp_value_unlock;
+	wxBitmap 			m_bmp_white_bullet;
+	// The following bitmap points to either m_bmp_value_unlock or m_bmp_white_bullet, depending on whether the current preset has a parent preset.
+	wxBitmap 		   *m_bmp_non_system;
+	// Bitmaps to be shown on the "Undo user changes" button next to each input field.
+	wxBitmap 			m_bmp_value_revert;
+	wxBitmap 			m_bmp_value_unmodified;
+
 	int					m_icon_count;
 	std::map<std::string, size_t>	m_icon_index;		// Map from an icon file name to its index
 	std::vector<PageShp>			m_pages;
@@ -124,7 +136,6 @@ public:
 	bool				m_show_btn_incompatible_presets = false;
 	PresetCollection*	m_presets;
 	DynamicPrintConfig*	m_config;
-	std::string			m_nonsys_btn_icon;
 	ogStaticText*		m_parent_preset_description_line;
 	wxStaticText*		m_colored_Label = nullptr;
 

From 5d3912698963d30edf0beada8b5e3b6182a81d73 Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Mon, 16 Apr 2018 13:43:01 +0200
Subject: [PATCH 02/20] Changes to performance.

---
 xs/src/slic3r/GUI/Tab.cpp | 45 ++++++++++++++++++++++++++++-----------
 xs/src/slic3r/GUI/Tab.hpp |  3 ++-
 2 files changed, 35 insertions(+), 13 deletions(-)

diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp
index cc4b18c7c..7fd50d5aa 100644
--- a/xs/src/slic3r/GUI/Tab.cpp
+++ b/xs/src/slic3r/GUI/Tab.cpp
@@ -268,6 +268,8 @@ void add_correct_opts_to_sys_options(const std::string &opt_key, std::vector<std
 // Update UI according to changes
 void Tab::update_changed_ui()
 {
+	if (m_postpone_update_ui) 
+		return;
 	auto dirty_options = m_presets->current_dirty_options();
 
 	if (name() == "printer"){
@@ -504,6 +506,8 @@ void Tab::on_back_to_initial_value()
 {
 	if (!m_is_modified_values) return;
 
+	m_postpone_update_ui = true;
+
 	auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection());
 	for (auto page : m_pages)
 		if (page->title() == selection)	{
@@ -513,16 +517,21 @@ void Tab::on_back_to_initial_value()
 						group->back_to_initial_value("extruders_count");
 				}
 				if (group->title == _("Size and coordinates")){
-					if (find(m_dirty_options.begin(), m_dirty_options.end(), "bed_shape") != m_dirty_options.end())
+					if (find(m_dirty_options.begin(), m_dirty_options.end(), "bed_shape") != m_dirty_options.end()){
 						group->back_to_initial_value("bed_shape");
+						load_key_value("bed_shape", true/*some value*/, true);
+					}
+
 				}
 				if (group->title == _("Profile dependencies")){
-					if (find(m_dirty_options.begin(), m_dirty_options.end(), "compatible_printers") != m_dirty_options.end())
+					if (find(m_dirty_options.begin(), m_dirty_options.end(), "compatible_printers") != m_dirty_options.end()){
 						group->back_to_initial_value("compatible_printers");
+						load_key_value("compatible_printers", true/*some value*/, true);
 
-					bool is_empty = m_config->option<ConfigOptionStrings>("compatible_printers")->values.empty();
-					m_compatible_printers_checkbox->SetValue(is_empty);
-					is_empty ? m_compatible_printers_btn->Disable() : m_compatible_printers_btn->Enable();
+						bool is_empty = m_config->option<ConfigOptionStrings>("compatible_printers")->values.empty();
+						m_compatible_printers_checkbox->SetValue(is_empty);
+						is_empty ? m_compatible_printers_btn->Disable() : m_compatible_printers_btn->Enable();
+					}
 				}
 				for (t_opt_map::iterator it = group->m_opt_map.begin(); it != group->m_opt_map.end(); ++it) {
 					const std::string& opt_key = it->first;
@@ -532,6 +541,8 @@ void Tab::on_back_to_initial_value()
 			}
 			break;
 		}
+
+	m_postpone_update_ui = false;
 	update_changed_ui();
 }
 
@@ -539,6 +550,8 @@ void Tab::on_back_to_sys_value()
 {
 	if (!m_is_nonsys_values) return;
 
+	m_postpone_update_ui = true;
+
 	auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection());
 	for (auto page : m_pages)
 		if (page->title() == selection)	{
@@ -548,16 +561,20 @@ void Tab::on_back_to_sys_value()
 						group->back_to_sys_value("extruders_count");
 				}
 				if (group->title == _("Size and coordinates")){
-					if (find(m_sys_options.begin(), m_sys_options.end(), "bed_shape") == m_sys_options.end())
+					if (find(m_sys_options.begin(), m_sys_options.end(), "bed_shape") == m_sys_options.end()){
 						group->back_to_sys_value("bed_shape");
+						load_key_value("bed_shape", true/*some value*/, true);
+					}
 				}
 				if (group->title == _("Profile dependencies")){
-					if (find(m_sys_options.begin(), m_sys_options.end(), "compatible_printers") == m_sys_options.end())
+					if (find(m_sys_options.begin(), m_sys_options.end(), "compatible_printers") == m_sys_options.end()){
 						group->back_to_sys_value("compatible_printers");
+						load_key_value("compatible_printers", true/*some value*/, true);
 
-					bool is_empty = m_config->option<ConfigOptionStrings>("compatible_printers")->values.empty();
-					m_compatible_printers_checkbox->SetValue(is_empty);
-					is_empty ? m_compatible_printers_btn->Disable() : m_compatible_printers_btn->Enable();
+						bool is_empty = m_config->option<ConfigOptionStrings>("compatible_printers")->values.empty();
+						m_compatible_printers_checkbox->SetValue(is_empty);
+						is_empty ? m_compatible_printers_btn->Disable() : m_compatible_printers_btn->Enable();
+					}
 				}
 				for (t_opt_map::iterator it = group->m_opt_map.begin(); it != group->m_opt_map.end(); ++it) {
 					const std::string& opt_key = it->first;
@@ -567,6 +584,8 @@ void Tab::on_back_to_sys_value()
 			}
 			break;
 		}
+
+	m_postpone_update_ui = false;
 	update_changed_ui();
 }
 
@@ -636,9 +655,11 @@ bool Tab::set_value(const t_config_option_key& opt_key, const boost::any& value)
 
 // To be called by custom widgets, load a value into a config,
 // update the preset selection boxes (the dirty flags)
-void Tab::load_key_value(const std::string& opt_key, const boost::any& value)
+// If value is saved before calling this function, put saved_value = true,
+// and value can be some random value because in this case it will not been used
+void Tab::load_key_value(const std::string& opt_key, const boost::any& value, bool saved_value /*= false*/)
 {
-	change_opt_value(*m_config, opt_key, value);
+	if (!saved_value) change_opt_value(*m_config, opt_key, value);
 	// Mark the print & filament enabled if they are compatible with the currently selected preset.
 	if (opt_key.compare("compatible_printers") == 0) {
 		m_preset_bundle->update_compatible_with_printer(0);
diff --git a/xs/src/slic3r/GUI/Tab.hpp b/xs/src/slic3r/GUI/Tab.hpp
index f9ee4f363..f7eba6186 100644
--- a/xs/src/slic3r/GUI/Tab.hpp
+++ b/xs/src/slic3r/GUI/Tab.hpp
@@ -118,6 +118,7 @@ protected:
 
 	bool				m_is_modified_values{ false };
 	bool				m_is_nonsys_values{ true };
+	bool				m_postpone_update_ui {false};
 
 public:
 	PresetBundle*		m_preset_bundle;
@@ -153,7 +154,7 @@ public:
 	wxSizer*	compatible_printers_widget(wxWindow* parent, wxCheckBox** checkbox, wxButton** btn);
 
 	void		update_presetsctrl(wxDataViewTreeCtrl* ui, bool show_incompatible);
-	void		load_key_value(const std::string& opt_key, const boost::any& value);
+	void		load_key_value(const std::string& opt_key, const boost::any& value, bool saved_value = false);
 	void		reload_compatible_printers_widget();
 
 	void		OnTreeSelChange(wxTreeEvent& event);

From d254c39a7743aaf202e8ba2bba2141c456b0e3b0 Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Tue, 17 Apr 2018 10:15:48 +0200
Subject: [PATCH 03/20] Added "smart" setting of label color

---
 xs/src/slic3r/GUI/Field.cpp |  9 ++-------
 xs/src/slic3r/GUI/Field.hpp | 18 +++++++++++++++---
 xs/src/slic3r/GUI/Tab.cpp   | 27 +++++++++++++++------------
 xs/src/slic3r/GUI/Tab.hpp   |  5 +++++
 4 files changed, 37 insertions(+), 22 deletions(-)

diff --git a/xs/src/slic3r/GUI/Field.cpp b/xs/src/slic3r/GUI/Field.cpp
index a32943da0..e959c7966 100644
--- a/xs/src/slic3r/GUI/Field.cpp
+++ b/xs/src/slic3r/GUI/Field.cpp
@@ -20,23 +20,18 @@ namespace Slic3r { namespace GUI {
 
 	void Field::PostInitialize(){
 		auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
-		m_Undo_btn			= new wxButton(m_parent, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER);
-		m_Undo_to_sys_btn	= new wxButton(m_parent, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER);
+		m_Undo_btn			= new wxButton(m_parent, wxID_ANY, "", wxDefaultPosition, wxSize(16, 16), wxNO_BORDER);
+		m_Undo_to_sys_btn	= new wxButton(m_parent, wxID_ANY, "", wxDefaultPosition, wxSize(16, 16), wxNO_BORDER);
 		if (wxMSW) {
 			m_Undo_btn->SetBackgroundColour(color);
 			m_Undo_to_sys_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(); }));
 		m_Undo_to_sys_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ on_back_to_sys_value(); }));
 
 		BUILD();
 	}
 
-//	void Field::set_nonsys_btn_icon(const wxBitmap& icon){
-//		m_Undo_to_sys_btn->SetBitmap(icon);
-//	}
-
 	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 
diff --git a/xs/src/slic3r/GUI/Field.hpp b/xs/src/slic3r/GUI/Field.hpp
index 2b2646b7c..292bfd81f 100644
--- a/xs/src/slic3r/GUI/Field.hpp
+++ b/xs/src/slic3r/GUI/Field.hpp
@@ -90,9 +90,7 @@ public:
     virtual void		enable() = 0;
     virtual void		disable() = 0;
 
-	wxStaticText*		m_Label = nullptr;
-
-    /// Fires the enable or disable function, based on the input.
+	/// Fires the enable or disable function, based on the input.
     inline void			toggle(bool en) { en ? enable() : disable(); }
 
 	virtual wxString	get_tooltip_text(const wxString& default_string);
@@ -137,6 +135,16 @@ public:
     	return false;
     }
 
+	bool	set_label_colour(const wxColour *clr) {
+		if (m_Label == nullptr) return false;
+		if (m_label_color != clr) {
+			m_label_color = clr;
+			m_Label->SetForegroundColour(*clr);
+			m_Label->Refresh(true);
+		}
+		return false;
+	}
+
 protected:
 	wxButton*			m_Undo_btn = nullptr;
 	// Bitmap for m_Undo_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one.
@@ -145,6 +153,10 @@ protected:
 	// Bitmap for m_Undo_to_sys_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one.
 	const wxBitmap*		m_undo_to_sys_bitmap = nullptr;
 
+	wxStaticText*		m_Label = nullptr;
+	// Color for Label. The wxColour will be updated only if the new wxColour pointer differs from the currently rendered one.
+	const wxColour*		m_label_color;
+
 	friend class OptionsGroup;
 };
 
diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp
index 6ed124eaa..825243749 100644
--- a/xs/src/slic3r/GUI/Tab.cpp
+++ b/xs/src/slic3r/GUI/Tab.cpp
@@ -23,6 +23,7 @@
 
 #include <boost/algorithm/string/predicate.hpp>
 #include "wxExtensions.hpp"
+#include <wx/wupdlock.h>
 
 namespace Slic3r {
 namespace GUI {
@@ -115,6 +116,11 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
 	m_undo_to_sys_btn->SetBitmap(m_bmp_white_bullet);
 	m_undo_to_sys_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ on_back_to_sys_value(); }));
 
+	// Colors for ui "decoration"
+	m_sys_label_clr			= get_sys_label_clr();
+	m_modified_label_clr	= get_modified_label_clr();
+	m_default_text_clr		= wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
+
 	m_hsizer = new wxBoxSizer(wxHORIZONTAL);
 	sizer->Add(m_hsizer, 0, wxBOTTOM, 3);
 	m_hsizer->Add(m_presets_choice, 1, wxLEFT | wxRIGHT | wxTOP | wxALIGN_CENTER_VERTICAL, 3);
@@ -344,14 +350,14 @@ void Tab::update_changed_ui()
 		bool is_modified_value = true;
 		const wxBitmap *sys_icon = &m_bmp_value_lock;
 		const wxBitmap *icon     = &m_bmp_value_revert;
-		wxColour color = get_sys_label_clr();
+		const wxColour *color    = &m_sys_label_clr;
 		if (find(m_sys_options.begin(), m_sys_options.end(), opt_key) == m_sys_options.end()) {
 			is_nonsys_value = true;
 			sys_icon = m_bmp_non_system;
 			if(find(m_dirty_options.begin(), m_dirty_options.end(), opt_key) == m_dirty_options.end())
-				color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
+				color = &m_default_text_clr;
 			else
-				color = get_modified_label_clr();
+				color = &m_modified_label_clr;
 		}
 		if (find(m_dirty_options.begin(), m_dirty_options.end(), opt_key) == m_dirty_options.end())
 		{
@@ -360,7 +366,7 @@ void Tab::update_changed_ui()
 		}
 		if (opt_key == "bed_shape" || opt_key == "compatible_printers") {
 			if (m_colored_Label != nullptr)	{
-				m_colored_Label->SetForegroundColour(color);
+				m_colored_Label->SetForegroundColour(*color);
 				m_colored_Label->Refresh(true);
 			}
 			continue;
@@ -372,10 +378,7 @@ void Tab::update_changed_ui()
 		field->m_is_modified_value = is_modified_value;
 		field->set_undo_bitmap(icon);
 		field->set_undo_to_sys_bitmap(sys_icon);
-		if (field->m_Label != nullptr){
-			field->m_Label->SetForegroundColour(color);
-			field->m_Label->Refresh(true);
-		}
+		field->set_label_colour(color);
 	}
 	Thaw();
 
@@ -425,15 +428,13 @@ void Tab::update_full_options_list()
 
 void Tab::update_sys_ui_after_sel_preset()
 {
+	const wxColour* clr = &m_default_text_clr;
 	for (const auto opt_key : m_full_options_list){
 		Field* field = get_field(opt_key);
 		if (field != nullptr){
 			field->set_undo_to_sys_bitmap(m_bmp_non_system);
 			field->m_is_nonsys_value = true;
-			if (field->m_Label != nullptr){
-				field->m_Label->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
-				field->m_Label->Refresh(true);
-			}
+			field->set_label_colour(clr);
 		}
 	}
 	m_sys_options.resize(0);
@@ -2039,6 +2040,8 @@ bool Tab::may_discard_current_dirty_preset(PresetCollection* presets /*= nullptr
 void Tab::OnTreeSelChange(wxTreeEvent& event)
 {
 	if (m_disable_tree_sel_changed_event) return;
+	wxWindowUpdateLocker noUpdates(this);
+
 	Page* page = nullptr;
 	auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection());
 	for (auto p : m_pages)
diff --git a/xs/src/slic3r/GUI/Tab.hpp b/xs/src/slic3r/GUI/Tab.hpp
index df91ef01b..4668c1238 100644
--- a/xs/src/slic3r/GUI/Tab.hpp
+++ b/xs/src/slic3r/GUI/Tab.hpp
@@ -112,6 +112,11 @@ protected:
 	wxBitmap 			m_bmp_value_revert;
 	wxBitmap 			m_bmp_value_unmodified;
 
+	// Colors for ui "decoration"
+	wxColour			m_sys_label_clr;
+	wxColour			m_modified_label_clr;
+	wxColour			m_default_text_clr;
+
 	int					m_icon_count;
 	std::map<std::string, size_t>	m_icon_index;		// Map from an icon file name to its index
 	std::vector<PageShp>			m_pages;

From 3ca2dfbc1dc83d3b976573dba6aa065c6fed236c Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Wed, 18 Apr 2018 13:32:21 +0200
Subject: [PATCH 04/20] Added some performance changes

---
 xs/src/libslic3r/Config.cpp  |  38 +++
 xs/src/libslic3r/Config.hpp  |   3 +
 xs/src/slic3r/GUI/GUI.cpp    |   6 +
 xs/src/slic3r/GUI/GUI.hpp    |   1 +
 xs/src/slic3r/GUI/Preset.cpp |   8 +-
 xs/src/slic3r/GUI/Preset.hpp |  10 +-
 xs/src/slic3r/GUI/Tab.cpp    | 529 ++++++++++++++++++++++++-----------
 xs/src/slic3r/GUI/Tab.hpp    |  41 ++-
 8 files changed, 455 insertions(+), 181 deletions(-)

diff --git a/xs/src/libslic3r/Config.cpp b/xs/src/libslic3r/Config.cpp
index a4eaf3072..8c1349e08 100644
--- a/xs/src/libslic3r/Config.cpp
+++ b/xs/src/libslic3r/Config.cpp
@@ -206,6 +206,44 @@ t_config_option_keys ConfigBase::diff(const ConfigBase &other) const
     return diff;
 }
 
+template<class T>
+void add_correct_opts_to_diff(const std::string &opt_key, t_config_option_keys& vec, const ConfigBase &other, const ConfigBase *this_c)
+{
+	const T* opt_init = static_cast<const T*>(other.option(opt_key));
+	const T* opt_cur = static_cast<const T*>(this_c->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));
+	}
+}
+
+t_config_option_keys ConfigBase::deep_diff(const ConfigBase &other) const
+{
+    t_config_option_keys diff;
+    for (const t_config_option_key &opt_key : this->keys()) {
+        const ConfigOption *this_opt  = this->option(opt_key);
+        const ConfigOption *other_opt = other.option(opt_key);
+		if (this_opt != nullptr && other_opt != nullptr && *this_opt != *other_opt)
+		{
+			if (opt_key == "bed_shape"){ diff.emplace_back(opt_key);		continue; }
+			switch (other_opt->type())
+			{
+			case coInts:	add_correct_opts_to_diff<ConfigOptionInts		>(opt_key, diff, other, this);	break;
+			case coBools:	add_correct_opts_to_diff<ConfigOptionBools		>(opt_key, diff, other, this);	break;
+			case coFloats:	add_correct_opts_to_diff<ConfigOptionFloats		>(opt_key, diff, other, this);	break;
+			case coStrings:	add_correct_opts_to_diff<ConfigOptionStrings	>(opt_key, diff, other, this);	break;
+			case coPercents:add_correct_opts_to_diff<ConfigOptionPercents	>(opt_key, diff, other, this);	break;
+			case coPoints:	add_correct_opts_to_diff<ConfigOptionPoints		>(opt_key, diff, other, this);	break;
+			default:		diff.emplace_back(opt_key);		break;
+			}
+		}
+    }
+    return diff;
+}
+
 t_config_option_keys ConfigBase::equal(const ConfigBase &other) const
 {
     t_config_option_keys equal;
diff --git a/xs/src/libslic3r/Config.hpp b/xs/src/libslic3r/Config.hpp
index 6eb307c5c..24a887130 100644
--- a/xs/src/libslic3r/Config.hpp
+++ b/xs/src/libslic3r/Config.hpp
@@ -1046,6 +1046,9 @@ public:
     void apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent = false);
     bool equals(const ConfigBase &other) const { return this->diff(other).empty(); }
     t_config_option_keys diff(const ConfigBase &other) const;
+	// Use deep_diff to correct return of changed options,
+	// considering individual options for each extruder
+	t_config_option_keys deep_diff(const ConfigBase &other) const;
     t_config_option_keys equal(const ConfigBase &other) const;
     std::string serialize(const t_config_option_key &opt_key) const;
     // Set a configuration value from a string, it will call an overridable handle_legacy() 
diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp
index cc135931a..c4f07935c 100644
--- a/xs/src/slic3r/GUI/GUI.cpp
+++ b/xs/src/slic3r/GUI/GUI.cpp
@@ -179,6 +179,7 @@ AppConfig	*g_AppConfig	= nullptr;
 PresetBundle *g_PresetBundle= nullptr;
 wxColour    g_color_label_modified;
 wxColour    g_color_label_sys;
+wxColour    g_color_label_default;
 
 std::vector<Tab *> g_tabs_list;
 
@@ -198,6 +199,7 @@ static void init_label_colours()
 		g_color_label_modified = wxColour(253, 111, 40);
 		g_color_label_sys = wxColour(115, 220, 103);
 	}
+	g_color_label_default = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
 }
 
 void set_wxapp(wxApp *app)
@@ -548,6 +550,10 @@ const wxColour& get_sys_label_clr() {
 	return g_color_label_sys;
 }
 
+const wxColour& get_default_label_clr() {
+	return g_color_label_default;
+}
+
 unsigned get_colour_approx_luma(const wxColour &colour)
 {
 	double r = colour.Red();
diff --git a/xs/src/slic3r/GUI/GUI.hpp b/xs/src/slic3r/GUI/GUI.hpp
index 0b681f48f..75600a57b 100644
--- a/xs/src/slic3r/GUI/GUI.hpp
+++ b/xs/src/slic3r/GUI/GUI.hpp
@@ -83,6 +83,7 @@ wxApp*		get_app();
 
 const wxColour& get_modified_label_clr();
 const wxColour& get_sys_label_clr();
+const wxColour& get_default_label_clr();
 unsigned get_colour_approx_luma(const wxColour &colour);
 
 void add_debug_menu(wxMenuBar *menu, int event_language_change);
diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp
index d48c9bf8f..30f49df08 100644
--- a/xs/src/slic3r/GUI/Preset.cpp
+++ b/xs/src/slic3r/GUI/Preset.cpp
@@ -629,11 +629,13 @@ bool PresetCollection::update_dirty_ui(wxBitmapComboBox *ui)
     return was_dirty != is_dirty;
 }
 
-std::vector<std::string> PresetCollection::dirty_options(const Preset *edited, const Preset *reference)
+std::vector<std::string> PresetCollection::dirty_options(const Preset *edited, const Preset *reference, const bool is_printer_type /*= false*/)
 {
     std::vector<std::string> changed;
-    if (edited != nullptr && reference != nullptr) {
-        changed = reference->config.diff(edited->config);
+	if (edited != nullptr && reference != nullptr) {
+        changed = is_printer_type  ? 
+				reference->config.deep_diff(edited->config) :
+				reference->config.diff(edited->config);
         // The "compatible_printers" option key is handled differently from the others:
         // It is not mandatory. If the key is missing, it means it is compatible with any printer.
         // If the key exists and it is empty, it means it is compatible with no printer.
diff --git a/xs/src/slic3r/GUI/Preset.hpp b/xs/src/slic3r/GUI/Preset.hpp
index c038160f4..e12f18b88 100644
--- a/xs/src/slic3r/GUI/Preset.hpp
+++ b/xs/src/slic3r/GUI/Preset.hpp
@@ -253,11 +253,11 @@ public:
     // Compare the content of get_selected_preset() with get_edited_preset() configs, return true if they differ.
     bool                        current_is_dirty() const { return ! this->current_dirty_options().empty(); }
     // Compare the content of get_selected_preset() with get_edited_preset() configs, return the list of keys where they differ.
-    std::vector<std::string>    current_dirty_options() const 
-        { return dirty_options(&this->get_edited_preset(), &this->get_selected_preset()); }
+    std::vector<std::string>    current_dirty_options(const bool is_printer_type = false) const
+        { return dirty_options(&this->get_edited_preset(), &this->get_selected_preset(), is_printer_type); }
     // Compare the content of get_selected_preset() with get_edited_preset() configs, return the list of keys where they differ.
-    std::vector<std::string>    current_different_from_parent_options() const
-        { return dirty_options(&this->get_edited_preset(), this->get_selected_preset_parent()); }
+    std::vector<std::string>    current_different_from_parent_options(const bool is_printer_type = false) const
+        { return dirty_options(&this->get_edited_preset(), this->get_selected_preset_parent(), is_printer_type); }
     // Compare the content of get_selected_preset() with get_selected_preset_parent() configs, return the list of keys where they equal.
 	std::vector<std::string>    system_equal_options() const;
 
@@ -299,7 +299,7 @@ private:
     std::deque<Preset>::const_iterator find_preset_internal(const std::string &name) const
         { return const_cast<PresetCollection*>(this)->find_preset_internal(name); }
 
-    static std::vector<std::string> dirty_options(const Preset *edited, const Preset *reference);
+    static std::vector<std::string> dirty_options(const Preset *edited, const Preset *reference, const bool is_printer_type = false);
 
     // Type of this PresetCollection: TYPE_PRINT, TYPE_FILAMENT or TYPE_PRINTER.
     Preset::Type            m_type;
diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp
index 825243749..dcf61f574 100644
--- a/xs/src/slic3r/GUI/Tab.cpp
+++ b/xs/src/slic3r/GUI/Tab.cpp
@@ -25,6 +25,8 @@
 #include "wxExtensions.hpp"
 #include <wx/wupdlock.h>
 
+#include <chrono>
+
 namespace Slic3r {
 namespace GUI {
 
@@ -112,14 +114,14 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
 	m_bmp_value_revert	  .LoadFile(from_u8(var("action_undo.png")),  wxBITMAP_TYPE_PNG);
 	m_bmp_white_bullet	  .LoadFile(from_u8(var("bullet_white.png")), wxBITMAP_TYPE_PNG);
 	m_undo_btn->SetBitmap(m_bmp_white_bullet);
-	m_undo_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ on_back_to_initial_value(); }));
+	m_undo_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ /*on_back_to_initial_value*/on_roll_back_value(); }));
 	m_undo_to_sys_btn->SetBitmap(m_bmp_white_bullet);
-	m_undo_to_sys_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ on_back_to_sys_value(); }));
+	m_undo_to_sys_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ /*on_back_to_sys_value*/on_roll_back_value(true); }));
 
 	// Colors for ui "decoration"
 	m_sys_label_clr			= get_sys_label_clr();
 	m_modified_label_clr	= get_modified_label_clr();
-	m_default_text_clr		= wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
+	m_default_text_clr		= get_default_label_clr();
 
 	m_hsizer = new wxBoxSizer(wxHORIZONTAL);
 	sizer->Add(m_hsizer, 0, wxBOTTOM, 3);
@@ -246,45 +248,108 @@ PageShp Tab::add_options_page(const wxString& title, const std::string& icon, bo
 	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));
-	}
-}
-
-template<class T>
-void add_correct_opts_to_sys_options(const std::string &opt_key, std::vector<std::string> *vec, TabPrinter *tab)
-{
-	const Preset* sys_preset = tab->m_presets->get_selected_preset_parent();
-	if (sys_preset == nullptr)
-		return;
-	T *opt_cur = static_cast<T*>(tab->m_config->option(opt_key));
-	const T *opt_sys = static_cast<const T*>(sys_preset->config.option(opt_key));
-	int opt_max_id = opt_sys->values.size()-1;
-	for (int i = 0; i < opt_cur->values.size(); i++)
-	{
-		int init_id = i <= opt_max_id ? i : 0;
-		if (opt_cur->values[i] == opt_sys->values[init_id])
-			vec->emplace_back(opt_key + "#" + std::to_string(i));
-	}
-}
+// 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));
+// 	}
+// }
+// 
+// template<class T>
+// void add_correct_opts_to_sys_options(const std::string &opt_key, std::vector<std::string> *vec, TabPrinter *tab)
+// {
+// 	const Preset* sys_preset = tab->m_presets->get_selected_preset_parent();
+// 	if (sys_preset == nullptr)
+// 		return;
+// 	T *opt_cur = static_cast<T*>(tab->m_config->option(opt_key));
+// 	const T *opt_sys = static_cast<const T*>(sys_preset->config.option(opt_key));
+// 	int opt_max_id = opt_sys->values.size()-1;
+// 	for (int i = 0; i < opt_cur->values.size(); i++)
+// 	{
+// 		int init_id = i <= opt_max_id ? i : 0;
+// 		if (opt_cur->values[i] == opt_sys->values[init_id])
+// 			vec->emplace_back(opt_key + "#" + std::to_string(i));
+// 	}
+// }
 
 // Update UI according to changes
 void Tab::update_changed_ui()
 {
 	if (m_postpone_update_ui) 
 		return;
-	auto dirty_options = m_presets->current_dirty_options();
 
-	if (name() == "printer"){
+	const bool is_printer_type = (name() == "printer");
+	auto m_dirty_options = m_presets->current_dirty_options(is_printer_type);
+	auto m_nonsys_options = m_presets->current_different_from_parent_options(is_printer_type);
+	if (is_printer_type){
+		TabPrinter* tab = static_cast<TabPrinter*>(this);
+		if (tab->m_initial_extruders_count != tab->m_extruders_count)
+			m_dirty_options.emplace_back("extruders_count");
+		if (tab->m_sys_extruders_count != tab->m_extruders_count)
+			m_nonsys_options.emplace_back("extruders_count");
+	}
+
+	for (auto& it : m_options_list)
+		it.second = m_opt_status_value;
+
+//	auto m_options_list = m_options_list;
+	for (auto opt_key : m_dirty_options)	m_options_list[opt_key] &= ~osInitValue;
+	for (auto opt_key : m_nonsys_options)	m_options_list[opt_key] &= ~osSystemValue;
+
+	Freeze();
+	//update options "decoration"
+	for (const auto opt : m_options_list/*m_options_list*/)
+	{
+		bool is_nonsys_value = false;
+		bool is_modified_value = true;
+		const wxBitmap *sys_icon = &m_bmp_value_lock;
+		const wxBitmap *icon = &m_bmp_value_revert;
+		const wxColour *color = &m_sys_label_clr;
+
+		if ((opt.second & osSystemValue) == 0){
+//		if (find(m_sys_options.begin(), m_sys_options.end(), opt_key) == m_sys_options.end()) {
+			is_nonsys_value = true;
+			sys_icon = m_bmp_non_system;
+			if ((opt.second & osInitValue) != 0)
+//			if (find(m_dirty_options.begin(), m_dirty_options.end(), opt_key) == m_dirty_options.end())
+				color = &m_default_text_clr;
+			else
+				color = &m_modified_label_clr;
+		}
+		if ((opt.second & osInitValue) != 0)
+//		if (find(m_dirty_options.begin(), m_dirty_options.end(), opt_key) == m_dirty_options.end())
+		{
+			is_modified_value = false;
+			icon = &m_bmp_white_bullet;
+		}
+		if (opt.first == "bed_shape" || opt.first == "compatible_printers") {
+			if (m_colored_Label != nullptr)	{
+				m_colored_Label->SetForegroundColour(*color);
+				m_colored_Label->Refresh(true);
+			}
+			continue;
+		}
+
+		Field* field = get_field(opt.first);
+		if (field == nullptr) continue;
+		field->m_is_nonsys_value = is_nonsys_value;
+		field->m_is_modified_value = is_modified_value;
+		field->set_undo_bitmap(icon);
+		field->set_undo_to_sys_bitmap(sys_icon);
+		field->set_label_colour(color);
+	}
+	Thaw();
+//	m_options_list = m_options_list;
+/*	auto dirty_options = m_presets->current_dirty_options();
+
+	if (){
 		// Update dirty_options in case changes of Extruder's options 
 		TabPrinter* tab = static_cast<TabPrinter*>(this);
 		m_dirty_options.resize(0);
@@ -381,71 +446,113 @@ void Tab::update_changed_ui()
 		field->set_label_colour(color);
 	}
 	Thaw();
-
+*/
 	wxTheApp->CallAfter([this]() {
 		update_changed_tree_ui();
 	});
 }
 
+void Tab::init_options_list()
+{
+	if (!m_options_list.empty())
+		m_options_list.clear();
+
+	for (const auto opt_key : m_config->keys())
+		m_options_list.emplace(opt_key, m_opt_status_value);
+}
+
 template<class T>
-void add_correct_opts_to_full_options_list(const std::string &opt_key, std::vector<std::string> *vec, TabPrinter *tab)
+void add_correct_opts_to_options_list(const std::string &opt_key, std::map<std::string, int>& map, TabPrinter *tab, const int& value)
 {
 	T *opt_cur = static_cast<T*>(tab->m_config->option(opt_key));
 	for (int i = 0; i < opt_cur->values.size(); i++)
-		vec->emplace_back(opt_key + "#" + std::to_string(i));
+		map.emplace(opt_key + "#" + std::to_string(i), value);
 }
 
-void Tab::update_full_options_list()
+void TabPrinter::init_options_list()
 {
-	if (!m_full_options_list.empty())
-		m_full_options_list.resize(0);
+	if (!m_options_list.empty())
+		m_options_list.clear();
 
-	if (m_name != "printer"){
-		m_full_options_list = m_config->keys();
-		return;
-	}
-
-	TabPrinter* tab = static_cast<TabPrinter*>(this);
 	for (const auto opt_key : m_config->keys())
 	{
 		if (opt_key == "bed_shape"){
-			m_full_options_list.emplace_back(opt_key);
+			m_options_list.emplace(opt_key, m_opt_status_value);
 			continue;
 		}
 		switch (m_config->option(opt_key)->type())
 		{
-		case coInts:	add_correct_opts_to_full_options_list<ConfigOptionInts		>(opt_key, &m_full_options_list, tab);	break;
-		case coBools:	add_correct_opts_to_full_options_list<ConfigOptionBools		>(opt_key, &m_full_options_list, tab);	break;
-		case coFloats:	add_correct_opts_to_full_options_list<ConfigOptionFloats	>(opt_key, &m_full_options_list, tab);	break;
-		case coStrings:	add_correct_opts_to_full_options_list<ConfigOptionStrings	>(opt_key, &m_full_options_list, tab);	break;
-		case coPercents:add_correct_opts_to_full_options_list<ConfigOptionPercents	>(opt_key, &m_full_options_list, tab);	break;
-		case coPoints:	add_correct_opts_to_full_options_list<ConfigOptionPoints	>(opt_key, &m_full_options_list, tab);	break;
-		default:		m_full_options_list.emplace_back(opt_key);		break;
+		case coInts:	add_correct_opts_to_options_list<ConfigOptionInts		>(opt_key, m_options_list, this, m_opt_status_value);	break;
+		case coBools:	add_correct_opts_to_options_list<ConfigOptionBools		>(opt_key, m_options_list, this, m_opt_status_value);	break;
+		case coFloats:	add_correct_opts_to_options_list<ConfigOptionFloats		>(opt_key, m_options_list, this, m_opt_status_value);	break;
+		case coStrings:	add_correct_opts_to_options_list<ConfigOptionStrings	>(opt_key, m_options_list, this, m_opt_status_value);	break;
+		case coPercents:add_correct_opts_to_options_list<ConfigOptionPercents	>(opt_key, m_options_list, this, m_opt_status_value);	break;
+		case coPoints:	add_correct_opts_to_options_list<ConfigOptionPoints		>(opt_key, m_options_list, this, m_opt_status_value);	break;
+		default:		m_options_list.emplace(opt_key, m_opt_status_value);		break;
 		}
 	}
-	m_full_options_list.emplace_back("extruders_count");
+	m_options_list.emplace("extruders_count", m_opt_status_value);
 }
 
-void Tab::update_sys_ui_after_sel_preset()
-{
-	const wxColour* clr = &m_default_text_clr;
-	for (const auto opt_key : m_full_options_list){
-		Field* field = get_field(opt_key);
-		if (field != nullptr){
-			field->set_undo_to_sys_bitmap(m_bmp_non_system);
-			field->m_is_nonsys_value = true;
-			field->set_label_colour(clr);
-		}
-	}
-	m_sys_options.resize(0);
-}
+
+// template<class T>
+// void add_correct_opts_to_full_options_list(const std::string &opt_key, std::vector<std::string> *vec, TabPrinter *tab)
+// {
+// 	T *opt_cur = static_cast<T*>(tab->m_config->option(opt_key));
+// 	for (int i = 0; i < opt_cur->values.size(); i++)
+// 		vec->emplace_back(opt_key + "#" + std::to_string(i));
+// }
+
+// void Tab::update_full_options_list()
+// {
+// 	if (!m_full_options_list.empty())
+// 		m_full_options_list.resize(0);
+// 
+// 	if (m_name != "printer"){
+// 		m_full_options_list = m_config->keys();
+// 		return;
+// 	}
+// 
+// 	TabPrinter* tab = static_cast<TabPrinter*>(this);
+// 	for (const auto opt_key : m_config->keys())
+// 	{
+// 		if (opt_key == "bed_shape"){
+// 			m_full_options_list.emplace_back(opt_key);
+// 			continue;
+// 		}
+// 		switch (m_config->option(opt_key)->type())
+// 		{
+// 		case coInts:	add_correct_opts_to_full_options_list<ConfigOptionInts		>(opt_key, &m_full_options_list, tab);	break;
+// 		case coBools:	add_correct_opts_to_full_options_list<ConfigOptionBools		>(opt_key, &m_full_options_list, tab);	break;
+// 		case coFloats:	add_correct_opts_to_full_options_list<ConfigOptionFloats	>(opt_key, &m_full_options_list, tab);	break;
+// 		case coStrings:	add_correct_opts_to_full_options_list<ConfigOptionStrings	>(opt_key, &m_full_options_list, tab);	break;
+// 		case coPercents:add_correct_opts_to_full_options_list<ConfigOptionPercents	>(opt_key, &m_full_options_list, tab);	break;
+// 		case coPoints:	add_correct_opts_to_full_options_list<ConfigOptionPoints	>(opt_key, &m_full_options_list, tab);	break;
+// 		default:		m_full_options_list.emplace_back(opt_key);		break;
+// 		}
+// 	}
+// 	m_full_options_list.emplace_back("extruders_count");
+// }
+
+// void Tab::update_sys_ui_after_sel_preset()
+// {
+// 	const wxColour* clr = &m_default_text_clr;
+// 	for (const auto opt_key : m_full_options_list){
+// 		Field* field = get_field(opt_key);
+// 		if (field != nullptr){
+// 			field->set_undo_to_sys_bitmap(m_bmp_non_system);
+// 			field->m_is_nonsys_value = true;
+// 			field->set_label_colour(clr);
+// 		}
+// 	}
+// 	m_sys_options.resize(0);
+// }
 
 void Tab::get_sys_and_mod_flags(const std::string& opt_key, bool& sys_page, bool& modified_page)
 {
-	if (sys_page && find(m_sys_options.begin(), m_sys_options.end(), opt_key) == m_sys_options.end())
-		sys_page = false;
-	if (!modified_page && find(m_dirty_options.begin(), m_dirty_options.end(), opt_key) != m_dirty_options.end())
-		modified_page = true;
+	auto opt = m_options_list.find(opt_key);
+	if (sys_page) sys_page = (opt->second & osSystemValue) != 0;
+	if (!modified_page) modified_page = (opt->second & osInitValue) == 0;
 }
 
 void Tab::update_changed_tree_ui()
@@ -466,7 +573,7 @@ void Tab::update_changed_tree_ui()
 					get_sys_and_mod_flags(opt_key, sys_page, modified_page);
 				}
 			}
-			if (title == _("Dependencies")){
+			if (title == _("Dependencies") && name() != "printer"){
 				get_sys_and_mod_flags("compatible_printers", sys_page, modified_page);
 			}
 			for (auto group : page->m_optgroups)
@@ -478,12 +585,13 @@ void Tab::update_changed_tree_ui()
 					get_sys_and_mod_flags(opt_key, sys_page, modified_page);
 				}
 			}
-			if (sys_page)
-				m_treectrl->SetItemTextColour(cur_item, get_sys_label_clr());
-			else if (modified_page)
-				m_treectrl->SetItemTextColour(cur_item, get_modified_label_clr());
-			else
-				m_treectrl->SetItemTextColour(cur_item, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
+
+			const wxColor *clr = sys_page		?	&m_sys_label_clr :
+								 modified_page	?	&m_modified_label_clr : 
+													&m_default_text_clr;
+
+			if (page->set_item_colour(clr))
+				m_treectrl->SetItemTextColour(cur_item, *clr);
 
 			page->m_is_nonsys_values = !sys_page;
 			page->m_is_modified_values = modified_page;
@@ -506,9 +614,17 @@ void Tab::update_undo_buttons()
 	m_undo_to_sys_btn->SetBitmap(m_is_nonsys_values ? *m_bmp_non_system : m_bmp_value_lock);
 }
 
-void Tab::on_back_to_initial_value()
+void Tab::on_roll_back_value(const bool to_sys /*= true*/)
 {
-	if (!m_is_modified_values) return;
+	int os;
+	if (to_sys)	{
+		if (!m_is_nonsys_values) return;
+		os = osSystemValue;
+	}
+	else {
+		if (!m_is_modified_values) return;
+		os = osInitValue;
+	}
 
 	m_postpone_update_ui = true;
 
@@ -517,19 +633,19 @@ void Tab::on_back_to_initial_value()
 		if (page->title() == selection)	{
 			for (auto group : page->m_optgroups){
 				if (group->title == _("Capabilities")){
-					if (find(m_dirty_options.begin(), m_dirty_options.end(), "extruders_count") != m_dirty_options.end())
-						group->back_to_initial_value("extruders_count");
+					if ((m_options_list["extruders_count"] & os) == 0)
+						to_sys ? group->back_to_sys_value("extruders_count") : group->back_to_initial_value("extruders_count");
 				}
 				if (group->title == _("Size and coordinates")){
-					if (find(m_dirty_options.begin(), m_dirty_options.end(), "bed_shape") != m_dirty_options.end()){
-						group->back_to_initial_value("bed_shape");
+					if ((m_options_list["bed_shape"] & os) == 0){
+						to_sys ? group->back_to_sys_value("bed_shape") : group->back_to_initial_value("bed_shape");
 						load_key_value("bed_shape", true/*some value*/, true);
 					}
 
 				}
-				if (group->title == _("Profile dependencies")){
-					if (find(m_dirty_options.begin(), m_dirty_options.end(), "compatible_printers") != m_dirty_options.end()){
-						group->back_to_initial_value("compatible_printers");
+				if (group->title == _("Profile dependencies") && name() != "printer"){
+					if ((m_options_list["compatible_printers"] & os) == 0){
+						to_sys ? group->back_to_sys_value("compatible_printers") : group->back_to_initial_value("compatible_printers");
 						load_key_value("compatible_printers", true/*some value*/, true);
 
 						bool is_empty = m_config->option<ConfigOptionStrings>("compatible_printers")->values.empty();
@@ -539,8 +655,8 @@ void Tab::on_back_to_initial_value()
 				}
 				for (t_opt_map::iterator it = group->m_opt_map.begin(); it != group->m_opt_map.end(); ++it) {
 					const std::string& opt_key = it->first;
-					if (find(m_dirty_options.begin(), m_dirty_options.end(), opt_key) != m_dirty_options.end())
-						group->back_to_initial_value(opt_key);
+					if ((m_options_list[opt_key] & os) == 0)
+						to_sys ? group->back_to_sys_value(opt_key) : group->back_to_initial_value(opt_key);
 				}
 			}
 			break;
@@ -550,48 +666,111 @@ void Tab::on_back_to_initial_value()
 	update_changed_ui();
 }
 
-void Tab::on_back_to_sys_value()
-{
-	if (!m_is_nonsys_values) return;
-
-	m_postpone_update_ui = true;
-
-	auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection());
-	for (auto page : m_pages)
-		if (page->title() == selection)	{
-			for (auto group : page->m_optgroups) {
-				if (group->title == _("Capabilities")){
-					if (find(m_sys_options.begin(), m_sys_options.end(), "extruders_count") == m_sys_options.end())
-						group->back_to_sys_value("extruders_count");
-				}
-				if (group->title == _("Size and coordinates")){
-					if (find(m_sys_options.begin(), m_sys_options.end(), "bed_shape") == m_sys_options.end()){
-						group->back_to_sys_value("bed_shape");
-						load_key_value("bed_shape", true/*some value*/, true);
-					}
-				}
-				if (group->title == _("Profile dependencies")){
-					if (find(m_sys_options.begin(), m_sys_options.end(), "compatible_printers") == m_sys_options.end()){
-						group->back_to_sys_value("compatible_printers");
-						load_key_value("compatible_printers", true/*some value*/, true);
-
-						bool is_empty = m_config->option<ConfigOptionStrings>("compatible_printers")->values.empty();
-						m_compatible_printers_checkbox->SetValue(is_empty);
-						is_empty ? m_compatible_printers_btn->Disable() : m_compatible_printers_btn->Enable();
-					}
-				}
-				for (t_opt_map::iterator it = group->m_opt_map.begin(); it != group->m_opt_map.end(); ++it) {
-					const std::string& opt_key = it->first;
-					if (find(m_sys_options.begin(), m_sys_options.end(), opt_key) == m_sys_options.end())
-						group->back_to_sys_value(opt_key);
-				}
-			}
-			break;
-		}
-
-	m_postpone_update_ui = false;
-	update_changed_ui();
-}
+// void Tab::on_back_to_initial_value()
+// {
+// 	if (!m_is_modified_values) return;
+// 	std::chrono::milliseconds ms1 = std::chrono::duration_cast<std::chrono::milliseconds>(
+// 		std::chrono::system_clock::now().time_since_epoch()
+// 		);
+// 
+// 	m_postpone_update_ui = true;
+// 
+// 	auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection());
+// 	for (auto page : m_pages)
+// 		if (page->title() == selection)	{
+// 			for (auto group : page->m_optgroups){
+// 				if (group->title == _("Capabilities")){
+// 					if (find(m_dirty_options.begin(), m_dirty_options.end(), "extruders_count") != m_dirty_options.end())
+// 						group->back_to_initial_value("extruders_count");
+// 				}
+// 				if (group->title == _("Size and coordinates")){
+// 					if (find(m_dirty_options.begin(), m_dirty_options.end(), "bed_shape") != m_dirty_options.end()){
+// 						group->back_to_initial_value("bed_shape");
+// 						load_key_value("bed_shape", true/*some value*/, true);
+// 					}
+// 
+// 				}
+// 				if (group->title == _("Profile dependencies")){
+// 					if (find(m_dirty_options.begin(), m_dirty_options.end(), "compatible_printers") != m_dirty_options.end()){
+// 						group->back_to_initial_value("compatible_printers");
+// 						load_key_value("compatible_printers", true/*some value*/, true);
+// 
+// 						bool is_empty = m_config->option<ConfigOptionStrings>("compatible_printers")->values.empty();
+// 						m_compatible_printers_checkbox->SetValue(is_empty);
+// 						is_empty ? m_compatible_printers_btn->Disable() : m_compatible_printers_btn->Enable();
+// 					}
+// 				}
+// 				for (t_opt_map::iterator it = group->m_opt_map.begin(); it != group->m_opt_map.end(); ++it) {
+// 					const std::string& opt_key = it->first;
+// 					if (find(m_dirty_options.begin(), m_dirty_options.end(), opt_key) != m_dirty_options.end())
+// 						group->back_to_initial_value(opt_key);
+// 				}
+// 			}
+// 			break;
+// 		}
+// 
+// 	std::chrono::milliseconds ms2 = std::chrono::duration_cast<std::chrono::milliseconds>(
+// 		std::chrono::system_clock::now().time_since_epoch()
+// 		);
+// 
+// 	m_postpone_update_ui = false;
+// 	update_changed_ui();
+// 
+// 	std::chrono::milliseconds ms3 = std::chrono::duration_cast<std::chrono::milliseconds>(
+// 		std::chrono::system_clock::now().time_since_epoch()
+// 		);
+// 
+// 	auto roll_back_duration = std::chrono::microseconds(ms2 - ms1).count();
+// 	auto update_ui_duration = std::chrono::microseconds(ms3 - ms2).count();
+// 	printf("back_to init_duration duration = %lld ms \n", roll_back_duration);
+// 	printf("update_ui_duration duration = %lld ms \n", update_ui_duration);
+// 
+// // 	m_postpone_update_ui = false;
+// // 	update_changed_ui();
+// }
+// 
+// void Tab::on_back_to_sys_value()
+// {
+// 	if (!m_is_nonsys_values) return;
+// 
+// 	m_postpone_update_ui = true;
+// 
+// 	auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection());
+// 	for (auto page : m_pages)
+// 		if (page->title() == selection)	{
+// 			for (auto group : page->m_optgroups) {
+// 				if (group->title == _("Capabilities")){
+// 					if (find(m_sys_options.begin(), m_sys_options.end(), "extruders_count") == m_sys_options.end())
+// 						group->back_to_sys_value("extruders_count");
+// 				}
+// 				if (group->title == _("Size and coordinates")){
+// 					if (find(m_sys_options.begin(), m_sys_options.end(), "bed_shape") == m_sys_options.end()){
+// 						group->back_to_sys_value("bed_shape");
+// 						load_key_value("bed_shape", true/*some value*/, true);
+// 					}
+// 				}
+// 				if (group->title == _("Profile dependencies")){
+// 					if (find(m_sys_options.begin(), m_sys_options.end(), "compatible_printers") == m_sys_options.end()){
+// 						group->back_to_sys_value("compatible_printers");
+// 						load_key_value("compatible_printers", true/*some value*/, true);
+// 
+// 						bool is_empty = m_config->option<ConfigOptionStrings>("compatible_printers")->values.empty();
+// 						m_compatible_printers_checkbox->SetValue(is_empty);
+// 						is_empty ? m_compatible_printers_btn->Disable() : m_compatible_printers_btn->Enable();
+// 					}
+// 				}
+// 				for (t_opt_map::iterator it = group->m_opt_map.begin(); it != group->m_opt_map.end(); ++it) {
+// 					const std::string& opt_key = it->first;
+// 					if (find(m_sys_options.begin(), m_sys_options.end(), opt_key) == m_sys_options.end())
+// 						group->back_to_sys_value(opt_key);
+// 				}
+// 			}
+// 			break;
+// 		}
+// 
+// 	m_postpone_update_ui = false;
+// 	update_changed_ui();
+// }
 
 // Update the combo box label of the selected preset based on its "dirty" state,
 // comparing the selected preset config with $self->{config}.
@@ -1698,12 +1877,34 @@ void TabPrinter::extruders_count_changed(size_t extruders_count){
 }
 
 void TabPrinter::build_extruder_pages(){
-	for (auto extruder_idx = m_extruder_pages.size(); extruder_idx < m_extruders_count; ++extruder_idx){
+	if (m_extruders_count_old == m_extruders_count)
+	{
+		// if we have a single extruder MM setup, add a page with configuration options:
+		for (int i = 0; i < m_pages.size(); ++i) // first make sure it's not there already
+			if (m_pages[i]->title().find(_(L("Single extruder MM setup"))) != std::string::npos) {
+				m_pages.erase(m_pages.begin() + i);
+				break;
+			}
+		if (m_extruders_count > 1 && m_config->opt_bool("single_extruder_multi_material")) {
+			// create a page, but pretend it's an extruder page, so we can add it to m_pages ourselves
+			auto page = add_options_page(_(L("Single extruder MM setup")), "printer_empty.png", true);
+			auto optgroup = page->new_optgroup(_(L("Single extruder multimaterial parameters")));
+			optgroup->append_single_option_line("cooling_tube_retraction");
+			optgroup->append_single_option_line("cooling_tube_length");
+			optgroup->append_single_option_line("parking_pos_retraction");
+			m_pages.insert(m_pages.end()-2, page);
+		}
+		rebuild_page_tree();
+		return;
+	}
+		
+	for (auto extruder_idx = m_extruders_count_old; extruder_idx < m_extruders_count; ++extruder_idx){
 		//# build page
 		char buf[MIN_BUF_LENGTH_FOR_L];
 		sprintf(buf, _CHB(L("Extruder %d")), extruder_idx + 1);
 		auto page = add_options_page(from_u8(buf), "funnel.png", true);
-		m_extruder_pages.push_back(page);
+		m_pages.insert(m_pages.begin() + 2+extruder_idx, page);
+//  		m_extruder_pages.push_back(page);
 			
 			auto optgroup = page->new_optgroup(_(L("Size")));
 			optgroup->append_single_option_line("nozzle_diameter", extruder_idx);
@@ -1741,36 +1942,31 @@ void TabPrinter::build_extruder_pages(){
 	}
  
 	// # remove extra pages
-	if (m_extruders_count <= m_extruder_pages.size()) {
-		m_extruder_pages.resize(m_extruders_count);
-	}
+// 	if (m_extruders_count <= m_extruders_count_old) {
+// 		m_extruder_pages.resize(m_extruders_count);
+// 	}
+
+	if (m_extruders_count < m_extruders_count_old)
+		m_pages.erase(m_pages.begin() + 2 + m_extruders_count, m_pages.begin() + 2 + m_extruders_count_old);
+
+	m_extruders_count_old = m_extruders_count;
 
 	// # rebuild page list
-	PageShp page_note = m_pages.back();
-	m_pages.pop_back();
-	while (m_pages.back()->title().find(_(L("Extruder"))) != std::string::npos)
-		m_pages.pop_back();
-	for (auto page_extruder : m_extruder_pages)
-		m_pages.push_back(page_extruder);
-	m_pages.push_back(page_note);
-
-    {
-        // if we have a single extruder MM setup, add a page with configuration options:
-        for (int i=0;i<m_pages.size();++i) // first make sure it's not there already
-            if (m_pages[i]->title().find(_(L("Single extruder MM setup"))) != std::string::npos) {
-                m_pages.erase(m_pages.begin()+i);
-                break;
-            }
-        if ( m_extruder_pages.size()>1 && m_config->opt_bool("single_extruder_multi_material")) {
-            // create a page, but pretend it's an extruder page, so we can add it to m_pages ourselves
-            auto page = add_options_page(_(L("Single extruder MM setup")), "printer_empty.png",true);
-                auto optgroup = page->new_optgroup(_(L("Single extruder multimaterial parameters")));
-                optgroup->append_single_option_line("cooling_tube_retraction");
-                optgroup->append_single_option_line("cooling_tube_length");
-                optgroup->append_single_option_line("parking_pos_retraction");
-            m_pages.insert(m_pages.begin()+1,page);
-        }
-    }
+// 	PageShp page_note = m_pages.back();
+// 	m_pages.pop_back();
+// 	PageShp page_depend = m_pages.back();
+// 	m_pages.pop_back();
+// 	auto counter = m_extruders_count_old;
+// 	while (counter > m_extruders_count/*m_pages.back()->title().find(_(L("Extruder"))) != std::string::npos*/){
+// 		m_pages.pop_back();
+// 		--counter;
+// 	}
+// // 	for (auto page_extruder : m_extruder_pages)
+// //		m_pages.push_back(page_extruder);
+// 	for (auto extruder_idx = m_extruders_count_old; extruder_idx < m_extruders_count; ++extruder_idx)
+// 		m_pages.push_back(m_extruder_pages[extruder_idx]);
+//  	m_pages.push_back(page_note);
+// 	m_pages.push_back(page_depend);
 
 	rebuild_page_tree();
 }
@@ -1899,8 +2095,10 @@ void Tab::load_current_preset()
 			static_cast<TabPrinter*>(this)->m_sys_extruders_count = parent_preset == nullptr ? 0 :
 				static_cast<const ConfigOptionFloats*>(parent_preset->config.option("nozzle_diameter"))->values.size();
 		}
-		update_sys_ui_after_sel_preset();
-		update_full_options_list();
+//		update_sys_ui_after_sel_preset();
+//		update_full_options_list();
+		m_opt_status_value = (m_presets->get_selected_preset_parent() ? osSystemValue : 0) | osInitValue;
+		init_options_list();
 		update_changed_ui();
 	});
 }
@@ -1917,6 +2115,7 @@ void Tab::rebuild_page_tree()
 	for (auto p : m_pages)
 	{
 		auto itemId = m_treectrl->AppendItem(rootItem, p->title(), p->iconID());
+		m_treectrl->SetItemTextColour(itemId, p->get_item_colour());
 		if (p->title() == selected) {
 			m_disable_tree_sel_changed_event = 1;
 			m_treectrl->SelectItem(itemId);
diff --git a/xs/src/slic3r/GUI/Tab.hpp b/xs/src/slic3r/GUI/Tab.hpp
index 4668c1238..2ac1e969b 100644
--- a/xs/src/slic3r/GUI/Tab.hpp
+++ b/xs/src/slic3r/GUI/Tab.hpp
@@ -51,6 +51,7 @@ public:
 	{
 		Create(m_parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
 		m_vsizer = new wxBoxSizer(wxVERTICAL);
+		m_item_color = &get_default_label_clr();
 		SetSizer(m_vsizer);
 	}
 	~Page(){}
@@ -71,6 +72,22 @@ public:
 	Field*		get_field(const t_config_option_key& opt_key, int opt_index = -1) const;
 	bool		set_value(const t_config_option_key& opt_key, const boost::any& value);
 	ConfigOptionsGroupShp	new_optgroup(const wxString& title, int noncommon_label_width = -1);
+
+	bool		set_item_colour(const wxColour *clr) {
+		if (m_item_color != clr) {
+			m_item_color = clr;
+			return true;
+		}
+		return false;
+	}
+
+	const wxColour	get_item_colour() {
+			return *m_item_color;
+	}
+
+protected:
+	// Color of TreeCtrlItem. The wxColour will be updated only if the new wxColour pointer differs from the currently rendered one.
+	const wxColour*		m_item_color;
 };
 
 // Slic3r::GUI::Tab;
@@ -125,9 +142,13 @@ protected:
 	bool				m_no_controller;
 
 	std::vector<std::string>	m_reload_dependent_tabs = {};
-	std::vector<std::string>	m_dirty_options = {};
-	std::vector<std::string>	m_sys_options = {};
-	std::vector<std::string>	m_full_options_list = {};
+// 	std::vector<std::string>	m_dirty_options = {};
+// 	std::vector<std::string>	m_nonsys_options = {};
+//  std::vector<std::string>	m_sys_options = {};
+// 	std::vector<std::string>	m_full_options_list = {};
+	enum OptStatus { osSystemValue = 1, osInitValue = 2 };
+	std::map<std::string, int>	m_options_list;
+	int							m_opt_status_value;
 
 	// The two following two event IDs are generated at Plater.pm by calling Wx::NewEventType.
 	wxEventType			m_event_value_change = 0;
@@ -182,14 +203,15 @@ public:
 	void		update_show_hide_incompatible_button();
 	void		update_ui_from_settings();
 	void		update_changed_ui();
-	void		update_full_options_list();
-	void		update_sys_ui_after_sel_preset();
+// 	void		update_full_options_list();
+// 	void		update_sys_ui_after_sel_preset();
 	void		get_sys_and_mod_flags(const std::string& opt_key, bool& sys_page, bool& modified_page);
 	void		update_changed_tree_ui();
 	void		update_undo_buttons();
 
-	void		on_back_to_initial_value();
-	void		on_back_to_sys_value();
+	void		on_roll_back_value(const bool to_sys = false);
+// 	void		on_back_to_initial_value();
+// 	void		on_back_to_sys_value();
 
 	PageShp		add_options_page(const wxString& title, const std::string& icon, bool is_extruder_pages = false);
 
@@ -197,6 +219,7 @@ public:
 	virtual void	on_preset_loaded(){}
 	virtual void	build() = 0;
 	virtual void	update() = 0;
+	virtual void	init_options_list();
 	void			load_initial_data();
 	void			update_dirty();
 	void			update_tab_ui();
@@ -265,9 +288,10 @@ public:
 	wxButton*	m_octoprint_host_test_btn;
 
 	size_t		m_extruders_count;
+	size_t		m_extruders_count_old = 0;
 	size_t		m_initial_extruders_count;
 	size_t		m_sys_extruders_count;
-	std::vector<PageShp>	m_extruder_pages;
+//	std::vector<PageShp>	m_extruder_pages;
 
 	TabPrinter() {}
 	TabPrinter(wxNotebook* parent, bool no_controller) : Tab(parent, _(L("Printer Settings")), "printer", no_controller) {}
@@ -279,6 +303,7 @@ public:
 	void		extruders_count_changed(size_t extruders_count);
 	void		build_extruder_pages();
 	void		on_preset_loaded() override;
+	void		init_options_list() override;
 };
 
 class SavePresetWindow :public wxDialog

From f38f0edaaf3dc2b7c748e3b7c642ecbeaf140113 Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Wed, 18 Apr 2018 14:15:13 +0200
Subject: [PATCH 05/20] Cleaned code from commented code

---
 xs/src/slic3r/GUI/Tab.cpp | 333 +-------------------------------------
 xs/src/slic3r/GUI/Tab.hpp |   9 --
 2 files changed, 7 insertions(+), 335 deletions(-)

diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp
index dcf61f574..2cc51e0b5 100644
--- a/xs/src/slic3r/GUI/Tab.cpp
+++ b/xs/src/slic3r/GUI/Tab.cpp
@@ -248,37 +248,6 @@ PageShp Tab::add_options_page(const wxString& title, const std::string& icon, bo
 	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));
-// 	}
-// }
-// 
-// template<class T>
-// void add_correct_opts_to_sys_options(const std::string &opt_key, std::vector<std::string> *vec, TabPrinter *tab)
-// {
-// 	const Preset* sys_preset = tab->m_presets->get_selected_preset_parent();
-// 	if (sys_preset == nullptr)
-// 		return;
-// 	T *opt_cur = static_cast<T*>(tab->m_config->option(opt_key));
-// 	const T *opt_sys = static_cast<const T*>(sys_preset->config.option(opt_key));
-// 	int opt_max_id = opt_sys->values.size()-1;
-// 	for (int i = 0; i < opt_cur->values.size(); i++)
-// 	{
-// 		int init_id = i <= opt_max_id ? i : 0;
-// 		if (opt_cur->values[i] == opt_sys->values[init_id])
-// 			vec->emplace_back(opt_key + "#" + std::to_string(i));
-// 	}
-// }
-
 // Update UI according to changes
 void Tab::update_changed_ui()
 {
@@ -286,26 +255,25 @@ void Tab::update_changed_ui()
 		return;
 
 	const bool is_printer_type = (name() == "printer");
-	auto m_dirty_options = m_presets->current_dirty_options(is_printer_type);
-	auto m_nonsys_options = m_presets->current_different_from_parent_options(is_printer_type);
+	auto dirty_options = m_presets->current_dirty_options(is_printer_type);
+	auto nonsys_options = m_presets->current_different_from_parent_options(is_printer_type);
 	if (is_printer_type){
 		TabPrinter* tab = static_cast<TabPrinter*>(this);
 		if (tab->m_initial_extruders_count != tab->m_extruders_count)
-			m_dirty_options.emplace_back("extruders_count");
+			dirty_options.emplace_back("extruders_count");
 		if (tab->m_sys_extruders_count != tab->m_extruders_count)
-			m_nonsys_options.emplace_back("extruders_count");
+			nonsys_options.emplace_back("extruders_count");
 	}
 
 	for (auto& it : m_options_list)
 		it.second = m_opt_status_value;
 
-//	auto m_options_list = m_options_list;
-	for (auto opt_key : m_dirty_options)	m_options_list[opt_key] &= ~osInitValue;
-	for (auto opt_key : m_nonsys_options)	m_options_list[opt_key] &= ~osSystemValue;
+	for (auto opt_key : dirty_options)	m_options_list[opt_key] &= ~osInitValue;
+	for (auto opt_key : nonsys_options)	m_options_list[opt_key] &= ~osSystemValue;
 
 	Freeze();
 	//update options "decoration"
-	for (const auto opt : m_options_list/*m_options_list*/)
+	for (const auto opt : m_options_list)
 	{
 		bool is_nonsys_value = false;
 		bool is_modified_value = true;
@@ -314,17 +282,14 @@ void Tab::update_changed_ui()
 		const wxColour *color = &m_sys_label_clr;
 
 		if ((opt.second & osSystemValue) == 0){
-//		if (find(m_sys_options.begin(), m_sys_options.end(), opt_key) == m_sys_options.end()) {
 			is_nonsys_value = true;
 			sys_icon = m_bmp_non_system;
 			if ((opt.second & osInitValue) != 0)
-//			if (find(m_dirty_options.begin(), m_dirty_options.end(), opt_key) == m_dirty_options.end())
 				color = &m_default_text_clr;
 			else
 				color = &m_modified_label_clr;
 		}
 		if ((opt.second & osInitValue) != 0)
-//		if (find(m_dirty_options.begin(), m_dirty_options.end(), opt_key) == m_dirty_options.end())
 		{
 			is_modified_value = false;
 			icon = &m_bmp_white_bullet;
@@ -346,107 +311,7 @@ void Tab::update_changed_ui()
 		field->set_label_colour(color);
 	}
 	Thaw();
-//	m_options_list = m_options_list;
-/*	auto dirty_options = m_presets->current_dirty_options();
 
-	if (){
-		// Update dirty_options in case changes of Extruder's options 
-		TabPrinter* tab = static_cast<TabPrinter*>(this);
-		m_dirty_options.resize(0);
-		for (auto opt_key : dirty_options)
-		{
-			if (opt_key == "bed_shape"){ m_dirty_options.emplace_back(opt_key);		continue; }
-			switch (m_config->option(opt_key)->type())
-			{
-			case coInts:	add_correct_opts_to_dirty_options<ConfigOptionInts		>(opt_key, &m_dirty_options, tab);	break;
-			case coBools:	add_correct_opts_to_dirty_options<ConfigOptionBools		>(opt_key, &m_dirty_options, tab);	break;
-			case coFloats:	add_correct_opts_to_dirty_options<ConfigOptionFloats	>(opt_key, &m_dirty_options, tab);	break;
-			case coStrings:	add_correct_opts_to_dirty_options<ConfigOptionStrings	>(opt_key, &m_dirty_options, tab);	break;
-			case coPercents:add_correct_opts_to_dirty_options<ConfigOptionPercents	>(opt_key, &m_dirty_options, tab);	break;
-			case coPoints:	add_correct_opts_to_dirty_options<ConfigOptionPoints	>(opt_key, &m_dirty_options, tab);	break;
-			default:		m_dirty_options.emplace_back(opt_key);		break;
-			}
-		}
-		if (tab->m_initial_extruders_count != tab->m_extruders_count)
-			m_dirty_options.emplace_back("extruders_count");
-
-		m_sys_options.resize(0);
-		const auto sys_preset = m_presets->get_selected_preset_parent();
-		if (sys_preset){
-			for (auto opt_key : m_config->keys())
-			{
-				if (opt_key == "bed_shape"){ 
-					if (*tab->m_config->option(opt_key) == *sys_preset->config.option(opt_key))
-						m_sys_options.emplace_back(opt_key);		
-					continue; 
-				}
-				switch (m_config->option(opt_key)->type())
-				{
-				case coInts:	add_correct_opts_to_sys_options<ConfigOptionInts	>(opt_key, &m_sys_options, tab);	break;
-				case coBools:	add_correct_opts_to_sys_options<ConfigOptionBools	>(opt_key, &m_sys_options, tab);	break;
-				case coFloats:	add_correct_opts_to_sys_options<ConfigOptionFloats	>(opt_key, &m_sys_options, tab);	break;
-				case coStrings:	add_correct_opts_to_sys_options<ConfigOptionStrings	>(opt_key, &m_sys_options, tab);	break;
-				case coPercents:add_correct_opts_to_sys_options<ConfigOptionPercents>(opt_key, &m_sys_options, tab);	break;
-				case coPoints:	add_correct_opts_to_sys_options<ConfigOptionPoints	>(opt_key, &m_sys_options, tab);	break;
-				default:{
-					const ConfigOption *opt_cur = tab->m_config->option(opt_key);
-					const ConfigOption *opt_sys = sys_preset->config.option(opt_key);
-					if (opt_cur != nullptr && opt_sys != nullptr && *opt_cur == *opt_sys)
-						m_sys_options.emplace_back(opt_key);		
-					break;
-				}
-				}
-			}
-
-			if (tab->m_sys_extruders_count == tab->m_extruders_count)
-				m_sys_options.emplace_back("extruders_count");
-		}
-	}
-	else{
-		m_sys_options = m_presets->system_equal_options();
-		m_dirty_options = dirty_options;
-	}
-
-	Freeze();
-	//update options "decoration"
-	for (const auto opt_key : m_full_options_list)
-	{
-		bool is_nonsys_value = false;
-		bool is_modified_value = true;
-		const wxBitmap *sys_icon = &m_bmp_value_lock;
-		const wxBitmap *icon     = &m_bmp_value_revert;
-		const wxColour *color    = &m_sys_label_clr;
-		if (find(m_sys_options.begin(), m_sys_options.end(), opt_key) == m_sys_options.end()) {
-			is_nonsys_value = true;
-			sys_icon = m_bmp_non_system;
-			if(find(m_dirty_options.begin(), m_dirty_options.end(), opt_key) == m_dirty_options.end())
-				color = &m_default_text_clr;
-			else
-				color = &m_modified_label_clr;
-		}
-		if (find(m_dirty_options.begin(), m_dirty_options.end(), opt_key) == m_dirty_options.end())
-		{
-			is_modified_value = false;
-			icon = &m_bmp_white_bullet;
-		}
-		if (opt_key == "bed_shape" || opt_key == "compatible_printers") {
-			if (m_colored_Label != nullptr)	{
-				m_colored_Label->SetForegroundColour(*color);
-				m_colored_Label->Refresh(true);
-			}
-			continue;
-		}
-
-		Field* field = get_field(opt_key);
-		if (field == nullptr) continue;
-		field->m_is_nonsys_value = is_nonsys_value;
-		field->m_is_modified_value = is_modified_value;
-		field->set_undo_bitmap(icon);
-		field->set_undo_to_sys_bitmap(sys_icon);
-		field->set_label_colour(color);
-	}
-	Thaw();
-*/
 	wxTheApp->CallAfter([this]() {
 		update_changed_tree_ui();
 	});
@@ -494,60 +359,6 @@ void TabPrinter::init_options_list()
 	m_options_list.emplace("extruders_count", m_opt_status_value);
 }
 
-
-// template<class T>
-// void add_correct_opts_to_full_options_list(const std::string &opt_key, std::vector<std::string> *vec, TabPrinter *tab)
-// {
-// 	T *opt_cur = static_cast<T*>(tab->m_config->option(opt_key));
-// 	for (int i = 0; i < opt_cur->values.size(); i++)
-// 		vec->emplace_back(opt_key + "#" + std::to_string(i));
-// }
-
-// void Tab::update_full_options_list()
-// {
-// 	if (!m_full_options_list.empty())
-// 		m_full_options_list.resize(0);
-// 
-// 	if (m_name != "printer"){
-// 		m_full_options_list = m_config->keys();
-// 		return;
-// 	}
-// 
-// 	TabPrinter* tab = static_cast<TabPrinter*>(this);
-// 	for (const auto opt_key : m_config->keys())
-// 	{
-// 		if (opt_key == "bed_shape"){
-// 			m_full_options_list.emplace_back(opt_key);
-// 			continue;
-// 		}
-// 		switch (m_config->option(opt_key)->type())
-// 		{
-// 		case coInts:	add_correct_opts_to_full_options_list<ConfigOptionInts		>(opt_key, &m_full_options_list, tab);	break;
-// 		case coBools:	add_correct_opts_to_full_options_list<ConfigOptionBools		>(opt_key, &m_full_options_list, tab);	break;
-// 		case coFloats:	add_correct_opts_to_full_options_list<ConfigOptionFloats	>(opt_key, &m_full_options_list, tab);	break;
-// 		case coStrings:	add_correct_opts_to_full_options_list<ConfigOptionStrings	>(opt_key, &m_full_options_list, tab);	break;
-// 		case coPercents:add_correct_opts_to_full_options_list<ConfigOptionPercents	>(opt_key, &m_full_options_list, tab);	break;
-// 		case coPoints:	add_correct_opts_to_full_options_list<ConfigOptionPoints	>(opt_key, &m_full_options_list, tab);	break;
-// 		default:		m_full_options_list.emplace_back(opt_key);		break;
-// 		}
-// 	}
-// 	m_full_options_list.emplace_back("extruders_count");
-// }
-
-// void Tab::update_sys_ui_after_sel_preset()
-// {
-// 	const wxColour* clr = &m_default_text_clr;
-// 	for (const auto opt_key : m_full_options_list){
-// 		Field* field = get_field(opt_key);
-// 		if (field != nullptr){
-// 			field->set_undo_to_sys_bitmap(m_bmp_non_system);
-// 			field->m_is_nonsys_value = true;
-// 			field->set_label_colour(clr);
-// 		}
-// 	}
-// 	m_sys_options.resize(0);
-// }
-
 void Tab::get_sys_and_mod_flags(const std::string& opt_key, bool& sys_page, bool& modified_page)
 {
 	auto opt = m_options_list.find(opt_key);
@@ -666,112 +477,6 @@ void Tab::on_roll_back_value(const bool to_sys /*= true*/)
 	update_changed_ui();
 }
 
-// void Tab::on_back_to_initial_value()
-// {
-// 	if (!m_is_modified_values) return;
-// 	std::chrono::milliseconds ms1 = std::chrono::duration_cast<std::chrono::milliseconds>(
-// 		std::chrono::system_clock::now().time_since_epoch()
-// 		);
-// 
-// 	m_postpone_update_ui = true;
-// 
-// 	auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection());
-// 	for (auto page : m_pages)
-// 		if (page->title() == selection)	{
-// 			for (auto group : page->m_optgroups){
-// 				if (group->title == _("Capabilities")){
-// 					if (find(m_dirty_options.begin(), m_dirty_options.end(), "extruders_count") != m_dirty_options.end())
-// 						group->back_to_initial_value("extruders_count");
-// 				}
-// 				if (group->title == _("Size and coordinates")){
-// 					if (find(m_dirty_options.begin(), m_dirty_options.end(), "bed_shape") != m_dirty_options.end()){
-// 						group->back_to_initial_value("bed_shape");
-// 						load_key_value("bed_shape", true/*some value*/, true);
-// 					}
-// 
-// 				}
-// 				if (group->title == _("Profile dependencies")){
-// 					if (find(m_dirty_options.begin(), m_dirty_options.end(), "compatible_printers") != m_dirty_options.end()){
-// 						group->back_to_initial_value("compatible_printers");
-// 						load_key_value("compatible_printers", true/*some value*/, true);
-// 
-// 						bool is_empty = m_config->option<ConfigOptionStrings>("compatible_printers")->values.empty();
-// 						m_compatible_printers_checkbox->SetValue(is_empty);
-// 						is_empty ? m_compatible_printers_btn->Disable() : m_compatible_printers_btn->Enable();
-// 					}
-// 				}
-// 				for (t_opt_map::iterator it = group->m_opt_map.begin(); it != group->m_opt_map.end(); ++it) {
-// 					const std::string& opt_key = it->first;
-// 					if (find(m_dirty_options.begin(), m_dirty_options.end(), opt_key) != m_dirty_options.end())
-// 						group->back_to_initial_value(opt_key);
-// 				}
-// 			}
-// 			break;
-// 		}
-// 
-// 	std::chrono::milliseconds ms2 = std::chrono::duration_cast<std::chrono::milliseconds>(
-// 		std::chrono::system_clock::now().time_since_epoch()
-// 		);
-// 
-// 	m_postpone_update_ui = false;
-// 	update_changed_ui();
-// 
-// 	std::chrono::milliseconds ms3 = std::chrono::duration_cast<std::chrono::milliseconds>(
-// 		std::chrono::system_clock::now().time_since_epoch()
-// 		);
-// 
-// 	auto roll_back_duration = std::chrono::microseconds(ms2 - ms1).count();
-// 	auto update_ui_duration = std::chrono::microseconds(ms3 - ms2).count();
-// 	printf("back_to init_duration duration = %lld ms \n", roll_back_duration);
-// 	printf("update_ui_duration duration = %lld ms \n", update_ui_duration);
-// 
-// // 	m_postpone_update_ui = false;
-// // 	update_changed_ui();
-// }
-// 
-// void Tab::on_back_to_sys_value()
-// {
-// 	if (!m_is_nonsys_values) return;
-// 
-// 	m_postpone_update_ui = true;
-// 
-// 	auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection());
-// 	for (auto page : m_pages)
-// 		if (page->title() == selection)	{
-// 			for (auto group : page->m_optgroups) {
-// 				if (group->title == _("Capabilities")){
-// 					if (find(m_sys_options.begin(), m_sys_options.end(), "extruders_count") == m_sys_options.end())
-// 						group->back_to_sys_value("extruders_count");
-// 				}
-// 				if (group->title == _("Size and coordinates")){
-// 					if (find(m_sys_options.begin(), m_sys_options.end(), "bed_shape") == m_sys_options.end()){
-// 						group->back_to_sys_value("bed_shape");
-// 						load_key_value("bed_shape", true/*some value*/, true);
-// 					}
-// 				}
-// 				if (group->title == _("Profile dependencies")){
-// 					if (find(m_sys_options.begin(), m_sys_options.end(), "compatible_printers") == m_sys_options.end()){
-// 						group->back_to_sys_value("compatible_printers");
-// 						load_key_value("compatible_printers", true/*some value*/, true);
-// 
-// 						bool is_empty = m_config->option<ConfigOptionStrings>("compatible_printers")->values.empty();
-// 						m_compatible_printers_checkbox->SetValue(is_empty);
-// 						is_empty ? m_compatible_printers_btn->Disable() : m_compatible_printers_btn->Enable();
-// 					}
-// 				}
-// 				for (t_opt_map::iterator it = group->m_opt_map.begin(); it != group->m_opt_map.end(); ++it) {
-// 					const std::string& opt_key = it->first;
-// 					if (find(m_sys_options.begin(), m_sys_options.end(), opt_key) == m_sys_options.end())
-// 						group->back_to_sys_value(opt_key);
-// 				}
-// 			}
-// 			break;
-// 		}
-// 
-// 	m_postpone_update_ui = false;
-// 	update_changed_ui();
-// }
-
 // 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(){
@@ -1904,7 +1609,6 @@ void TabPrinter::build_extruder_pages(){
 		sprintf(buf, _CHB(L("Extruder %d")), extruder_idx + 1);
 		auto page = add_options_page(from_u8(buf), "funnel.png", true);
 		m_pages.insert(m_pages.begin() + 2+extruder_idx, page);
-//  		m_extruder_pages.push_back(page);
 			
 			auto optgroup = page->new_optgroup(_(L("Size")));
 			optgroup->append_single_option_line("nozzle_diameter", extruder_idx);
@@ -1942,32 +1646,11 @@ void TabPrinter::build_extruder_pages(){
 	}
  
 	// # remove extra pages
-// 	if (m_extruders_count <= m_extruders_count_old) {
-// 		m_extruder_pages.resize(m_extruders_count);
-// 	}
-
 	if (m_extruders_count < m_extruders_count_old)
 		m_pages.erase(m_pages.begin() + 2 + m_extruders_count, m_pages.begin() + 2 + m_extruders_count_old);
 
 	m_extruders_count_old = m_extruders_count;
 
-	// # rebuild page list
-// 	PageShp page_note = m_pages.back();
-// 	m_pages.pop_back();
-// 	PageShp page_depend = m_pages.back();
-// 	m_pages.pop_back();
-// 	auto counter = m_extruders_count_old;
-// 	while (counter > m_extruders_count/*m_pages.back()->title().find(_(L("Extruder"))) != std::string::npos*/){
-// 		m_pages.pop_back();
-// 		--counter;
-// 	}
-// // 	for (auto page_extruder : m_extruder_pages)
-// //		m_pages.push_back(page_extruder);
-// 	for (auto extruder_idx = m_extruders_count_old; extruder_idx < m_extruders_count; ++extruder_idx)
-// 		m_pages.push_back(m_extruder_pages[extruder_idx]);
-//  	m_pages.push_back(page_note);
-// 	m_pages.push_back(page_depend);
-
 	rebuild_page_tree();
 }
 
@@ -2095,8 +1778,6 @@ void Tab::load_current_preset()
 			static_cast<TabPrinter*>(this)->m_sys_extruders_count = parent_preset == nullptr ? 0 :
 				static_cast<const ConfigOptionFloats*>(parent_preset->config.option("nozzle_diameter"))->values.size();
 		}
-//		update_sys_ui_after_sel_preset();
-//		update_full_options_list();
 		m_opt_status_value = (m_presets->get_selected_preset_parent() ? osSystemValue : 0) | osInitValue;
 		init_options_list();
 		update_changed_ui();
diff --git a/xs/src/slic3r/GUI/Tab.hpp b/xs/src/slic3r/GUI/Tab.hpp
index 2ac1e969b..2eef29500 100644
--- a/xs/src/slic3r/GUI/Tab.hpp
+++ b/xs/src/slic3r/GUI/Tab.hpp
@@ -142,10 +142,6 @@ protected:
 	bool				m_no_controller;
 
 	std::vector<std::string>	m_reload_dependent_tabs = {};
-// 	std::vector<std::string>	m_dirty_options = {};
-// 	std::vector<std::string>	m_nonsys_options = {};
-//  std::vector<std::string>	m_sys_options = {};
-// 	std::vector<std::string>	m_full_options_list = {};
 	enum OptStatus { osSystemValue = 1, osInitValue = 2 };
 	std::map<std::string, int>	m_options_list;
 	int							m_opt_status_value;
@@ -203,15 +199,11 @@ public:
 	void		update_show_hide_incompatible_button();
 	void		update_ui_from_settings();
 	void		update_changed_ui();
-// 	void		update_full_options_list();
-// 	void		update_sys_ui_after_sel_preset();
 	void		get_sys_and_mod_flags(const std::string& opt_key, bool& sys_page, bool& modified_page);
 	void		update_changed_tree_ui();
 	void		update_undo_buttons();
 
 	void		on_roll_back_value(const bool to_sys = false);
-// 	void		on_back_to_initial_value();
-// 	void		on_back_to_sys_value();
 
 	PageShp		add_options_page(const wxString& title, const std::string& icon, bool is_extruder_pages = false);
 
@@ -291,7 +283,6 @@ public:
 	size_t		m_extruders_count_old = 0;
 	size_t		m_initial_extruders_count;
 	size_t		m_sys_extruders_count;
-//	std::vector<PageShp>	m_extruder_pages;
 
 	TabPrinter() {}
 	TabPrinter(wxNotebook* parent, bool no_controller) : Tab(parent, _(L("Printer Settings")), "printer", no_controller) {}

From 7083f58326c07050349fe8c0d999a1ee49702e5c Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Thu, 19 Apr 2018 12:08:59 +0200
Subject: [PATCH 06/20] Added lock icons to system presets in ComboBoxes.

Added right event handling if informative string is selected in ComboBoxes
---
 xs/src/slic3r/GUI/Preset.cpp       | 109 ++++++++++++++++++++---------
 xs/src/slic3r/GUI/Preset.hpp       |   8 ++-
 xs/src/slic3r/GUI/PresetBundle.cpp |  25 ++++---
 xs/src/slic3r/GUI/Tab.cpp          |  10 ++-
 xs/src/slic3r/GUI/Tab.hpp          |   2 +
 5 files changed, 106 insertions(+), 48 deletions(-)

diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp
index 30f49df08..04c5865b8 100644
--- a/xs/src/slic3r/GUI/Preset.cpp
+++ b/xs/src/slic3r/GUI/Preset.cpp
@@ -2,6 +2,7 @@
 #include <cassert>
 
 #include "Preset.hpp"
+#include "BitmapCache.hpp"
 
 #include <fstream>
 #include <boost/filesystem.hpp>
@@ -252,7 +253,8 @@ PresetCollection::PresetCollection(Preset::Type type, const std::vector<std::str
     m_type(type),
     m_edited_preset(type, "", false),
     m_idx_selected(0),
-    m_bitmap_main_frame(new wxBitmap)
+    m_bitmap_main_frame(new wxBitmap),
+	m_bitmap_cache(new GUI::BitmapCache)
 {
     // Insert just the default preset.
     m_presets.emplace_back(Preset(type, "- default -", true));
@@ -264,6 +266,8 @@ PresetCollection::~PresetCollection()
 {
     delete m_bitmap_main_frame;
     m_bitmap_main_frame = nullptr;
+	delete m_bitmap_cache;
+	m_bitmap_cache = nullptr;
 }
 
 void PresetCollection::reset(bool delete_files)
@@ -511,17 +515,41 @@ void PresetCollection::update_platter_ui(wxBitmapComboBox *ui)
     // Otherwise fill in the list from scratch.
     ui->Freeze();
     ui->Clear();
-	std::map<wxString, bool> nonsys_presets;
+
+	const Preset &selected_preset = this->get_selected_preset();
+	// Show wide icons if the currently selected preset is not compatible with the current printer,
+	// and draw a red flag in front of the selected preset.
+	bool wide_icons = !selected_preset.is_compatible && m_bitmap_incompatible != nullptr;
+
+	std::map<wxString, wxBitmap*> nonsys_presets;
 	wxString selected = "";
-    for (size_t i = this->m_presets.front().is_visible ? 0 : 1; i < this->m_presets.size(); ++ i) {
+	if (!this->m_presets.front().is_visible)
+		ui->Append("------- System presets -------", wxNullBitmap);
+	for (size_t i = this->m_presets.front().is_visible ? 0 : 1; i < this->m_presets.size(); ++i) {
         const Preset &preset = this->m_presets[i];
         if (! preset.is_visible || (! preset.is_compatible && i != m_idx_selected))
             continue;
-        const wxBitmap *bmp = (i == 0 || preset.is_compatible) ? m_bitmap_main_frame : m_bitmap_incompatible;
-//         ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()),
-//             (bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp);
-// 		if (i == m_idx_selected)
-//             ui->SetSelection(ui->GetCount() - 1);
+		std::string   bitmap_key = "";
+		// If the filament preset is not compatible and there is a "red flag" icon loaded, show it left
+		// to the filament color image.
+		if (wide_icons)
+			bitmap_key += preset.is_compatible ? ",cmpt" : ",ncmpt";
+		bitmap_key += (preset.is_system || preset.is_default) ? ",syst" : ",nsyst";
+		wxBitmap     *bmp = m_bitmap_cache->find(bitmap_key);
+		if (bmp == nullptr) {
+			// Create the bitmap with color bars.
+			std::vector<wxBitmap> bmps;
+			if (wide_icons)
+				// Paint a red flag for incompatible presets.
+				bmps.emplace_back(preset.is_compatible ? m_bitmap_cache->mkclear(16, 16) : *m_bitmap_incompatible);
+			// Paint the color bars.
+			bmps.emplace_back(m_bitmap_cache->mkclear(4, 16));
+			bmps.emplace_back(*m_bitmap_main_frame);
+			// Paint a lock at the system presets.
+ 			bmps.emplace_back(m_bitmap_cache->mkclear(6, 16));
+			bmps.emplace_back((preset.is_system || preset.is_default) ? *m_bitmap_lock : m_bitmap_cache->mkclear(16, 16));
+			bmp = m_bitmap_cache->insert(bitmap_key, bmps);
+		}
 
 		if (preset.is_default || preset.is_system){
 			ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()),
@@ -531,20 +559,18 @@ void PresetCollection::update_platter_ui(wxBitmapComboBox *ui)
 		}
 		else
 		{
-			nonsys_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), preset.is_compatible);
+			nonsys_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), bmp/*preset.is_compatible*/);
 			if (i == m_idx_selected)
 				selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str());
 		}
 		if (preset.is_default)
-			ui->Append("------------------------------------", wxNullBitmap);
+			ui->Append("------- System presets -------", wxNullBitmap);
 	}
 	if (!nonsys_presets.empty())
 	{
-		ui->Append("------------------------------------", wxNullBitmap);
-		for (std::map<wxString, bool>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) {
-			const wxBitmap *bmp = it->second ? m_bitmap_compatible : m_bitmap_incompatible;
-			ui->Append(it->first,
-				(bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp);
+		ui->Append("-------  User presets  -------", wxNullBitmap);
+		for (std::map<wxString, wxBitmap*>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) {
+			ui->Append(it->first, *it->second);
 			if (it->first == selected)
 				ui->SetSelection(ui->GetCount() - 1);
 		}
@@ -552,51 +578,63 @@ void PresetCollection::update_platter_ui(wxBitmapComboBox *ui)
     ui->Thaw();
 }
 
-void PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompatible)
+size_t PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompatible)
 {
     if (ui == nullptr)
-        return;
+        return 0;
     ui->Freeze();
     ui->Clear();
-	std::map<wxString, bool> nonsys_presets;
+	size_t selected_preset_item = 0;
+
+	std::map<wxString, wxBitmap*> nonsys_presets;
 	wxString selected = "";
-    for (size_t i = this->m_presets.front().is_visible ? 0 : 1; i < this->m_presets.size(); ++ i) {
+	if (!this->m_presets.front().is_visible)
+		ui->Append("------- System presets -------", wxNullBitmap);
+	for (size_t i = this->m_presets.front().is_visible ? 0 : 1; i < this->m_presets.size(); ++i) {
         const Preset &preset = this->m_presets[i];
         if (! preset.is_visible || (! show_incompatible && ! preset.is_compatible && i != m_idx_selected))
             continue;
-        const wxBitmap *bmp = preset.is_compatible ? m_bitmap_compatible : m_bitmap_incompatible;
-//         ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()),
-//             (bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp);
-// 		if (i == m_idx_selected)
-//             ui->SetSelection(ui->GetCount() - 1);
+		std::string   bitmap_key = "tab";
+		bitmap_key += preset.is_compatible ? ",cmpt" : ",ncmpt";
+		bitmap_key += (preset.is_system || preset.is_default) ? ",syst" : ",nsyst";
+		wxBitmap     *bmp = m_bitmap_cache->find(bitmap_key);
+		if (bmp == nullptr) {
+			// Create the bitmap with color bars.
+			std::vector<wxBitmap> bmps;
+			const wxBitmap* tmp_bmp = preset.is_compatible ? m_bitmap_compatible : m_bitmap_incompatible;
+			bmps.emplace_back((tmp_bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *tmp_bmp);
+			// Paint a lock at the system presets.
+			bmps.emplace_back((preset.is_system || preset.is_default) ? *m_bitmap_lock : m_bitmap_cache->mkclear(16, 16));
+			bmp = m_bitmap_cache->insert(bitmap_key, bmps);
+		}
 
 		if (preset.is_default || preset.is_system){
 			ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()),
 				(bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp);
 			if (i == m_idx_selected)
-				ui->SetSelection(ui->GetCount() - 1);
+				selected_preset_item = ui->GetCount() - 1;
 		}
 		else
 		{
-			nonsys_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), preset.is_compatible);
+			nonsys_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()), bmp/*preset.is_compatible*/);
 			if (i == m_idx_selected)
 				selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str());
 		}
 		if (preset.is_default)
-			ui->Append("------------------------------------", wxNullBitmap);
+			ui->Append("------- System presets -------", wxNullBitmap);
     }
 	if (!nonsys_presets.empty())
 	{
-		ui->Append("------------------------------------", wxNullBitmap);
-		for (std::map<wxString, bool>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) {
-			const wxBitmap *bmp = it->second ? m_bitmap_compatible : m_bitmap_incompatible;
-			ui->Append(it->first,
-				(bmp == 0) ? (m_bitmap_main_frame ? *m_bitmap_main_frame : wxNullBitmap) : *bmp);
+		ui->Append("-------  User presets  -------", wxNullBitmap);
+		for (std::map<wxString, wxBitmap*>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) {
+			ui->Append(it->first, *it->second);
 			if (it->first == selected)
-				ui->SetSelection(ui->GetCount() - 1);
+				selected_preset_item = ui->GetCount() - 1;
 		}
 	}
+	ui->SetSelection(selected_preset_item);
     ui->Thaw();
+	return selected_preset_item;
 }
 
 // Update a dirty floag of the current preset, update the labels of the UI component accordingly.
@@ -692,6 +730,11 @@ bool PresetCollection::select_preset_by_name(const std::string &name_w_suffix, b
         // If the first visible preset was not found, return the 0th element, which is the default preset.
     }
 
+	// Temporary decision
+	if (name_w_suffix == "------- System presets -------" ||
+		name_w_suffix == "-------  User presets  -------")
+		return true;
+
     // 2) Select the new preset.
     if (m_idx_selected != idx || force) {
         this->select_preset(idx);
diff --git a/xs/src/slic3r/GUI/Preset.hpp b/xs/src/slic3r/GUI/Preset.hpp
index e12f18b88..cc409addc 100644
--- a/xs/src/slic3r/GUI/Preset.hpp
+++ b/xs/src/slic3r/GUI/Preset.hpp
@@ -13,6 +13,10 @@ class wxItemContainer;
 
 namespace Slic3r {
 
+namespace GUI {
+	class BitmapCache;
+}
+
 enum ConfigFileType
 {
     CONFIG_FILE_TYPE_UNKNOWN,
@@ -264,7 +268,7 @@ public:
     // Update the choice UI from the list of presets.
     // If show_incompatible, all presets are shown, otherwise only the compatible presets are shown.
     // If an incompatible preset is selected, it is shown as well.
-    void            update_tab_ui(wxBitmapComboBox *ui, bool show_incompatible);
+    size_t          update_tab_ui(wxBitmapComboBox *ui, bool show_incompatible);
     // Update the choice UI from the list of presets.
     // Only the compatible presets are shown.
     // If an incompatible preset is selected, it is shown as well.
@@ -324,6 +328,8 @@ private:
     wxBitmap               *m_bitmap_main_frame;
     // Path to the directory to store the config files into.
     std::string             m_dir_path;
+	// Caching color bitmaps for the filament combo box.
+	GUI::BitmapCache       *m_bitmap_cache = nullptr;
 };
 
 } // namespace Slic3r
diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp
index 1c3a6dcac..d6cde84a8 100644
--- a/xs/src/slic3r/GUI/PresetBundle.cpp
+++ b/xs/src/slic3r/GUI/PresetBundle.cpp
@@ -1025,9 +1025,11 @@ void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, wxBitma
     // and draw a red flag in front of the selected preset.
     bool          wide_icons      = selected_preset != nullptr && ! selected_preset->is_compatible && m_bitmapIncompatible != nullptr;
     assert(selected_preset != nullptr);
-	std::map<wxString, wxBitmap> nonsys_presets;
+	std::map<wxString, wxBitmap*> nonsys_presets;
 	wxString selected_str = "";
-    for (int i = this->filaments().front().is_visible ? 0 : 1; i < int(this->filaments().size()); ++ i) {
+	if (!this->filaments().front().is_visible)
+		ui->Append("------- System presets -------", wxNullBitmap);
+	for (int i = this->filaments().front().is_visible ? 0 : 1; i < int(this->filaments().size()); ++i) {
         const Preset &preset    = this->filaments.preset(i);
         bool          selected  = this->filament_presets[idx_extruder] == preset.name;
 		if (! preset.is_visible || (! preset.is_compatible && ! selected))
@@ -1059,14 +1061,11 @@ void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, wxBitma
                 bmps.emplace_back(m_bitmapCache->mksolid(8,  16, rgb));
             }
             // Paint a lock at the system presets.
-            bmps.emplace_back(m_bitmapCache->mkclear(4, 16));
-            bmps.emplace_back((preset.is_system || preset.is_default) ? 
-                (preset.is_dirty ? *m_bitmapLockOpen : *m_bitmapLock) : m_bitmapCache->mkclear(16, 16));
+            bmps.emplace_back(m_bitmapCache->mkclear(2, 16));
+			bmps.emplace_back((preset.is_system || preset.is_default) ? *m_bitmapLock : m_bitmapCache->mkclear(16, 16));
+//                 (preset.is_dirty ? *m_bitmapLockOpen : *m_bitmapLock) : m_bitmapCache->mkclear(16, 16));
             bitmap = m_bitmapCache->insert(bitmap_key, bmps);
 		}
-// 		ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()), (bitmap == 0) ? wxNullBitmap : *bitmap);
-//         if (selected)
-//             ui->SetSelection(ui->GetCount() - 1);
 
 		if (preset.is_default || preset.is_system){
 			ui->Append(wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()), 
@@ -1077,19 +1076,19 @@ void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, wxBitma
 		else
 		{
 			nonsys_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()), 
-				(bitmap == 0) ? wxNullBitmap : *bitmap);
+				(bitmap == 0) ? &wxNullBitmap : bitmap);
 			if (selected)
 				selected_str = wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str());
 		}
 		if (preset.is_default)
-			ui->Append("------------------------------------", wxNullBitmap);
+			ui->Append("------- System presets -------", wxNullBitmap);
     }
 
 	if (!nonsys_presets.empty())
 	{
-		ui->Append("------------------------------------", wxNullBitmap);
-		for (std::map<wxString, wxBitmap>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) {
-			ui->Append(it->first, it->second);
+		ui->Append("-------  User presets  -------", wxNullBitmap);
+		for (std::map<wxString, wxBitmap*>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) {
+			ui->Append(it->first, *it->second);
 			if (it->first == selected_str)
 				ui->SetSelection(ui->GetCount() - 1);
 		}
diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp
index 2cc51e0b5..810ee6e14 100644
--- a/xs/src/slic3r/GUI/Tab.cpp
+++ b/xs/src/slic3r/GUI/Tab.cpp
@@ -198,8 +198,16 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
 		//! select_preset(m_presets_choice->GetStringSelection().ToStdString()); 
 		//! we doing next:
 		int selected_item = m_presets_choice->GetSelection();
+		if (m_selected_preset_item == selected_item)
+			return;
 		if (selected_item >= 0){
 			std::string selected_string = m_presets_choice->GetString(selected_item).ToUTF8().data();
+			if (selected_string == "------- System presets -------" ||
+				selected_string == "-------  User presets  -------"){
+				m_presets_choice->SetSelection(m_selected_preset_item);
+				return;
+			}
+			m_selected_preset_item = selected_item;
 			select_preset(selected_string);
 		}
 	}));
@@ -488,7 +496,7 @@ void Tab::update_dirty(){
 
 void Tab::update_tab_ui()
 {
-	m_presets->update_tab_ui(m_presets_choice, m_show_incompatible_presets);
+	m_selected_preset_item = m_presets->update_tab_ui(m_presets_choice, m_show_incompatible_presets);
 // 	update_tab_presets(m_cc_presets_choice, m_show_incompatible_presets);
 // 	update_presetsctrl(m_presetctrl, m_show_incompatible_presets);
 }
diff --git a/xs/src/slic3r/GUI/Tab.hpp b/xs/src/slic3r/GUI/Tab.hpp
index 2eef29500..d5a679564 100644
--- a/xs/src/slic3r/GUI/Tab.hpp
+++ b/xs/src/slic3r/GUI/Tab.hpp
@@ -154,6 +154,8 @@ protected:
 	bool				m_is_nonsys_values{ true };
 	bool				m_postpone_update_ui {false};
 
+	size_t				m_selected_preset_item{ 0 };
+
 public:
 	PresetBundle*		m_preset_bundle;
 	bool				m_show_btn_incompatible_presets = false;

From 88dadcec78185c00bef759643c3ccd427f9e0d06 Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Thu, 19 Apr 2018 16:20:30 +0200
Subject: [PATCH 07/20] Added tooltips for reverse buttons

* Corrected default size of undo buttons for GTK
* Experiment with rich tooltips
---
 xs/src/slic3r/GUI/Field.cpp |  8 +++++--
 xs/src/slic3r/GUI/Tab.cpp   | 42 +++++++++++++++++++++++++++++++++++--
 xs/src/slic3r/GUI/Tab.hpp   | 16 ++++++++++++--
 3 files changed, 60 insertions(+), 6 deletions(-)

diff --git a/xs/src/slic3r/GUI/Field.cpp b/xs/src/slic3r/GUI/Field.cpp
index e959c7966..ff17a2ef8 100644
--- a/xs/src/slic3r/GUI/Field.cpp
+++ b/xs/src/slic3r/GUI/Field.cpp
@@ -20,8 +20,12 @@ namespace Slic3r { namespace GUI {
 
 	void Field::PostInitialize(){
 		auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
-		m_Undo_btn			= new wxButton(m_parent, wxID_ANY, "", wxDefaultPosition, wxSize(16, 16), wxNO_BORDER);
-		m_Undo_to_sys_btn	= new wxButton(m_parent, wxID_ANY, "", wxDefaultPosition, wxSize(16, 16), wxNO_BORDER);
+		auto sz = 16;
+	#ifdef __WXGTK__
+		sz = 28
+	#endif // __WXGTK__
+		m_Undo_btn			= new wxButton(m_parent, wxID_ANY, "", wxDefaultPosition, wxSize(sz,sz), wxNO_BORDER);
+		m_Undo_to_sys_btn	= new wxButton(m_parent, wxID_ANY, "", wxDefaultPosition, wxSize(sz,sz), wxNO_BORDER);
 		if (wxMSW) {
 			m_Undo_btn->SetBackgroundColour(color);
 			m_Undo_to_sys_btn->SetBackgroundColour(color);
diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp
index 810ee6e14..049196599 100644
--- a/xs/src/slic3r/GUI/Tab.cpp
+++ b/xs/src/slic3r/GUI/Tab.cpp
@@ -102,10 +102,42 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
 
 	m_undo_btn = new wxButton(panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER);
 	m_undo_to_sys_btn = new wxButton(panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER);
+	m_question_btn = new wxButton(panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER);
+	m_undo_btns_legent = new wxStaticText(panel, wxID_ANY, _(L("For more information about buttons hover the mouse cursor over them.")), wxDefaultPosition, wxDefaultSize);
 	if (wxMSW) {
 		m_undo_btn->SetBackgroundColour(color);
 		m_undo_to_sys_btn->SetBackgroundColour(color);
+		m_question_btn->SetBackgroundColour(color);
 	}
+
+#ifdef __WXMSW__
+	m_undo_to_sys_btn->SetToolTip(_(L(	"Unlocked lock icon indicates about some value changes compared with system values "
+										"in current option group.\n"
+										"Locked lock icon indicates about same values compared with system values "
+										"in current option group.\n"
+										"White bullet icon indicates about nonsystem preset.\n"
+										"Click the unlocked lock to revert all values in current option group to system values.")));
+#else
+	// ToolTips to undo buttons
+	m_undo_btn_tip = new wxRichToolTip("Information about current button",
+		_(L("Unlocked lock icon indicates about some value changes compared with system values "
+			"in current option group.\n"
+			"Locked lock icon indicates about same values compared with system values "
+			"in current option group.\n"
+			"White bullet icon indicates about nonsystem preset.\n"
+			"Click the unlocked lock to revert all values in current option group to system values.")));
+	m_undo_btn_tip->SetIcon(wxICON_INFORMATION);
+	m_undo_btn_tip->ShowFor(m_undo_btn);
+#endif //__WXMSW__
+
+	m_undo_btn->SetToolTip(_(L(	"Back arrow icon indicates about some value changes compared with last saved preset values "
+								"in current option group.\n"
+								"White bullet icon indicates about same values compared with last saved preset values "
+								"in current option group.\n"
+								"Click the Back arrow to revert all values in current option group to last saved preset values.")));
+
+	m_question_btn->SetToolTip(_(L("Hover the cursor over buttons to find more information.")));
+
 	// Bitmaps to be shown on the "Revert to system" aka "Lock to system" button next to each input field.
 	m_bmp_value_lock  	  .LoadFile(from_u8(var("sys_lock.png")),     wxBITMAP_TYPE_PNG);
 	m_bmp_value_unlock	  .LoadFile(from_u8(var("sys_unlock.png")),   wxBITMAP_TYPE_PNG);
@@ -113,10 +145,13 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
 	// Bitmaps to be shown on the "Undo user changes" button next to each input field.
 	m_bmp_value_revert	  .LoadFile(from_u8(var("action_undo.png")),  wxBITMAP_TYPE_PNG);
 	m_bmp_white_bullet	  .LoadFile(from_u8(var("bullet_white.png")), wxBITMAP_TYPE_PNG);
+	m_bmp_question        .LoadFile(from_u8(var("question_mark_01.png")), wxBITMAP_TYPE_PNG);
+
 	m_undo_btn->SetBitmap(m_bmp_white_bullet);
-	m_undo_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ /*on_back_to_initial_value*/on_roll_back_value(); }));
+	m_undo_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ on_roll_back_value(); }));
 	m_undo_to_sys_btn->SetBitmap(m_bmp_white_bullet);
-	m_undo_to_sys_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ /*on_back_to_sys_value*/on_roll_back_value(true); }));
+	m_undo_to_sys_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ on_roll_back_value(true); }));
+	m_question_btn->SetBitmap(m_bmp_question);
 
 	// Colors for ui "decoration"
 	m_sys_label_clr			= get_sys_label_clr();
@@ -135,6 +170,9 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
 	m_hsizer->AddSpacer(64);
 	m_hsizer->Add(m_undo_to_sys_btn, 0, wxALIGN_CENTER_VERTICAL);
 	m_hsizer->Add(m_undo_btn, 0, wxALIGN_CENTER_VERTICAL);
+	m_hsizer->AddSpacer(16);
+	m_hsizer->Add(m_question_btn, 0, wxALIGN_CENTER_VERTICAL);
+	m_hsizer->Add(m_undo_btns_legent, 0, wxALIGN_CENTER_VERTICAL);
 // 	m_hsizer->AddSpacer(64);
 // 	m_hsizer->Add(m_cc_presets_choice, 1, wxLEFT | wxRIGHT | wxTOP | wxALIGN_CENTER_VERTICAL, 3);
 
diff --git a/xs/src/slic3r/GUI/Tab.hpp b/xs/src/slic3r/GUI/Tab.hpp
index d5a679564..364608dc1 100644
--- a/xs/src/slic3r/GUI/Tab.hpp
+++ b/xs/src/slic3r/GUI/Tab.hpp
@@ -22,6 +22,7 @@
 #include <wx/imaglist.h>
 #include <wx/statbox.h>
 #include <wx/dataview.h>
+#include <wx/richtooltip.h>
 
 #include <map>
 #include <vector>
@@ -110,7 +111,11 @@ protected:
 	wxCheckBox*			m_compatible_printers_checkbox;
 	wxButton*			m_compatible_printers_btn;
 	wxButton*			m_undo_btn;
-	wxButton*			m_undo_to_sys_btn;	
+	wxButton*			m_undo_to_sys_btn;
+	wxButton*			m_question_btn;
+	wxStaticText*		m_undo_btns_legent;
+	wxRichToolTip*		m_undo_btn_tip;
+
 	wxComboCtrl*		m_cc_presets_choice;
 	wxDataViewTreeCtrl*	m_presetctrl;
 	wxImageList*		m_preset_icons;
@@ -128,6 +133,7 @@ protected:
 	// Bitmaps to be shown on the "Undo user changes" button next to each input field.
 	wxBitmap 			m_bmp_value_revert;
 	wxBitmap 			m_bmp_value_unmodified;
+	wxBitmap			m_bmp_question;
 
 	// Colors for ui "decoration"
 	wxColour			m_sys_label_clr;
@@ -171,7 +177,13 @@ public:
 		Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL);
 		get_tabs_list().push_back(this);
 	}
-	~Tab() { delete_tab_from_list(this); }
+	~Tab(){
+		delete_tab_from_list(this);
+		if (m_undo_btn_tip){
+			delete m_undo_btn_tip;
+			m_undo_btn_tip = nullptr;
+		}
+	}
 
 	wxWindow*	parent() const { return m_parent; }
 	wxString	title()	 const { return m_title; }

From 1e1bf03f61c5fe3aab4a9396b1fd56f4a76b6bc1 Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Fri, 20 Apr 2018 12:58:07 +0200
Subject: [PATCH 08/20] Added reset buttons description

---
 resources/icons/question_mark_01.png | Bin 0 -> 523 bytes
 xs/src/slic3r/GUI/2DBed.hpp          |   5 +++
 xs/src/slic3r/GUI/BedShapeDialog.hpp |   5 +++
 xs/src/slic3r/GUI/Field.cpp          |   2 +-
 xs/src/slic3r/GUI/OptionsGroup.hpp   |   5 +++
 xs/src/slic3r/GUI/Preferences.hpp    |   5 +++
 xs/src/slic3r/GUI/Tab.cpp            |  59 ++++++++++++++++-----------
 xs/src/slic3r/GUI/Tab.hpp            |  19 +++++----
 xs/src/slic3r/GUI/TabIface.hpp       |   7 +++-
 9 files changed, 74 insertions(+), 33 deletions(-)
 create mode 100644 resources/icons/question_mark_01.png

diff --git a/resources/icons/question_mark_01.png b/resources/icons/question_mark_01.png
new file mode 100644
index 0000000000000000000000000000000000000000..25814a61d4e7aa408640e206b6c58b10122962d5
GIT binary patch
literal 523
zcmV+m0`&cfP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00001b5ch_0Itp)
z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0ia1lK~y+Tol(y#
z1yLBilvrRR*`Z9Cd*7^3Qc6i7C589y^&>^u*|79Gmi`ADTWecUEU+ZKNNj8{b1#u!
zGtM1fjqvnxYMQ#|eCIpg_pz^t7%K=esX8tBav;T?R{RYAY@o!BR$|3uQap-S0m*+t
zE3X9wNBG`R5PkjZTOj$dFGag;L?sE#fKv(4c3cn}@B{o;1I5>Dio}TTS}m0&Fv@L%
z_@26*-lkp8c8V5Rp_XnB%ru#6qeLr}B?zR~1cNJx3`8@wkSJz`g#dR==1&hQ)k#!>
z!^y@XEU!5j;vLbTD5Yl>jn$N3i3^DSLL*!n<+()v4c+Hf#CwoPMcrXAXPc2EH}0iZ
zg+v>O{`@&Rzr$je!twetlH`V+KaQ>VD|J4_`3ACGPBBUThMgPTwmv&!`%?7&diz|6
zPp8B*VxJqu*KdZMa-#A_IOP=knfluBKgBk#pLQFthk2t?{TCRCsQh3rfW_^@AjH{x
zo#EX?<%eKII9TFkd;uli{2@L;RDK9?E}U={CMQU+`8X=7iTVb{J^=r2>{O*7e`o*z
N002ovPDHLkV1kV-<Msdm

literal 0
HcmV?d00001

diff --git a/xs/src/slic3r/GUI/2DBed.hpp b/xs/src/slic3r/GUI/2DBed.hpp
index a170b708a..4b14986a2 100644
--- a/xs/src/slic3r/GUI/2DBed.hpp
+++ b/xs/src/slic3r/GUI/2DBed.hpp
@@ -1,3 +1,6 @@
+#ifndef slic3r_2DBed_hpp_
+#define slic3r_2DBed_hpp_
+
 #include <wx/wx.h>
 #include "Config.hpp"
 
@@ -45,3 +48,5 @@ public:
 
 } // GUI
 } // Slic3r
+
+#endif /* slic3r_2DBed_hpp_ */
diff --git a/xs/src/slic3r/GUI/BedShapeDialog.hpp b/xs/src/slic3r/GUI/BedShapeDialog.hpp
index f4614c342..5ff488063 100644
--- a/xs/src/slic3r/GUI/BedShapeDialog.hpp
+++ b/xs/src/slic3r/GUI/BedShapeDialog.hpp
@@ -1,3 +1,5 @@
+#ifndef slic3r_BedShapeDialog_hpp_
+#define slic3r_BedShapeDialog_hpp_
 // The bed shape dialog.
 // The dialog opens from Print Settins tab->Bed Shape : Set...
 
@@ -49,3 +51,6 @@ public:
 
 } // GUI
 } // Slic3r
+
+
+#endif  /* slic3r_BedShapeDialog_hpp_ */
diff --git a/xs/src/slic3r/GUI/Field.cpp b/xs/src/slic3r/GUI/Field.cpp
index ff17a2ef8..252720287 100644
--- a/xs/src/slic3r/GUI/Field.cpp
+++ b/xs/src/slic3r/GUI/Field.cpp
@@ -22,7 +22,7 @@ namespace Slic3r { namespace GUI {
 		auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
 		auto sz = 16;
 	#ifdef __WXGTK__
-		sz = 28
+		sz = 28;
 	#endif // __WXGTK__
 		m_Undo_btn			= new wxButton(m_parent, wxID_ANY, "", wxDefaultPosition, wxSize(sz,sz), wxNO_BORDER);
 		m_Undo_to_sys_btn	= new wxButton(m_parent, wxID_ANY, "", wxDefaultPosition, wxSize(sz,sz), wxNO_BORDER);
diff --git a/xs/src/slic3r/GUI/OptionsGroup.hpp b/xs/src/slic3r/GUI/OptionsGroup.hpp
index 92ebb4488..6a00cbe0d 100644
--- a/xs/src/slic3r/GUI/OptionsGroup.hpp
+++ b/xs/src/slic3r/GUI/OptionsGroup.hpp
@@ -1,3 +1,6 @@
+#ifndef slic3r_OptionsGroup_hpp_
+#define slic3r_OptionsGroup_hpp_
+
 #include <wx/wx.h>
 #include <wx/stattext.h>
 #include <wx/settings.h>
@@ -204,3 +207,5 @@ public:
 };
 
 }}
+
+#endif /* slic3r_OptionsGroup_hpp_ */
diff --git a/xs/src/slic3r/GUI/Preferences.hpp b/xs/src/slic3r/GUI/Preferences.hpp
index c30e94d22..f94a1db69 100644
--- a/xs/src/slic3r/GUI/Preferences.hpp
+++ b/xs/src/slic3r/GUI/Preferences.hpp
@@ -1,3 +1,6 @@
+#ifndef slic3r_Preferences_hpp_
+#define slic3r_Preferences_hpp_
+
 #include "GUI.hpp"
 
 #include <wx/dialog.h>
@@ -25,3 +28,5 @@ public:
 } // GUI
 } // Slic3r
 
+
+#endif /* slic3r_Preferences_hpp_ */
diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp
index 049196599..48521461c 100644
--- a/xs/src/slic3r/GUI/Tab.cpp
+++ b/xs/src/slic3r/GUI/Tab.cpp
@@ -8,6 +8,7 @@
 #include "slic3r/Utils/OctoPrint.hpp"
 #include "BonjourDialog.hpp"
 #include "WipeTowerDialog.hpp"
+#include "ButtonsDescription.hpp"
 
 #include <wx/app.h>
 #include <wx/button.h>
@@ -103,38 +104,25 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
 	m_undo_btn = new wxButton(panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER);
 	m_undo_to_sys_btn = new wxButton(panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER);
 	m_question_btn = new wxButton(panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER);
-	m_undo_btns_legent = new wxStaticText(panel, wxID_ANY, _(L("For more information about buttons hover the mouse cursor over them.")), wxDefaultPosition, wxDefaultSize);
+// 	m_undo_btns_legent = new wxStaticText(panel, wxID_ANY, _(L("For more information about buttons hover the mouse cursor over them.")), wxDefaultPosition, wxDefaultSize);
 	if (wxMSW) {
 		m_undo_btn->SetBackgroundColour(color);
 		m_undo_to_sys_btn->SetBackgroundColour(color);
 		m_question_btn->SetBackgroundColour(color);
 	}
 
-#ifdef __WXMSW__
-	m_undo_to_sys_btn->SetToolTip(_(L(	"Unlocked lock icon indicates about some value changes compared with system values "
+	m_undo_to_sys_btn->SetToolTip(_(L(	"UNLOCKED LOCK icon indicates about some value changes compared with system values "
 										"in current option group.\n"
-										"Locked lock icon indicates about same values compared with system values "
+										"LOCKED LOCK icon indicates about same values compared with system values "
 										"in current option group.\n"
-										"White bullet icon indicates about nonsystem preset.\n"
-										"Click the unlocked lock to revert all values in current option group to system values.")));
-#else
-	// ToolTips to undo buttons
-	m_undo_btn_tip = new wxRichToolTip("Information about current button",
-		_(L("Unlocked lock icon indicates about some value changes compared with system values "
-			"in current option group.\n"
-			"Locked lock icon indicates about same values compared with system values "
-			"in current option group.\n"
-			"White bullet icon indicates about nonsystem preset.\n"
-			"Click the unlocked lock to revert all values in current option group to system values.")));
-	m_undo_btn_tip->SetIcon(wxICON_INFORMATION);
-	m_undo_btn_tip->ShowFor(m_undo_btn);
-#endif //__WXMSW__
+										"WHITE BULLET icon indicates about nonsystem preset.\n\n"
+										"Click the UNLOCKED LOCK to revert all values in current option group to system values.")));
 
-	m_undo_btn->SetToolTip(_(L(	"Back arrow icon indicates about some value changes compared with last saved preset values "
+	m_undo_btn->SetToolTip(_(L(	"BACK ARROW icon indicates about some value changes compared with last saved preset values "
 								"in current option group.\n"
-								"White bullet icon indicates about same values compared with last saved preset values "
-								"in current option group.\n"
-								"Click the Back arrow to revert all values in current option group to last saved preset values.")));
+								"WHITE BULLET icon indicates about same values compared with last saved preset values "
+								"in current option group.\n\n"
+								"Click the BACK ARROW to revert all values in current option group to last saved preset values.")));
 
 	m_question_btn->SetToolTip(_(L("Hover the cursor over buttons to find more information.")));
 
@@ -147,11 +135,18 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
 	m_bmp_white_bullet	  .LoadFile(from_u8(var("bullet_white.png")), wxBITMAP_TYPE_PNG);
 	m_bmp_question        .LoadFile(from_u8(var("question_mark_01.png")), wxBITMAP_TYPE_PNG);
 
+	fill_icon_descriptions();
+
 	m_undo_btn->SetBitmap(m_bmp_white_bullet);
 	m_undo_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ on_roll_back_value(); }));
 	m_undo_to_sys_btn->SetBitmap(m_bmp_white_bullet);
 	m_undo_to_sys_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ on_roll_back_value(true); }));
 	m_question_btn->SetBitmap(m_bmp_question);
+	m_question_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent)
+	{
+		auto dlg = new ButtonsDescription(parent(), &m_icon_descriptions);
+		dlg->ShowModal();
+	}));
 
 	// Colors for ui "decoration"
 	m_sys_label_clr			= get_sys_label_clr();
@@ -170,9 +165,9 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
 	m_hsizer->AddSpacer(64);
 	m_hsizer->Add(m_undo_to_sys_btn, 0, wxALIGN_CENTER_VERTICAL);
 	m_hsizer->Add(m_undo_btn, 0, wxALIGN_CENTER_VERTICAL);
-	m_hsizer->AddSpacer(16);
+	m_hsizer->AddSpacer(32);
 	m_hsizer->Add(m_question_btn, 0, wxALIGN_CENTER_VERTICAL);
-	m_hsizer->Add(m_undo_btns_legent, 0, wxALIGN_CENTER_VERTICAL);
+// 	m_hsizer->Add(m_undo_btns_legent, 0, wxALIGN_CENTER_VERTICAL);
 // 	m_hsizer->AddSpacer(64);
 // 	m_hsizer->Add(m_cc_presets_choice, 1, wxLEFT | wxRIGHT | wxTOP | wxALIGN_CENTER_VERTICAL, 3);
 
@@ -2354,6 +2349,22 @@ void Tab::update_tab_presets(wxComboCtrl* ui, bool show_incompatible)
 	ui->Thaw();
 }
 
+void Tab::fill_icon_descriptions()
+{
+	m_icon_descriptions.push_back(t_icon_description(&m_bmp_value_lock, L("LOCKED LOCK;"
+		"indicates about same values compared with system values in current option group")));
+
+	m_icon_descriptions.push_back(t_icon_description(&m_bmp_value_unlock, L("UNLOCKED LOCK;"
+		"indicates about some value changes compared with system values in current option group")));
+
+	m_icon_descriptions.push_back(t_icon_description(&m_bmp_white_bullet, L("WHITE BULLET;"
+		"indicates about : \n - nonsystem preset (on left button)"
+		"\n - same values compared with last saved preset values in current option group(on right button)")));
+
+	m_icon_descriptions.push_back(t_icon_description(&m_bmp_value_revert, L("BACK ARROW;"
+		"indicates about some value changes compared with last saved preset values in current option group")));
+}
+
 void Page::reload_config()
 {
 	for (auto group : m_optgroups)
diff --git a/xs/src/slic3r/GUI/Tab.hpp b/xs/src/slic3r/GUI/Tab.hpp
index 364608dc1..ba449c8c7 100644
--- a/xs/src/slic3r/GUI/Tab.hpp
+++ b/xs/src/slic3r/GUI/Tab.hpp
@@ -1,3 +1,6 @@
+#ifndef slic3r_Tab_hpp_
+#define slic3r_Tab_hpp_
+
 //	 The "Expert" tab at the right of the main tabbed window.
 //	
 //	 This file implements following packages:
@@ -22,7 +25,6 @@
 #include <wx/imaglist.h>
 #include <wx/statbox.h>
 #include <wx/dataview.h>
-#include <wx/richtooltip.h>
 
 #include <map>
 #include <vector>
@@ -35,6 +37,9 @@
 namespace Slic3r {
 namespace GUI {
 
+typedef std::pair<wxBitmap*, std::string>				t_icon_description;
+typedef std::vector<std::pair<wxBitmap*, std::string>>	t_icon_descriptions;
+
 // Single Tab page containing a{ vsizer } of{ optgroups }
 // package Slic3r::GUI::Tab::Page;
 using ConfigOptionsGroupShp = std::shared_ptr<ConfigOptionsGroup>;
@@ -113,8 +118,7 @@ protected:
 	wxButton*			m_undo_btn;
 	wxButton*			m_undo_to_sys_btn;
 	wxButton*			m_question_btn;
-	wxStaticText*		m_undo_btns_legent;
-	wxRichToolTip*		m_undo_btn_tip;
+// 	wxStaticText*		m_undo_btns_legent;
 
 	wxComboCtrl*		m_cc_presets_choice;
 	wxDataViewTreeCtrl*	m_presetctrl;
@@ -152,6 +156,8 @@ protected:
 	std::map<std::string, int>	m_options_list;
 	int							m_opt_status_value;
 
+	t_icon_descriptions	m_icon_descriptions = {};
+
 	// The two following two event IDs are generated at Plater.pm by calling Wx::NewEventType.
 	wxEventType			m_event_value_change = 0;
 	wxEventType 		m_event_presets_changed = 0;
@@ -179,10 +185,6 @@ public:
 	}
 	~Tab(){
 		delete_tab_from_list(this);
-		if (m_undo_btn_tip){
-			delete m_undo_btn_tip;
-			m_undo_btn_tip = nullptr;
-		}
 	}
 
 	wxWindow*	parent() const { return m_parent; }
@@ -249,6 +251,7 @@ protected:
 	void			update_frequently_changed_parameters();
     void            update_wiping_button_visibility();
 	void			update_tab_presets(wxComboCtrl* ui, bool show_incompatible);
+	void			fill_icon_descriptions();
 };
 
 //Slic3r::GUI::Tab::Print;
@@ -327,3 +330,5 @@ public:
 
 } // GUI
 } // Slic3r
+
+#endif /* slic3r_Tab_hpp_ */
diff --git a/xs/src/slic3r/GUI/TabIface.hpp b/xs/src/slic3r/GUI/TabIface.hpp
index 0325c855c..5622634e8 100644
--- a/xs/src/slic3r/GUI/TabIface.hpp
+++ b/xs/src/slic3r/GUI/TabIface.hpp
@@ -1,3 +1,6 @@
+#ifndef slic3r_TabIface_hpp_
+#define slic3r_TabIface_hpp_
+
 #include <vector>
 #include <string>
 
@@ -30,6 +33,8 @@ public:
 
 protected:
 	GUI::Tab   *m_tab;
-};
+}; // namespace GUI
 
 }; // namespace Slic3r
+
+#endif /* slic3r_TabIface_hpp_ */

From 669b0b68ab112972d711e0b01efc9588925ece2a Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Fri, 20 Apr 2018 13:27:25 +0200
Subject: [PATCH 09/20] Added missed files to commit

---
 xs/src/slic3r/GUI/ButtonsDescription.cpp | 42 ++++++++++++++++++++++++
 xs/src/slic3r/GUI/ButtonsDescription.hpp | 27 +++++++++++++++
 2 files changed, 69 insertions(+)
 create mode 100644 xs/src/slic3r/GUI/ButtonsDescription.cpp
 create mode 100644 xs/src/slic3r/GUI/ButtonsDescription.hpp

diff --git a/xs/src/slic3r/GUI/ButtonsDescription.cpp b/xs/src/slic3r/GUI/ButtonsDescription.cpp
new file mode 100644
index 000000000..6831d0ddd
--- /dev/null
+++ b/xs/src/slic3r/GUI/ButtonsDescription.cpp
@@ -0,0 +1,42 @@
+#include "ButtonsDescription.hpp"
+#include <wx/sizer.h>
+#include <wx/stattext.h>
+#include <wx/statbmp.h>
+
+#include "GUI.hpp"
+
+namespace Slic3r {
+namespace GUI {
+
+ButtonsDescription::ButtonsDescription(wxWindow* parent, t_icon_descriptions* icon_descriptions) :
+	wxDialog(parent, wxID_ANY, "Buttons Description", wxDefaultPosition, wxDefaultSize),
+	m_icon_descriptions(icon_descriptions)
+{
+	auto grid_sizer = new wxFlexGridSizer(3, 20, 20);
+
+	auto main_sizer = new wxBoxSizer(wxVERTICAL);
+	main_sizer->Add(grid_sizer, 0, wxEXPAND | wxALL, 20);
+
+	for (auto pair : *m_icon_descriptions)
+	{
+		auto icon = new wxStaticBitmap(this, wxID_ANY, *pair.first);
+		grid_sizer->Add(icon, -1, wxALIGN_CENTRE_VERTICAL);
+
+		std::istringstream f(pair.second);
+		std::string s;
+		while (getline(f, s, ';')) {
+			auto description = new wxStaticText(this, wxID_ANY, _(s));
+			grid_sizer->Add(description, -1, wxALIGN_CENTRE_VERTICAL);
+		}
+	}
+
+	auto button = CreateStdDialogButtonSizer(wxOK);
+	main_sizer->Add(button, 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM, 10);
+
+	SetSizer(main_sizer);
+	main_sizer->SetSizeHints(this);
+}
+
+} // GUI
+} // Slic3r
+
diff --git a/xs/src/slic3r/GUI/ButtonsDescription.hpp b/xs/src/slic3r/GUI/ButtonsDescription.hpp
new file mode 100644
index 000000000..4858eaaea
--- /dev/null
+++ b/xs/src/slic3r/GUI/ButtonsDescription.hpp
@@ -0,0 +1,27 @@
+#ifndef slic3r_ButtonsDescription_hpp
+#define slic3r_ButtonsDescription_hpp
+
+#include <wx/dialog.h>
+#include <vector>
+
+namespace Slic3r {
+namespace GUI {
+
+using t_icon_descriptions = std::vector<std::pair<wxBitmap*, std::string>>;
+
+class ButtonsDescription : public wxDialog
+{
+	t_icon_descriptions* m_icon_descriptions;
+public:
+	ButtonsDescription(wxWindow* parent, t_icon_descriptions* icon_descriptions);
+	~ButtonsDescription(){}
+
+
+};
+
+} // GUI
+} // Slic3r
+
+
+#endif 
+

From 48bbd2d22adc14a2b373804129f78a5a58712dd0 Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Fri, 20 Apr 2018 15:02:54 +0200
Subject: [PATCH 10/20] Added new files to MackList

---
 xs/CMakeLists.txt         | 2 ++
 xs/src/slic3r/GUI/Tab.cpp | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/xs/CMakeLists.txt b/xs/CMakeLists.txt
index abd9c3617..c20a1102a 100644
--- a/xs/CMakeLists.txt
+++ b/xs/CMakeLists.txt
@@ -208,6 +208,8 @@ add_library(libslic3r_gui STATIC
     ${LIBDIR}/slic3r/GUI/RammingChart.hpp
     ${LIBDIR}/slic3r/GUI/BonjourDialog.cpp
     ${LIBDIR}/slic3r/GUI/BonjourDialog.hpp
+    ${LIBDIR}/slic3r/GUI/ButtonsDescription.cpp
+    ${LIBDIR}/slic3r/GUI/ButtonsDescription.hpp
     ${LIBDIR}/slic3r/Config/Snapshot.cpp
     ${LIBDIR}/slic3r/Config/Snapshot.hpp
     ${LIBDIR}/slic3r/Config/Version.cpp
diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp
index 48521461c..e2b07a556 100644
--- a/xs/src/slic3r/GUI/Tab.cpp
+++ b/xs/src/slic3r/GUI/Tab.cpp
@@ -144,7 +144,7 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
 	m_question_btn->SetBitmap(m_bmp_question);
 	m_question_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent)
 	{
-		auto dlg = new ButtonsDescription(parent(), &m_icon_descriptions);
+		auto dlg = new ButtonsDescription(this, &m_icon_descriptions);
 		dlg->ShowModal();
 	}));
 

From 27f77c7680a23e6449d47b9cdb30c5c10c2e3bc2 Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Fri, 20 Apr 2018 15:40:43 +0200
Subject: [PATCH 11/20] Added little more information to ButtonsDescription
 dialog

---
 xs/src/slic3r/GUI/Tab.cpp | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp
index e2b07a556..2b82694db 100644
--- a/xs/src/slic3r/GUI/Tab.cpp
+++ b/xs/src/slic3r/GUI/Tab.cpp
@@ -2355,14 +2355,16 @@ void Tab::fill_icon_descriptions()
 		"indicates about same values compared with system values in current option group")));
 
 	m_icon_descriptions.push_back(t_icon_description(&m_bmp_value_unlock, L("UNLOCKED LOCK;"
-		"indicates about some value changes compared with system values in current option group")));
+		"indicates about some value changes compared with system values in current option group.\n"
+		"Click the UNLOCKED LOCK to revert all values in current option group to system values.")));
 
 	m_icon_descriptions.push_back(t_icon_description(&m_bmp_white_bullet, L("WHITE BULLET;"
 		"indicates about : \n - nonsystem preset (on left button)"
 		"\n - same values compared with last saved preset values in current option group(on right button)")));
 
 	m_icon_descriptions.push_back(t_icon_description(&m_bmp_value_revert, L("BACK ARROW;"
-		"indicates about some value changes compared with last saved preset values in current option group")));
+		"indicates about some value changes compared with last saved preset values in current option group.\n"
+		"Click the BACK ARROW to revert all values in current option group to last saved preset values.")));
 }
 
 void Page::reload_config()

From b8cb9369732757f427c264181d49e50a0f943237 Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Fri, 20 Apr 2018 17:32:08 +0200
Subject: [PATCH 12/20] Added effective update of ComboBoxes on Plater

---
 lib/Slic3r/GUI/MainFrame.pm        |  1 +
 lib/Slic3r/GUI/Plater.pm           | 25 +++++++++++++++++++++++--
 xs/src/slic3r/GUI/PresetBundle.cpp |  4 ++++
 xs/src/slic3r/GUI/Tab.hpp          |  7 +++----
 xs/src/slic3r/GUI/TabIface.cpp     |  1 +
 xs/src/slic3r/GUI/TabIface.hpp     |  1 +
 xs/xsp/GUI_Tab.xsp                 |  1 +
 7 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm
index b2f51b9e1..f5d466018 100644
--- a/lib/Slic3r/GUI/MainFrame.pm
+++ b/lib/Slic3r/GUI/MainFrame.pm
@@ -149,6 +149,7 @@ sub _init_tabpanel {
             if (defined $presets){
                 my $reload_dependent_tabs = $tab->get_dependent_tabs;
                 $self->{plater}->update_presets($tab_name, $reload_dependent_tabs, $presets);
+                $self->{plater}->{"selected_item_$tab_name"} = $tab->get_selected_preset_item;
                 if ($tab_name eq 'printer') {
                     # Printer selected at the Printer tab, update "compatible" marks at the print and filament selectors.
                     for my $tab_name_other (qw(print filament)) {
diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm
index d59865491..023ec4ae5 100644
--- a/lib/Slic3r/GUI/Plater.pm
+++ b/lib/Slic3r/GUI/Plater.pm
@@ -514,6 +514,13 @@ sub new {
         $self->SetSizer($sizer);
     }
 
+    # Last correct selected item for each preset
+    {
+        $self->{selected_item_print} = 0;
+        $self->{selected_item_filament} = 0;
+        $self->{selected_item_printer} = 0;
+    }
+
     $self->update_ui_from_settings();
     
     return $self;
@@ -538,9 +545,23 @@ sub _on_select_preset {
         # Only update the platter UI for the 2nd and other filaments.
         wxTheApp->{preset_bundle}->update_platter_filament_ui($idx, $choice);
 	} else {
+        my $selected_item = $choice->GetSelection();
+        print ("selected_item = $selected_item\n");
+        print ("selected_item_$group = ". $self->{"selected_item_$group"}. "\n");
+        return if ($selected_item == $self->{"selected_item_$group"});
+
+        my $selected_string = $choice->GetString($selected_item);
+        if ($selected_string eq "------- System presets -------" ||
+            $selected_string eq "-------  User presets  -------"){
+            $choice->SetSelection($self->{"selected_item_$group"});
+            return;
+        }
+        
     	# call GetSelection() in scalar context as it's context-aware
-    	$self->{on_select_preset}->($group, $choice->GetStringSelection)
-    	    if $self->{on_select_preset};
+#    	$self->{on_select_preset}->($group, $choice->GetStringSelection)
+        $self->{on_select_preset}->($group, $selected_string)
+            if $self->{on_select_preset};
+        $self->{"selected_item_$group"} = $selected_item;
     }
     # Synchronize config.ini with the current selections.
     wxTheApp->{preset_bundle}->export_selections(wxTheApp->{app_config});
diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp
index d6cde84a8..92525fcbf 100644
--- a/xs/src/slic3r/GUI/PresetBundle.cpp
+++ b/xs/src/slic3r/GUI/PresetBundle.cpp
@@ -977,6 +977,10 @@ void PresetBundle::export_configbundle(const std::string &path) //, const Dynami
 // an optional "(modified)" suffix will be removed from the filament name.
 void PresetBundle::set_filament_preset(size_t idx, const std::string &name)
 {
+	if (name == "------- System presets -------" ||
+		name == "-------  User presets  -------")
+		return;
+
     if (idx >= filament_presets.size())
         filament_presets.resize(idx + 1, filaments.default_preset().name);
     filament_presets[idx] = Preset::remove_suffix_modified(name);
diff --git a/xs/src/slic3r/GUI/Tab.hpp b/xs/src/slic3r/GUI/Tab.hpp
index ba449c8c7..eda6727a8 100644
--- a/xs/src/slic3r/GUI/Tab.hpp
+++ b/xs/src/slic3r/GUI/Tab.hpp
@@ -237,12 +237,11 @@ public:
 	bool			set_value(const t_config_option_key& opt_key, const boost::any& value);
 	wxSizer*		description_line_widget(wxWindow* parent, ogStaticText** StaticText);
 	bool			current_preset_is_dirty();
+
 	DynamicPrintConfig*	get_config() { return m_config; }
-	PresetCollection*	get_presets()
-	{
-		return m_presets;
-	}
+	PresetCollection*	get_presets() { return m_presets; }
 	std::vector<std::string>	get_dependent_tabs() { return m_reload_dependent_tabs; }
+	size_t				get_selected_preset_item() { return m_selected_preset_item; }
 
 	void			on_value_change(const std::string& opt_key, const boost::any& value);
 
diff --git a/xs/src/slic3r/GUI/TabIface.cpp b/xs/src/slic3r/GUI/TabIface.cpp
index 4df0e72e5..29833322b 100644
--- a/xs/src/slic3r/GUI/TabIface.cpp
+++ b/xs/src/slic3r/GUI/TabIface.cpp
@@ -11,6 +11,7 @@ void	TabIface::load_config(DynamicPrintConfig* config)	{ m_tab->load_config(*con
 void	TabIface::load_key_value(char* opt_key, char* value){ m_tab->load_key_value(opt_key, static_cast<std::string>(value)); }
 bool	TabIface::current_preset_is_dirty()					{ return m_tab->current_preset_is_dirty();}
 void	TabIface::OnActivate()								{ return m_tab->OnActivate();}
+size_t	TabIface::get_selected_preset_item()				{ return m_tab->get_selected_preset_item(); }
 std::string					TabIface::title()				{ return m_tab->title().ToUTF8().data(); }
 DynamicPrintConfig*			TabIface::get_config()			{ return m_tab->get_config(); }
 PresetCollection*			TabIface::get_presets()			{ return m_tab!=nullptr ? m_tab->get_presets() : nullptr; }
diff --git a/xs/src/slic3r/GUI/TabIface.hpp b/xs/src/slic3r/GUI/TabIface.hpp
index 5622634e8..2f7f4e8e7 100644
--- a/xs/src/slic3r/GUI/TabIface.hpp
+++ b/xs/src/slic3r/GUI/TabIface.hpp
@@ -30,6 +30,7 @@ public:
 	DynamicPrintConfig*			get_config();
 	PresetCollection*			get_presets();
 	std::vector<std::string>	get_dependent_tabs();
+	size_t						get_selected_preset_item();
 
 protected:
 	GUI::Tab   *m_tab;
diff --git a/xs/xsp/GUI_Tab.xsp b/xs/xsp/GUI_Tab.xsp
index 9cacac74f..bcbdc0d9f 100644
--- a/xs/xsp/GUI_Tab.xsp
+++ b/xs/xsp/GUI_Tab.xsp
@@ -16,6 +16,7 @@
 	bool		current_preset_is_dirty();
 	void		load_key_value(char* opt_key, char* value);
 	void		OnActivate();
+	size_t		get_selected_preset_item();
 	std::string	title();
 	Ref<DynamicPrintConfig>		get_config();
 	Ref<PresetCollection>		get_presets();

From 9a1dbfa6cf4fbef9c9ad92972f23aa246c9d6701 Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Mon, 23 Apr 2018 10:27:42 +0200
Subject: [PATCH 13/20] Updated action_undo.png icon and added
 sys_unlock_grey.png & action_undo_grey.png for dark themes of OS

---
 lib/Slic3r/GUI/Plater.pm             |   2 --
 resources/icons/action_undo.png      | Bin 491 -> 510 bytes
 resources/icons/action_undo_grey.png | Bin 0 -> 480 bytes
 resources/icons/sys_unlock_grey.png  | Bin 0 -> 423 bytes
 xs/src/slic3r/GUI/Tab.cpp            |   8 +++++---
 5 files changed, 5 insertions(+), 5 deletions(-)
 create mode 100644 resources/icons/action_undo_grey.png
 create mode 100644 resources/icons/sys_unlock_grey.png

diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm
index 023ec4ae5..893cc366b 100644
--- a/lib/Slic3r/GUI/Plater.pm
+++ b/lib/Slic3r/GUI/Plater.pm
@@ -546,8 +546,6 @@ sub _on_select_preset {
         wxTheApp->{preset_bundle}->update_platter_filament_ui($idx, $choice);
 	} else {
         my $selected_item = $choice->GetSelection();
-        print ("selected_item = $selected_item\n");
-        print ("selected_item_$group = ". $self->{"selected_item_$group"}. "\n");
         return if ($selected_item == $self->{"selected_item_$group"});
 
         my $selected_string = $choice->GetString($selected_item);
diff --git a/resources/icons/action_undo.png b/resources/icons/action_undo.png
index 877f159868640a0399143631438313a31dacf1a1..06bb98b22a6d98e035059205bc4cc35f5164443f 100644
GIT binary patch
delta 434
zcmV;j0Zsnv1O5Y$R)3R8L_t(IPnDCqO9Md=#$)0mf`WyextrNXE|AhR0g-^EwdoXW
zt!!-dK(Me7dmH}=D?7Edw6IVD#zH|%p&-5zzgcr3xyvCA40}8G&2MM+<}zUzX6yBO
zF7BBW>(@xG3)E`0(YTA)klL4Z*n4qzP#jRHRK_Gp`|8ZFYJdC}kSC%U<Ed*y+-9N|
z!+cyMy)Gbu_i2*=XmUtuT2>tZI<ks$!TZ4evRp1tS!*W-0C6joO4FM7wVU{k3L0jP
z-vmg$e-|aE0wOa7?-A`Z<=K+j!2UrXhUipce*(mMVxqid-T~kX7uzZ-wb%nh6o}6u
z_zr?#R`$aT?SHg>A-t9V$Y+zjoifGbbX@YMRcbW>K%YmhN6?)*X4=<FQX%{~(0U;O
zC~CbdCqU3fzuO3nNL&oiEk*p~4j?{}*Z@E_5=7#G`*eWFNtXBuiMQQYhly{Z<OCps
zVE%WJbdLln*9{aZ!yM2BUgt1O<Ea4gYPC9PjG0F@n=2^&5bGW;ZAIWiM>*|x7LP<}
c9)@A|2OVI(RMldGuK)l507*qoM6N<$f{oS4Pyhe`

delta 415
zcmV;Q0bu_A1M35jR)2s=L_t(IPqmRtO9D|8$4AW>N5}VDvzJgotHwuA(wC7a+NVXi
zsW#HCT1k(!Eey1!jV<hBsJSu}cP@p0_g;ojMhl64a5!^@d;aIe{VPd12K94xHrCc@
z^6Ua1t(M}n+AtpoBH;EScY3D0R4NL99JS$a$V`1c&ReaPB7Y9ckp)B-mzeonZrIEg
zgnWLq+ifN^Re+K`%A^Ft980D`3!yL^l9hQQr$?{XW1XnaC-Yn?rHnc~cw#hutyW<*
ziEOOIrcCmG5umi1P5S72iFbtpybdR5cb}b(Rv;ORLo$hq8Zx@w?pQ1dBItrE<+AoV
zTk!<EP8asl>3^}LQ6#~{1jtpi0*Ctt@Vh;5+Z_{ce|vqy3h+7u`u)Ckgl3}w1DTmE
zN|wh&o{B|SNcFHkfZgq#i3J$PnGDRlfJiXJ{OU>+9<n%>&CdRbMjnH~V7dV1DxW9!
z*0E9O)@j>xb}B|%|2cV-$NLB6B%4((&o7ksdVT6*{}>3zeF4rRxG}NPf+PR{002ov
JPDHLkV1jTT#y<c6

diff --git a/resources/icons/action_undo_grey.png b/resources/icons/action_undo_grey.png
new file mode 100644
index 0000000000000000000000000000000000000000..eaa1593e349246886e990731ae331d224f909308
GIT binary patch
literal 480
zcmV<60U!Q}P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00001b5ch_0Itp)
z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0d+}4K~y+TwNgDx
z!%!5BScQVKo0EgiIye@=(M2(vu37s71Ura>Lvi;vI6664)NYm1Av9?|nl@i3hz<%;
zZ5z)C7c32>3VPrY?z`und)|Ff{teY?b-C4Qol5#UG#ZVKPN#Dd1c4_<KS#6K-060^
zrtkYh#H(%FOH!JSdcD5od0r65aWWcF6n#MKUf1;np-zVDx@U0kmNrLmkJo^}J9Avi
zuT&~Ip-zTlSw&2IL}S3*G|g2AJx~M=uTs)D9LHH~x7#a{au>U!WYmu!+7H9<g?XV+
z$f>G2n-&QaZxM%Bnp!HA<~2>5lTu3Nm(93dADn}X0H2K(LAWTF%Xtz;gB%KA$fspl
z`xyb)J*NPdR;$(4#+xzq7~%tnJTuP-KshfHh9F)iNiriP-hUkqpEv+}x|HKA@Pymg
ze2*fW1UEXqF3-fBBh<-&)lD>o5E-zE!T$hPyo0N6%hP~G75P)a@`+&>dvg5OP?RtC
WJ3qPv{k%&60000<MNUMnLSTXf=EW)i

literal 0
HcmV?d00001

diff --git a/resources/icons/sys_unlock_grey.png b/resources/icons/sys_unlock_grey.png
new file mode 100644
index 0000000000000000000000000000000000000000..0dedf4deef59977f56e22231d0add7af4ad266f9
GIT binary patch
literal 423
zcmV;Y0a*TtP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00001b5ch_0Itp)
z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0X#`WK~y+TwNpJy
z!%!5B;2?-Nb$0Rx2(FU9;nb-`aC8x;ppMxb#8q^V3>`DN1>BlIV!mU(J1H$X6l&CS
z;T5C48iIJ>@E-4;d+yD>MEDmtj<cVp=`hQ(NuK8~IO8A)&NNNiV3Nh~JnxW_z~>}M
z?!a3ZjEbU|`M!V6WPIqlzJ<ye#E+(F?y0KUQ50p}FpM1}pW|F(Qa-44RIZ{Zx{_si
zRTRbLIVDM2p_57ZK$X+7EZ=b+)syRFQa-{kJVyId7##4DiA=f}Fj->PcEGf|sQv_w
zn+WaCZD3V>1S^`soV0(4hZyW@{T*)umiCD_j=vZnX=dB@CdIJY%hm?Czqzh^LNS<)
z8x2sU_pO7<vaD^2;Ztr}8&C&$dw}>J_i3X6ewJMXB9I36E3xVemiAW&!Uy&+mn{OD
R)@T3#002ovPDHLkV1i$rw$T6p

literal 0
HcmV?d00001

diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp
index 2b82694db..e15767329 100644
--- a/xs/src/slic3r/GUI/Tab.cpp
+++ b/xs/src/slic3r/GUI/Tab.cpp
@@ -126,13 +126,15 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
 
 	m_question_btn->SetToolTip(_(L("Hover the cursor over buttons to find more information.")));
 
+	// Determine the theme color of OS (dark or light)
+	auto luma = get_colour_approx_luma(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
 	// Bitmaps to be shown on the "Revert to system" aka "Lock to system" button next to each input field.
 	m_bmp_value_lock  	  .LoadFile(from_u8(var("sys_lock.png")),     wxBITMAP_TYPE_PNG);
-	m_bmp_value_unlock	  .LoadFile(from_u8(var("sys_unlock.png")),   wxBITMAP_TYPE_PNG);
+	m_bmp_value_unlock    .LoadFile(from_u8(var(luma >= 128 ? "sys_unlock.png" : "sys_unlock_grey.png")), wxBITMAP_TYPE_PNG);
 	m_bmp_non_system = &m_bmp_white_bullet;
 	// Bitmaps to be shown on the "Undo user changes" button next to each input field.
-	m_bmp_value_revert	  .LoadFile(from_u8(var("action_undo.png")),  wxBITMAP_TYPE_PNG);
-	m_bmp_white_bullet	  .LoadFile(from_u8(var("bullet_white.png")), wxBITMAP_TYPE_PNG);
+	m_bmp_value_revert    .LoadFile(from_u8(var(luma >= 128 ? "action_undo.png" : "action_undo_grey.png")), wxBITMAP_TYPE_PNG);
+	m_bmp_white_bullet    .LoadFile(from_u8(var("bullet_white.png")), wxBITMAP_TYPE_PNG);
 	m_bmp_question        .LoadFile(from_u8(var("question_mark_01.png")), wxBITMAP_TYPE_PNG);
 
 	fill_icon_descriptions();

From ec7e10e068f1b8d587ede2028aa43abd13869593 Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Mon, 23 Apr 2018 11:52:03 +0200
Subject: [PATCH 14/20] Fixed wrong behavior of options group Tree after
 extruders count change

---
 xs/src/slic3r/GUI/Tab.cpp | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp
index e15767329..3ad40d9f7 100644
--- a/xs/src/slic3r/GUI/Tab.cpp
+++ b/xs/src/slic3r/GUI/Tab.cpp
@@ -1348,6 +1348,9 @@ void TabPrinter::build()
 	m_presets = &m_preset_bundle->printers;
 	load_initial_data();
 
+	// to avoid redundant memory allocation / deallocation during extruders count changing
+	m_pages.reserve(30); 
+
 	auto   *nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(m_config->option("nozzle_diameter"));
 	m_initial_extruders_count = m_extruders_count = nozzle_diameter->values.size();
 	const Preset* parent_preset = m_presets->get_selected_preset_parent();
@@ -1625,7 +1628,7 @@ void TabPrinter::extruders_count_changed(size_t extruders_count){
 }
 
 void TabPrinter::build_extruder_pages(){
-	if (m_extruders_count_old == m_extruders_count)
+	if (m_extruders_count_old == m_extruders_count || m_extruders_count <= 2)
 	{
 		// if we have a single extruder MM setup, add a page with configuration options:
 		for (int i = 0; i < m_pages.size(); ++i) // first make sure it's not there already
@@ -1642,8 +1645,6 @@ void TabPrinter::build_extruder_pages(){
 			optgroup->append_single_option_line("parking_pos_retraction");
 			m_pages.insert(m_pages.end()-2, page);
 		}
-		rebuild_page_tree();
-		return;
 	}
 		
 	for (auto extruder_idx = m_extruders_count_old; extruder_idx < m_extruders_count; ++extruder_idx){

From 6432ec8a9b91939b3e433e9a44c1f437a4b35b82 Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Mon, 23 Apr 2018 15:09:01 +0200
Subject: [PATCH 15/20] Experiment with extruders count change

---
 xs/src/slic3r/GUI/Tab.cpp | 86 ++++++++++++++++++++++++++++++++++-----
 xs/src/slic3r/GUI/Tab.hpp |  5 +++
 2 files changed, 81 insertions(+), 10 deletions(-)

diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp
index 3ad40d9f7..f0471cea0 100644
--- a/xs/src/slic3r/GUI/Tab.cpp
+++ b/xs/src/slic3r/GUI/Tab.cpp
@@ -1306,6 +1306,7 @@ void TabFilament::reload_config(){
 
 void TabFilament::update()
 {
+	Freeze();
 	wxString text = from_u8(PresetHints::cooling_description(m_presets->get_edited_preset()));
 	m_cooling_description_line->SetText(text);
 	text = from_u8(PresetHints::maximum_volumetric_flow_description(*m_preset_bundle));
@@ -1319,6 +1320,7 @@ void TabFilament::update()
 
 	for (auto el : { "min_fan_speed", "disable_fan_first_layers" })
 		get_field(el)->toggle(fan_always_on);
+	Thaw();
 }
 
 void TabFilament::OnActivate()
@@ -1349,7 +1351,8 @@ void TabPrinter::build()
 	load_initial_data();
 
 	// to avoid redundant memory allocation / deallocation during extruders count changing
-	m_pages.reserve(30); 
+	m_pages.reserve(30);
+	m_extruders_tree_items.reserve(30);
 
 	auto   *nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(m_config->option("nozzle_diameter"));
 	m_initial_extruders_count = m_extruders_count = nozzle_diameter->values.size();
@@ -1400,8 +1403,10 @@ void TabPrinter::build()
 			size_t extruders_count = boost::any_cast<int>(optgroup->get_value("extruders_count"));
 			wxTheApp->CallAfter([this, opt_key, value, extruders_count](){
 				if (opt_key.compare("extruders_count")==0 || opt_key.compare("single_extruder_multi_material")==0) {
+					m_correct_treectrl = true;
 					extruders_count_changed(extruders_count);
 					update_dirty();
+					m_correct_treectrl = false;
                     if (opt_key.compare("single_extruder_multi_material")==0) // the single_extruder_multimaterial was added to force pages
                         on_value_change(opt_key, value);                      // rebuild - let's make sure the on_value_change is not skipped
 				}
@@ -1835,19 +1840,80 @@ void Tab::rebuild_page_tree()
 	// get label of the currently selected item
 	auto selected = m_treectrl->GetItemText(m_treectrl->GetSelection());
 	auto rootItem = m_treectrl->GetRootItem();
-	m_treectrl->DeleteChildren(rootItem);
+
 	auto have_selection = 0;
-	for (auto p : m_pages)
+	if (name() == "printer")
 	{
-		auto itemId = m_treectrl->AppendItem(rootItem, p->title(), p->iconID());
-		m_treectrl->SetItemTextColour(itemId, p->get_item_colour());
-		if (p->title() == selected) {
-			m_disable_tree_sel_changed_event = 1;
-			m_treectrl->SelectItem(itemId);
-			m_disable_tree_sel_changed_event = 0;
-			have_selection = 1;
+		TabPrinter* tab = dynamic_cast<TabPrinter*>(this);
+		if (!tab->m_correct_treectrl){
+			m_treectrl->DeleteChildren(rootItem);
+			tab->m_extruders_tree_items.resize(0);
+			tab->m_single_extruder_MM_item = nullptr;
+			for (auto p : m_pages)
+			{
+				auto itemId = m_treectrl->AppendItem(rootItem, p->title(), p->iconID());
+				m_treectrl->SetItemTextColour(itemId, p->get_item_colour());
+
+				if (p->title().Contains(_("Extruder")))
+					tab->m_extruders_tree_items.push_back(itemId);
+
+				if (p->title() == _("Single extruder MM setup"))
+					tab->m_single_extruder_MM_item = itemId;
+
+				if (p->title() == selected) {
+					m_disable_tree_sel_changed_event = 1;
+					m_treectrl->SelectItem(itemId);
+					m_disable_tree_sel_changed_event = 0;
+					have_selection = 1;
+				}
+			}
+		}
+		else
+		{
+			while (tab->m_extruders_tree_items.size() > tab->m_extruders_count){
+				m_treectrl->Delete(tab->m_extruders_tree_items.back());
+				tab->m_extruders_tree_items.pop_back();
+			}
+
+			size_t i = 2 + tab->m_extruders_tree_items.size();
+			for (; i < 2 + tab->m_extruders_count; ++i)
+			{
+				auto p = m_pages[i];
+				auto itemId = m_treectrl->InsertItem(rootItem, tab->m_extruders_tree_items.back(), p->title(), p->iconID());
+				m_treectrl->SetItemTextColour(itemId, p->get_item_colour());
+				tab->m_extruders_tree_items.push_back(itemId);
+			}
+
+			if (tab->m_extruders_count == 1 || !m_config->opt_bool("single_extruder_multi_material") 
+				&& tab->m_single_extruder_MM_item)
+			{
+				m_treectrl->Delete(tab->m_single_extruder_MM_item);
+				tab->m_single_extruder_MM_item = nullptr;
+			}
+			else if (tab->m_single_extruder_MM_item == nullptr)
+			{
+				auto p = m_pages[i];
+				auto itemId = tab->m_single_extruder_MM_item =
+					m_treectrl->InsertItem(rootItem, tab->m_extruders_tree_items.back(), p->title(), p->iconID());
+				m_treectrl->SetItemTextColour(itemId, p->get_item_colour());
+			}
 		}
 	}
+	else 
+	{
+		m_treectrl->DeleteChildren(rootItem);
+		for (auto p : m_pages)
+		{
+			auto itemId = m_treectrl->AppendItem(rootItem, p->title(), p->iconID());
+			m_treectrl->SetItemTextColour(itemId, p->get_item_colour());
+			if (p->title() == selected) {
+				m_disable_tree_sel_changed_event = 1;
+				m_treectrl->SelectItem(itemId);
+				m_disable_tree_sel_changed_event = 0;
+				have_selection = 1;
+			}
+		}
+ 	}
 	
 	if (!have_selection) {
 		// this is triggered on first load, so we don't disable the sel change event
diff --git a/xs/src/slic3r/GUI/Tab.hpp b/xs/src/slic3r/GUI/Tab.hpp
index eda6727a8..0961c71fb 100644
--- a/xs/src/slic3r/GUI/Tab.hpp
+++ b/xs/src/slic3r/GUI/Tab.hpp
@@ -300,6 +300,11 @@ public:
 	size_t		m_initial_extruders_count;
 	size_t		m_sys_extruders_count;
 
+	std::vector<wxTreeItemId> m_extruders_tree_items;
+	wxTreeItemId	m_single_extruder_MM_item = nullptr;
+	bool			m_correct_treectrl = false;	// m_correct_tree = false -> delete/create m_treectrl
+												// m_correct_tree = true  -> just correct m_treectrl
+
 	TabPrinter() {}
 	TabPrinter(wxNotebook* parent, bool no_controller) : Tab(parent, _(L("Printer Settings")), "printer", no_controller) {}
 	~TabPrinter(){}

From b0841f78f4f602858bdaf23c2d9b41fb3b4f1958 Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Mon, 23 Apr 2018 15:39:55 +0200
Subject: [PATCH 16/20] Experiment failed

---
 xs/src/slic3r/GUI/Tab.cpp | 95 ++++++++-------------------------------
 xs/src/slic3r/GUI/Tab.hpp |  5 ---
 2 files changed, 18 insertions(+), 82 deletions(-)

diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp
index f0471cea0..fa6ed7ca6 100644
--- a/xs/src/slic3r/GUI/Tab.cpp
+++ b/xs/src/slic3r/GUI/Tab.cpp
@@ -1352,7 +1352,6 @@ void TabPrinter::build()
 
 	// to avoid redundant memory allocation / deallocation during extruders count changing
 	m_pages.reserve(30);
-	m_extruders_tree_items.reserve(30);
 
 	auto   *nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(m_config->option("nozzle_diameter"));
 	m_initial_extruders_count = m_extruders_count = nozzle_diameter->values.size();
@@ -1403,10 +1402,8 @@ void TabPrinter::build()
 			size_t extruders_count = boost::any_cast<int>(optgroup->get_value("extruders_count"));
 			wxTheApp->CallAfter([this, opt_key, value, extruders_count](){
 				if (opt_key.compare("extruders_count")==0 || opt_key.compare("single_extruder_multi_material")==0) {
-					m_correct_treectrl = true;
 					extruders_count_changed(extruders_count);
 					update_dirty();
-					m_correct_treectrl = false;
                     if (opt_key.compare("single_extruder_multi_material")==0) // the single_extruder_multimaterial was added to force pages
                         on_value_change(opt_key, value);                      // rebuild - let's make sure the on_value_change is not skipped
 				}
@@ -1633,6 +1630,9 @@ void TabPrinter::extruders_count_changed(size_t extruders_count){
 }
 
 void TabPrinter::build_extruder_pages(){
+	size_t		n_before_extruders = 2;			//	Count of pages before Extruder pages
+	size_t		n_after_single_extruder_MM = 2; //	Count of pages after single_extruder_multi_material page
+
 	if (m_extruders_count_old == m_extruders_count || m_extruders_count <= 2)
 	{
 		// if we have a single extruder MM setup, add a page with configuration options:
@@ -1648,16 +1648,16 @@ void TabPrinter::build_extruder_pages(){
 			optgroup->append_single_option_line("cooling_tube_retraction");
 			optgroup->append_single_option_line("cooling_tube_length");
 			optgroup->append_single_option_line("parking_pos_retraction");
-			m_pages.insert(m_pages.end()-2, page);
+			m_pages.insert(m_pages.end() - n_after_single_extruder_MM, page);
 		}
 	}
-		
+
 	for (auto extruder_idx = m_extruders_count_old; extruder_idx < m_extruders_count; ++extruder_idx){
 		//# build page
 		char buf[MIN_BUF_LENGTH_FOR_L];
 		sprintf(buf, _CHB(L("Extruder %d")), extruder_idx + 1);
 		auto page = add_options_page(from_u8(buf), "funnel.png", true);
-		m_pages.insert(m_pages.begin() + 2+extruder_idx, page);
+		m_pages.insert(m_pages.begin() + n_before_extruders + extruder_idx, page);
 			
 			auto optgroup = page->new_optgroup(_(L("Size")));
 			optgroup->append_single_option_line("nozzle_diameter", extruder_idx);
@@ -1696,7 +1696,8 @@ void TabPrinter::build_extruder_pages(){
  
 	// # remove extra pages
 	if (m_extruders_count < m_extruders_count_old)
-		m_pages.erase(m_pages.begin() + 2 + m_extruders_count, m_pages.begin() + 2 + m_extruders_count_old);
+		m_pages.erase(	m_pages.begin() + n_before_extruders + m_extruders_count, 
+						m_pages.begin() + n_before_extruders + m_extruders_count_old);
 
 	m_extruders_count_old = m_extruders_count;
 
@@ -1842,79 +1843,19 @@ void Tab::rebuild_page_tree()
 	auto rootItem = m_treectrl->GetRootItem();
 
 	auto have_selection = 0;
-	if (name() == "printer")
+	m_treectrl->DeleteChildren(rootItem);
+	for (auto p : m_pages)
 	{
-		TabPrinter* tab = dynamic_cast<TabPrinter*>(this);
-		if (!tab->m_correct_treectrl){
-			m_treectrl->DeleteChildren(rootItem);
-			tab->m_extruders_tree_items.resize(0);
-			tab->m_single_extruder_MM_item = nullptr;
-			for (auto p : m_pages)
-			{
-				auto itemId = m_treectrl->AppendItem(rootItem, p->title(), p->iconID());
-				m_treectrl->SetItemTextColour(itemId, p->get_item_colour());
-
-				if (p->title().Contains(_("Extruder")))
-					tab->m_extruders_tree_items.push_back(itemId);
-
-				if (p->title() == _("Single extruder MM setup"))
-					tab->m_single_extruder_MM_item = itemId;
-
-				if (p->title() == selected) {
-					m_disable_tree_sel_changed_event = 1;
-					m_treectrl->SelectItem(itemId);
-					m_disable_tree_sel_changed_event = 0;
-					have_selection = 1;
-				}
-			}
-		}
-		else
-		{
-			while (tab->m_extruders_tree_items.size() > tab->m_extruders_count){
-				m_treectrl->Delete(tab->m_extruders_tree_items.back());
-				tab->m_extruders_tree_items.pop_back();
-			}
-
-			size_t i = 2 + tab->m_extruders_tree_items.size();
-			for (; i < 2 + tab->m_extruders_count; ++i)
-			{
-				auto p = m_pages[i];
-				auto itemId = m_treectrl->InsertItem(rootItem, tab->m_extruders_tree_items.back(), p->title(), p->iconID());
-				m_treectrl->SetItemTextColour(itemId, p->get_item_colour());
-				tab->m_extruders_tree_items.push_back(itemId);
-			}
-
-			if (tab->m_extruders_count == 1 || !m_config->opt_bool("single_extruder_multi_material") 
-				&& tab->m_single_extruder_MM_item)
-			{
-				m_treectrl->Delete(tab->m_single_extruder_MM_item);
-				tab->m_single_extruder_MM_item = nullptr;
-			}
-			else if (tab->m_single_extruder_MM_item == nullptr)
-			{
-				auto p = m_pages[i];
-				auto itemId = tab->m_single_extruder_MM_item =
-					m_treectrl->InsertItem(rootItem, tab->m_extruders_tree_items.back(), p->title(), p->iconID());
-				m_treectrl->SetItemTextColour(itemId, p->get_item_colour());
-			}
+		auto itemId = m_treectrl->AppendItem(rootItem, p->title(), p->iconID());
+		m_treectrl->SetItemTextColour(itemId, p->get_item_colour());
+		if (p->title() == selected) {
+			m_disable_tree_sel_changed_event = 1;
+			m_treectrl->SelectItem(itemId);
+			m_disable_tree_sel_changed_event = 0;
+			have_selection = 1;
 		}
 	}
-	else 
-	{
-		m_treectrl->DeleteChildren(rootItem);
-		for (auto p : m_pages)
-		{
-			auto itemId = m_treectrl->AppendItem(rootItem, p->title(), p->iconID());
-			m_treectrl->SetItemTextColour(itemId, p->get_item_colour());
-			if (p->title() == selected) {
-				m_disable_tree_sel_changed_event = 1;
-				m_treectrl->SelectItem(itemId);
-				m_disable_tree_sel_changed_event = 0;
-				have_selection = 1;
-			}
-		}
- 	}
-	
+
 	if (!have_selection) {
 		// this is triggered on first load, so we don't disable the sel change event
 		m_treectrl->SelectItem(m_treectrl->GetFirstVisibleItem());//! (treectrl->GetFirstChild(rootItem));
diff --git a/xs/src/slic3r/GUI/Tab.hpp b/xs/src/slic3r/GUI/Tab.hpp
index 0961c71fb..eda6727a8 100644
--- a/xs/src/slic3r/GUI/Tab.hpp
+++ b/xs/src/slic3r/GUI/Tab.hpp
@@ -300,11 +300,6 @@ public:
 	size_t		m_initial_extruders_count;
 	size_t		m_sys_extruders_count;
 
-	std::vector<wxTreeItemId> m_extruders_tree_items;
-	wxTreeItemId	m_single_extruder_MM_item = nullptr;
-	bool			m_correct_treectrl = false;	// m_correct_tree = false -> delete/create m_treectrl
-												// m_correct_tree = true  -> just correct m_treectrl
-
 	TabPrinter() {}
 	TabPrinter(wxNotebook* parent, bool no_controller) : Tab(parent, _(L("Printer Settings")), "printer", no_controller) {}
 	~TabPrinter(){}

From e31f5fc4b6d69a67f755cd8570d469b50237a6bb Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Tue, 24 Apr 2018 08:49:37 +0200
Subject: [PATCH 17/20] Modified text for tooltips and ButtonsDescription

---
 xs/src/slic3r/GUI/ButtonsDescription.cpp | 10 +++---
 xs/src/slic3r/GUI/Tab.cpp                | 44 +++++++++++++-----------
 2 files changed, 30 insertions(+), 24 deletions(-)

diff --git a/xs/src/slic3r/GUI/ButtonsDescription.cpp b/xs/src/slic3r/GUI/ButtonsDescription.cpp
index 6831d0ddd..b932985bf 100644
--- a/xs/src/slic3r/GUI/ButtonsDescription.cpp
+++ b/xs/src/slic3r/GUI/ButtonsDescription.cpp
@@ -24,10 +24,12 @@ ButtonsDescription::ButtonsDescription(wxWindow* parent, t_icon_descriptions* ic
 
 		std::istringstream f(pair.second);
 		std::string s;
-		while (getline(f, s, ';')) {
-			auto description = new wxStaticText(this, wxID_ANY, _(s));
-			grid_sizer->Add(description, -1, wxALIGN_CENTRE_VERTICAL);
-		}
+		getline(f, s, ';');
+		auto description = new wxStaticText(this, wxID_ANY, _(s));
+		grid_sizer->Add(description, -1, wxALIGN_CENTRE_VERTICAL);
+		getline(f, s, ';');
+		description = new wxStaticText(this, wxID_ANY, _(s));
+		grid_sizer->Add(description, -1, wxALIGN_CENTRE_VERTICAL | wxEXPAND);
 	}
 
 	auto button = CreateStdDialogButtonSizer(wxOK);
diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp
index fa6ed7ca6..c9c7ad632 100644
--- a/xs/src/slic3r/GUI/Tab.cpp
+++ b/xs/src/slic3r/GUI/Tab.cpp
@@ -111,18 +111,20 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
 		m_question_btn->SetBackgroundColour(color);
 	}
 
-	m_undo_to_sys_btn->SetToolTip(_(L(	"UNLOCKED LOCK icon indicates about some value changes compared with system values "
-										"in current option group.\n"
-										"LOCKED LOCK icon indicates about same values compared with system values "
-										"in current option group.\n"
-										"WHITE BULLET icon indicates about nonsystem preset.\n\n"
-										"Click the UNLOCKED LOCK to revert all values in current option group to system values.")));
+	m_undo_to_sys_btn->SetToolTip(_(L(	"LOCKED LOCK icon indicates that the settings are the same as the system values "
+										"for the current option group.\n"
+										"UNLOCKED LOCK icon indicates that some settings were changed and are not equal "
+										"to the system values for the current option group.\n"
+										"WHITE BULLET icon indicates a nonsystem preset.\n\n"
+										"Click the UNLOCKED LOCK icon to reset all settings for current option group to "
+										"the system values.")));
 
-	m_undo_btn->SetToolTip(_(L(	"BACK ARROW icon indicates about some value changes compared with last saved preset values "
-								"in current option group.\n"
-								"WHITE BULLET icon indicates about same values compared with last saved preset values "
-								"in current option group.\n\n"
-								"Click the BACK ARROW to revert all values in current option group to last saved preset values.")));
+	m_undo_btn->SetToolTip(_(L(	"WHITE BULLET icon indicates that the settings are the same as in the last saved"
+								"preset  for the current option group.\n"
+								"BACK ARROW icon indicates that the settings were changed and are not equal to "
+								"the last saved preset for the current option group.\n\n"
+								"Click the BACK ARROW icon to reset all settings for the current option group to "
+								"the last saved preset.")));
 
 	m_question_btn->SetToolTip(_(L("Hover the cursor over buttons to find more information.")));
 
@@ -2362,19 +2364,23 @@ void Tab::update_tab_presets(wxComboCtrl* ui, bool show_incompatible)
 void Tab::fill_icon_descriptions()
 {
 	m_icon_descriptions.push_back(t_icon_description(&m_bmp_value_lock, L("LOCKED LOCK;"
-		"indicates about same values compared with system values in current option group")));
+		"indicates that the settings are the same as the system values for the current option group")));
 
 	m_icon_descriptions.push_back(t_icon_description(&m_bmp_value_unlock, L("UNLOCKED LOCK;"
-		"indicates about some value changes compared with system values in current option group.\n"
-		"Click the UNLOCKED LOCK to revert all values in current option group to system values.")));
+		"indicates that some settings were changed and are not equal to the system values for "
+		"the current option group.\n"
+		"Click the UNLOCKED LOCK icon to reset all settings for current option group to "
+		"the system values.")));
 
 	m_icon_descriptions.push_back(t_icon_description(&m_bmp_white_bullet, L("WHITE BULLET;"
-		"indicates about : \n - nonsystem preset (on left button)"
-		"\n - same values compared with last saved preset values in current option group(on right button)")));
+		"for the left button: \tindicates a non-system preset,\n"
+		"for the right button: \tindicates that the settings hasn't been modified.")));
 
 	m_icon_descriptions.push_back(t_icon_description(&m_bmp_value_revert, L("BACK ARROW;"
-		"indicates about some value changes compared with last saved preset values in current option group.\n"
-		"Click the BACK ARROW to revert all values in current option group to last saved preset values.")));
+		"indicates that the settings were changed and are not equal to the last saved preset for "
+		"the current option group.\n"
+		"Click the BACK ARROW icon to reset all settings for the current option group to "
+		"the last saved preset.")));
 }
 
 void Page::reload_config()
@@ -2435,8 +2441,6 @@ ConfigOptionsGroupShp Page::new_optgroup(const wxString& title, int noncommon_la
 		return static_cast<Tab*>(GetParent())->m_presets->get_selected_preset_parent() != nullptr;
 	};
 
-//	optgroup->nonsys_btn_icon = m_bmp_non_system;
-
 	vsizer()->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 10);
 	m_optgroups.push_back(optgroup);
 

From 1e8d302fd4e4028faa17deecf32bb811dd913bb1 Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Tue, 24 Apr 2018 10:33:11 +0200
Subject: [PATCH 18/20] Fixed wrong updating of "Top/Bottom fill pattern"

---
 xs/src/slic3r/GUI/Field.cpp | 91 ++++++++++++++++++++++++-------------
 xs/src/slic3r/GUI/Field.hpp | 23 ++++++----
 2 files changed, 73 insertions(+), 41 deletions(-)

diff --git a/xs/src/slic3r/GUI/Field.cpp b/xs/src/slic3r/GUI/Field.cpp
index 252720287..d0a2ccec2 100644
--- a/xs/src/slic3r/GUI/Field.cpp
+++ b/xs/src/slic3r/GUI/Field.cpp
@@ -80,12 +80,13 @@ namespace Slic3r { namespace GUI {
 		return std::regex_match(string, regex_pattern);
 	}
 
-	boost::any Field::get_value_by_opt_type(wxString& str)
+// 	boost::any Field::get_value_by_opt_type(wxString& str)
+	void Field::get_value_by_opt_type(wxString& str)
 	{
-		boost::any ret_val;
+// 		boost::any m_value;
 		switch (m_opt.type){
 		case coInt:
-			ret_val = wxAtoi(str);
+			m_value = wxAtoi(str);
 			break;
 		case coPercent:
 		case coPercents:
@@ -95,18 +96,18 @@ namespace Slic3r { namespace GUI {
 				str.RemoveLast();
 			double val;
 			str.ToCDouble(&val);
-			ret_val = val;
+			m_value = val;
 			break; }
 		case coString:
 		case coStrings:
 		case coFloatOrPercent:
-			ret_val = str.ToStdString();
+			m_value = str.ToStdString();
 			break;
 		default:
 			break;
 		}
 
-		return ret_val;
+// 		return m_value;
 	}
 
 	void TextCtrl::BUILD() {
@@ -182,12 +183,12 @@ namespace Slic3r { namespace GUI {
         window = dynamic_cast<wxWindow*>(temp);
     }	
 
-	boost::any TextCtrl::get_value()
+	boost::any& TextCtrl::get_value()
 	{
 		wxString ret_str = static_cast<wxTextCtrl*>(window)->GetValue();
-		boost::any ret_val = get_value_by_opt_type(ret_str);
+		/*boost::any ret_val*/get_value_by_opt_type(ret_str);
 
-		return ret_val;
+		return m_value;//ret_val;
 	}
 
 	void TextCtrl::enable() { dynamic_cast<wxTextCtrl*>(window)->Enable(); dynamic_cast<wxTextCtrl*>(window)->SetEditable(true); }
@@ -215,15 +216,15 @@ void CheckBox::BUILD() {
 	window = dynamic_cast<wxWindow*>(temp);
 }
 
-boost::any CheckBox::get_value()
+boost::any& CheckBox::get_value()
 {
-	boost::any ret_val;
+// 	boost::any m_value;
 	bool value = dynamic_cast<wxCheckBox*>(window)->GetValue();
 	if (m_opt.type == coBool)
-		ret_val = static_cast<bool>(value);
+		m_value = static_cast<bool>(value);
 	else
-		ret_val = static_cast<unsigned char>(value);
- 	return ret_val;
+		m_value = static_cast<unsigned char>(value);
+ 	return m_value;
 }
 
 int undef_spin_val = -9999;		//! Probably, It's not necessary
@@ -423,7 +424,33 @@ void Choice::set_value(const boost::any& value, bool change_event)
 		break;
 	}
 	case coEnum:{
-		dynamic_cast<wxComboBox*>(window)->SetSelection(boost::any_cast<int>(value));
+		int val = boost::any_cast<int>(value);
+		if (m_opt_id.compare("external_fill_pattern") == 0)
+		{
+			if (!m_opt.enum_values.empty()){
+				std::string key;
+				t_config_enum_values map_names = ConfigOptionEnum<InfillPattern>::get_enum_values();				
+				for (auto it : map_names) {
+					if (val == it.second) {
+						key = it.first;
+						break;
+					}
+				}
+
+				size_t idx = 0;
+				for (auto el : m_opt.enum_values)
+				{
+					if (el.compare(key) == 0)
+						break;
+					++idx;
+				}
+
+				val = idx == m_opt.enum_values.size() ? 0 : idx;
+			}
+			else
+				val = 0;
+		}
+		dynamic_cast<wxComboBox*>(window)->SetSelection(val);
 		break;
 	}
 	default:
@@ -453,16 +480,16 @@ void Choice::set_values(const std::vector<std::string>& values)
 	m_disable_change_event = false;
 }
 
-boost::any Choice::get_value()
+boost::any& Choice::get_value()
 {
-	boost::any ret_val;
+// 	boost::any m_value;
 	wxString ret_str = static_cast<wxComboBox*>(window)->GetValue();	
 
 	if (m_opt_id == "support")
-		return ret_str;
+		return m_value = boost::any(ret_str);//ret_str;
 
 	if (m_opt.type != coEnum)
-		ret_val = get_value_by_opt_type(ret_str);
+		/*m_value = */get_value_by_opt_type(ret_str);
 	else
 	{
 		int ret_enum = static_cast<wxComboBox*>(window)->GetSelection(); 
@@ -473,22 +500,22 @@ boost::any Choice::get_value()
 				t_config_enum_values map_names = ConfigOptionEnum<InfillPattern>::get_enum_values();
 				int value = map_names.at(key);
 
-				ret_val = static_cast<InfillPattern>(value);
+				m_value = static_cast<InfillPattern>(value);
 			}
 			else
-				ret_val = static_cast<InfillPattern>(0);
+				m_value = static_cast<InfillPattern>(0);
 		}
 		if (m_opt_id.compare("fill_pattern") == 0)
-			ret_val = static_cast<InfillPattern>(ret_enum);
+			m_value = static_cast<InfillPattern>(ret_enum);
 		else if (m_opt_id.compare("gcode_flavor") == 0)
-			ret_val = static_cast<GCodeFlavor>(ret_enum);
+			m_value = static_cast<GCodeFlavor>(ret_enum);
 		else if (m_opt_id.compare("support_material_pattern") == 0)
-			ret_val = static_cast<SupportMaterialPattern>(ret_enum);
+			m_value = static_cast<SupportMaterialPattern>(ret_enum);
 		else if (m_opt_id.compare("seam_position") == 0)
-			ret_val = static_cast<SeamPosition>(ret_enum);
+			m_value = static_cast<SeamPosition>(ret_enum);
 	}	
 
-	return ret_val;
+	return m_value;
 }
 
 void ColourPicker::BUILD()
@@ -508,14 +535,14 @@ void ColourPicker::BUILD()
 	temp->SetToolTip(get_tooltip_text(clr));
 }
 
-boost::any ColourPicker::get_value(){
-	boost::any ret_val;
+boost::any& ColourPicker::get_value(){
+// 	boost::any m_value;
 
 	auto colour = static_cast<wxColourPickerCtrl*>(window)->GetColour();
 	auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), colour.Red(), colour.Green(), colour.Blue());
-	ret_val = clr_str.ToStdString();
+	m_value = clr_str.ToStdString();
 
-	return ret_val;
+	return m_value;
 }
 
 void PointCtrl::BUILD()
@@ -579,7 +606,7 @@ void PointCtrl::set_value(const boost::any& value, bool change_event)
 	set_value(pt, change_event);
 }
 
-boost::any PointCtrl::get_value()
+boost::any& PointCtrl::get_value()
 {
 	Pointf ret_point;
 	double val;
@@ -587,7 +614,7 @@ boost::any PointCtrl::get_value()
 	ret_point.x = val;
 	y_textctrl->GetValue().ToDouble(&val);
 	ret_point.y = val;
-	return ret_point;
+	return m_value = ret_point;
 }
 
 } // GUI
diff --git a/xs/src/slic3r/GUI/Field.hpp b/xs/src/slic3r/GUI/Field.hpp
index 292bfd81f..9e5730cf6 100644
--- a/xs/src/slic3r/GUI/Field.hpp
+++ b/xs/src/slic3r/GUI/Field.hpp
@@ -85,7 +85,7 @@ public:
     
     /// 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;
@@ -106,7 +106,8 @@ public:
     virtual wxWindow*	getWindow() { return nullptr; }
 
 	bool				is_matched(const std::string& string, const std::string& pattern);
-	boost::any			get_value_by_opt_type(wxString& str);
+// 	boost::any			get_value_by_opt_type(wxString& str);
+	void				get_value_by_opt_type(wxString& str);
 
     /// Factory method for generating new derived classes.
     template<class T>
@@ -157,6 +158,9 @@ protected:
 	// Color for Label. The wxColour will be updated only if the new wxColour pointer differs from the currently rendered one.
 	const wxColour*		m_label_color;
 
+	// current value
+	boost::any			m_value;
+
 	friend class OptionsGroup;
 };
 
@@ -191,7 +195,7 @@ public:
 		m_disable_change_event = false;
     }
 
-	boost::any		get_value() override;
+	boost::any&		get_value() override;
 
     virtual void	enable();
     virtual void	disable();
@@ -218,7 +222,7 @@ public:
 		dynamic_cast<wxCheckBox*>(window)->SetValue(boost::any_cast<bool>(value));
 		m_disable_change_event = false;
 	}
-	boost::any		get_value() override;
+	boost::any&		get_value() override;
 
 	void			enable() override { dynamic_cast<wxCheckBox*>(window)->Enable(); }
 	void			disable() override { dynamic_cast<wxCheckBox*>(window)->Disable(); }
@@ -248,8 +252,9 @@ public:
 		dynamic_cast<wxSpinCtrl*>(window)->SetValue(tmp_value);
 		m_disable_change_event = false;
 	}
-	boost::any		get_value() override {
-		return boost::any(tmp_value);
+	boost::any&		get_value() override {
+// 		return boost::any(tmp_value);
+		return m_value = tmp_value;
 	}
 
 	void			enable() override { dynamic_cast<wxSpinCtrl*>(window)->Enable(); }
@@ -271,7 +276,7 @@ public:
 	void			set_value(const std::string& value, bool change_event = false);
 	void			set_value(const boost::any& value, bool change_event = false);
 	void			set_values(const std::vector<std::string> &values);
-	boost::any		get_value() override;
+	boost::any&		get_value() override;
 
 	void			enable() override { dynamic_cast<wxComboBox*>(window)->Enable(); };
 	void			disable() override{ dynamic_cast<wxComboBox*>(window)->Disable(); };
@@ -299,7 +304,7 @@ public:
 		m_disable_change_event = false;
 	}
 
-	boost::any		get_value() override;
+	boost::any&		get_value() override;
 
 	void			enable() override { dynamic_cast<wxColourPickerCtrl*>(window)->Enable(); };
 	void			disable() override{ dynamic_cast<wxColourPickerCtrl*>(window)->Disable(); };
@@ -321,7 +326,7 @@ public:
 
 	void			set_value(const Pointf& value, bool change_event = false);
 	void			set_value(const boost::any& value, bool change_event = false);
-	boost::any		get_value() override;
+	boost::any&		get_value() override;
 
 	void			enable() override {
 		x_textctrl->Enable();

From 92b67fb62ea0b0c3019c8ae601ae19970718ddc9 Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Tue, 24 Apr 2018 12:12:15 +0200
Subject: [PATCH 19/20] Change reset buttons tooltips according to its state

---
 xs/src/slic3r/GUI/OptionsGroup.cpp |  3 +-
 xs/src/slic3r/GUI/Tab.cpp          | 49 ++++++++++++++++++++----------
 xs/src/slic3r/GUI/Tab.hpp          | 13 ++++++--
 3 files changed, 46 insertions(+), 19 deletions(-)

diff --git a/xs/src/slic3r/GUI/OptionsGroup.cpp b/xs/src/slic3r/GUI/OptionsGroup.cpp
index c71dd5ba6..265497e9c 100644
--- a/xs/src/slic3r/GUI/OptionsGroup.cpp
+++ b/xs/src/slic3r/GUI/OptionsGroup.cpp
@@ -149,7 +149,8 @@ void OptionsGroup::append_line(const Line& line, wxStaticText**	colored_Label/*
     // If there's a widget, build it and add the result to the sizer.
 	if (line.widget != nullptr) {
 		auto wgt = line.widget(parent());
-		grid_sizer->Add(wgt, 0, wxEXPAND | wxBOTTOM | wxTOP, wxOSX ? 0 : 5);
+		// If widget doesn't have label, don't use border
+		grid_sizer->Add(wgt, 0, wxEXPAND | wxBOTTOM | wxTOP, (wxOSX || line.label.IsEmpty()) ? 0 : 5);
 		if (colored_Label != nullptr) *colored_Label = label;
 		return;
 	}
diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp
index c9c7ad632..8200ec4b2 100644
--- a/xs/src/slic3r/GUI/Tab.cpp
+++ b/xs/src/slic3r/GUI/Tab.cpp
@@ -104,27 +104,41 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
 	m_undo_btn = new wxButton(panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER);
 	m_undo_to_sys_btn = new wxButton(panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER);
 	m_question_btn = new wxButton(panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER);
-// 	m_undo_btns_legent = new wxStaticText(panel, wxID_ANY, _(L("For more information about buttons hover the mouse cursor over them.")), wxDefaultPosition, wxDefaultSize);
 	if (wxMSW) {
 		m_undo_btn->SetBackgroundColour(color);
 		m_undo_to_sys_btn->SetBackgroundColour(color);
 		m_question_btn->SetBackgroundColour(color);
 	}
 
-	m_undo_to_sys_btn->SetToolTip(_(L(	"LOCKED LOCK icon indicates that the settings are the same as the system values "
-										"for the current option group.\n"
-										"UNLOCKED LOCK icon indicates that some settings were changed and are not equal "
-										"to the system values for the current option group.\n"
-										"WHITE BULLET icon indicates a nonsystem preset.\n\n"
-										"Click the UNLOCKED LOCK icon to reset all settings for current option group to "
-										"the system values.")));
+// 	m_undo_to_sys_btn->SetToolTip(_(L(	"LOCKED LOCK icon indicates that the settings are the same as the system values "
+// 										"for the current option group.\n"
+// 										"UNLOCKED LOCK icon indicates that some settings were changed and are not equal "
+// 										"to the system values for the current option group.\n"
+// 										"WHITE BULLET icon indicates a non system preset.\n\n"
+// 										"Click the UNLOCKED LOCK icon to reset all settings for current option group to "
+// 										"the system values.")));
+// 
+// 	m_undo_btn->SetToolTip(_(L(	"WHITE BULLET icon indicates that the settings are the same as in the last saved"
+// 								"preset  for the current option group.\n"
+// 								"BACK ARROW icon indicates that the settings were changed and are not equal to "
+// 								"the last saved preset for the current option group.\n\n"
+// 								"Click the BACK ARROW icon to reset all settings for the current option group to "
+// 								"the last saved preset.")));
 
-	m_undo_btn->SetToolTip(_(L(	"WHITE BULLET icon indicates that the settings are the same as in the last saved"
-								"preset  for the current option group.\n"
-								"BACK ARROW icon indicates that the settings were changed and are not equal to "
-								"the last saved preset for the current option group.\n\n"
-								"Click the BACK ARROW icon to reset all settings for the current option group to "
-								"the last saved preset.")));
+	// Text to be shown on the "Revert to system" aka "Lock to system" button next to each input field.
+	m_tt_value_lock =		_(L("LOCKED LOCK icon indicates that the settings are the same as the system values "
+								"for the current option group"));
+	m_tt_value_unlock =		_(L("UNLOCKED LOCK icon indicates that some settings were changed and are not equal "
+								"to the system values for the current option group.\n"
+								"Click it to reset all settings for current option group to the system values."));
+	m_tt_white_bullet_ns=	_(L("WHITE BULLET icon indicates a non system preset."));
+	m_tt_non_system = &m_tt_white_bullet_ns;
+	// Bitmaps to be shown on the "Undo user changes" button next to each input field.
+	m_tt_white_bullet =		_(L("WHITE BULLET icon indicates that the settings are the same as in the last saved "
+								"preset for the current option group."));
+	m_tt_value_revert =		_(L("BACK ARROW icon indicates that the settings were changed and are not equal to "
+								"the last saved preset for the current option group.\n"
+								"Click it to reset all settings for the current option group to the last saved preset."));
 
 	m_question_btn->SetToolTip(_(L("Hover the cursor over buttons to find more information.")));
 
@@ -171,8 +185,6 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
 	m_hsizer->Add(m_undo_btn, 0, wxALIGN_CENTER_VERTICAL);
 	m_hsizer->AddSpacer(32);
 	m_hsizer->Add(m_question_btn, 0, wxALIGN_CENTER_VERTICAL);
-// 	m_hsizer->Add(m_undo_btns_legent, 0, wxALIGN_CENTER_VERTICAL);
-// 	m_hsizer->AddSpacer(64);
 // 	m_hsizer->Add(m_cc_presets_choice, 1, wxLEFT | wxRIGHT | wxTOP | wxALIGN_CENTER_VERTICAL, 3);
 
 	//Horizontal sizer to hold the tree and the selected page.
@@ -265,6 +277,7 @@ void Tab::load_initial_data()
 {
 	m_config = &m_presets->get_edited_preset().config;
 	m_bmp_non_system = m_presets->get_selected_preset_parent() ? &m_bmp_value_unlock : &m_bmp_white_bullet;
+	m_tt_non_system = m_presets->get_selected_preset_parent() ? &m_tt_value_unlock : &m_tt_white_bullet_ns;
 }
 
 PageShp Tab::add_options_page(const wxString& title, const std::string& icon, bool is_extruder_pages/* = false*/)
@@ -468,6 +481,9 @@ void Tab::update_undo_buttons()
 {
 	m_undo_btn->SetBitmap(m_is_modified_values ? m_bmp_value_revert : m_bmp_white_bullet);
 	m_undo_to_sys_btn->SetBitmap(m_is_nonsys_values ? *m_bmp_non_system : m_bmp_value_lock);
+
+	m_undo_btn->SetToolTip(m_is_modified_values ? m_tt_value_revert : m_tt_white_bullet);
+	m_undo_to_sys_btn->SetToolTip(m_is_nonsys_values ? *m_tt_non_system : m_tt_value_lock);
 }
 
 void Tab::on_roll_back_value(const bool to_sys /*= true*/)
@@ -1810,6 +1826,7 @@ void Tab::load_current_preset()
 	// Reload preset pages with the new configuration values.
 	reload_config();
 	m_bmp_non_system = m_presets->get_selected_preset_parent() ? &m_bmp_value_unlock : &m_bmp_white_bullet;
+	m_tt_non_system = m_presets->get_selected_preset_parent() ? &m_tt_value_unlock : &m_tt_white_bullet_ns;
 
 	// 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 
diff --git a/xs/src/slic3r/GUI/Tab.hpp b/xs/src/slic3r/GUI/Tab.hpp
index eda6727a8..8c6e7f329 100644
--- a/xs/src/slic3r/GUI/Tab.hpp
+++ b/xs/src/slic3r/GUI/Tab.hpp
@@ -118,7 +118,6 @@ protected:
 	wxButton*			m_undo_btn;
 	wxButton*			m_undo_to_sys_btn;
 	wxButton*			m_question_btn;
-// 	wxStaticText*		m_undo_btns_legent;
 
 	wxComboCtrl*		m_cc_presets_choice;
 	wxDataViewTreeCtrl*	m_presetctrl;
@@ -136,7 +135,7 @@ protected:
 	wxBitmap 		   *m_bmp_non_system;
 	// Bitmaps to be shown on the "Undo user changes" button next to each input field.
 	wxBitmap 			m_bmp_value_revert;
-	wxBitmap 			m_bmp_value_unmodified;
+// 	wxBitmap 			m_bmp_value_unmodified;
 	wxBitmap			m_bmp_question;
 
 	// Colors for ui "decoration"
@@ -144,6 +143,16 @@ protected:
 	wxColour			m_modified_label_clr;
 	wxColour			m_default_text_clr;
 
+	// Text for reset buttons tooltips
+	wxString			m_tt_value_lock;
+	wxString			m_tt_value_unlock;
+	wxString			m_tt_white_bullet_ns;
+	// The following text points to either m_bmp_value_unlock or m_bmp_white_bullet, depending on whether the current preset has a parent preset.
+	wxString			*m_tt_non_system;
+	// Bitmaps to be shown on the "Undo user changes" button next to each input field.
+	wxString			m_tt_white_bullet;
+	wxString			m_tt_value_revert;
+
 	int					m_icon_count;
 	std::map<std::string, size_t>	m_icon_index;		// Map from an icon file name to its index
 	std::vector<PageShp>			m_pages;

From 7c7c37a4f4b8c4f14fc5ece0cee84e2742e3e64d Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Tue, 24 Apr 2018 14:11:23 +0200
Subject: [PATCH 20/20] Added tooltips for reset buttons near each option

---
 xs/src/slic3r/GUI/Field.hpp |  24 ++++++++-
 xs/src/slic3r/GUI/Tab.cpp   | 105 +++++++++++++++++++++++-------------
 xs/src/slic3r/GUI/Tab.hpp   |  18 +++++--
 3 files changed, 104 insertions(+), 43 deletions(-)

diff --git a/xs/src/slic3r/GUI/Field.hpp b/xs/src/slic3r/GUI/Field.hpp
index 9e5730cf6..c7eb25c75 100644
--- a/xs/src/slic3r/GUI/Field.hpp
+++ b/xs/src/slic3r/GUI/Field.hpp
@@ -146,13 +146,33 @@ public:
 		return false;
 	}
 
+	bool 	set_undo_tooltip(const wxString *tip) {
+		if (m_undo_tooltip != tip) {
+			m_undo_tooltip = tip;
+			m_Undo_btn->SetToolTip(*tip);
+			return true;
+		}
+		return false;
+	}
+
+	bool 	set_undo_to_sys_tooltip(const wxString *tip) {
+		if (m_undo_to_sys_tooltip != tip) {
+			m_undo_to_sys_tooltip = tip;
+			m_Undo_to_sys_btn->SetToolTip(*tip);
+			return true;
+		}
+		return false;
+	}
+
 protected:
 	wxButton*			m_Undo_btn = nullptr;
-	// Bitmap for m_Undo_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one.
+	// Bitmap and Tooltip text for m_Undo_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one.
 	const wxBitmap*		m_undo_bitmap = nullptr;
+	const wxString*		m_undo_tooltip = nullptr;
 	wxButton*			m_Undo_to_sys_btn = nullptr;
-	// Bitmap for m_Undo_to_sys_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one.
+	// Bitmap and Tooltip text for m_Undo_to_sys_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one.
 	const wxBitmap*		m_undo_to_sys_bitmap = nullptr;
+	const wxString*		m_undo_to_sys_tooltip = nullptr;
 
 	wxStaticText*		m_Label = nullptr;
 	// Color for Label. The wxColour will be updated only if the new wxColour pointer differs from the currently rendered one.
diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp
index 8200ec4b2..5fbd9c96d 100644
--- a/xs/src/slic3r/GUI/Tab.cpp
+++ b/xs/src/slic3r/GUI/Tab.cpp
@@ -110,36 +110,6 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
 		m_question_btn->SetBackgroundColour(color);
 	}
 
-// 	m_undo_to_sys_btn->SetToolTip(_(L(	"LOCKED LOCK icon indicates that the settings are the same as the system values "
-// 										"for the current option group.\n"
-// 										"UNLOCKED LOCK icon indicates that some settings were changed and are not equal "
-// 										"to the system values for the current option group.\n"
-// 										"WHITE BULLET icon indicates a non system preset.\n\n"
-// 										"Click the UNLOCKED LOCK icon to reset all settings for current option group to "
-// 										"the system values.")));
-// 
-// 	m_undo_btn->SetToolTip(_(L(	"WHITE BULLET icon indicates that the settings are the same as in the last saved"
-// 								"preset  for the current option group.\n"
-// 								"BACK ARROW icon indicates that the settings were changed and are not equal to "
-// 								"the last saved preset for the current option group.\n\n"
-// 								"Click the BACK ARROW icon to reset all settings for the current option group to "
-// 								"the last saved preset.")));
-
-	// Text to be shown on the "Revert to system" aka "Lock to system" button next to each input field.
-	m_tt_value_lock =		_(L("LOCKED LOCK icon indicates that the settings are the same as the system values "
-								"for the current option group"));
-	m_tt_value_unlock =		_(L("UNLOCKED LOCK icon indicates that some settings were changed and are not equal "
-								"to the system values for the current option group.\n"
-								"Click it to reset all settings for current option group to the system values."));
-	m_tt_white_bullet_ns=	_(L("WHITE BULLET icon indicates a non system preset."));
-	m_tt_non_system = &m_tt_white_bullet_ns;
-	// Bitmaps to be shown on the "Undo user changes" button next to each input field.
-	m_tt_white_bullet =		_(L("WHITE BULLET icon indicates that the settings are the same as in the last saved "
-								"preset for the current option group."));
-	m_tt_value_revert =		_(L("BACK ARROW icon indicates that the settings were changed and are not equal to "
-								"the last saved preset for the current option group.\n"
-								"Click it to reset all settings for the current option group to the last saved preset."));
-
 	m_question_btn->SetToolTip(_(L("Hover the cursor over buttons to find more information.")));
 
 	// Determine the theme color of OS (dark or light)
@@ -154,6 +124,7 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
 	m_bmp_question        .LoadFile(from_u8(var("question_mark_01.png")), wxBITMAP_TYPE_PNG);
 
 	fill_icon_descriptions();
+	set_tooltips_text();
 
 	m_undo_btn->SetBitmap(m_bmp_white_bullet);
 	m_undo_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent){ on_roll_back_value(); }));
@@ -277,7 +248,8 @@ void Tab::load_initial_data()
 {
 	m_config = &m_presets->get_edited_preset().config;
 	m_bmp_non_system = m_presets->get_selected_preset_parent() ? &m_bmp_value_unlock : &m_bmp_white_bullet;
-	m_tt_non_system = m_presets->get_selected_preset_parent() ? &m_tt_value_unlock : &m_tt_white_bullet_ns;
+	m_ttg_non_system = m_presets->get_selected_preset_parent() ? &m_ttg_value_unlock : &m_ttg_white_bullet_ns;
+	m_tt_non_system = m_presets->get_selected_preset_parent() ? &m_tt_value_unlock : &m_ttg_white_bullet_ns;
 }
 
 PageShp Tab::add_options_page(const wxString& title, const std::string& icon, bool is_extruder_pages/* = false*/)
@@ -335,15 +307,23 @@ void Tab::update_changed_ui()
 	{
 		bool is_nonsys_value = false;
 		bool is_modified_value = true;
-		const wxBitmap *sys_icon = &m_bmp_value_lock;
-		const wxBitmap *icon = &m_bmp_value_revert;
-		const wxColour *color = &m_sys_label_clr;
+		const wxBitmap *sys_icon =	&m_bmp_value_lock;
+		const wxBitmap *icon =		&m_bmp_value_revert;
 
+		const wxColour *color =		&m_sys_label_clr;
+
+		const wxString *sys_tt =	&m_tt_value_lock;
+		const wxString *tt =		&m_tt_value_revert;
+
+		// value isn't equal to system value
 		if ((opt.second & osSystemValue) == 0){
 			is_nonsys_value = true;
 			sys_icon = m_bmp_non_system;
+			sys_tt = m_tt_non_system;
+			// value is equal to last saved
 			if ((opt.second & osInitValue) != 0)
 				color = &m_default_text_clr;
+			// value is modified
 			else
 				color = &m_modified_label_clr;
 		}
@@ -351,6 +331,7 @@ void Tab::update_changed_ui()
 		{
 			is_modified_value = false;
 			icon = &m_bmp_white_bullet;
+			tt = &m_tt_white_bullet;
 		}
 		if (opt.first == "bed_shape" || opt.first == "compatible_printers") {
 			if (m_colored_Label != nullptr)	{
@@ -366,6 +347,8 @@ void Tab::update_changed_ui()
 		field->m_is_modified_value = is_modified_value;
 		field->set_undo_bitmap(icon);
 		field->set_undo_to_sys_bitmap(sys_icon);
+		field->set_undo_tooltip(tt);
+		field->set_undo_to_sys_tooltip(sys_tt);
 		field->set_label_colour(color);
 	}
 	Thaw();
@@ -482,8 +465,8 @@ void Tab::update_undo_buttons()
 	m_undo_btn->SetBitmap(m_is_modified_values ? m_bmp_value_revert : m_bmp_white_bullet);
 	m_undo_to_sys_btn->SetBitmap(m_is_nonsys_values ? *m_bmp_non_system : m_bmp_value_lock);
 
-	m_undo_btn->SetToolTip(m_is_modified_values ? m_tt_value_revert : m_tt_white_bullet);
-	m_undo_to_sys_btn->SetToolTip(m_is_nonsys_values ? *m_tt_non_system : m_tt_value_lock);
+	m_undo_btn->SetToolTip(m_is_modified_values ? m_ttg_value_revert : m_ttg_white_bullet);
+	m_undo_to_sys_btn->SetToolTip(m_is_nonsys_values ? *m_ttg_non_system : m_ttg_value_lock);
 }
 
 void Tab::on_roll_back_value(const bool to_sys /*= true*/)
@@ -1826,7 +1809,8 @@ void Tab::load_current_preset()
 	// Reload preset pages with the new configuration values.
 	reload_config();
 	m_bmp_non_system = m_presets->get_selected_preset_parent() ? &m_bmp_value_unlock : &m_bmp_white_bullet;
-	m_tt_non_system = m_presets->get_selected_preset_parent() ? &m_tt_value_unlock : &m_tt_white_bullet_ns;
+	m_ttg_non_system = m_presets->get_selected_preset_parent() ? &m_ttg_value_unlock : &m_ttg_white_bullet_ns;
+	m_tt_non_system = m_presets->get_selected_preset_parent() ? &m_tt_value_unlock : &m_ttg_white_bullet_ns;
 
 	// 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 
@@ -2400,6 +2384,53 @@ void Tab::fill_icon_descriptions()
 		"the last saved preset.")));
 }
 
+void Tab::set_tooltips_text()
+{
+// 	m_undo_to_sys_btn->SetToolTip(_(L(	"LOCKED LOCK icon indicates that the settings are the same as the system values "
+// 										"for the current option group.\n"
+// 										"UNLOCKED LOCK icon indicates that some settings were changed and are not equal "
+// 										"to the system values for the current option group.\n"
+// 										"WHITE BULLET icon indicates a non system preset.\n\n"
+// 										"Click the UNLOCKED LOCK icon to reset all settings for current option group to "
+// 										"the system values.")));
+// 
+// 	m_undo_btn->SetToolTip(_(L(	"WHITE BULLET icon indicates that the settings are the same as in the last saved"
+// 								"preset  for the current option group.\n"
+// 								"BACK ARROW icon indicates that the settings were changed and are not equal to "
+// 								"the last saved preset for the current option group.\n\n"
+// 								"Click the BACK ARROW icon to reset all settings for the current option group to "
+// 								"the last saved preset.")));
+
+	// --- Tooltip text for reset buttons (for whole options group)
+	// Text to be shown on the "Revert to system" aka "Lock to system" button next to each input field.
+	m_ttg_value_lock =		_(L("LOCKED LOCK icon indicates that the settings are the same as the system values "
+								"for the current option group"));
+	m_ttg_value_unlock =	_(L("UNLOCKED LOCK icon indicates that some settings were changed and are not equal "
+								"to the system values for the current option group.\n"
+								"Click to reset all settings for current option group to the system values."));
+	m_ttg_white_bullet_ns =	_(L("WHITE BULLET icon indicates a non system preset."));
+	m_ttg_non_system =		&m_ttg_white_bullet_ns;
+	// Text to be shown on the "Undo user changes" button next to each input field.
+	m_ttg_white_bullet =	_(L("WHITE BULLET icon indicates that the settings are the same as in the last saved "
+								"preset for the current option group."));
+	m_ttg_value_revert =	_(L("BACK ARROW icon indicates that the settings were changed and are not equal to "
+								"the last saved preset for the current option group.\n"
+								"Click to reset all settings for the current option group to the last saved preset."));
+
+	// --- Tooltip text for reset buttons (for each option in group)
+	// Text to be shown on the "Revert to system" aka "Lock to system" button next to each input field.
+	m_tt_value_lock =		_(L("LOCKED LOCK icon indicates that the value is the same as the system value."));
+	m_tt_value_unlock =		_(L("UNLOCKED LOCK icon indicates that the value was changed and is not equal "
+								"to the system value.\n"
+								"Click to reset current value to the system value."));
+	// 	m_tt_white_bullet_ns=	_(L("WHITE BULLET icon indicates a non system preset."));
+	m_tt_non_system =		&m_ttg_white_bullet_ns;
+	// Text to be shown on the "Undo user changes" button next to each input field.
+	m_tt_white_bullet =		_(L("WHITE BULLET icon indicates that the value is the same as in the last saved preset."));
+	m_tt_value_revert =		_(L("BACK ARROW icon indicates that the value was changed and is not equal to the last saved preset.\n"
+								"Click to reset current value to the last saved preset."));
+}
+
 void Page::reload_config()
 {
 	for (auto group : m_optgroups)
diff --git a/xs/src/slic3r/GUI/Tab.hpp b/xs/src/slic3r/GUI/Tab.hpp
index 8c6e7f329..de04fc4cd 100644
--- a/xs/src/slic3r/GUI/Tab.hpp
+++ b/xs/src/slic3r/GUI/Tab.hpp
@@ -143,13 +143,22 @@ protected:
 	wxColour			m_modified_label_clr;
 	wxColour			m_default_text_clr;
 
-	// Text for reset buttons tooltips
+	// Tooltip text for reset buttons (for whole options group)
+	wxString			m_ttg_value_lock;
+	wxString			m_ttg_value_unlock;
+	wxString			m_ttg_white_bullet_ns;
+	// The following text points to either m_ttg_value_unlock or m_ttg_white_bullet_ns, depending on whether the current preset has a parent preset.
+	wxString			*m_ttg_non_system;
+	// Tooltip text to be shown on the "Undo user changes" button next to each input field.
+	wxString			m_ttg_white_bullet;
+	wxString			m_ttg_value_revert;
+
+	// Tooltip text for reset buttons (for each option in group)
 	wxString			m_tt_value_lock;
 	wxString			m_tt_value_unlock;
-	wxString			m_tt_white_bullet_ns;
-	// The following text points to either m_bmp_value_unlock or m_bmp_white_bullet, depending on whether the current preset has a parent preset.
+	// The following text points to either m_tt_value_unlock or m_ttg_white_bullet_ns, depending on whether the current preset has a parent preset.
 	wxString			*m_tt_non_system;
-	// Bitmaps to be shown on the "Undo user changes" button next to each input field.
+	// Tooltip text to be shown on the "Undo user changes" button next to each input field.
 	wxString			m_tt_white_bullet;
 	wxString			m_tt_value_revert;
 
@@ -260,6 +269,7 @@ protected:
     void            update_wiping_button_visibility();
 	void			update_tab_presets(wxComboCtrl* ui, bool show_incompatible);
 	void			fill_icon_descriptions();
+	void			set_tooltips_text();
 };
 
 //Slic3r::GUI::Tab::Print;