From 27b6c061d81122729e38446c961066316b23760b Mon Sep 17 00:00:00 2001
From: Vojtech Kral <vojtech@kral.hk>
Date: Fri, 22 Jun 2018 15:01:33 +0200
Subject: [PATCH 01/15] ConfigWizard: Fix default printer selection

---
 xs/src/slic3r/GUI/ConfigWizard.cpp         | 14 +++++++++-----
 xs/src/slic3r/GUI/ConfigWizard_private.hpp |  1 +
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/xs/src/slic3r/GUI/ConfigWizard.cpp b/xs/src/slic3r/GUI/ConfigWizard.cpp
index ce06da853..f723e7f4b 100644
--- a/xs/src/slic3r/GUI/ConfigWizard.cpp
+++ b/xs/src/slic3r/GUI/ConfigWizard.cpp
@@ -113,11 +113,6 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, cons
 	sizer->Add(all_none_sizer, 0, wxEXPAND);
 
 	SetSizer(sizer);
-
-	if (cboxes.size() > 0) {
-		cboxes[0]->SetValue(true);
-		on_checkbox(cboxes[0], true);
-	}
 }
 
 void PrinterPicker::select_all(bool select)
@@ -130,6 +125,14 @@ void PrinterPicker::select_all(bool select)
 	}
 }
 
+void PrinterPicker::select_one(size_t i, bool select)
+{
+	if (i < cboxes.size() && cboxes[i]->GetValue() != select) {
+		cboxes[i]->SetValue(select);
+		on_checkbox(cboxes[i], select);
+	}
+}
+
 void PrinterPicker::on_checkbox(const Checkbox *cbox, bool checked)
 {
 	variants_checked += checked ? 1 : -1;
@@ -232,6 +235,7 @@ PageWelcome::PageWelcome(ConfigWizard *parent) :
 		AppConfig &appconfig_vendors = this->wizard_p()->appconfig_vendors;
 
 		printer_picker = new PrinterPicker(this, vendor_prusa->second, appconfig_vendors);
+		printer_picker->select_one(0, true);    // Select the default (first) model/variant on the Prusa vendor
 		printer_picker->Bind(EVT_PRINTER_PICK, [this, &appconfig_vendors](const PrinterPickerEvent &evt) {
 			appconfig_vendors.set_variant(evt.vendor_id, evt.model_id, evt.variant_name, evt.enable);
 			this->on_variant_checked();
diff --git a/xs/src/slic3r/GUI/ConfigWizard_private.hpp b/xs/src/slic3r/GUI/ConfigWizard_private.hpp
index 72cb88655..04319a1b4 100644
--- a/xs/src/slic3r/GUI/ConfigWizard_private.hpp
+++ b/xs/src/slic3r/GUI/ConfigWizard_private.hpp
@@ -56,6 +56,7 @@ struct PrinterPicker: wxPanel
 	PrinterPicker(wxWindow *parent, const VendorProfile &vendor, const AppConfig &appconfig_vendors);
 
 	void select_all(bool select);
+	void select_one(size_t i, bool select);
 	void on_checkbox(const Checkbox *cbox, bool checked);
 };
 

From ac829ea0637e2108f4d4d90b5ad2dc650761f1dd Mon Sep 17 00:00:00 2001
From: Vojtech Kral <vojtech@kral.hk>
Date: Fri, 22 Jun 2018 15:27:04 +0200
Subject: [PATCH 02/15] PresetUpdater: Fix double update detection
 (had_config_update)

---
 xs/src/slic3r/Utils/PresetUpdater.cpp | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/xs/src/slic3r/Utils/PresetUpdater.cpp b/xs/src/slic3r/Utils/PresetUpdater.cpp
index 8159a75e2..1ce814b89 100644
--- a/xs/src/slic3r/Utils/PresetUpdater.cpp
+++ b/xs/src/slic3r/Utils/PresetUpdater.cpp
@@ -537,15 +537,15 @@ bool PresetUpdater::config_update() const
 			incompats_map.emplace(std::make_pair(std::move(vendor), std::move(restrictions)));
 		}
 
+		p->had_config_update = true;   // This needs to be done before a dialog is shown because of OnIdle() + CallAfter() in Perl
+
 		GUI::MsgDataIncompatible dlg(std::move(incompats_map));
 		const auto res = dlg.ShowModal();
 		if (res == wxID_REPLACE) {
 			BOOST_LOG_TRIVIAL(info) << "User wants to re-configure...";
 			p->perform_updates(std::move(updates));
 			GUI::ConfigWizard wizard(nullptr, GUI::ConfigWizard::RR_DATA_INCOMPAT);
-			if (wizard.run(GUI::get_preset_bundle(), this)) {
-				p->had_config_update = true;
-			} else {
+			if (! wizard.run(GUI::get_preset_bundle(), this)) {	
 				return false;
 			}
 		} else {
@@ -566,6 +566,8 @@ bool PresetUpdater::config_update() const
 			updates_map.emplace(std::make_pair(std::move(vendor), std::move(ver_str)));
 		}
 
+		p->had_config_update = true;   // Ditto, see above
+
 		GUI::MsgUpdateConfig dlg(std::move(updates_map));
 
 		const auto res = dlg.ShowModal();
@@ -581,8 +583,6 @@ bool PresetUpdater::config_update() const
 		} else {
 			BOOST_LOG_TRIVIAL(info) << "User refused the update";
 		}
-
-		p->had_config_update = true;
 	} else {
 		BOOST_LOG_TRIVIAL(info) << "No configuration updates available.";
 	}

From 5c89a80ef4b1efb493af1e5ace21360fbfd193d4 Mon Sep 17 00:00:00 2001
From: Vojtech Kral <vojtech@kral.hk>
Date: Mon, 25 Jun 2018 13:29:54 +0200
Subject: [PATCH 03/15] ConfigWizard: Mark the first variant of each printer as
 default in the GUI

---
 xs/src/slic3r/GUI/ConfigWizard.cpp | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/xs/src/slic3r/GUI/ConfigWizard.cpp b/xs/src/slic3r/GUI/ConfigWizard.cpp
index f723e7f4b..642c6dce7 100644
--- a/xs/src/slic3r/GUI/ConfigWizard.cpp
+++ b/xs/src/slic3r/GUI/ConfigWizard.cpp
@@ -83,8 +83,11 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, cons
 
 		const auto model_id = model.id;
 
