From 770d944283cda7c90ea7aa614be824aaa3de3519 Mon Sep 17 00:00:00 2001
From: Vojtech Kral <vojtech@kral.hk>
Date: Wed, 3 Oct 2018 11:34:39 +0200
Subject: [PATCH] Replace PerlCallbacks with events in GLCanvas3d et al.

---
 src/slic3r/GUI/3DScene.cpp           | 186 --------------
 src/slic3r/GUI/3DScene.hpp           |  36 ---
 src/slic3r/GUI/Event.hpp             |  55 ++++
 src/slic3r/GUI/GLCanvas3D.cpp        | 371 +++++----------------------
 src/slic3r/GUI/GLCanvas3D.hpp        | 128 ++++-----
 src/slic3r/GUI/GLCanvas3DManager.cpp | 240 -----------------
 src/slic3r/GUI/GLCanvas3DManager.hpp |  41 +--
 src/slic3r/GUI/GLToolbar.cpp         |  20 +-
 src/slic3r/GUI/GLToolbar.hpp         |  23 +-
 src/slic3r/GUI/GUI_Preview.cpp       |   6 -
 src/slic3r/GUI/GUI_Preview.hpp       |   3 +-
 src/slic3r/GUI/GUI_PreviewIface.cpp  |   5 -
 src/slic3r/GUI/GUI_PreviewIface.hpp  |   1 -
 src/slic3r/GUI/Plater.cpp            |  15 +-
 14 files changed, 197 insertions(+), 933 deletions(-)
 create mode 100644 src/slic3r/GUI/Event.hpp

diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp
index 744275e22..44a068303 100644
--- a/src/slic3r/GUI/3DScene.cpp
+++ b/src/slic3r/GUI/3DScene.cpp
@@ -2045,192 +2045,6 @@ void _3DScene::set_toolpaths_range(wxGLCanvas* canvas, double low, double high)
     s_canvas_mgr.set_toolpaths_range(canvas, low, high);
 }
 
