From 3e0ff5e9efe545493e20837269ba96b8834a244c Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Thu, 14 Jun 2018 21:48:06 +0200
Subject: [PATCH] Added LambdaObjectDialog

---
 xs/CMakeLists.txt                        |   2 +
 xs/src/slic3r/GUI/GUI.cpp                |   7 ++
 xs/src/slic3r/GUI/GUI.hpp                |  11 ++
 xs/src/slic3r/GUI/GUI_ObjectParts.cpp    |  26 ++--
 xs/src/slic3r/GUI/GUI_ObjectParts.hpp    |   2 +-
 xs/src/slic3r/GUI/LambdaObjectDialog.cpp | 151 +++++++++++++++++++++++
 xs/src/slic3r/GUI/LambdaObjectDialog.hpp |  34 +++++
 7 files changed, 220 insertions(+), 13 deletions(-)
 create mode 100644 xs/src/slic3r/GUI/LambdaObjectDialog.cpp
 create mode 100644 xs/src/slic3r/GUI/LambdaObjectDialog.hpp

diff --git a/xs/CMakeLists.txt b/xs/CMakeLists.txt
index 8555fb015..46072b091 100644
--- a/xs/CMakeLists.txt
+++ b/xs/CMakeLists.txt
@@ -194,6 +194,8 @@ add_library(libslic3r_gui STATIC
     ${LIBDIR}/slic3r/GUI/GUI.hpp
     ${LIBDIR}/slic3r/GUI/GUI_ObjectParts.cpp
     ${LIBDIR}/slic3r/GUI/GUI_ObjectParts.hpp
+    ${LIBDIR}/slic3r/GUI/LambdaObjectDialog.cpp
+    ${LIBDIR}/slic3r/GUI/LambdaObjectDialog.hpp
     ${LIBDIR}/slic3r/GUI/Tab.cpp
     ${LIBDIR}/slic3r/GUI/Tab.hpp
     ${LIBDIR}/slic3r/GUI/TabIface.cpp
diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp
index 46e1a96d6..6b4195e94 100644
--- a/xs/src/slic3r/GUI/GUI.cpp
+++ b/xs/src/slic3r/GUI/GUI.cpp
@@ -60,6 +60,7 @@
 #include "../Utils/PresetUpdater.hpp"
 #include "../Config/Snapshot.hpp"
 #include "Model.hpp"
+#include "LambdaObjectDialog.hpp"
 
 
 namespace Slic3r { namespace GUI {
@@ -1025,6 +1026,12 @@ wxBoxSizer* content_edit_object_buttons(wxWindow* win)
 		on_btn_load(win, true);
 	});
 
+	btn_load_lambda_modifier->Bind(wxEVT_BUTTON, [win](wxEvent&)
+	{
+		auto dlg = new LambdaObjectDialog(win);
+		dlg->ShowModal();
+	});
+
 	btn_delete->Bind(wxEVT_BUTTON, [](wxEvent&)
 	{
 		auto item = m_objects_ctrl->GetSelection();
diff --git a/xs/src/slic3r/GUI/GUI.hpp b/xs/src/slic3r/GUI/GUI.hpp
index 5c5a1a6a9..12eef0b62 100644
--- a/xs/src/slic3r/GUI/GUI.hpp
+++ b/xs/src/slic3r/GUI/GUI.hpp
@@ -89,6 +89,17 @@ inline t_file_wild_card& get_file_wild_card() {
 	return FILE_WILDCARDS;
 }
 
+struct OBJECT_PARAMETERS
+{
+	std::string	type = "box";
+	double dim[3];// = { 1.0, 1.0, 1.0 };
+	int	cyl_r = 1;
+	int	cyl_h = 1;
+	double sph_rho = 1.0;
+	double slab_h = 1.0;
+	double slab_z = 0.0;
+};
+
 void disable_screensaver();
 void enable_screensaver();
 bool debugged();
diff --git a/xs/src/slic3r/GUI/GUI_ObjectParts.cpp b/xs/src/slic3r/GUI/GUI_ObjectParts.cpp
index 57d46c977..2f88b58f7 100644
--- a/xs/src/slic3r/GUI/GUI_ObjectParts.cpp
+++ b/xs/src/slic3r/GUI/GUI_ObjectParts.cpp
@@ -55,8 +55,6 @@ void load_part(wxWindow* parent, ModelObject* model_object, wxArrayString& part_
 			}
 		}
 	}
-
-	parts_changed();
 }
 
 void on_btn_load(wxWindow* parent, bool is_modifier /*= false*/)
@@ -77,21 +75,25 @@ void on_btn_load(wxWindow* parent, bool is_modifier /*= false*/)
 	ModelObjectPtrs& objects = get_objects();
 	load_part(parent, objects[obj_idx], part_names, is_modifier);
 
