From f985f5190c8260b28b1a3d06d20138ee16113dad Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Tue, 9 Jul 2019 20:45:00 +0200
Subject: [PATCH] Completed undo/redo from a toolbar

---
 src/slic3r/GUI/GLCanvas3D.cpp |  2 +-
 src/slic3r/GUI/Plater.cpp     | 48 ++++++++++++++++++++++++++++++++---
 src/slic3r/GUI/Plater.hpp     |  2 ++
 3 files changed, 47 insertions(+), 5 deletions(-)

diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index dc59f4e5b..d87b97f53 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -3492,7 +3492,7 @@ void GLCanvas3D::_render_undo_redo_stack(const bool is_undo, float pos_x)
         if (imgui->undo_redo_list(ImVec2(12 * em, 20 * em), is_undo, &string_getter, hovered, selected))
             m_toolbar.set_imgui_hovered_pos(hovered);
         if (selected >= 0)
-            m_toolbar.hide_imgui(is_undo);
+            is_undo ? wxGetApp().plater()->undo_to(selected) : wxGetApp().plater()->redo_to(selected);
 
         imgui->text(wxString::Format(_(L("%s %d Action")), stack_name, hovered + 1));
 
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index 3dfc1d1b8..a450ac0e5 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -1583,8 +1583,11 @@ struct Plater::priv
 
 	void take_snapshot(const std::string& snapshot_name) { this->undo_redo_stack.take_snapshot(snapshot_name, model, view3D->get_canvas3d()->get_selection()); }
 	void take_snapshot(const wxString& snapshot_name) { this->take_snapshot(std::string(snapshot_name.ToUTF8().data())); }
+    int  get_active_snapshot_index();
     void undo();
     void redo();
+    void undo_to(size_t time_to_load);
+    void redo_to(size_t time_to_load);
 
     bool background_processing_enabled() const { return this->get_config("background_processing") == "1"; }
     void update_print_volume_state();
@@ -3560,6 +3563,14 @@ void Plater::priv::show_action_buttons(const bool is_ready_to_slice) const
 	}
 }
 
+int Plater::priv::get_active_snapshot_index()
+{
+    const size_t& active_snapshot_time = this->undo_redo_stack.active_snapshot_time();
+    const std::vector<UndoRedo::Snapshot>& ss_stack = this->undo_redo_stack.snapshots();
+    const auto it = std::lower_bound(ss_stack.begin(), ss_stack.end(), UndoRedo::Snapshot(active_snapshot_time));
+    return it - ss_stack.begin();
+}
+
 void Plater::priv::undo()
 {
 	if (this->undo_redo_stack.undo(model, this->view3D->get_canvas3d()->get_selection()))
@@ -3572,6 +3583,18 @@ void Plater::priv::redo()
 		this->update_after_undo_redo();
 }
 
+void Plater::priv::undo_to(size_t time_to_load)
+{
+	if (this->undo_redo_stack.undo(model, this->view3D->get_canvas3d()->get_selection(), time_to_load))
+		this->update_after_undo_redo();
+}
+
+void Plater::priv::redo_to(size_t time_to_load)
+{ 
+	if (this->undo_redo_stack.redo(model, time_to_load))
+		this->update_after_undo_redo();
+}
+
 void Plater::priv::update_after_undo_redo()
 {
 	this->view3D->get_canvas3d()->get_selection().clear();
@@ -4110,13 +4133,30 @@ void Plater::take_snapshot(const std::string &snapshot_name) { p->take_snapshot(
 void Plater::take_snapshot(const wxString &snapshot_name) { p->take_snapshot(snapshot_name); }
 void Plater::undo() { p->undo(); }
 void Plater::redo() { p->redo(); }
+void Plater::undo_to(int selection)
+{
+    if (selection == 0) {
+        p->undo();
+        return;
+    }
+    
+    const int idx = p->get_active_snapshot_index() - selection - 1;
+    p->undo_to(p->undo_redo_stack.snapshots()[idx].timestamp);
+}
+void Plater::redo_to(int selection)
+{
+    if (selection == 0) {
+        p->redo();
+        return;
+    }
+    
+    const int idx = selection + p->get_active_snapshot_index();
+    p->redo_to(p->undo_redo_stack.snapshots()[idx].timestamp);
+}
 bool Plater::undo_redo_string_getter(const bool is_undo, int idx, const char** out_text)
 {
-    const size_t& active_snapshot_time = p->undo_redo_stack.active_snapshot_time();
     const std::vector<UndoRedo::Snapshot>& ss_stack = p->undo_redo_stack.snapshots();
-    const auto it = std::lower_bound(ss_stack.begin(), ss_stack.end(), UndoRedo::Snapshot(active_snapshot_time));
-
-    const int idx_in_ss_stack = it - ss_stack.begin() + (is_undo ? -(++idx) : idx);
+    const int idx_in_ss_stack = p->get_active_snapshot_index() + (is_undo ? -(++idx) : idx);
 
     if (0 < idx_in_ss_stack && idx_in_ss_stack < ss_stack.size() - 1) {
         *out_text = ss_stack[idx_in_ss_stack].name.c_str();
diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp
index 7f379c638..ca3d59224 100644
--- a/src/slic3r/GUI/Plater.hpp
+++ b/src/slic3r/GUI/Plater.hpp
@@ -187,6 +187,8 @@ public:
     void take_snapshot(const wxString &snapshot_name);
     void undo();
     void redo();
+    void undo_to(int selection);
+    void redo_to(int selection);
     bool undo_redo_string_getter(const bool is_undo, int idx, const char** out_text);
 
     void on_extruders_change(int extruders_count);