-void _3DScene::register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback)
-{
-    s_canvas_mgr.register_on_viewport_changed_callback(canvas, callback);
-}
-
-void _3DScene::register_on_double_click_callback(wxGLCanvas* canvas, void* callback)
-{
-    s_canvas_mgr.register_on_double_click_callback(canvas, callback);
-}
-
-void _3DScene::register_on_right_click_callback(wxGLCanvas* canvas, void* callback)
-{
-    s_canvas_mgr.register_on_right_click_callback(canvas, callback);
-}
-
-void _3DScene::register_on_select_object_callback(wxGLCanvas* canvas, void* callback)
-{
-    s_canvas_mgr.register_on_select_object_callback(canvas, callback);
-}
-
-void _3DScene::register_on_model_update_callback(wxGLCanvas* canvas, void* callback)
-{
-    s_canvas_mgr.register_on_model_update_callback(canvas, callback);
-}
-
-void _3DScene::register_on_remove_object_callback(wxGLCanvas* canvas, void* callback)
-{
-    s_canvas_mgr.register_on_remove_object_callback(canvas, callback);
-}
-
-void _3DScene::register_on_arrange_callback(wxGLCanvas* canvas, void* callback)
-{
-    s_canvas_mgr.register_on_arrange_callback(canvas, callback);
-}
-
-void _3DScene::register_on_rotate_object_left_callback(wxGLCanvas* canvas, void* callback)
-{
-    s_canvas_mgr.register_on_rotate_object_left_callback(canvas, callback);
-}
-
-void _3DScene::register_on_rotate_object_right_callback(wxGLCanvas* canvas, void* callback)
-{
-    s_canvas_mgr.register_on_rotate_object_right_callback(canvas, callback);
-}
-
-void _3DScene::register_on_scale_object_uniformly_callback(wxGLCanvas* canvas, void* callback)
-{
-    s_canvas_mgr.register_on_scale_object_uniformly_callback(canvas, callback);
-}
-
-void _3DScene::register_on_increase_objects_callback(wxGLCanvas* canvas, void* callback)
-{
-    s_canvas_mgr.register_on_increase_objects_callback(canvas, callback);
-}
-
-void _3DScene::register_on_decrease_objects_callback(wxGLCanvas* canvas, void* callback)
-{
-    s_canvas_mgr.register_on_decrease_objects_callback(canvas, callback);
-}
-
-void _3DScene::register_on_instance_moved_callback(wxGLCanvas* canvas, void* callback)
-{
-    s_canvas_mgr.register_on_instance_moved_callback(canvas, callback);
-}
-
-void _3DScene::register_on_wipe_tower_moved_callback(wxGLCanvas* canvas, void* callback)
-{
-    s_canvas_mgr.register_on_wipe_tower_moved_callback(canvas, callback);
-}
-
-void _3DScene::register_on_enable_action_buttons_callback(wxGLCanvas* canvas, void* callback)
-{
-    s_canvas_mgr.register_on_enable_action_buttons_callback(canvas, callback);
-}
-
-void _3DScene::register_on_gizmo_scale_uniformly_callback(wxGLCanvas* canvas, void* callback)
-{
-#if !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-    s_canvas_mgr.register_on_gizmo_scale_uniformly_callback(canvas, callback);
-#endif // !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-}
-
-void _3DScene::register_on_gizmo_scale_3D_callback(wxGLCanvas* canvas, void* callback)
-{
-#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-    s_canvas_mgr.register_on_gizmo_scale_3D_callback(canvas, callback);
-#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-}
-
-void _3DScene::register_on_gizmo_rotate_callback(wxGLCanvas* canvas, void* callback)
-{
-#if !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-    s_canvas_mgr.register_on_gizmo_rotate_callback(canvas, callback);
-#endif // !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-}
-
-void _3DScene::register_on_gizmo_rotate_3D_callback(wxGLCanvas* canvas, void* callback)
-{
-#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-    s_canvas_mgr.register_on_gizmo_rotate_3D_callback(canvas, callback);
-#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-}
-
-void _3DScene::register_on_gizmo_flatten_callback(wxGLCanvas* canvas, void* callback)
-{
-#if !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-    s_canvas_mgr.register_on_gizmo_flatten_callback(canvas, callback);
-#endif // !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-}
-
-void _3DScene::register_on_gizmo_flatten_3D_callback(wxGLCanvas* canvas, void* callback)
-{
-#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-    s_canvas_mgr.register_on_gizmo_flatten_3D_callback(canvas, callback);
-#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-}
-
-void _3DScene::register_on_update_geometry_info_callback(wxGLCanvas* canvas, void* callback)
-{
-#if !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-    s_canvas_mgr.register_on_update_geometry_info_callback(canvas, callback);
-#endif // !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-}
-
-void _3DScene::register_on_update_geometry_3D_info_callback(wxGLCanvas* canvas, void* callback)
-{
-#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-    s_canvas_mgr.register_on_update_geometry_3D_info_callback(canvas, callback);
-#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-}
-
-void _3DScene::register_action_add_callback(wxGLCanvas* canvas, void* callback)
-{
-    s_canvas_mgr.register_action_add_callback(canvas, callback);
-}
-
-void _3DScene::register_action_delete_callback(wxGLCanvas* canvas, void* callback)
-{
-    s_canvas_mgr.register_action_delete_callback(canvas, callback);
-}
-
-void _3DScene::register_action_deleteall_callback(wxGLCanvas* canvas, void* callback)
-{
-    s_canvas_mgr.register_action_deleteall_callback(canvas, callback);
-}
-
-void _3DScene::register_action_arrange_callback(wxGLCanvas* canvas, void* callback)
-{
-    s_canvas_mgr.register_action_arrange_callback(canvas, callback);
-}
-
-void _3DScene::register_action_more_callback(wxGLCanvas* canvas, void* callback)
-{
-    s_canvas_mgr.register_action_more_callback(canvas, callback);
-}
-
-void _3DScene::register_action_fewer_callback(wxGLCanvas* canvas, void* callback)
-{
-    s_canvas_mgr.register_action_fewer_callback(canvas, callback);
-}
-
-void _3DScene::register_action_split_callback(wxGLCanvas* canvas, void* callback)
-{
-    s_canvas_mgr.register_action_split_callback(canvas, callback);
-}
-
-void _3DScene::register_action_cut_callback(wxGLCanvas* canvas, void* callback)
-{
-    s_canvas_mgr.register_action_cut_callback(canvas, callback);
-}
-
-void _3DScene::register_action_settings_callback(wxGLCanvas* canvas, void* callback)
-{
-    s_canvas_mgr.register_action_settings_callback(canvas, callback);
-}
-
-void _3DScene::register_action_layersediting_callback(wxGLCanvas* canvas, void* callback)
-{
-    s_canvas_mgr.register_action_layersediting_callback(canvas, callback);
-}
-
-void _3DScene::register_action_selectbyparts_callback(wxGLCanvas* canvas, void* callback)
-{
-    s_canvas_mgr.register_action_selectbyparts_callback(canvas, callback);
-}
-
 static inline int hex_digit_to_int(const char c)
 {
     return 
diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp
index a5f4c5189..971083ab6 100644
--- a/src/slic3r/GUI/3DScene.hpp
+++ b/src/slic3r/GUI/3DScene.hpp
@@ -555,42 +555,6 @@ public:
     static std::vector<double> get_current_print_zs(wxGLCanvas* canvas, bool active_only);
     static void set_toolpaths_range(wxGLCanvas* canvas, double low, double high);
 
-    static void register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback);
-    static void register_on_double_click_callback(wxGLCanvas* canvas, void* callback);
-    static void register_on_right_click_callback(wxGLCanvas* canvas, void* callback);
-    static void register_on_select_object_callback(wxGLCanvas* canvas, void* callback);
-    static void register_on_model_update_callback(wxGLCanvas* canvas, void* callback);
-    static void register_on_remove_object_callback(wxGLCanvas* canvas, void* callback);
-    static void register_on_arrange_callback(wxGLCanvas* canvas, void* callback);
-    static void register_on_rotate_object_left_callback(wxGLCanvas* canvas, void* callback);
-    static void register_on_rotate_object_right_callback(wxGLCanvas* canvas, void* callback);
-    static void register_on_scale_object_uniformly_callback(wxGLCanvas* canvas, void* callback);
-    static void register_on_increase_objects_callback(wxGLCanvas* canvas, void* callback);
-    static void register_on_decrease_objects_callback(wxGLCanvas* canvas, void* callback);
-    static void register_on_instance_moved_callback(wxGLCanvas* canvas, void* callback);
-    static void register_on_wipe_tower_moved_callback(wxGLCanvas* canvas, void* callback);
-    static void register_on_enable_action_buttons_callback(wxGLCanvas* canvas, void* callback);
-    static void register_on_gizmo_scale_uniformly_callback(wxGLCanvas* canvas, void* callback);
-    static void register_on_gizmo_scale_3D_callback(wxGLCanvas* canvas, void* callback);
-    static void register_on_gizmo_rotate_callback(wxGLCanvas* canvas, void* callback);
-    static void register_on_gizmo_rotate_3D_callback(wxGLCanvas* canvas, void* callback);
-    static void register_on_gizmo_flatten_callback(wxGLCanvas* canvas, void* callback);
-    static void register_on_gizmo_flatten_3D_callback(wxGLCanvas* canvas, void* callback);
-    static void register_on_update_geometry_info_callback(wxGLCanvas* canvas, void* callback);
-    static void register_on_update_geometry_3D_info_callback(wxGLCanvas* canvas, void* callback);
-
-    static void register_action_add_callback(wxGLCanvas* canvas, void* callback);
-    static void register_action_delete_callback(wxGLCanvas* canvas, void* callback);
-    static void register_action_deleteall_callback(wxGLCanvas* canvas, void* callback);
-    static void register_action_arrange_callback(wxGLCanvas* canvas, void* callback);
-    static void register_action_more_callback(wxGLCanvas* canvas, void* callback);
-    static void register_action_fewer_callback(wxGLCanvas* canvas, void* callback);
-    static void register_action_split_callback(wxGLCanvas* canvas, void* callback);
-    static void register_action_cut_callback(wxGLCanvas* canvas, void* callback);
-    static void register_action_settings_callback(wxGLCanvas* canvas, void* callback);
-    static void register_action_layersediting_callback(wxGLCanvas* canvas, void* callback);
-    static void register_action_selectbyparts_callback(wxGLCanvas* canvas, void* callback);
-
     static std::vector<int> load_object(wxGLCanvas* canvas, const ModelObject* model_object, int obj_idx, std::vector<int> instance_idxs);
     static std::vector<int> load_object(wxGLCanvas* canvas, const Model* model, int obj_idx);
 
diff --git a/src/slic3r/GUI/Event.hpp b/src/slic3r/GUI/Event.hpp
new file mode 100644
index 000000000..ffcad7f9f
--- /dev/null
+++ b/src/slic3r/GUI/Event.hpp
@@ -0,0 +1,55 @@
+#ifndef slic3r_Events_hpp_
+#define slic3r_Events_hpp_
+
+#include <wx/event.h>
+
+
+namespace Slic3r {
+
+namespace GUI {
+
+
+struct SimpleEvent : public wxEvent
+{
+    SimpleEvent(wxEventType type, int id = 0) : wxEvent(id, type) {}
+
+    virtual wxEvent* Clone() const
+    {
+        return new SimpleEvent(GetEventType(), GetId());
+    }
+};
+
+template<class T, size_t N> struct ArrayEvent : public wxEvent
+{
+    std::array<T, N> data;
+
+    ArrayEvent(wxEventType type, std::array<T, N> data, int id = 0)
+        : wxEvent(id, type), data(std::move(data))
+    {}
+
+    virtual wxEvent* Clone() const
+    {
+        return new ArrayEvent<T, N>(GetEventType(), data, GetId());
+    }
+};
+template<class T> struct ArrayEvent<T, 1> : public wxEvent
+{
+    T data;
+
+    ArrayEvent(wxEventType type, T data, int id = 0)
+        : wxEvent(id, type), data(std::move(data))
+    {}
+
+    virtual wxEvent* Clone() const
+    {
+        return new ArrayEvent<T, 1>(GetEventType(), data, GetId());
+    }
+};
+
+template <class T> using Event = ArrayEvent<T, 1>;
+
+
+}
+}
+
+#endif // slic3r_Events_hpp_
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index 89f092017..b6de0d820 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -1936,6 +1936,26 @@ GLGizmoBase* GLCanvas3D::Gizmos::_get_current() const
     return (it != m_gizmos.end()) ? it->second : nullptr;
 }
 
+wxDEFINE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, ObjectSelectEvent);
+wxDEFINE_EVENT(EVT_GLCANVAS_VIEWPORT_CHANGED, SimpleEvent);
+wxDEFINE_EVENT(EVT_GLCANVAS_DOUBLE_CLICK, SimpleEvent);
+wxDEFINE_EVENT(EVT_GLCANVAS_RIGHT_CLICK, Vec2dEvent);
+wxDEFINE_EVENT(EVT_GLCANVAS_MODEL_UPDATE, SimpleEvent);
+wxDEFINE_EVENT(EVT_GLCANVAS_REMOVE_OBJECT, SimpleEvent);
+wxDEFINE_EVENT(EVT_GLCANVAS_ARRANGE, SimpleEvent);
+wxDEFINE_EVENT(EVT_GLCANVAS_ROTATE_OBJECT, Event<int>);
+wxDEFINE_EVENT(EVT_GLCANVAS_SCALE_UNIFORMLY, SimpleEvent);
+wxDEFINE_EVENT(EVT_GLCANVAS_INCREASE_OBJECTS, Event<int>);
+wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_MOVES, SimpleEvent);
+wxDEFINE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent);
+wxDEFINE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event<bool>);
+wxDEFINE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>);
+
+wxDEFINE_EVENT(EVT_GIZMO_SCALE, Vec3dEvent);
+wxDEFINE_EVENT(EVT_GIZMO_ROTATE, Vec3dEvent);
+wxDEFINE_EVENT(EVT_GIZMO_FLATTEN, Vec3dEvent);
+
+
 GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas)
     : m_canvas(canvas)
     , m_context(nullptr)
@@ -1985,8 +2005,16 @@ GLCanvas3D::~GLCanvas3D()
         delete m_context;
         m_context = nullptr;
     }