-	auto event = get_event_object_settings_changed();
-	if (event > 0) {
-		wxCommandEvent e(event);
-		auto event_str = wxString::Format("%d %d %d", obj_idx,
-			is_parts_changed() ? 1 : 0,
-			is_part_settings_changed() ? 1 : 0);
-		e.SetString(event_str);
-		get_main_frame()->ProcessWindowEvent(e);
-	}
+	parts_changed(obj_idx);
 
 	for (int i = 0; i < part_names.size(); ++i)
 		objects_ctrl->Select(objects_model->AddChild(item, part_names.Item(i)));
 }
 
-void parts_changed(){ ; }
+void parts_changed(int obj_idx)
+{ 
+	auto event = get_event_object_settings_changed();
+	if (event <= 0)
+		return;
+
+	wxCommandEvent e(event);
+	auto event_str = wxString::Format("%d %d %d", obj_idx,
+		is_parts_changed() ? 1 : 0,
+		is_part_settings_changed() ? 1 : 0);
+	e.SetString(event_str);
+	get_main_frame()->ProcessWindowEvent(e);
+}
 
 } //namespace GUI
 } //namespace Slic3r 
\ No newline at end of file
diff --git a/xs/src/slic3r/GUI/GUI_ObjectParts.hpp b/xs/src/slic3r/GUI/GUI_ObjectParts.hpp
index 9ee982b96..cf07bb242 100644
--- a/xs/src/slic3r/GUI/GUI_ObjectParts.hpp
+++ b/xs/src/slic3r/GUI/GUI_ObjectParts.hpp
@@ -11,7 +11,7 @@ bool is_part_settings_changed();
 void load_part(	wxWindow* parent, ModelObject* model_object, 
 				wxArrayString& part_names, bool is_modifier); 
 void on_btn_load(wxWindow* parent, bool is_modifier = false);
-void parts_changed();		
+void parts_changed(int obj_idx);
 } //namespace GUI
 } //namespace Slic3r 
 #endif  //slic3r_GUI_ObjectParts_hpp_
