From c857b68fbebec2745ea7f10654585c16eba14e54 Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Wed, 30 May 2018 17:52:28 +0200
Subject: [PATCH] Functions "Add/Delete" objects to/from list works correct now

---
 xs/src/slic3r/GUI/GUI.cpp          | 34 ++++++++++++++++--------
 xs/src/slic3r/GUI/GUI.hpp          |  4 +++
 xs/src/slic3r/GUI/wxExtensions.cpp | 42 +++++++++++++++++++-----------
 xs/src/slic3r/GUI/wxExtensions.hpp |  8 +++---
 xs/xsp/GUI.xsp                     |  6 +++++
 5 files changed, 64 insertions(+), 30 deletions(-)

diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp
index 296dd7691..77a1a54b8 100644
--- a/xs/src/slic3r/GUI/GUI.cpp
+++ b/xs/src/slic3r/GUI/GUI.cpp
@@ -917,15 +917,18 @@ wxBoxSizer* content_edit_object_buttons(wxWindow* win)
 	{
 		auto item = m_objects_ctrl->GetSelection();
 		if (!item) return;
+		if (m_objects_model->GetParent(item) != wxDataViewItem(0))
+			item = m_objects_model->GetParent(item);
+		if (!item) return;
 		wxString name = "Part";
-		m_objects_model->AddChild(item, name);
+		m_objects_ctrl->Select(m_objects_model->AddChild(item, name));
 	});
 
 	btn_delete->Bind(wxEVT_BUTTON, [](wxEvent&)
 	{
 		auto item = m_objects_ctrl->GetSelection();
 		if (!item) return;
-		m_objects_model->Delete(item);
+		m_objects_ctrl->Select(m_objects_model->Delete(item));
 	});
 	//***
 
@@ -1035,6 +1038,22 @@ wxBoxSizer* content_settings(wxWindow *win)
 	return sizer;
 }
 
+void add_object(const std::string &name)
+{
+	wxString item = name;
+	m_objects_ctrl->Select(m_objects_model->Add(item));
+}
+
+void del_object()
+{
+	auto item = m_objects_ctrl->GetSelection();
+	if (!item) return;
+	m_objects_ctrl->Select(m_objects_model->Delete(item));
+
+	if (m_objects_model->IsEmpty())
+		m_collpane_settings->show_it(false);
+}
+
 void add_expert_mode_part(wxWindow* parent, wxBoxSizer* sizer)
 {
 	wxWindowUpdateLocker noUpdates(parent);
@@ -1073,17 +1092,10 @@ void add_expert_mode_part(wxWindow* parent, wxBoxSizer* sizer)
 	add_btn->Bind(wxEVT_BUTTON, [](wxEvent& )
 	{
 		wxString name = "Object";
-		m_objects_model->Add(name);
+		m_objects_ctrl->Select(m_objects_model->Add(name));
 	});
 
-	del_btn->Bind(wxEVT_BUTTON, [](wxEvent& )
-	{
-		auto item = m_objects_ctrl->GetSelection();
-		if (!item) return;
-		m_objects_model->Delete(item);
-		if (m_objects_model->IsEmpty())
-			m_collpane_settings->show_it(false);
-	});
+	del_btn->Bind(wxEVT_BUTTON, [](wxEvent& ) { del_object(); });
 
 	// More experiments with UI
 // 	auto listctrl = new wxDataViewListCtrl(main_page, wxID_ANY, wxDefaultPosition, wxSize(-1, 100));
diff --git a/xs/src/slic3r/GUI/GUI.hpp b/xs/src/slic3r/GUI/GUI.hpp
index 19ee54533..79dc2c595 100644
--- a/xs/src/slic3r/GUI/GUI.hpp
+++ b/xs/src/slic3r/GUI/GUI.hpp
@@ -174,6 +174,10 @@ wxString	L_str(const std::string &str);
 // Return wxString from std::string in UTF8
 wxString	from_u8(const std::string &str);
 
+// Add object to the list
+void add_object(const std::string &name);
+// Delete object from the list
+void del_object();
 
 void add_expert_mode_part(wxWindow* parent, wxBoxSizer* sizer);
 void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFlexGridSizer* preset_sizer);
diff --git a/xs/src/slic3r/GUI/wxExtensions.cpp b/xs/src/slic3r/GUI/wxExtensions.cpp
index 84953ebaa..ecb79caaf 100644
--- a/xs/src/slic3r/GUI/wxExtensions.cpp
+++ b/xs/src/slic3r/GUI/wxExtensions.cpp
@@ -352,20 +352,21 @@ bool PrusaCollapsiblePane::Layout()
 // MyObjectTreeModel
 // ----------------------------------------------------------------------------
 
-void MyObjectTreeModel::Add(wxString &name)
+wxDataViewItem MyObjectTreeModel::Add(wxString &name)
 {
 	auto root = new MyObjectTreeModelNode(name);
-	m_objects.emplace(root);
+	m_objects.push_back(root);
 	// notify control
 	wxDataViewItem child((void*)root);
 	wxDataViewItem parent((void*)NULL);
 	ItemAdded(parent, child);
+	return child;
 }
 