+}
 
-    _deregister_callbacks();
+void GLCanvas3D::post_event(const wxEvent &event)
+{
+    wxPostEvent(m_canvas, event);
+}
+
+void GLCanvas3D::viewport_changed()
+{
+    post_event(SimpleEvent(EVT_GLCANVAS_VIEWPORT_CHANGED));
 }
 
 bool GLCanvas3D::init(bool useVBOs, bool use_legacy_opengl)
@@ -2412,7 +2440,7 @@ void GLCanvas3D::select_view(const std::string& direction)
         m_camera.phi = dir_vec[0];
         m_camera.set_theta(dir_vec[1]);
 
-        m_on_viewport_changed_callback.call();
+        viewport_changed();
         
         if (m_canvas != nullptr)
             m_canvas->Refresh();
@@ -2657,21 +2685,21 @@ void GLCanvas3D::reload_scene(bool force)
         {
             enable_warning_texture(true);
             _generate_warning_texture(L("Detected object outside print volume"));
-            m_on_enable_action_buttons_callback.call(state == ModelInstance::PVS_Fully_Outside);
+            post_event(Event<bool>(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, state == ModelInstance::PVS_Fully_Outside));
         }
         else
         {
             enable_warning_texture(false);
             m_volumes.reset_outside_state();
             _reset_warning_texture();
-            m_on_enable_action_buttons_callback.call(!m_model->objects.empty());
+            post_event(Event<bool>(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, !m_model->objects.empty()));
         }
     }
     else
     {
         enable_warning_texture(false);
         _reset_warning_texture();
-        m_on_enable_action_buttons_callback.call(false);
+        post_event(Event<bool>(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, false));
     }
 }
 
@@ -2737,215 +2765,6 @@ void GLCanvas3D::load_preview(const std::vector<std::string>& str_tool_colors)
     reset_legend_texture();
 }
 
-void GLCanvas3D::register_on_viewport_changed_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_on_viewport_changed_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_on_double_click_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_on_double_click_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_on_right_click_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_on_right_click_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_on_select_object_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_on_select_object_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_on_model_update_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_on_model_update_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_on_remove_object_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_on_remove_object_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_on_arrange_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_on_arrange_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_on_rotate_object_left_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_on_rotate_object_left_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_on_rotate_object_right_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_on_rotate_object_right_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_on_scale_object_uniformly_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_on_scale_object_uniformly_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_on_increase_objects_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_on_increase_objects_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_on_decrease_objects_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_on_decrease_objects_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_on_instance_moved_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_on_instance_moved_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_on_wipe_tower_moved_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_on_wipe_tower_moved_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_on_enable_action_buttons_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_on_enable_action_buttons_callback.register_callback(callback);
-}
-
-#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-void GLCanvas3D::register_on_gizmo_scale_3D_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_on_gizmo_scale_3D_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_on_gizmo_rotate_3D_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_on_gizmo_rotate_3D_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_on_gizmo_flatten_3D_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_on_gizmo_flatten_3D_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_on_update_geometry_3D_info_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_on_update_geometry_3D_info_callback.register_callback(callback);
-}
-#else
-void GLCanvas3D::register_on_gizmo_scale_uniformly_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_on_gizmo_scale_uniformly_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_on_gizmo_rotate_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_on_gizmo_rotate_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_on_gizmo_flatten_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_on_gizmo_flatten_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_on_update_geometry_info_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_on_update_geometry_info_callback.register_callback(callback);
-}
-#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-
-// void GLCanvas3D::register_action_add_callback(GLToolbarItem::Callback callback)
-void GLCanvas3D::register_action_add_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_action_add_callback.register_callback(callback);
-    // if (callback)
-    //     m_action_add_callback = std::move(callback);
-}
-
-void GLCanvas3D::register_action_delete_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_action_delete_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_action_deleteall_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_action_deleteall_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_action_arrange_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_action_arrange_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_action_more_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_action_more_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_action_fewer_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_action_fewer_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_action_split_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_action_split_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_action_cut_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_action_cut_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_action_settings_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_action_settings_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_action_layersediting_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_action_layersediting_callback.register_callback(callback);
-}
-
-void GLCanvas3D::register_action_selectbyparts_callback(void* callback)
-{
-    if (callback != nullptr)
-        m_action_selectbyparts_callback.register_callback(callback);
-}
-
 void GLCanvas3D::bind_event_handlers()
 {
     if (m_canvas != nullptr)
@@ -3034,24 +2853,24 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
                 switch (keyCode)
                 {
                 // key +
-                case 43: { m_on_increase_objects_callback.call(); break; }
+                case 43: { post_event(Event<int>(EVT_GLCANVAS_INCREASE_OBJECTS, +1)); break; }
                 // key -
-                case 45: { m_on_decrease_objects_callback.call(); break; }
+                case 45: { post_event(Event<int>(EVT_GLCANVAS_INCREASE_OBJECTS, -1)); break; }
                 // key A/a
                 case 65:
-                case 97: { m_on_arrange_callback.call(); break; }
+                case 97: { post_event(SimpleEvent(EVT_GLCANVAS_ARRANGE)); break; }
                 // key B/b
                 case 66:
                 case 98: { zoom_to_bed(); break; }
                 // key L/l
                 case 76:
-                case 108: { m_on_rotate_object_left_callback.call(); break; }
+                case 108: { post_event(Event<int>(EVT_GLCANVAS_ROTATE_OBJECT, -1)); break; }
                 // key R/r
                 case 82:
-                case 114: { m_on_rotate_object_right_callback.call(); break; }
+                case 114: { post_event(Event<int>(EVT_GLCANVAS_ROTATE_OBJECT, +1)); break; }
                 // key S/s
                 case 83:
-                case 115: { m_on_scale_object_uniformly_callback.call(); break; }
+                case 115: { post_event(SimpleEvent(EVT_GLCANVAS_SCALE_UNIFORMLY)); break; }
                 // key Z/z
                 case 90:
                 case 122: { zoom_to_volumes(); break; }
@@ -3102,7 +2921,7 @@ void GLCanvas3D::on_mouse_wheel(wxMouseEvent& evt)
         zoom = std::max(zoom, zoom_min * 0.8f);
     
     m_camera.zoom = zoom;
-    m_on_viewport_changed_callback.call();
+    viewport_changed();
 
     _refresh_if_shown_on_screen();
 }
@@ -3142,7 +2961,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
         m_dirty = true;
     }
     else if (evt.LeftDClick() && (m_hover_volume_id != -1) && !gizmos_overlay_contains_mouse && (toolbar_contains_mouse == -1))