\ No newline at end of file
diff --git a/xs/src/slic3r/GUI/LambdaObjectDialog.cpp b/xs/src/slic3r/GUI/LambdaObjectDialog.cpp
new file mode 100644
index 000000000..5657c7a71
--- /dev/null
+++ b/xs/src/slic3r/GUI/LambdaObjectDialog.cpp
@@ -0,0 +1,151 @@
+#include "LambdaObjectDialog.hpp"
+
+#include <wx/window.h>
+#include <wx/button.h>
+#include "OptionsGroup.hpp"
+
+namespace Slic3r
+{
+namespace GUI
+{
+static wxString dots("…", wxConvUTF8);
+
+LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent)
+{
+	Create(parent, wxID_ANY, _(L("Lambda Object")),
+		wxDefaultPosition, wxSize(500, 500),
+		wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
+
+	// instead of double dim[3] = { 1.0, 1.0, 1.0 };
+	object_parameters.dim[0] = 1.0;
+	object_parameters.dim[1] = 1.0;
+	object_parameters.dim[2] = 1.0;
+
+	sizer = new wxBoxSizer(wxVERTICAL);
+
+	// modificator options
+	m_modificator_options_book = new wxChoicebook(this, wxID_ANY, wxDefaultPosition, wxSize(300, -1), wxCHB_TOP);
+	sizer->Add(m_modificator_options_book, 1, wxEXPAND| wxALL, 10);
+
+	auto optgroup = init_modificator_options_page(_(L("Box")));
+		optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){
+			int opt_id =	opt_key == "L" ? 0 :
+							opt_key == "W" ? 1 : 
+							opt_key == "L" ? 2 : -1;
+			if (opt_id < 0) return;
+			object_parameters.dim[opt_id] = boost::any_cast<double>(value);
+		};
+
+		ConfigOptionDef def;
+		def.type = coFloat;
+		def.default_value = new ConfigOptionFloat{ 1.0 };
+		def.label = L("L");
+		Option option(def, "l");
+		optgroup->append_single_option_line(option);
+		
+		def.label = L("W");
+		option = Option(def, "w");
+		optgroup->append_single_option_line(option);
+		
+		def.label = L("H");
+		option = Option(def, "h");
+		optgroup->append_single_option_line(option);
+
+	optgroup = init_modificator_options_page(_(L("Cylinder")));
+		optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){
+			int val = boost::any_cast<int>(value);
+			if (opt_key == "cyl_r")
+				object_parameters.cyl_r = val;
+			else if (opt_key == "cyl_h")
+				object_parameters.cyl_h = val;
+			else return;
+		};
+
+		def.type = coInt;
+		def.default_value = new ConfigOptionInt{ 1 };
+		def.label = L("Radius");
+		option = Option(def, "cyl_r");
+		optgroup->append_single_option_line(option);
+
+		def.label = L("Height");
+		option = Option(def, "cyl_h");
+		optgroup->append_single_option_line(option);
+
+	optgroup = init_modificator_options_page(_(L("Sphere")));
+		optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){
+			if (opt_key == "sph_rho")
+				object_parameters.sph_rho = boost::any_cast<double>(value);
+			else return;
+		};
+
+		def.type = coFloat;
+		def.default_value = new ConfigOptionFloat{ 1.0 };
+		def.label = L("Rho");
+		option = Option(def, "sph_rho");
+		optgroup->append_single_option_line(option);
+
+	optgroup = init_modificator_options_page(_(L("Slab")));
+		optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){
+			double val = boost::any_cast<double>(value);
+			if (opt_key == "slab_z")
+				object_parameters.slab_z = val;
+			else if (opt_key == "slab_h")
+				object_parameters.slab_h = val;
+			else return;
+		};
+
+		def.label = L("H");
+		option = Option(def, "slab_h");
+		optgroup->append_single_option_line(option);
+
+		def.label = L("Initial Z");
+		option = Option(def, "slab_z");
+		optgroup->append_single_option_line(option);
+
+
+	auto button_sizer = CreateStdDialogButtonSizer(wxOK | wxCANCEL);
+
+	wxButton* btn_OK = static_cast<wxButton*>(FindWindowById(wxID_OK, this));
+	btn_OK->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) {
+		// validate user input
+		if (!CanClose())return;
+		EndModal(wxID_OK);
+		Destroy();
+	});
+
+	wxButton* btn_CANCEL = static_cast<wxButton*>(FindWindowById(wxID_CANCEL, this));
+	btn_CANCEL->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) {
+		// validate user input
+		if (!CanClose())return;
+		EndModal(wxID_CANCEL);
+		Destroy();
+	});
+
+	sizer->Add(button_sizer, 0, wxALIGN_CENTER_HORIZONTAL | wxBOTTOM, 10);
+
+	SetSizer(sizer);
+	sizer->Fit(this);
+	sizer->SetSizeHints(this);
+}
+
+// Called from the constructor.
+// Create a panel for a rectangular / circular / custom bed shape.
+ConfigOptionsGroupShp LambdaObjectDialog::init_modificator_options_page(wxString title){
+
+	auto panel = new wxPanel(m_modificator_options_book);
+
+	ConfigOptionsGroupShp optgroup;
+	optgroup = std::make_shared<ConfigOptionsGroup>(panel, _(L("Add")) + " " +title + " " +dots);
+	optgroup->label_width = 100;
+
+	m_optgroups.push_back(optgroup);
+
+	panel->SetSizerAndFit(optgroup->sizer);
+	m_modificator_options_book->AddPage(panel, title);
+
+	return optgroup;
+}
+
+
+} //namespace GUI
+} //namespace Slic3r 
diff --git a/xs/src/slic3r/GUI/LambdaObjectDialog.hpp b/xs/src/slic3r/GUI/LambdaObjectDialog.hpp
new file mode 100644
index 000000000..712722b2d
--- /dev/null
+++ b/xs/src/slic3r/GUI/LambdaObjectDialog.hpp
@@ -0,0 +1,34 @@
+#ifndef slic3r_LambdaObjectDialog_hpp_
+#define slic3r_LambdaObjectDialog_hpp_
+
+#include "GUI.hpp"
+
+#include <wx/dialog.h>
+#include <wx/sizer.h>
+#include <wx/choicebk.h>
+
+namespace Slic3r
+{
+namespace GUI
+{
+using ConfigOptionsGroupShp = std::shared_ptr<ConfigOptionsGroup>;
+class LambdaObjectDialog : public wxDialog
+{
+	wxChoicebook*	m_modificator_options_book;
+	std::vector <ConfigOptionsGroupShp>	m_optgroups;
+public:
+	LambdaObjectDialog(wxWindow* parent);
+	~LambdaObjectDialog(){}
+
+	bool CanClose() { return true; }	// ???
+
+	ConfigOptionsGroupShp init_modificator_options_page(wxString title);
+	
+	// Note whether the window was already closed, so a pending update is not executed.
+	bool m_already_closed = false;
+	OBJECT_PARAMETERS object_parameters;
+	wxBoxSizer* sizer = nullptr;
+};
+} //namespace GUI
+} //namespace Slic3r 
+#endif  //slic3r_LambdaObjectDialog_hpp_