+		bool default_variant = true;   // Mark the first variant as default in the GUI
 		for (const auto &variant : model.variants) {
-			const auto label = wxString::Format("%s %s %s", variant.name, _(L("mm")), _(L("nozzle")));
+			const auto label = wxString::Format("%s %s %s %s", variant.name, _(L("mm")), _(L("nozzle")),
+				(default_variant ? _(L("(default)")) : wxString()));
+			default_variant = false;
 			auto *cbox = new Checkbox(panel, label, model_id, variant.name);
 			const size_t idx = cboxes.size();
 			cboxes.push_back(cbox);

From 2a23a9c5bc6d5ee335c5ec55b52c215c07024f96 Mon Sep 17 00:00:00 2001
From: Vojtech Kral <vojtech@kral.hk>
Date: Wed, 27 Jun 2018 10:34:21 +0200
Subject: [PATCH 04/15] Fix: Http: Body size limit not properly initialized

---
 xs/src/slic3r/Utils/Http.cpp | 1 +
 xs/src/slic3r/Utils/Http.hpp | 3 ++-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/xs/src/slic3r/Utils/Http.cpp b/xs/src/slic3r/Utils/Http.cpp
index 47021d39f..949a0e7d6 100644
--- a/xs/src/slic3r/Utils/Http.cpp
+++ b/xs/src/slic3r/Utils/Http.cpp
@@ -71,6 +71,7 @@ Http::priv::priv(const std::string &url) :
 	form(nullptr),
 	form_end(nullptr),
 	headerlist(nullptr),
+	limit(0),
 	cancel(false)
 {
 	if (curl == nullptr) {
diff --git a/xs/src/slic3r/Utils/Http.hpp b/xs/src/slic3r/Utils/Http.hpp
index 73656bf88..7c2bd84fc 100644
--- a/xs/src/slic3r/Utils/Http.hpp
+++ b/xs/src/slic3r/Utils/Http.hpp
@@ -46,7 +46,8 @@ public:
 	Http& operator=(const Http &) = delete;
 	Http& operator=(Http &&) = delete;
 
-	// Sets a maximum size of the data that can be received. The default is 5MB.
+	// Sets a maximum size of the data that can be received.
+	// A value of zero sets the default limit, which is is 5MB.
 	Http& size_limit(size_t sizeLimit);
 	// Sets a HTTP header field.
 	Http& header(std::string name, const std::string &value);

From 5787c495d670a980ec5120c3740aa2470e4096a3 Mon Sep 17 00:00:00 2001
From: Vojtech Kral <vojtech@kral.hk>
Date: Wed, 27 Jun 2018 17:00:20 +0200
Subject: [PATCH 05/15] Octoprint: Improve error reporting

---
 xs/src/slic3r/Utils/Http.cpp      | 18 ++++++++++--------
 xs/src/slic3r/Utils/Http.hpp      |  9 +++++++++
 xs/src/slic3r/Utils/OctoPrint.cpp | 20 +++++++++-----------
 xs/src/slic3r/Utils/OctoPrint.hpp |  2 +-
 4 files changed, 29 insertions(+), 20 deletions(-)

diff --git a/xs/src/slic3r/Utils/Http.cpp b/xs/src/slic3r/Utils/Http.cpp
index 47021d39f..1a202b2ad 100644
--- a/xs/src/slic3r/Utils/Http.cpp
+++ b/xs/src/slic3r/Utils/Http.cpp
@@ -201,7 +201,6 @@ std::string Http::priv::body_size_error()
 
 void Http::priv::http_perform()
 {
-	::curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
 	::curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
 	::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writecb);
 	::curl_easy_setopt(curl, CURLOPT_WRITEDATA, static_cast<void*>(this));
@@ -230,8 +229,6 @@ void Http::priv::http_perform()
 	}
 
 	CURLcode res = ::curl_easy_perform(curl);
-	long http_status = 0;
-	::curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_status);
 
 	if (res != CURLE_OK) {
 		if (res == CURLE_ABORTED_BY_CALLBACK) {
@@ -242,17 +239,22 @@ void Http::priv::http_perform()
 				if (progressfn) { progressfn(dummyprogress, cancel); }
 			} else {
 				// The abort comes from the CURLOPT_READFUNCTION callback, which means reading file failed
-				if (errorfn) { errorfn(std::move(buffer), "Error reading file for file upload", http_status); }
+				if (errorfn) { errorfn(std::move(buffer), "Error reading file for file upload", 0); }
 			}
 		}
 		else if (res == CURLE_WRITE_ERROR) {
-			if (errorfn) { errorfn(std::move(buffer), body_size_error(), http_status); }
+			if (errorfn) { errorfn(std::move(buffer), body_size_error(), 0); }
 		} else {
-			if (errorfn) { errorfn(std::move(buffer), curl_error(res), http_status); }
+			if (errorfn) { errorfn(std::move(buffer), curl_error(res), 0); }
 		};
 	} else {
-		if (completefn) {
-			completefn(std::move(buffer), http_status);
+		long http_status = 0;
+		::curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_status);
+		
+		if (http_status >= 400) {
+			if (errorfn) { errorfn(std::move(buffer), std::string(), http_status); }
+		} else {
+			if (completefn) { completefn(std::move(buffer), http_status); }
 		}
 	}
 }
diff --git a/xs/src/slic3r/Utils/Http.hpp b/xs/src/slic3r/Utils/Http.hpp
index 73656bf88..0724da9ee 100644
--- a/xs/src/slic3r/Utils/Http.hpp
+++ b/xs/src/slic3r/Utils/Http.hpp
@@ -29,7 +29,16 @@ public:
 
 	typedef std::shared_ptr<Http> Ptr;
 	typedef std::function<void(std::string /* body */, unsigned /* http_status */)> CompleteFn;
+	
+	// A HTTP request may fail at various stages of completeness (URL parsing, DNS lookup, TCP connection, ...).
+	// If the HTTP request could not be made or failed before completion, the `error` arg contains a description
+	// of the error and `http_status` is zero.
+	// If the HTTP request was completed but the response HTTP code is >= 400, `error` is empty and `http_status` contains the response code.
+	// In either case there may or may not be a body.
 	typedef std::function<void(std::string /* body */, std::string /* error */, unsigned /* http_status */)> ErrorFn;
+
+	// See the Progress struct above.
+	// Writing true to the `cancel` reference cancels the request in progress.
 	typedef std::function<void(Progress, bool& /* cancel */)> ProgressFn;
 
 	Http(Http &&other);
diff --git a/xs/src/slic3r/Utils/OctoPrint.cpp b/xs/src/slic3r/Utils/OctoPrint.cpp
index 86049de16..97b4123d4 100644
--- a/xs/src/slic3r/Utils/OctoPrint.cpp
+++ b/xs/src/slic3r/Utils/OctoPrint.cpp
@@ -78,10 +78,10 @@ bool OctoPrint::test(wxString &msg) const
 
 	auto http = Http::get(std::move(url));
 	set_auth(http);