-        m_on_double_click_callback.call();
+        post_event(SimpleEvent(EVT_GLCANVAS_DOUBLE_CLICK));
     else if (evt.LeftDClick() && (toolbar_contains_mouse != -1))
     {
         m_toolbar_action_running = true;
@@ -3158,8 +2977,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
         case Gizmos::Scale:
         {
 #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-            const Vec3d& scale = m_gizmos.get_scale();
-            m_on_gizmo_scale_3D_callback.call(scale(0), scale(1), scale(2));
+            post_event(Vec3dEvent(EVT_GIZMO_SCALE, m_gizmos.get_scale()));
 #else
             m_on_gizmo_scale_uniformly_callback.call((double)m_gizmos.get_scale());
 #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
@@ -3170,8 +2988,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
         case Gizmos::Rotate:
         {
 #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-            const Vec3d& rotation = m_gizmos.get_rotation();
-            m_on_gizmo_rotate_3D_callback.call(rotation(0), rotation(1), rotation(2));
+            post_event(Vec3dEvent(EVT_GIZMO_ROTATE, std::move(m_gizmos.get_rotation())));
 #else
             m_on_gizmo_rotate_callback.call((double)m_gizmos.get_angle_z());
 #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
@@ -3228,8 +3045,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
             if (m_gizmos.get_current_type() == Gizmos::Flatten) {
 #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
                 // Rotate the object so the normal points downward:
-                const Vec3d& rotation = m_gizmos.get_flattening_rotation();
-                m_on_gizmo_flatten_3D_callback.call(rotation(0), rotation(1), rotation(2));
+                post_event(Vec3dEvent(EVT_GIZMO_FLATTEN, m_gizmos.get_flattening_rotation()));
 #else
                 // Rotate the object so the normal points downward:
                 Vec3d normal = m_gizmos.get_flattening_normal();
@@ -3311,7 +3127,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
                     {
                         // if right clicking on volume, propagate event through callback (shows context menu)
                         if (m_volumes.volumes[volume_idx]->hover)
-                            m_on_right_click_callback.call(pos(0), pos(1));
+                            post_event(Vec2dEvent(EVT_GLCANVAS_RIGHT_CLICK, pos.cast<double>()));
                     }
                 }
             }
@@ -3464,7 +3280,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
             const Vec3d& size = bb.size();
 #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
             const Vec3d& scale = m_gizmos.get_scale();
-            m_on_update_geometry_3D_info_callback.call(size(0), size(1), size(2), scale(0), scale(1), scale(2));
+            post_event(Vec3dsEvent<2>(EVT_GLCANVAS_UPDATE_GEOMETRY, {size, scale}));
 #else
             m_on_update_geometry_info_callback.call(size(0), size(1), size(2), m_gizmos.get_scale());
 #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
@@ -3490,7 +3306,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
                 m_camera.phi += (((float)pos(0) - (float)orig(0)) * TRACKBALLSIZE);
                 m_camera.set_theta(m_camera.get_theta() - ((float)pos(1) - (float)orig(1)) * TRACKBALLSIZE);
 
-                m_on_viewport_changed_callback.call();
+                viewport_changed();
 
                 m_dirty = true;
             }
@@ -3507,7 +3323,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
                 Vec3d orig = _mouse_to_3d(m_mouse.drag.start_position_2D, &z);
                 m_camera.target += orig - cur_pos;
 
-                m_on_viewport_changed_callback.call();
+                viewport_changed();
 
                 m_dirty = true;
             }
@@ -3523,7 +3339,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
             _stop_timer();
 
             if (layer_editing_object_idx != -1)
-                m_on_model_update_callback.call();
+                post_event(SimpleEvent(EVT_GLCANVAS_MODEL_UPDATE));
         }
         else if ((m_mouse.drag.move_volume_idx != -1) && m_mouse.dragging)
         {
@@ -3594,8 +3410,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
             case Gizmos::Scale:
             {
 #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-                const Vec3d& scale = m_gizmos.get_scale();
-                m_on_gizmo_scale_3D_callback.call(scale(0), scale(1), scale(2));
+                post_event(Vec3dEvent(EVT_GIZMO_SCALE, m_gizmos.get_scale()));
 #else
                 m_on_gizmo_scale_uniformly_callback.call((double)m_gizmos.get_scale());
 #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
@@ -3604,8 +3419,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
             case Gizmos::Rotate:
             {
 #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-                const Vec3d& rotation = m_gizmos.get_rotation();
-                m_on_gizmo_rotate_3D_callback.call(rotation(0), rotation(1), rotation(2));
+                post_event(Vec3dEvent(EVT_GIZMO_ROTATE, m_gizmos.get_rotation()));
 #else
                 m_on_gizmo_rotate_callback.call((double)m_gizmos.get_angle_z());
 #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
@@ -3653,12 +3467,12 @@ void GLCanvas3D::on_key_down(wxKeyEvent& evt)
     {
         int key = evt.GetKeyCode();
         if (key == WXK_DELETE)
-            m_on_remove_object_callback.call();
+            post_event(SimpleEvent(EVT_GLCANVAS_REMOVE_OBJECT));
         else
 		{
 #ifdef __WXOSX__
 			if (key == WXK_BACK)
-				m_on_remove_object_callback.call();
+				post_event(SimpleEvent(EVT_GLCANVAS_REMOVE_OBJECT));
 #endif
 			evt.Skip();
 		}
@@ -3733,7 +3547,6 @@ bool GLCanvas3D::_init_toolbar()
     item.tooltip = GUI::L_str("Add...");
     item.sprite_id = 0;
     item.is_toggable = false;
-    // item.action_callback = &m_action_add_callback;
     item.action_event = EVT_GLTOOLBAR_ADD;
     if (!m_toolbar.add_item(item))
         return false;
@@ -3742,7 +3555,6 @@ bool GLCanvas3D::_init_toolbar()
     item.tooltip = GUI::L_str("Delete");
     item.sprite_id = 1;
     item.is_toggable = false;
-    // item.action_callback = &m_action_delete_callback;
     item.action_event = EVT_GLTOOLBAR_DELETE;
     if (!m_toolbar.add_item(item))
         return false;
@@ -3751,8 +3563,7 @@ bool GLCanvas3D::_init_toolbar()
     item.tooltip = GUI::L_str("Delete all");
     item.sprite_id = 2;
     item.is_toggable = false;
-    // item.action_callback = &m_action_deleteall_callback;
-    item.action_event = EVT_GLTOOLBAR_TODO_MORE;
+    item.action_event = EVT_GLTOOLBAR_DELETE_ALL;
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -3760,8 +3571,7 @@ bool GLCanvas3D::_init_toolbar()
     item.tooltip = GUI::L_str("Arrange");
     item.sprite_id = 3;
     item.is_toggable = false;
-    // item.action_callback = &m_action_arrange_callback;
-    item.action_event = EVT_GLTOOLBAR_TODO_MORE;
+    item.action_event = EVT_GLTOOLBAR_ARRANGE;
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -3772,8 +3582,7 @@ bool GLCanvas3D::_init_toolbar()
     item.tooltip = GUI::L_str("Add instance");
     item.sprite_id = 4;
     item.is_toggable = false;
-    // item.action_callback = &m_action_more_callback;
-    item.action_event = EVT_GLTOOLBAR_TODO_MORE;
+    item.action_event = EVT_GLTOOLBAR_MORE;
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -3781,8 +3590,7 @@ bool GLCanvas3D::_init_toolbar()
     item.tooltip = GUI::L_str("Remove instance");
     item.sprite_id = 5;
     item.is_toggable = false;
-    // item.action_callback = &m_action_fewer_callback;
-    item.action_event = EVT_GLTOOLBAR_TODO_MORE;
+    item.action_event = EVT_GLTOOLBAR_FEWER;
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -3793,8 +3601,7 @@ bool GLCanvas3D::_init_toolbar()
     item.tooltip = GUI::L_str("Split");
     item.sprite_id = 6;
     item.is_toggable = false;
-    // item.action_callback = &m_action_split_callback;
-    item.action_event = EVT_GLTOOLBAR_TODO_MORE;
+    item.action_event = EVT_GLTOOLBAR_SPLIT;
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -3802,8 +3609,7 @@ bool GLCanvas3D::_init_toolbar()
     item.tooltip = GUI::L_str("Cut...");
     item.sprite_id = 7;
     item.is_toggable = false;
-    // item.action_callback = &m_action_cut_callback;
-    item.action_event = EVT_GLTOOLBAR_TODO_MORE;
+    item.action_event = EVT_GLTOOLBAR_CUT;
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -3814,8 +3620,7 @@ bool GLCanvas3D::_init_toolbar()
     item.tooltip = GUI::L_str("Settings...");
     item.sprite_id = 8;
     item.is_toggable = false;
-    // item.action_callback = &m_action_settings_callback;
-    item.action_event = EVT_GLTOOLBAR_TODO_MORE;
+    item.action_event = EVT_GLTOOLBAR_SETTINGS;
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -3823,8 +3628,7 @@ bool GLCanvas3D::_init_toolbar()
     item.tooltip = GUI::L_str("Layers editing");
     item.sprite_id = 9;
     item.is_toggable = true;
-    // item.action_callback = &m_action_layersediting_callback;
-    item.action_event = EVT_GLTOOLBAR_TODO_MORE;
+    item.action_event = EVT_GLTOOLBAR_LAYERSEDITING;
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -3835,8 +3639,7 @@ bool GLCanvas3D::_init_toolbar()
     item.tooltip = GUI::L_str("Select by parts");
     item.sprite_id = 10;
     item.is_toggable = true;
-    // item.action_callback = &m_action_selectbyparts_callback;
-    item.action_event = EVT_GLTOOLBAR_TODO_MORE;
+    item.action_event = EVT_GLTOOLBAR_SELECTBYPARTS;
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -3975,7 +3778,7 @@ void GLCanvas3D::_zoom_to_bounding_box(const BoundingBoxf3& bbox)
         // center view around bounding box center
         m_camera.target = bbox.center();
 
-        m_on_viewport_changed_callback.call();
+        viewport_changed();
 
         _refresh_if_shown_on_screen();
     }
@@ -4048,48 +3851,6 @@ float GLCanvas3D::_get_zoom_to_bounding_box_factor(const BoundingBoxf3& bbox) co
     return (float)std::min((double)cnv_size.get_width() / max_x, (double)cnv_size.get_height() / max_y);
 }
 
-void GLCanvas3D::_deregister_callbacks()
-{
-    m_on_viewport_changed_callback.deregister_callback();
-    m_on_double_click_callback.deregister_callback();
-    m_on_right_click_callback.deregister_callback();
-    m_on_select_object_callback.deregister_callback();
-    m_on_model_update_callback.deregister_callback();
-    m_on_remove_object_callback.deregister_callback();
-    m_on_arrange_callback.deregister_callback();
-    m_on_rotate_object_left_callback.deregister_callback();
-    m_on_rotate_object_right_callback.deregister_callback();
-    m_on_scale_object_uniformly_callback.deregister_callback();
-    m_on_increase_objects_callback.deregister_callback();
-    m_on_decrease_objects_callback.deregister_callback();
-    m_on_instance_moved_callback.deregister_callback();
-    m_on_wipe_tower_moved_callback.deregister_callback();
-    m_on_enable_action_buttons_callback.deregister_callback();
-#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-    m_on_gizmo_scale_3D_callback.deregister_callback();
-    m_on_gizmo_rotate_3D_callback.deregister_callback();
-    m_on_gizmo_flatten_3D_callback.deregister_callback();
-    m_on_update_geometry_3D_info_callback.deregister_callback();
-#else
-    m_on_gizmo_scale_uniformly_callback.deregister_callback();
-    m_on_gizmo_rotate_callback.deregister_callback();
-    m_on_gizmo_flatten_callback.deregister_callback();
-    m_on_update_geometry_info_callback.deregister_callback();
-#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-
-    m_action_add_callback.deregister_callback();
-    m_action_delete_callback.deregister_callback();
-    m_action_deleteall_callback.deregister_callback();
-    m_action_arrange_callback.deregister_callback();
-    m_action_more_callback.deregister_callback();
-    m_action_fewer_callback.deregister_callback();
-    m_action_split_callback.deregister_callback();
-    m_action_cut_callback.deregister_callback();
-    m_action_settings_callback.deregister_callback();
-    m_action_layersediting_callback.deregister_callback();
-    m_action_selectbyparts_callback.deregister_callback();
-}
-
 void GLCanvas3D::_mark_volumes_for_layer_height() const
 {
     if (m_print == nullptr)
@@ -5599,10 +5360,10 @@ void GLCanvas3D::_on_move(const std::vector<int>& volume_idxs)
     }
 
     if (object_moved)
-        m_on_instance_moved_callback.call();
+        post_event(SimpleEvent(EVT_GLCANVAS_WIPETOWER_MOVED));
 
     if (wipe_tower_origin != Vec3d::Zero())
-        m_on_wipe_tower_moved_callback.call(wipe_tower_origin(0), wipe_tower_origin(1));
+        post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_MOVED, std::move(wipe_tower_origin)));
 }
 
 void GLCanvas3D::_on_select(int volume_idx, int object_idx)