-void MyObjectTreeModel::AddChild(const wxDataViewItem &parent_item, wxString &name)
+wxDataViewItem MyObjectTreeModel::AddChild(const wxDataViewItem &parent_item, wxString &name)
 {
 	MyObjectTreeModelNode *root = (MyObjectTreeModelNode*)parent_item.GetID();
-	if (!root) return;
+	if (!root) return wxDataViewItem(0);
 
 	if (root->GetChildren().Count() == 0)
 	{
@@ -381,13 +382,15 @@ void MyObjectTreeModel::AddChild(const wxDataViewItem &parent_item, wxString &na
 	// notify control
 	wxDataViewItem child((void*)node);
 	ItemAdded(parent_item, child);
+	return child;
 }
 
-void MyObjectTreeModel::Delete(const wxDataViewItem &item)
+wxDataViewItem MyObjectTreeModel::Delete(const wxDataViewItem &item)
 {
+	auto ret_item = wxDataViewItem(0);
 	MyObjectTreeModelNode *node = (MyObjectTreeModelNode*)item.GetID();
 	if (!node)      // happens if item.IsOk()==false
-		return;
+		return ret_item;
 
 	auto node_parent = node->GetParent();
 	wxDataViewItem parent(node_parent);
@@ -395,23 +398,37 @@ void MyObjectTreeModel::Delete(const wxDataViewItem &item)
 	// first remove the node from the parent's array of children;
 	// NOTE: MyObjectTreeModelNodePtrArray is only an array of _pointers_
 	//       thus removing the node from it doesn't result in freeing it
-	if (node_parent)
+	if (node_parent){
+		auto id = node_parent->GetChildren().Index(node);
 		node_parent->GetChildren().Remove(node);
+		if (id > 0){ 
+			if(id == node_parent->GetChildCount()) id--;
+			ret_item = wxDataViewItem(node_parent->GetChildren().Item(id));
+		}
+	}
 	else
 	{
-		auto it = m_objects.find(node);
+		auto it = find(m_objects.begin(), m_objects.end(), node);
+		auto id = it - m_objects.begin();
 		if (it != m_objects.end())
 			m_objects.erase(it);
+		if (id > 0){ 
+			if(id == m_objects.size()) id--;
+			ret_item = wxDataViewItem(m_objects[id]);
+		}
 	}
 	// free the node
 	delete node;
 
 	// set m_containet to FALSE if parent has no child
-	if (node_parent && node_parent->GetChildCount() == 0)
+	if (node_parent && node_parent->GetChildCount() == 0){
 		node_parent->m_container = false;
+		ret_item = parent;
+	}
 
 	// notify control
 	ItemDeleted(parent, item);
+	return ret_item;
 }
 
 wxString MyObjectTreeModel::GetName(const wxDataViewItem &item) const
@@ -441,11 +458,6 @@ wxString MyObjectTreeModel::GetScale(const wxDataViewItem &item) const
 	return node->m_scale;
 }
 
-// void MyObjectTreeModel::Delete(const wxDataViewItem &item)
-// {
-// 
-// }
-
 void MyObjectTreeModel::GetValue(wxVariant &variant, const wxDataViewItem &item, unsigned int col) const
 {
 	wxASSERT(item.IsOk());
@@ -504,7 +516,7 @@ wxDataViewItem MyObjectTreeModel::GetParent(const wxDataViewItem &item) const
 	MyObjectTreeModelNode *node = (MyObjectTreeModelNode*)item.GetID();
 
 	// objects nodes has no parent too
-	if (m_objects.find(node) != m_objects.end())
+	if (find(m_objects.begin(), m_objects.end(),node) != m_objects.end())
 		return wxDataViewItem(0);
 
 	return wxDataViewItem((void*)node->GetParent());
diff --git a/xs/src/slic3r/GUI/wxExtensions.hpp b/xs/src/slic3r/GUI/wxExtensions.hpp
index cabd1e7ca..329eecd59 100644
--- a/xs/src/slic3r/GUI/wxExtensions.hpp
+++ b/xs/src/slic3r/GUI/wxExtensions.hpp
@@ -207,7 +207,7 @@ public:
 
 class MyObjectTreeModel :public wxDataViewModel
 {
-	std::set<MyObjectTreeModelNode*> m_objects;
+	std::vector<MyObjectTreeModelNode*> m_objects;
 public:
 	MyObjectTreeModel(){}
 	~MyObjectTreeModel()
@@ -216,9 +216,9 @@ public:
 			delete object;		
 	}
 
-	void Add(wxString &name);
-	void AddChild(const wxDataViewItem &parent_item, wxString &name);
- 	void Delete(const wxDataViewItem &item);
+	wxDataViewItem Add(wxString &name);
+	wxDataViewItem AddChild(const wxDataViewItem &parent_item, wxString &name);
+	wxDataViewItem Delete(const wxDataViewItem &item);
 	bool IsEmpty() { return m_objects.empty(); }
 
 	// helper method for wxLog
diff --git a/xs/xsp/GUI.xsp b/xs/xsp/GUI.xsp
index f7d84d87c..905954172 100644
--- a/xs/xsp/GUI.xsp
+++ b/xs/xsp/GUI.xsp
@@ -122,6 +122,12 @@ void set_show_manifold_warning_icon(bool show)
 void update_mode()
     %code%{ Slic3r::GUI::update_mode(); %};
 
+void add_object(const char *name)
+    %code%{ Slic3r::GUI::add_object(name); %};
+
+void del_object()
+    %code%{ Slic3r::GUI::del_object(); %};
+
 std::string fold_utf8_to_ascii(const char *src)
     %code%{ RETVAL = Slic3r::fold_utf8_to_ascii(src); %};