-	http.on_error([&](std::string, std::string error, unsigned status) {
-			BOOST_LOG_TRIVIAL(error) << boost::format("Octoprint: Error getting version: %1% (HTTP %2%)") % error % status;
+	http.on_error([&](std::string body, std::string error, unsigned status) {
+			BOOST_LOG_TRIVIAL(error) << boost::format("Octoprint: Error getting version: %1%, HTTP %2%, body: `%3%`") % error % status % body;
 			res = false;
-			msg = format_error(error, status);
+			msg = format_error(body, error, status);
 		})
 		.on_complete([&](std::string body, unsigned) {
 			BOOST_LOG_TRIVIAL(debug) << boost::format("Octoprint: Got version: %1%") % body;
@@ -140,8 +140,8 @@ bool OctoPrint::send_gcode(const std::string &filename) const
 			progress_dialog.Update(PROGRESS_RANGE);
 		})
 		.on_error([&](std::string body, std::string error, unsigned status) {
-			BOOST_LOG_TRIVIAL(error) << boost::format("Octoprint: Error uploading file: %1% (HTTP %2%)") % error % status;
-			auto errormsg = wxString::Format("%s: %s", errortitle, format_error(error, status));
+			BOOST_LOG_TRIVIAL(error) << boost::format("Octoprint: Error uploading file: %1%, HTTP %2%, body: `%3%`") % error % status % body;
+			auto errormsg = wxString::Format("%s: %s", errortitle, format_error(body, error, status));
 			GUI::show_error(&progress_dialog, std::move(errormsg));
 			res = false;
 		})
@@ -183,15 +183,13 @@ std::string OctoPrint::make_url(const std::string &path) const
 	}
 }
 
-wxString OctoPrint::format_error(const std::string &error, unsigned status)
+wxString OctoPrint::format_error(const std::string &body, const std::string &error, unsigned status)
 {
-	auto wxerror = wxString::FromUTF8(error.data());
-
 	if (status != 0) {
-		return wxString::Format("HTTP %u: %s", status,
-			(status == 401 ? _(L("Invalid API key")) : wxerror));
+		auto wxbody = wxString::FromUTF8(body.data());
+		return wxString::Format("HTTP %u: %s", status, wxbody);
 	} else {
-		return wxerror;
+		return wxString::FromUTF8(error.data());
 	}
 }
 
diff --git a/xs/src/slic3r/Utils/OctoPrint.hpp b/xs/src/slic3r/Utils/OctoPrint.hpp
index a8599faa9..1e2098ae3 100644
--- a/xs/src/slic3r/Utils/OctoPrint.hpp
+++ b/xs/src/slic3r/Utils/OctoPrint.hpp
@@ -26,7 +26,7 @@ private:
 
 	void set_auth(Http &http) const;
 	std::string make_url(const std::string &path) const;
-	static wxString format_error(const std::string &error, unsigned status);
+	static wxString format_error(const std::string &body, const std::string &error, unsigned status);
 };
 
 

From 19f5863d75b286e7459f2ce163ec5e5befe1ac78 Mon Sep 17 00:00:00 2001
From: Lukas Matena <lukasmatena@seznam.cz>
Date: Thu, 28 Jun 2018 10:22:04 +0200
Subject: [PATCH 06/15] Wipe tower fix - incorrect start/end position reported
 to the GCode generator when the tower was rotated

---
 xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp
index fbde83754..5aa6470a2 100644
--- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp
+++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp
@@ -142,10 +142,10 @@ public:
 		}
 
 		m_gcode += "G1";
-		if (std::abs(dx) > EPSILON)
+		if (std::abs(rot.x - rotated_current_pos.x) > EPSILON)
 			m_gcode += set_format_X(rot.x);
 
-		if (std::abs(dy) > EPSILON)
+		if (std::abs(rot.y - rotated_current_pos.y) > EPSILON)
 			m_gcode += set_format_Y(rot.y);
 
 		if (e != 0.f)

From 5f1f7dcbedcdc884b4cd489562b444ad372b89c9 Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Wed, 27 Jun 2018 09:07:04 +0200
Subject: [PATCH 07/15] Fix of tooltips on OSX showing on the first page of a
 parameter tab.

---
 lib/Slic3r/GUI/MainFrame.pm        |   4 +
 xs/src/slic3r/GUI/ConfigWizard.cpp |   4 +-
 xs/src/slic3r/GUI/GUI.cpp          |   7 +-
 xs/src/slic3r/GUI/Tab.cpp          | 132 +++++++++++------------------
 xs/src/slic3r/GUI/Tab.hpp          |   6 +-
 5 files changed, 63 insertions(+), 90 deletions(-)

diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm
index 910b86dd8..ea4a158f4 100644
--- a/lib/Slic3r/GUI/MainFrame.pm
+++ b/lib/Slic3r/GUI/MainFrame.pm
@@ -110,6 +110,10 @@ sub _init_tabpanel {
     EVT_NOTEBOOK_PAGE_CHANGED($self, $self->{tabpanel}, sub {
         my $panel = $self->{tabpanel}->GetCurrentPage;
         $panel->OnActivate if $panel->can('OnActivate');
+
+        for my $tab_name (qw(print filament printer)) {
+            Slic3r::GUI::get_preset_tab("$tab_name")->OnActivate if ("$tab_name" eq $panel->GetName);
+        }
     });
     
     if (!$self->{no_plater}) {
diff --git a/xs/src/slic3r/GUI/ConfigWizard.cpp b/xs/src/slic3r/GUI/ConfigWizard.cpp
index ce06da853..b19515dd4 100644
--- a/xs/src/slic3r/GUI/ConfigWizard.cpp
+++ b/xs/src/slic3r/GUI/ConfigWizard.cpp
@@ -886,9 +886,9 @@ const wxString& ConfigWizard::name()
 {
 	// A different naming convention is used for the Wizard on Windows vs. OSX & GTK.
 #if WIN32
-	static const wxString config_wizard_name = _(L("Configuration Wizard"));
+	static const wxString config_wizard_name = L("Configuration Wizard");
 #else
-	static const wxString config_wizard_name = _(L("Configuration Assistant"));
+	static const wxString config_wizard_name = L("Configuration Assistant");
 #endif
 	return config_wizard_name;
 }
diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp
index c1f8adaf1..12af36d19 100644
--- a/xs/src/slic3r/GUI/GUI.cpp
+++ b/xs/src/slic3r/GUI/GUI.cpp
@@ -317,10 +317,11 @@ void add_config_menu(wxMenuBar *menu, int event_preferences_changed, int event_l
     auto local_menu = new wxMenu();
     wxWindowID config_id_base = wxWindow::NewControlId((int)ConfigMenuCnt);
 
-    const auto config_wizard_tooltip = wxString::Format(_(L("Run %s")), ConfigWizard::name());
+	auto config_wizard_name = _(ConfigWizard::name().wx_str());
+	const auto config_wizard_tooltip = wxString::Format(_(L("Run %s")), config_wizard_name);
     // Cmd+, is standard on OS X - what about other operating systems?
-   	local_menu->Append(config_id_base + ConfigMenuWizard, 		ConfigWizard::name() + dots, 			config_wizard_tooltip);
-   	local_menu->Append(config_id_base + ConfigMenuSnapshots, 	_(L("Configuration Snapshots"))+dots,	_(L("Inspect / activate configuration snapshots")));
+	local_menu->Append(config_id_base + ConfigMenuWizard, 		config_wizard_name + dots,					config_wizard_tooltip);
+   	local_menu->Append(config_id_base + ConfigMenuSnapshots, 	_(L("Configuration Snapshots"))+dots,		_(L("Inspect / activate configuration snapshots")));
    	local_menu->Append(config_id_base + ConfigMenuTakeSnapshot, _(L("Take Configuration Snapshot")), 		_(L("Capture a configuration snapshot")));
 // 	local_menu->Append(config_id_base + ConfigMenuUpdate, 		_(L("Check for updates")), 					_(L("Check for configuration updates")));
    	local_menu->AppendSeparator();
diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp
index 94f8cc3ea..b3b3c6139 100644
--- a/xs/src/slic3r/GUI/Tab.cpp
+++ b/xs/src/slic3r/GUI/Tab.cpp
@@ -47,66 +47,32 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
 
 	// preset chooser
 	m_presets_choice = new wxBitmapComboBox(panel, wxID_ANY, "", wxDefaultPosition, wxSize(270, -1), 0, 0,wxCB_READONLY);
-	/*
-	m_cc_presets_choice = new wxComboCtrl(panel, wxID_ANY, L(""), wxDefaultPosition, wxDefaultSize, wxCB_READONLY);
-	wxDataViewTreeCtrlComboPopup* popup = new wxDataViewTreeCtrlComboPopup;
-	if (popup != nullptr)
-	{
-		// FIXME If the following line is removed, the combo box popup list will not react to mouse clicks.
-		//  On the other side, with this line the combo box popup cannot be closed by clicking on the combo button on Windows 10.
-//		m_cc_presets_choice->UseAltPopupWindow();
-
-//		m_cc_presets_choice->EnablePopupAnimation(false);
-		m_cc_presets_choice->SetPopupControl(popup);
-		popup->SetStringValue(from_u8("Text1"));
-
-		popup->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this, popup](wxCommandEvent& evt)
-		{
-			auto selected = popup->GetItemText(popup->GetSelection());
-			if (selected != _(L("System presets")) && selected != _(L("Default presets")))
-			{
-				m_cc_presets_choice->SetText(selected);
-				std::string selected_string = selected.ToUTF8().data();
-#ifdef __APPLE__
-#else
- 				select_preset(selected_string);
-#endif
-			}				
-		});
-
-// 		popup->Bind(wxEVT_KEY_DOWN, [popup](wxKeyEvent& evt) { popup->OnKeyEvent(evt); });
-// 		popup->Bind(wxEVT_KEY_UP, [popup](wxKeyEvent& evt) { popup->OnKeyEvent(evt); });
-
-		auto icons = new wxImageList(16, 16, true, 1);
-		popup->SetImageList(icons);
-		icons->Add(*new wxIcon(from_u8(Slic3r::var("flag-green-icon.png")), wxBITMAP_TYPE_PNG));
-		icons->Add(*new wxIcon(from_u8(Slic3r::var("flag-red-icon.png")), wxBITMAP_TYPE_PNG));
-	}
-*/
 	auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
 
 	//buttons
+	m_btn_panel = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL);
+	
 	wxBitmap bmpMenu;
 	bmpMenu = wxBitmap(from_u8(Slic3r::var("disk.png")), wxBITMAP_TYPE_PNG);
-	m_btn_save_preset = new wxBitmapButton(panel, wxID_ANY, bmpMenu, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
+	m_btn_save_preset = new wxBitmapButton(m_btn_panel, wxID_ANY, bmpMenu, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
 	if (wxMSW) m_btn_save_preset->SetBackgroundColour(color);
 	bmpMenu = wxBitmap(from_u8(Slic3r::var("delete.png")), wxBITMAP_TYPE_PNG);
-	m_btn_delete_preset = new wxBitmapButton(panel, wxID_ANY, bmpMenu, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
+	m_btn_delete_preset = new wxBitmapButton(m_btn_panel, wxID_ANY, bmpMenu, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
 	if (wxMSW) m_btn_delete_preset->SetBackgroundColour(color);
 
 	m_show_incompatible_presets = false;
 	m_bmp_show_incompatible_presets.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);
+	m_btn_hide_incompatible_presets = new wxBitmapButton(m_btn_panel, wxID_ANY, m_bmp_hide_incompatible_presets, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
 	if (wxMSW) m_btn_hide_incompatible_presets->SetBackgroundColour(color);
 
 	m_btn_save_preset->SetToolTip(_(L("Save current ")) + m_title);
 	m_btn_delete_preset->SetToolTip(_(L("Delete this preset")));
 	m_btn_delete_preset->Disable();
 
-	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_btn = new wxButton(m_btn_panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER);
+	m_undo_to_sys_btn = new wxButton(m_btn_panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER);
+	m_question_btn = new wxButton(m_btn_panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER);
 	if (wxMSW) {
 		m_undo_btn->SetBackgroundColour(color);
 		m_undo_to_sys_btn->SetBackgroundColour(color);
@@ -153,57 +119,32 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
 	m_modified_label_clr	= get_label_clr_modified();
 	m_default_text_clr		= get_label_clr_default();
 
+	auto  btn_sizer = new wxBoxSizer(wxHORIZONTAL);
+	m_btn_panel->SetSizer(btn_sizer);
+	m_btn_panel->Layout();
+
+	btn_sizer->Add(m_btn_save_preset, 0, wxALIGN_CENTER_VERTICAL);
+	btn_sizer->AddSpacer(4);
+	btn_sizer->Add(m_btn_delete_preset, 0, wxALIGN_CENTER_VERTICAL);
+	btn_sizer->AddSpacer(16);
+	btn_sizer->Add(m_btn_hide_incompatible_presets, 0, wxALIGN_CENTER_VERTICAL);
+	btn_sizer->AddSpacer(64);
+	btn_sizer->Add(m_undo_to_sys_btn, 0, wxALIGN_CENTER_VERTICAL);
+	btn_sizer->Add(m_undo_btn, 0, wxALIGN_CENTER_VERTICAL);
+	btn_sizer->AddSpacer(32);
+	btn_sizer->Add(m_question_btn, 0, wxALIGN_CENTER_VERTICAL);
+
 	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);
 	m_hsizer->AddSpacer(4);
-	m_hsizer->Add(m_btn_save_preset, 0, wxALIGN_CENTER_VERTICAL);
-	m_hsizer->AddSpacer(4);
-	m_hsizer->Add(m_btn_delete_preset, 0, wxALIGN_CENTER_VERTICAL);
-	m_hsizer->AddSpacer(16);
-	m_hsizer->Add(m_btn_hide_incompatible_presets, 0, wxALIGN_CENTER_VERTICAL);
-	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(32);
-	m_hsizer->Add(m_question_btn, 0, wxALIGN_CENTER_VERTICAL);
-// 	m_hsizer->Add(m_cc_presets_choice, 1, wxLEFT | wxRIGHT | wxTOP | wxALIGN_CENTER_VERTICAL, 3);
+	m_hsizer->Add(m_btn_panel, 0, wxALIGN_CENTER_VERTICAL);
 
 	//Horizontal sizer to hold the tree and the selected page.
 	m_hsizer = new wxBoxSizer(wxHORIZONTAL);
 	sizer->Add(m_hsizer, 1, wxEXPAND, 0);
 
 
-/*
-
-
-	//temporary left vertical sizer
-	m_left_sizer = new wxBoxSizer(wxVERTICAL);
-	m_hsizer->Add(m_left_sizer, 0, wxEXPAND | wxLEFT | wxTOP | wxBOTTOM, 3);
-
-	// tree
-	m_presetctrl = new wxDataViewTreeCtrl(panel, wxID_ANY, wxDefaultPosition, wxSize(200, -1), wxDV_NO_HEADER);
-	m_left_sizer->Add(m_presetctrl, 1, wxEXPAND);
-	m_preset_icons = new wxImageList(16, 16, true, 1);
-	m_presetctrl->SetImageList(m_preset_icons);
-	m_preset_icons->Add(*new wxIcon(from_u8(Slic3r::var("flag-green-icon.png")), wxBITMAP_TYPE_PNG));
-	m_preset_icons->Add(*new wxIcon(from_u8(Slic3r::var("flag-red-icon.png")), wxBITMAP_TYPE_PNG));
-
-	m_presetctrl->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this](wxCommandEvent& evt)
-	{
-		auto selected = m_presetctrl->GetItemText(m_presetctrl->GetSelection());
-		if (selected != _(L("System presets")) && selected != _(L("Default presets")))
-		{
-			std::string selected_string = selected.ToUTF8().data();
-#ifdef __APPLE__
-#else
-			select_preset(selected_string);
-#endif
-		}
-	});
-
-*/
-
 	//left vertical sizer
 	m_left_sizer = new wxBoxSizer(wxVERTICAL);
 	m_hsizer->Add(m_left_sizer, 0, wxEXPAND | wxLEFT | wxTOP | wxBOTTOM, 3);
@@ -290,6 +231,28 @@ PageShp Tab::add_options_page(const wxString& title, const std::string& icon, bo
 	return page;
 }
 
+void Tab::OnActivate()
+{
+#ifdef __WXOSX__	
+	wxWindowUpdateLocker noUpdates(this);
+
+	m_btn_panel->Fit();
+
+	Page* page = nullptr;
+	auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection());
+	for (auto p : m_pages)
+		if (p->title() == selection)
+		{
+			page = p.get();
+			break;
+		}
+	if (page == nullptr) return;
+	page->Fit();
+	m_hsizer->Layout();
+	Refresh();
+#endif
+}
+
 void Tab::update_labels_colour()
 {
 	Freeze();
@@ -1246,6 +1209,7 @@ void TabPrint::update()
 
 void TabPrint::OnActivate()
 {
+	Tab::OnActivate();
 	m_recommended_thin_wall_thickness_description_line->SetText(
 		from_u8(PresetHints::recommended_thin_wall_thickness(*m_preset_bundle)));
 }
@@ -1404,6 +1368,7 @@ void TabFilament::update()
 
 void TabFilament::OnActivate()
 {
+	Tab::OnActivate();
 	m_volumetric_speed_description_line->SetText(from_u8(PresetHints::maximum_volumetric_flow_description(*m_preset_bundle)));
 }
 
@@ -2086,6 +2051,7 @@ void Tab::OnTreeSelChange(wxTreeEvent& event)
 #endif
 
 	page->Show();
+	page->Fit();
 	m_hsizer->Layout();
 	Refresh();
 
diff --git a/xs/src/slic3r/GUI/Tab.hpp b/xs/src/slic3r/GUI/Tab.hpp
index d6bf2cf43..633f89750 100644
--- a/xs/src/slic3r/GUI/Tab.hpp
+++ b/xs/src/slic3r/GUI/Tab.hpp
@@ -119,6 +119,8 @@ protected:
 	wxButton*			m_undo_to_sys_btn;
 	wxButton*			m_question_btn;
 
+	wxPanel*			m_btn_panel;
+
 	wxComboCtrl*		m_cc_presets_choice;
 	wxDataViewTreeCtrl*	m_presetctrl;
 	wxImageList*		m_preset_icons;
@@ -198,7 +200,7 @@ public:
 	Tab() {}
 	Tab(wxNotebook* parent, const wxString& title, const char* name, bool no_controller) : 
 		m_parent(parent), m_title(title), m_name(name), m_no_controller(no_controller) {
-		Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL);
+		Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL, name);
 		get_tabs_list().push_back(this);
 	}
 	~Tab(){
@@ -242,7 +244,7 @@ public:
 
 	PageShp		add_options_page(const wxString& title, const std::string& icon, bool is_extruder_pages = false);
 
-	virtual void	OnActivate(){}
+	virtual void	OnActivate();
 	virtual void	on_preset_loaded(){}
 	virtual void	build() = 0;
 	virtual void	update() = 0;

From 2cbf5b75db3ce89171a9cb0e39f94c72816e3230 Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Thu, 28 Jun 2018 18:30:22 +0200
Subject: [PATCH 08/15] Final Fix of tooltips on OSX showing on the first page
 of a parameter tab.

---
 xs/src/slic3r/GUI/Tab.cpp | 91 ++++++++++++++++++++-------------------
 xs/src/slic3r/GUI/Tab.hpp |  7 +--
 2 files changed, 51 insertions(+), 47 deletions(-)

diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp
index b3b3c6139..f41a14e93 100644
--- a/xs/src/slic3r/GUI/Tab.cpp
+++ b/xs/src/slic3r/GUI/Tab.cpp
@@ -40,39 +40,54 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
 	m_preset_bundle = preset_bundle;
 
 	// Vertical sizer to hold the choice menu and the rest of the page.
+#ifdef __WXOSX__
+	auto  *main_sizer = new wxBoxSizer(wxVERTICAL);
+	main_sizer->SetSizeHints(this);
+	this->SetSizer(main_sizer);
+
+	// Create additional panel to Fit() it from OnActivate()
+	// It's needed for tooltip showing on OSX
+	m_tmp_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL);
+	auto panel = m_tmp_panel; 
+	auto  sizer = new wxBoxSizer(wxVERTICAL);
+	m_tmp_panel->SetSizer(sizer);
+	m_tmp_panel->Layout();
+
+	main_sizer->Add(m_tmp_panel, 1, wxEXPAND | wxALL, 0);
+#else
 	Tab *panel = this;
 	auto  *sizer = new wxBoxSizer(wxVERTICAL);
 	sizer->SetSizeHints(panel);
 	panel->SetSizer(sizer);
+#endif //__WXOSX__
 
 	// preset chooser
 	m_presets_choice = new wxBitmapComboBox(panel, wxID_ANY, "", wxDefaultPosition, wxSize(270, -1), 0, 0,wxCB_READONLY);
+
 	auto color = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
 
 	//buttons
-	m_btn_panel = new wxPanel(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL);
-	
 	wxBitmap bmpMenu;
 	bmpMenu = wxBitmap(from_u8(Slic3r::var("disk.png")), wxBITMAP_TYPE_PNG);
-	m_btn_save_preset = new wxBitmapButton(m_btn_panel, wxID_ANY, bmpMenu, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
+	m_btn_save_preset = new wxBitmapButton(panel, wxID_ANY, bmpMenu, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
 	if (wxMSW) m_btn_save_preset->SetBackgroundColour(color);
 	bmpMenu = wxBitmap(from_u8(Slic3r::var("delete.png")), wxBITMAP_TYPE_PNG);
-	m_btn_delete_preset = new wxBitmapButton(m_btn_panel, wxID_ANY, bmpMenu, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
+	m_btn_delete_preset = new wxBitmapButton(panel, wxID_ANY, bmpMenu, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
 	if (wxMSW) m_btn_delete_preset->SetBackgroundColour(color);
 
 	m_show_incompatible_presets = false;
 	m_bmp_show_incompatible_presets.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(m_btn_panel, wxID_ANY, m_bmp_hide_incompatible_presets, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
+	m_btn_hide_incompatible_presets = new wxBitmapButton(panel, wxID_ANY, m_bmp_hide_incompatible_presets, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
 	if (wxMSW) m_btn_hide_incompatible_presets->SetBackgroundColour(color);
 
 	m_btn_save_preset->SetToolTip(_(L("Save current ")) + m_title);
 	m_btn_delete_preset->SetToolTip(_(L("Delete this preset")));
 	m_btn_delete_preset->Disable();
 
-	m_undo_btn = new wxButton(m_btn_panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER);
-	m_undo_to_sys_btn = new wxButton(m_btn_panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER);
-	m_question_btn = new wxButton(m_btn_panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER);
+	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);
 	if (wxMSW) {
 		m_undo_btn->SetBackgroundColour(color);
 		m_undo_to_sys_btn->SetBackgroundColour(color);
@@ -119,32 +134,26 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
 	m_modified_label_clr	= get_label_clr_modified();
 	m_default_text_clr		= get_label_clr_default();
 
-	auto  btn_sizer = new wxBoxSizer(wxHORIZONTAL);
-	m_btn_panel->SetSizer(btn_sizer);
-	m_btn_panel->Layout();
-
-	btn_sizer->Add(m_btn_save_preset, 0, wxALIGN_CENTER_VERTICAL);
-	btn_sizer->AddSpacer(4);
-	btn_sizer->Add(m_btn_delete_preset, 0, wxALIGN_CENTER_VERTICAL);
-	btn_sizer->AddSpacer(16);
-	btn_sizer->Add(m_btn_hide_incompatible_presets, 0, wxALIGN_CENTER_VERTICAL);
-	btn_sizer->AddSpacer(64);
-	btn_sizer->Add(m_undo_to_sys_btn, 0, wxALIGN_CENTER_VERTICAL);
-	btn_sizer->Add(m_undo_btn, 0, wxALIGN_CENTER_VERTICAL);
-	btn_sizer->AddSpacer(32);
-	btn_sizer->Add(m_question_btn, 0, wxALIGN_CENTER_VERTICAL);
-
 	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);
 	m_hsizer->AddSpacer(4);
-	m_hsizer->Add(m_btn_panel, 0, wxALIGN_CENTER_VERTICAL);
+	m_hsizer->Add(m_btn_save_preset, 0, wxALIGN_CENTER_VERTICAL);
+	m_hsizer->AddSpacer(4);
+	m_hsizer->Add(m_btn_delete_preset, 0, wxALIGN_CENTER_VERTICAL);
+	m_hsizer->AddSpacer(16);
+	m_hsizer->Add(m_btn_hide_incompatible_presets, 0, wxALIGN_CENTER_VERTICAL);
+	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(32);
+	m_hsizer->Add(m_question_btn, 0, wxALIGN_CENTER_VERTICAL);
+// 	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.
 	m_hsizer = new wxBoxSizer(wxHORIZONTAL);
 	sizer->Add(m_hsizer, 1, wxEXPAND, 0);
 
-
 	//left vertical sizer
 	m_left_sizer = new wxBoxSizer(wxVERTICAL);
 	m_hsizer->Add(m_left_sizer, 0, wxEXPAND | wxLEFT | wxTOP | wxBOTTOM, 3);
@@ -220,7 +229,12 @@ PageShp Tab::add_options_page(const wxString& title, const std::string& icon, bo
 		}
 	}
 	// Initialize the page.
-	PageShp page(new Page(this, title, icon_idx));
+#ifdef __WXOSX__
+	auto panel = m_tmp_panel;
+#else
+	auto panel = this;
+#endif
+	PageShp page(new Page(panel, title, icon_idx));
 	page->SetScrollbars(1, 1, 1, 1);
 	page->Hide();
 	m_hsizer->Add(page.get(), 1, wxEXPAND | wxLEFT, 5);
@@ -236,21 +250,11 @@ void Tab::OnActivate()
 #ifdef __WXOSX__	
 	wxWindowUpdateLocker noUpdates(this);
 
-	m_btn_panel->Fit();
-
-	Page* page = nullptr;
-	auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection());
-	for (auto p : m_pages)
-		if (p->title() == selection)
-		{
-			page = p.get();
-			break;
-		}
-	if (page == nullptr) return;
-	page->Fit();
-	m_hsizer->Layout();
-	Refresh();
-#endif
+	auto size = GetSizer()->GetSize();
+	m_tmp_panel->GetSizer()->SetMinSize(size.x + m_size_move, size.y);
+	Fit();
+	m_size_move *= -1;
+#endif // __WXOSX__
 }
 
 void Tab::update_labels_colour()
@@ -1209,9 +1213,9 @@ void TabPrint::update()
 
 void TabPrint::OnActivate()
 {
-	Tab::OnActivate();
 	m_recommended_thin_wall_thickness_description_line->SetText(
 		from_u8(PresetHints::recommended_thin_wall_thickness(*m_preset_bundle)));
+	Tab::OnActivate();
 }
 
 void TabFilament::build()
@@ -1368,8 +1372,8 @@ void TabFilament::update()
 
 void TabFilament::OnActivate()
 {
-	Tab::OnActivate();
 	m_volumetric_speed_description_line->SetText(from_u8(PresetHints::maximum_volumetric_flow_description(*m_preset_bundle)));
+	Tab::OnActivate();
 }
 
 wxSizer* Tab::description_line_widget(wxWindow* parent, ogStaticText* *StaticText)
@@ -2051,7 +2055,6 @@ void Tab::OnTreeSelChange(wxTreeEvent& event)
 #endif
 
 	page->Show();
-	page->Fit();
 	m_hsizer->Layout();
 	Refresh();
 
diff --git a/xs/src/slic3r/GUI/Tab.hpp b/xs/src/slic3r/GUI/Tab.hpp
index 633f89750..c755f91f1 100644
--- a/xs/src/slic3r/GUI/Tab.hpp
+++ b/xs/src/slic3r/GUI/Tab.hpp
@@ -102,6 +102,10 @@ using PageShp = std::shared_ptr<Page>;
 class Tab: public wxPanel
 {
 	wxNotebook*			m_parent;
+#ifdef __WXOSX__
+	wxPanel*			m_tmp_panel;
+	int					m_size_move = -1;
+#endif // __WXOSX__
 protected:
 	std::string			m_name;
 	const wxString		m_title;
@@ -118,9 +122,6 @@ protected:
 	wxButton*			m_undo_btn;
 	wxButton*			m_undo_to_sys_btn;
 	wxButton*			m_question_btn;
-
-	wxPanel*			m_btn_panel;
-
 	wxComboCtrl*		m_cc_presets_choice;
 	wxDataViewTreeCtrl*	m_presetctrl;
 	wxImageList*		m_preset_icons;

From d4b0d1b773b345f4aa93ea09b5362ef8e65b5efb Mon Sep 17 00:00:00 2001
From: bubnikv <bubnikv@gmail.com>
Date: Fri, 29 Jun 2018 10:59:58 +0200
Subject: [PATCH 09/15] bumped up the version number

---
 xs/src/libslic3r/libslic3r.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/xs/src/libslic3r/libslic3r.h b/xs/src/libslic3r/libslic3r.h
index 4aef4d5c1..a5926debe 100644
--- a/xs/src/libslic3r/libslic3r.h
+++ b/xs/src/libslic3r/libslic3r.h
@@ -14,7 +14,7 @@
 #include <boost/thread.hpp>
 
 #define SLIC3R_FORK_NAME "Slic3r Prusa Edition"
-#define SLIC3R_VERSION "1.40.0"
+#define SLIC3R_VERSION "1.40.1-rc"
 #define SLIC3R_BUILD "UNKNOWN"
 
 typedef int32_t coord_t;

From 07b28b2a8c1b20a4fca89c08719ae6421dc273a5 Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Mon, 2 Jul 2018 13:51:50 +0200
Subject: [PATCH 10/15] Bug-fixes of the OSX crashing

---
 xs/src/slic3r/GUI/Tab.cpp | 36 ++++++++++++++++++++++++------------
 1 file changed, 24 insertions(+), 12 deletions(-)

diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp
index f41a14e93..ebbf4caff 100644
--- a/xs/src/slic3r/GUI/Tab.cpp
+++ b/xs/src/slic3r/GUI/Tab.cpp
@@ -183,7 +183,7 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle)
 			return;
 		if (selected_item >= 0){
 			std::string selected_string = m_presets_choice->GetString(selected_item).ToUTF8().data();
-			if (selected_string.find_first_of("-------") == 0
+			if (selected_string.find("-------") == 0
 				/*selected_string == "------- System presets -------" ||
 				selected_string == "-------  User presets  -------"*/){
 				m_presets_choice->SetSelection(m_selected_preset_item);
@@ -454,8 +454,13 @@ void Tab::update_changed_tree_ui()
 					get_sys_and_mod_flags(opt_key, sys_page, modified_page);
 				}
 			}
-			if (title == _("Dependencies") && name() != "printer"){
-				get_sys_and_mod_flags("compatible_printers", sys_page, modified_page);
+			if (title == _("Dependencies")){
+				if (name() != "printer")
+					get_sys_and_mod_flags("compatible_printers", sys_page, modified_page);
+				else {
+					sys_page = m_presets->get_selected_preset_parent() ? true:false;
+					modified_page = false;
+				}
 			}
 			for (auto group : page->m_optgroups)
 			{
@@ -1863,6 +1868,8 @@ void Tab::load_current_preset()
 	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;
 
+	m_undo_to_sys_btn->Enable(!preset.is_default);
+
 	// use CallAfter because some field triggers schedule on_change calls using CallAfter,
 	// and we don't want them to be called after this update_dirty() as they would mark the 
 	// preset dirty again
@@ -2529,28 +2536,33 @@ ConfigOptionsGroupShp Page::new_optgroup(const wxString& title, int noncommon_la
 	if (noncommon_label_width >= 0)
 		optgroup->label_width = noncommon_label_width;
 
-	optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){
+#ifdef __WXOSX__
+		auto tab = GetParent()->GetParent();
+#else
+		auto tab = GetParent();
+#endif
+	optgroup->m_on_change = [this, tab](t_config_option_key opt_key, boost::any value){
 		//! This function will be called from OptionGroup.
 		//! Using of CallAfter is redundant.
 		//! And in some cases it causes update() function to be recalled again
 //!        wxTheApp->CallAfter([this, opt_key, value]() {
-			static_cast<Tab*>(GetParent())->update_dirty();
-			static_cast<Tab*>(GetParent())->on_value_change(opt_key, value);
+			static_cast<Tab*>(tab)->update_dirty();
+			static_cast<Tab*>(tab)->on_value_change(opt_key, value);
 //!        });
 	};
 
-	optgroup->m_get_initial_config = [this](){
-		DynamicPrintConfig config = static_cast<Tab*>(GetParent())->m_presets->get_selected_preset().config;
+	optgroup->m_get_initial_config = [this, tab](){
+		DynamicPrintConfig config = static_cast<Tab*>(tab)->m_presets->get_selected_preset().config;
 		return config;
 	};
 
-	optgroup->m_get_sys_config = [this](){
-		DynamicPrintConfig config = static_cast<Tab*>(GetParent())->m_presets->get_selected_preset_parent()->config;
+	optgroup->m_get_sys_config = [this, tab](){
+		DynamicPrintConfig config = static_cast<Tab*>(tab)->m_presets->get_selected_preset_parent()->config;
 		return config;
 	};
 
-	optgroup->have_sys_config = [this](){
-		return static_cast<Tab*>(GetParent())->m_presets->get_selected_preset_parent() != nullptr;
+	optgroup->have_sys_config = [this, tab](){
+		return static_cast<Tab*>(tab)->m_presets->get_selected_preset_parent() != nullptr;
 	};
 
 	vsizer()->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 10);

From 617b5158bdc7dc9802e050f691fa2e7e4f3e643c Mon Sep 17 00:00:00 2001
From: Vojtech Kral <vojtech@kral.hk>
Date: Mon, 2 Jul 2018 17:18:09 +0200
Subject: [PATCH 11/15] Fix: Leak in Tab.cpp in serial port test

---
 xs/src/slic3r/GUI/Tab.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp
index ebbf4caff..8af00b2b6 100644
--- a/xs/src/slic3r/GUI/Tab.cpp
+++ b/xs/src/slic3r/GUI/Tab.cpp
@@ -1492,7 +1492,7 @@ void TabPrinter::build()
 				sizer->Add(btn);
 
 				btn->Bind(wxEVT_BUTTON, [this, parent](wxCommandEvent e){
-					auto sender = new GCodeSender();					
+					auto sender = Slic3r::make_unique<GCodeSender>();
 					auto res = sender->connect(
 						m_config->opt_string("serial_port"), 
 						m_config->opt_int("serial_speed")

From c7f3014d260b5634883170543e79c57fd1ddf0c1 Mon Sep 17 00:00:00 2001
From: bubnikv <bubnikv@gmail.com>
Date: Mon, 2 Jul 2018 20:25:37 +0200
Subject: [PATCH 12/15] Fix of "Slic3r 1.40.1-rc fails to retain the filament
 list on" https://github.com/prusa3d/Slic3r/issues/1020

---
 xs/src/slic3r/GUI/PresetBundle.cpp | 40 +++++++++++++++---------------
 1 file changed, 20 insertions(+), 20 deletions(-)

diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp
index d36ef7b6f..0a280eee1 100644
--- a/xs/src/slic3r/GUI/PresetBundle.cpp
+++ b/xs/src/slic3r/GUI/PresetBundle.cpp
@@ -264,36 +264,38 @@ void PresetBundle::load_selections(const AppConfig &config)
 	this->load_installed_printers(config);
 
     // Parse the initial print / filament / printer profile names.
-    std::string                 initial_print_profile_name     = remove_ini_suffix(config.get("presets", "print"));
-    std::vector<std::string>    initial_filament_profile_names;
-    std::string                 initial_printer_profile_name   = remove_ini_suffix(config.get("presets", "printer"));
-
-    auto   *nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(printers.get_selected_preset().config.option("nozzle_diameter"));
-    size_t  num_extruders   = nozzle_diameter->values.size();   
-    initial_filament_profile_names.emplace_back(remove_ini_suffix(config.get("presets", "filament")));
-    this->set_filament_preset(0, initial_filament_profile_names.back());
-    for (unsigned int i = 1; i < (unsigned int)num_extruders; ++ i) {
-        char name[64];
-        sprintf(name, "filament_%d", i);
-        if (! config.has("presets", name))
-            break;
-        initial_filament_profile_names.emplace_back(remove_ini_suffix(config.get("presets", name)));
-        this->set_filament_preset(i, initial_filament_profile_names.back());
-    }
+    std::string initial_print_profile_name    = remove_ini_suffix(config.get("presets", "print"));
+    std::string initial_filament_profile_name = remove_ini_suffix(config.get("presets", "filament"));
+	std::string initial_printer_profile_name  = remove_ini_suffix(config.get("presets", "printer"));
 
 	// Activate print / filament / printer profiles from the config.
 	// If the printer profile enumerated by the config are not visible, select an alternate preset.
     // Do not select alternate profiles for the print / filament profiles as those presets
     // will be selected by the following call of this->update_compatible_with_printer(true).
     prints.select_preset_by_name_strict(initial_print_profile_name);
-    filaments.select_preset_by_name_strict(initial_filament_profile_names.front());
+    filaments.select_preset_by_name_strict(initial_filament_profile_name);
     printers.select_preset_by_name(initial_printer_profile_name, true);
 
+    // Load the names of the other filament profiles selected for a multi-material printer.
+    auto   *nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(printers.get_selected_preset().config.option("nozzle_diameter"));
+    size_t  num_extruders = nozzle_diameter->values.size();
+    this->filament_presets = { initial_filament_profile_name };
+    for (unsigned int i = 1; i < (unsigned int)num_extruders; ++ i) {
+        char name[64];
+        sprintf(name, "filament_%d", i);
+        if (! config.has("presets", name))
+            break;
+        this->filament_presets.emplace_back(remove_ini_suffix(config.get("presets", name)));
+    }
+    // Do not define the missing filaments, so that the update_compatible_with_printer() will use the preferred filaments.
+    this->filament_presets.resize(num_extruders, "");
+
     // Update visibility of presets based on their compatibility with the active printer.
     // Always try to select a compatible print and filament preset to the current printer preset,
     // as the application may have been closed with an active "external" preset, which does not
     // exist.
     this->update_compatible_with_printer(true);
+    this->update_multi_material_filament_presets();
 }
 
 // Export selections (current print, current filaments, current printer) into config.ini
@@ -946,9 +948,7 @@ void PresetBundle::update_multi_material_filament_presets()
     for (size_t i = 0; i < std::min(this->filament_presets.size(), num_extruders); ++ i)
         this->filament_presets[i] = this->filaments.find_preset(this->filament_presets[i], true)->name;
     // Append the rest of filament presets.
-//    if (this->filament_presets.size() < num_extruders)
-        this->filament_presets.resize(num_extruders, this->filament_presets.empty() ? this->filaments.first_visible().name : this->filament_presets.back());
-
+    this->filament_presets.resize(num_extruders, this->filament_presets.empty() ? this->filaments.first_visible().name : this->filament_presets.back());
 
     // Now verify if wiping_volumes_matrix has proper size (it is used to deduce number of extruders in wipe tower generator):
     std::vector<double> old_matrix = this->project_config.option<ConfigOptionFloats>("wiping_volumes_matrix")->values;

From b682fb1829a870b5e95cecd9bf0a95967993ce99 Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Tue, 3 Jul 2018 12:19:34 +0200
Subject: [PATCH 13/15] Enabled "delete preset" button after current profile
 saving

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

diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp
index 8af00b2b6..9e0e4fc27 100644
--- a/xs/src/slic3r/GUI/Tab.cpp
+++ b/xs/src/slic3r/GUI/Tab.cpp
@@ -2134,6 +2134,8 @@ void Tab::save_preset(std::string name /*= ""*/)
 	update_tab_ui();
 	// Update the selection boxes at the platter.
 	on_presets_changed();
+	// If current profile is saved, "delete preset" button have to be enabled
+	m_btn_delete_preset->Enable(true);
 
 	if (m_name == "printer")
 		static_cast<TabPrinter*>(this)->m_initial_extruders_count = static_cast<TabPrinter*>(this)->m_extruders_count;

From bdc9b9daddbea905e55e5b89ecd11dcd2dd87266 Mon Sep 17 00:00:00 2001
From: bubnikv <bubnikv@gmail.com>
Date: Tue, 3 Jul 2018 16:46:52 +0200
Subject: [PATCH 14/15] Bumped up the version number.

---
 xs/src/libslic3r/libslic3r.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/xs/src/libslic3r/libslic3r.h b/xs/src/libslic3r/libslic3r.h
index a5926debe..253c340eb 100644
--- a/xs/src/libslic3r/libslic3r.h
+++ b/xs/src/libslic3r/libslic3r.h
@@ -14,7 +14,7 @@
 #include <boost/thread.hpp>
 
 #define SLIC3R_FORK_NAME "Slic3r Prusa Edition"
-#define SLIC3R_VERSION "1.40.1-rc"
+#define SLIC3R_VERSION "1.40.1-rc2"
 #define SLIC3R_BUILD "UNKNOWN"
 
 typedef int32_t coord_t;

From fa86d776cb78135e4ae3e07793a89b19e22d1224 Mon Sep 17 00:00:00 2001
From: bubnikv <bubnikv@gmail.com>
Date: Thu, 5 Jul 2018 15:27:48 +0200
Subject: [PATCH 15/15] Bumped up the version number to final.

---
 xs/src/libslic3r/libslic3r.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/xs/src/libslic3r/libslic3r.h b/xs/src/libslic3r/libslic3r.h
index 253c340eb..b0c144efe 100644
--- a/xs/src/libslic3r/libslic3r.h
+++ b/xs/src/libslic3r/libslic3r.h
@@ -14,7 +14,7 @@
 #include <boost/thread.hpp>
 
 #define SLIC3R_FORK_NAME "Slic3r Prusa Edition"
-#define SLIC3R_VERSION "1.40.1-rc2"
+#define SLIC3R_VERSION "1.40.1"
 #define SLIC3R_BUILD "UNKNOWN"
 
 typedef int32_t coord_t;