@@ -5633,7 +5394,7 @@ void GLCanvas3D::_on_select(int volume_idx, int object_idx)
         }
     }
 
-    m_on_select_object_callback.call(obj_id, vol_id);
+    post_event(ObjectSelectEvent(obj_id, vol_id));
     Slic3r::GUI::select_current_volume(obj_id, vol_id);
 }
 
diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp
index aba2b07c1..055d62b6a 100644
--- a/src/slic3r/GUI/GLCanvas3D.hpp
+++ b/src/slic3r/GUI/GLCanvas3D.hpp
@@ -1,11 +1,11 @@
 #ifndef slic3r_GLCanvas3D_hpp_
 #define slic3r_GLCanvas3D_hpp_
 
-#include <functional>
+#include <stddef.h>
 
 #include "3DScene.hpp"
 #include "GLToolbar.hpp"
-#include "callback.hpp"
+#include "Event.hpp"
 
 class wxWindow;
 class wxTimer;
@@ -16,6 +16,7 @@ class wxMouseEvent;
 class wxTimerEvent;
 class wxPaintEvent;
 
+
 namespace Slic3r {
 
 class GLShader;
@@ -80,6 +81,45 @@ public:
     void set_bottom(float bottom);
 };
 
+
+struct ObjectSelectEvent;
+wxDECLARE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, ObjectSelectEvent);
+struct ObjectSelectEvent : public ArrayEvent<ptrdiff_t, 2>
+{
+    ObjectSelectEvent(ptrdiff_t object_id, ptrdiff_t volume_id, int id = 0)
+        : ArrayEvent(EVT_GLCANVAS_OBJECT_SELECT, {object_id, volume_id}, id)
+    {}
+
+    ptrdiff_t object_id() const { return data[0]; }
+    ptrdiff_t volume_id() const { return data[1]; }
+};
+
+using Vec2dEvent = Event<Vec2d>;
+template <size_t N> using Vec2dsEvent = ArrayEvent<Vec2d, N>;
+
+using Vec3dEvent = Event<Vec3d>;
+template <size_t N> using Vec3dsEvent = ArrayEvent<Vec3d, N>;
+
+
+wxDECLARE_EVENT(EVT_GLCANVAS_VIEWPORT_CHANGED, SimpleEvent);
+wxDECLARE_EVENT(EVT_GLCANVAS_DOUBLE_CLICK, SimpleEvent);
+wxDECLARE_EVENT(EVT_GLCANVAS_RIGHT_CLICK, Vec2dEvent);
+wxDECLARE_EVENT(EVT_GLCANVAS_MODEL_UPDATE, SimpleEvent);
+wxDECLARE_EVENT(EVT_GLCANVAS_REMOVE_OBJECT, SimpleEvent);
+wxDECLARE_EVENT(EVT_GLCANVAS_ARRANGE, SimpleEvent);
+wxDECLARE_EVENT(EVT_GLCANVAS_ROTATE_OBJECT, Event<int>);    // data: -1 => rotate left, +1 => rotate right
+wxDECLARE_EVENT(EVT_GLCANVAS_SCALE_UNIFORMLY, SimpleEvent);
+wxDECLARE_EVENT(EVT_GLCANVAS_INCREASE_OBJECTS, Event<int>); // data: +1 => increase, -1 => decrease
+wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_MOVES, SimpleEvent);
+wxDECLARE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent);
+wxDECLARE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event<bool>);
+wxDECLARE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>);
+
+wxDECLARE_EVENT(EVT_GIZMO_SCALE, Vec3dEvent);
+wxDECLARE_EVENT(EVT_GIZMO_ROTATE, Vec3dEvent);
+wxDECLARE_EVENT(EVT_GIZMO_FLATTEN, Vec3dEvent);
+
+
 class GLCanvas3D
 {
     struct GCodePreviewVolumeIndex
@@ -506,46 +546,8 @@ class GLCanvas3D
 
     GCodePreviewVolumeIndex m_gcode_preview_volume_index;
 
-    PerlCallback m_on_viewport_changed_callback;
-    PerlCallback m_on_double_click_callback;
-    PerlCallback m_on_right_click_callback;
-    PerlCallback m_on_select_object_callback;
-    PerlCallback m_on_model_update_callback;
-    PerlCallback m_on_remove_object_callback;
-    PerlCallback m_on_arrange_callback;
-    PerlCallback m_on_rotate_object_left_callback;
-    PerlCallback m_on_rotate_object_right_callback;
-    PerlCallback m_on_scale_object_uniformly_callback;
-    PerlCallback m_on_increase_objects_callback;
-    PerlCallback m_on_decrease_objects_callback;
-    PerlCallback m_on_instance_moved_callback;
-    PerlCallback m_on_wipe_tower_moved_callback;
-    PerlCallback m_on_enable_action_buttons_callback;
-#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-    PerlCallback m_on_gizmo_rotate_3D_callback;
-    PerlCallback m_on_gizmo_flatten_3D_callback;
-    PerlCallback m_on_gizmo_scale_3D_callback;
-    PerlCallback m_on_update_geometry_3D_info_callback;
-#else
-    PerlCallback m_on_gizmo_scale_uniformly_callback;
-    PerlCallback m_on_gizmo_rotate_callback;
-    PerlCallback m_on_gizmo_flatten_callback;
-    PerlCallback m_on_update_geometry_info_callback;
-#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-
-    // TODO: Remove these
-    PerlCallback m_action_add_callback;
-    PerlCallback m_action_delete_callback;
-    PerlCallback m_action_deleteall_callback;
-    PerlCallback m_action_arrange_callback;
-    PerlCallback m_action_more_callback;
-    PerlCallback m_action_fewer_callback;
-    PerlCallback m_action_split_callback;
-    PerlCallback m_action_cut_callback;
-    PerlCallback m_action_settings_callback;
-    PerlCallback m_action_layersediting_callback;
-    PerlCallback m_action_selectbyparts_callback;
-
+    void post_event(const wxEvent &event);
+    void viewport_changed();
 public:
     GLCanvas3D(wxGLCanvas* canvas);
     ~GLCanvas3D();
@@ -641,46 +643,6 @@ public:
     void load_gcode_preview(const GCodePreviewData& preview_data, const std::vector<std::string>& str_tool_colors);
     void load_preview(const std::vector<std::string>& str_tool_colors);
 
-    void register_on_viewport_changed_callback(void* callback);
-    void register_on_double_click_callback(void* callback);
-    void register_on_right_click_callback(void* callback);
-    void register_on_select_object_callback(void* callback);
-    void register_on_model_update_callback(void* callback);
-    void register_on_remove_object_callback(void* callback);
-    void register_on_arrange_callback(void* callback);
-    void register_on_rotate_object_left_callback(void* callback);
-    void register_on_rotate_object_right_callback(void* callback);
-    void register_on_scale_object_uniformly_callback(void* callback);
-    void register_on_increase_objects_callback(void* callback);
-    void register_on_decrease_objects_callback(void* callback);
-    void register_on_instance_moved_callback(void* callback);
-    void register_on_wipe_tower_moved_callback(void* callback);
-    void register_on_enable_action_buttons_callback(void* callback);
-#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-    void register_on_gizmo_scale_3D_callback(void* callback);
-    void register_on_gizmo_rotate_3D_callback(void* callback);
-    void register_on_gizmo_flatten_3D_callback(void* callback);
-    void register_on_update_geometry_3D_info_callback(void* callback);
-#else
-    void register_on_gizmo_scale_uniformly_callback(void* callback);
-    void register_on_gizmo_rotate_callback(void* callback);
-    void register_on_gizmo_flatten_callback(void* callback);
-    void register_on_update_geometry_info_callback(void* callback);
-#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-
-    // void register_action_add_callback(GLToolbarItem::Callback);
-    void register_action_add_callback(void* callback);
-    void register_action_delete_callback(void* callback);
-    void register_action_deleteall_callback(void* callback);
-    void register_action_arrange_callback(void* callback);
-    void register_action_more_callback(void* callback);
-    void register_action_fewer_callback(void* callback);
-    void register_action_split_callback(void* callback);
-    void register_action_cut_callback(void* callback);
-    void register_action_settings_callback(void* callback);
-    void register_action_layersediting_callback(void* callback);
-    void register_action_selectbyparts_callback(void* callback);
-
     void bind_event_handlers();
     void unbind_event_handlers();
 
@@ -714,8 +676,6 @@ private:
     void _zoom_to_bounding_box(const BoundingBoxf3& bbox);
     float _get_zoom_to_bounding_box_factor(const BoundingBoxf3& bbox) const;
 
-    void _deregister_callbacks();
-
     void _mark_volumes_for_layer_height() const;
     void _refresh_if_shown_on_screen();
 
diff --git a/src/slic3r/GUI/GLCanvas3DManager.cpp b/src/slic3r/GUI/GLCanvas3DManager.cpp
index 771aa159e..41f5ef22a 100644
--- a/src/slic3r/GUI/GLCanvas3DManager.cpp
+++ b/src/slic3r/GUI/GLCanvas3DManager.cpp
@@ -587,246 +587,6 @@ void GLCanvas3DManager::reset_legend_texture(wxGLCanvas* canvas)
         it->second->reset_legend_texture();
 }
 
-void GLCanvas3DManager::register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_on_viewport_changed_callback(callback);
-}
-
-void GLCanvas3DManager::register_on_double_click_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_on_double_click_callback(callback);
-}
-
-void GLCanvas3DManager::register_on_right_click_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_on_right_click_callback(callback);
-}
-
-void GLCanvas3DManager::register_on_select_object_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_on_select_object_callback(callback);
-}
-
-void GLCanvas3DManager::register_on_model_update_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_on_model_update_callback(callback);
-}
-
-void GLCanvas3DManager::register_on_remove_object_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_on_remove_object_callback(callback);
-}
-
-void GLCanvas3DManager::register_on_arrange_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_on_arrange_callback(callback);
-}
-
-void GLCanvas3DManager::register_on_rotate_object_left_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_on_rotate_object_left_callback(callback);
-}
-
-void GLCanvas3DManager::register_on_rotate_object_right_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_on_rotate_object_right_callback(callback);
-}
-
-void GLCanvas3DManager::register_on_scale_object_uniformly_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_on_scale_object_uniformly_callback(callback);
-}
-
-void GLCanvas3DManager::register_on_increase_objects_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_on_increase_objects_callback(callback);
-}
-
-void GLCanvas3DManager::register_on_decrease_objects_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_on_decrease_objects_callback(callback);
-}
-
-void GLCanvas3DManager::register_on_instance_moved_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_on_instance_moved_callback(callback);
-}
-
-void GLCanvas3DManager::register_on_wipe_tower_moved_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_on_wipe_tower_moved_callback(callback);
-}
-
-void GLCanvas3DManager::register_on_enable_action_buttons_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_on_enable_action_buttons_callback(callback);
-}
-
-#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-void GLCanvas3DManager::register_on_gizmo_scale_3D_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_on_gizmo_scale_3D_callback(callback);
-}
-
-void GLCanvas3DManager::register_on_gizmo_rotate_3D_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_on_gizmo_rotate_3D_callback(callback);
-}
-
-void GLCanvas3DManager::register_on_gizmo_flatten_3D_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_on_gizmo_flatten_3D_callback(callback);
-}
-
-void GLCanvas3DManager::register_on_update_geometry_3D_info_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_on_update_geometry_3D_info_callback(callback);
-}
-#else
-void GLCanvas3DManager::register_on_gizmo_scale_uniformly_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_on_gizmo_scale_uniformly_callback(callback);
-}
-
-void GLCanvas3DManager::register_on_gizmo_rotate_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_on_gizmo_rotate_callback(callback);
-}
-
-void GLCanvas3DManager::register_on_gizmo_flatten_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_on_gizmo_flatten_callback(callback);
-}
-
-void GLCanvas3DManager::register_on_update_geometry_info_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_on_update_geometry_info_callback(callback);
-}
-#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-
-void GLCanvas3DManager::register_action_add_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_action_add_callback(callback);
-}
-
-void GLCanvas3DManager::register_action_delete_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_action_delete_callback(callback);
-}
-
-void GLCanvas3DManager::register_action_deleteall_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_action_deleteall_callback(callback);
-}
-
-void GLCanvas3DManager::register_action_arrange_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_action_arrange_callback(callback);
-}
-
-void GLCanvas3DManager::register_action_more_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_action_more_callback(callback);
-}
-
-void GLCanvas3DManager::register_action_fewer_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_action_fewer_callback(callback);
-}
-
-void GLCanvas3DManager::register_action_split_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_action_split_callback(callback);
-}
-
-void GLCanvas3DManager::register_action_cut_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_action_cut_callback(callback);
-}
-
-void GLCanvas3DManager::register_action_settings_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_action_settings_callback(callback);
-}
-
-void GLCanvas3DManager::register_action_layersediting_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_action_layersediting_callback(callback);
-}
-
-void GLCanvas3DManager::register_action_selectbyparts_callback(wxGLCanvas* canvas, void* callback)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->register_action_selectbyparts_callback(callback);
-}
-
 wxGLCanvas* GLCanvas3DManager::create_wxglcanvas(wxWindow *parent)
 {
     int attribList[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 24, WX_GL_SAMPLE_BUFFERS, GL_TRUE, WX_GL_SAMPLES, 4, 0 };
diff --git a/src/slic3r/GUI/GLCanvas3DManager.hpp b/src/slic3r/GUI/GLCanvas3DManager.hpp
index d3b7b177c..1a3036f9f 100644
--- a/src/slic3r/GUI/GLCanvas3DManager.hpp
+++ b/src/slic3r/GUI/GLCanvas3DManager.hpp
@@ -20,7 +20,7 @@ typedef std::vector<ExPolygon> ExPolygons;
 class ModelObject;
 class PrintObject;
 class GCodePreviewData;
-    
+
 namespace GUI {
 
 class GLCanvas3D;
@@ -156,45 +156,6 @@ public:
 
     void reset_legend_texture(wxGLCanvas* canvas);
 
-    void register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback);
-    void register_on_double_click_callback(wxGLCanvas* canvas, void* callback);
-    void register_on_right_click_callback(wxGLCanvas* canvas, void* callback);
-    void register_on_select_object_callback(wxGLCanvas* canvas, void* callback);
-    void register_on_model_update_callback(wxGLCanvas* canvas, void* callback);
-    void register_on_remove_object_callback(wxGLCanvas* canvas, void* callback);
-    void register_on_arrange_callback(wxGLCanvas* canvas, void* callback);
-    void register_on_rotate_object_left_callback(wxGLCanvas* canvas, void* callback);
-    void register_on_rotate_object_right_callback(wxGLCanvas* canvas, void* callback);
-    void register_on_scale_object_uniformly_callback(wxGLCanvas* canvas, void* callback);
-    void register_on_increase_objects_callback(wxGLCanvas* canvas, void* callback);
-    void register_on_decrease_objects_callback(wxGLCanvas* canvas, void* callback);
-    void register_on_instance_moved_callback(wxGLCanvas* canvas, void* callback);
-    void register_on_wipe_tower_moved_callback(wxGLCanvas* canvas, void* callback);
-    void register_on_enable_action_buttons_callback(wxGLCanvas* canvas, void* callback);
-#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-    void register_on_gizmo_scale_3D_callback(wxGLCanvas* canvas, void* callback);
-    void register_on_gizmo_rotate_3D_callback(wxGLCanvas* canvas, void* callback);
-    void register_on_gizmo_flatten_3D_callback(wxGLCanvas* canvas, void* callback);
-    void register_on_update_geometry_3D_info_callback(wxGLCanvas* canvas, void* callback);
-#else
-    void register_on_gizmo_scale_uniformly_callback(wxGLCanvas* canvas, void* callback);
-    void register_on_gizmo_rotate_callback(wxGLCanvas* canvas, void* callback);
-    void register_on_gizmo_flatten_callback(wxGLCanvas* canvas, void* callback);
-    void register_on_update_geometry_info_callback(wxGLCanvas* canvas, void* callback);
-#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
-
-    void register_action_add_callback(wxGLCanvas* canvas, void* callback);
-    void register_action_delete_callback(wxGLCanvas* canvas, void* callback);
-    void register_action_deleteall_callback(wxGLCanvas* canvas, void* callback);
-    void register_action_arrange_callback(wxGLCanvas* canvas, void* callback);
-    void register_action_more_callback(wxGLCanvas* canvas, void* callback);
-    void register_action_fewer_callback(wxGLCanvas* canvas, void* callback);
-    void register_action_split_callback(wxGLCanvas* canvas, void* callback);
-    void register_action_cut_callback(wxGLCanvas* canvas, void* callback);
-    void register_action_settings_callback(wxGLCanvas* canvas, void* callback);
-    void register_action_layersediting_callback(wxGLCanvas* canvas, void* callback);
-    void register_action_selectbyparts_callback(wxGLCanvas* canvas, void* callback);
-
     static bool can_multisample() { return s_multisample == MS_Enabled; }
     static wxGLCanvas* create_wxglcanvas(wxWindow *parent);
 
diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp
index 196dc663f..e1566e944 100644
--- a/src/slic3r/GUI/GLToolbar.cpp
+++ b/src/slic3r/GUI/GLToolbar.cpp
@@ -16,9 +16,18 @@ namespace Slic3r {
 namespace GUI {
 
 
-wxDEFINE_EVENT(EVT_GLTOOLBAR_ADD, wxCommandEvent);
-wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE, wxCommandEvent);
-wxDEFINE_EVENT(EVT_GLTOOLBAR_TODO_MORE, wxCommandEvent);
+wxDEFINE_EVENT(EVT_GLTOOLBAR_ADD, SimpleEvent);
+wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent);
+wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE_ALL, SimpleEvent);
+wxDEFINE_EVENT(EVT_GLTOOLBAR_ARRANGE, SimpleEvent);
+wxDEFINE_EVENT(EVT_GLTOOLBAR_MORE, SimpleEvent);
+wxDEFINE_EVENT(EVT_GLTOOLBAR_FEWER, SimpleEvent);
+wxDEFINE_EVENT(EVT_GLTOOLBAR_SPLIT, SimpleEvent);
+wxDEFINE_EVENT(EVT_GLTOOLBAR_CUT, SimpleEvent);
+wxDEFINE_EVENT(EVT_GLTOOLBAR_SETTINGS, SimpleEvent);
+wxDEFINE_EVENT(EVT_GLTOOLBAR_LAYERSEDITING, SimpleEvent);
+wxDEFINE_EVENT(EVT_GLTOOLBAR_SELECTBYPARTS, SimpleEvent);
+
 
 GLToolbarItem::Data::Data()
     : name("")
@@ -57,10 +66,7 @@ const std::string& GLToolbarItem::get_tooltip() const
 
 void GLToolbarItem::do_action(wxEvtHandler *target)
 {
-    // if (m_data.action_callback != nullptr)
-    //     m_data.action_callback->call();
-
-    wxPostEvent(target, wxCommandEvent(m_data.action_event));
+    wxPostEvent(target, SimpleEvent(m_data.action_event));
 }
 
 bool GLToolbarItem::is_enabled() const
diff --git a/src/slic3r/GUI/GLToolbar.hpp b/src/slic3r/GUI/GLToolbar.hpp
index 45d22e785..43097c007 100644
--- a/src/slic3r/GUI/GLToolbar.hpp
+++ b/src/slic3r/GUI/GLToolbar.hpp
@@ -5,10 +5,9 @@
 #include <string>
 #include <vector>
 
-#include <wx/event.h>
+#include "GLTexture.hpp"
+#include "Event.hpp"
 
-#include "../../slic3r/GUI/GLTexture.hpp"
-// #include "callback.hpp"
 
 class wxEvtHandler;
 
@@ -17,9 +16,17 @@ namespace GUI {
 
 class GLCanvas3D;
 
-wxDECLARE_EVENT(EVT_GLTOOLBAR_ADD, wxCommandEvent);
-wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE, wxCommandEvent);
-wxDECLARE_EVENT(EVT_GLTOOLBAR_TODO_MORE, wxCommandEvent);
+wxDECLARE_EVENT(EVT_GLTOOLBAR_ADD, SimpleEvent);
+wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent);
+wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE_ALL, SimpleEvent);
+wxDECLARE_EVENT(EVT_GLTOOLBAR_ARRANGE, SimpleEvent);
+wxDECLARE_EVENT(EVT_GLTOOLBAR_MORE, SimpleEvent);
+wxDECLARE_EVENT(EVT_GLTOOLBAR_FEWER, SimpleEvent);
+wxDECLARE_EVENT(EVT_GLTOOLBAR_SPLIT, SimpleEvent);
+wxDECLARE_EVENT(EVT_GLTOOLBAR_CUT, SimpleEvent);
+wxDECLARE_EVENT(EVT_GLTOOLBAR_SETTINGS, SimpleEvent);
+wxDECLARE_EVENT(EVT_GLTOOLBAR_LAYERSEDITING, SimpleEvent);
+wxDECLARE_EVENT(EVT_GLTOOLBAR_SELECTBYPARTS, SimpleEvent);
 
 class GLToolbarItem
 {
@@ -41,16 +48,12 @@ public:
         Num_States
     };
 
-    // typedef std::function<void()> Callback;
-    // typedef PerlCallback Callback;
-
     struct Data
     {
         std::string name;
         std::string tooltip;
         unsigned int sprite_id;
         bool is_toggable;
-        // Callback *action_callback;
         wxEventType action_event;
 
         Data();
diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp
index 870867218..988f6e507 100644
--- a/src/slic3r/GUI/GUI_Preview.cpp
+++ b/src/slic3r/GUI/GUI_Preview.cpp
@@ -170,12 +170,6 @@ Preview::~Preview()
     }
 }
 
-void Preview::register_on_viewport_changed_callback(void* callback)
-{
-    if ((m_canvas != nullptr) && (callback != nullptr))
-        _3DScene::register_on_viewport_changed_callback(m_canvas, callback);
-}
-
 void Preview::set_number_extruders(unsigned int number_extruders)
 {
     if (m_number_extruders != number_extruders)
diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp
index bdd69a075..ed6d9cba3 100644
--- a/src/slic3r/GUI/GUI_Preview.hpp
+++ b/src/slic3r/GUI/GUI_Preview.hpp
@@ -50,7 +50,6 @@ public:
     Preview(wxNotebook* notebook, DynamicPrintConfig* config, Print* print, GCodePreviewData* gcode_preview_data);
     virtual ~Preview();
 
-    void register_on_viewport_changed_callback(void* callback);
     void set_number_extruders(unsigned int number_extruders);
     void reset_gcode_preview_data();
     void set_canvas_as_dirty();
@@ -64,7 +63,7 @@ public:
     void load_print();
     void reload_print(bool force = false);
     void refresh_print();
-    
+
 private:
     bool init(wxNotebook* notebook, DynamicPrintConfig* config, Print* print, GCodePreviewData* gcode_preview_data);
 
diff --git a/src/slic3r/GUI/GUI_PreviewIface.cpp b/src/slic3r/GUI/GUI_PreviewIface.cpp
index 9048beb33..cbec51205 100644
--- a/src/slic3r/GUI/GUI_PreviewIface.cpp
+++ b/src/slic3r/GUI/GUI_PreviewIface.cpp
@@ -4,11 +4,6 @@
 
 namespace Slic3r {
 
-void PreviewIface::register_on_viewport_changed_callback(void* callback)
-{
-    m_preview->register_on_viewport_changed_callback(callback);
-}
-
 void PreviewIface::set_number_extruders(unsigned int number_extruders)
 {
     m_preview->set_number_extruders(number_extruders);
diff --git a/src/slic3r/GUI/GUI_PreviewIface.hpp b/src/slic3r/GUI/GUI_PreviewIface.hpp
index 86f155bd5..df5fccaaf 100644
--- a/src/slic3r/GUI/GUI_PreviewIface.hpp
+++ b/src/slic3r/GUI/GUI_PreviewIface.hpp
@@ -19,7 +19,6 @@ class PreviewIface
 public:
     explicit PreviewIface(GUI::Preview* preview) : m_preview(preview) {}
 
-    void register_on_viewport_changed_callback(void* callback);
     void set_number_extruders(unsigned int number_extruders);
     void reset_gcode_preview_data();
     void reload_print(bool force = false);
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index b13b5b65d..e366e12b5 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -1,6 +1,5 @@
 #include "Plater.hpp"
 
-#include <iostream>   // XXX
 #include <cstddef>
 #include <algorithm>
 #include <vector>
@@ -30,6 +29,7 @@
 #include "GUI_App.hpp"
 #include "MainFrame.hpp"
 #include "3DScene.hpp"
+#include "GLCanvas3D.hpp"
 #include "GUI_ObjectParts.hpp"
 #include "GLToolbar.hpp"
 #include "GUI_Preview.hpp"
@@ -273,7 +273,6 @@ Sidebar::Sidebar(wxWindow *parent)
     p->btn_send_gcode->SetBitmap(arrow_up);
     p->btn_send_gcode->Hide();
     auto *btns_sizer_scrolled = new wxBoxSizer(wxHORIZONTAL);
-    std::cerr << "btns_sizer_scrolled: " << btns_sizer_scrolled << std::endl;
     btns_sizer_scrolled->Add(p->btn_send_gcode);
 
     // Info boxes
@@ -285,7 +284,6 @@ Sidebar::Sidebar(wxWindow *parent)
     scrolled_sizer->SetMinSize(320, -1);
     p->scrolled->SetSizer(scrolled_sizer);
     p->scrolled->SetScrollbars(0, 1, 1, 1);
-    std::cerr << "scrolled_sizer: " << scrolled_sizer << std::endl;
     scrolled_sizer->Add(p->sizer_presets, 0, wxEXPAND | wxLEFT, 2);
     scrolled_sizer->Add(p->sizer_params, 1, wxEXPAND);
     scrolled_sizer->Add(p->object_info, 0, wxEXPAND | wxTOP | wxLEFT, 20);
@@ -299,12 +297,10 @@ Sidebar::Sidebar(wxWindow *parent)
     p->btn_reslice->SetFont(wxGetApp().bold_font());
 
     auto *btns_sizer = new wxBoxSizer(wxVERTICAL);
-    std::cerr << "btns_sizer: " << btns_sizer << std::endl;
     btns_sizer->Add(p->btn_reslice, 0, wxEXPAND | wxTOP, 5);
     btns_sizer->Add(p->btn_export_gcode, 0, wxEXPAND | wxTOP, 5);
 
     auto *sizer = new wxBoxSizer(wxVERTICAL);
-    std::cerr << "sizer: " << sizer << std::endl;
     sizer->Add(p->scrolled, 1, wxEXPAND | wxTOP, 5);
     sizer->Add(btns_sizer, 0, wxEXPAND | wxLEFT, 20);
     SetSizer(sizer);
@@ -433,7 +429,7 @@ struct Plater::priv
     void on_update_print_preview(wxCommandEvent &);
     void on_process_completed(wxCommandEvent &);
     void on_layer_editing_toggled(bool enable);
-    void on_action_add(const wxCommandEvent&);
+    void on_action_add(SimpleEvent&);
 };
 
 // TODO: multisample, see 3DScene.pm
@@ -520,9 +516,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) :
     });
 
     // 3DScene events:
-    // TODO: (?)
-    // on_layer_editing_toggled
-    // on_action_add
+    // TODO: more
     canvas3D->Bind(EVT_GLTOOLBAR_ADD, &priv::on_action_add, this);
 
     q->Bind(EVT_SLICING_COMPLETED, &priv::on_update_print_preview, this);
@@ -567,7 +561,6 @@ std::vector<int> Plater::priv::collect_selections()
 
 void Plater::priv::update(bool force_autocenter)
 {
-
     wxWindowUpdateLocker freeze_guard(q);
     if (get_config("autocenter") == "1" || force_autocenter) {
         // auto *bed_shape_opt = config->opt<ConfigOptionPoints>("bed_shape");
@@ -876,7 +869,7 @@ void Plater::priv::on_layer_editing_toggled(bool enable)
     canvas3D->Update();
 }
 
-void Plater::priv::on_action_add(const wxCommandEvent&)
+void Plater::priv::on_action_add(SimpleEvent&)
 {
     wxArrayString input_files;
     wxGetApp().open_model(q, input_files);