From 5018089351ef942194caa097f8420b20e48a1335 Mon Sep 17 00:00:00 2001
From: Enrico Turri <enricoturri@seznam.cz>
Date: Thu, 14 Mar 2019 13:54:05 +0100
Subject: [PATCH 1/8] Toolbar refactoring

1) toolbar items define 3 callback functions for setting the visibility, setting the enabling state and defining their action which are set while adding a new item to the toolbar

2) the toolbar takes care to update all its items visibility and enabled states through a new update method to be called by the parent idle event handler

3) the toolbar handles mouse events by calling its on_mouse method
---
 src/libslic3r/Technologies.hpp |   5 +
 src/slic3r/GUI/GLCanvas3D.cpp  | 218 ++++++++++++++++++++
 src/slic3r/GUI/GLCanvas3D.hpp  |  24 +++
 src/slic3r/GUI/GLToolbar.cpp   | 367 ++++++++++++++++++++++++++++++++-
 src/slic3r/GUI/GLToolbar.hpp   | 132 +++++++++++-
 src/slic3r/GUI/GUI_Preview.cpp |   6 +
 src/slic3r/GUI/GUI_Preview.hpp |   6 +
 src/slic3r/GUI/Plater.cpp      | 202 +++++++++++++++++-
 src/slic3r/GUI/Plater.hpp      |  13 ++
 9 files changed, 968 insertions(+), 5 deletions(-)

diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp
index e978b5838..da343ac20 100644
--- a/src/libslic3r/Technologies.hpp
+++ b/src/libslic3r/Technologies.hpp
@@ -59,4 +59,9 @@
 // Toolbars and Gizmos use icons imported from svg files
 #define ENABLE_SVG_ICONS (1 && ENABLE_1_42_0_ALPHA8 && ENABLE_TEXTURES_FROM_SVG)
 
+
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#define ENABLE_CANVAS_GUI_REFACTORING 1
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
 #endif // _technologies_h_
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index 8178c9cf6..87e004ee7 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -734,7 +734,13 @@ GLCanvas3D::Mouse::Drag::Drag()
 
 GLCanvas3D::Mouse::Mouse()
     : dragging(false)
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     , left_down(false)
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     , position(DBL_MAX, DBL_MAX)
     , scene_position(DBL_MAX, DBL_MAX, DBL_MAX)
     , ignore_up_event(false)
@@ -3727,7 +3733,13 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar
     , m_use_VBOs(false)
     , m_apply_zoom_to_volumes_filter(false)
     , m_hover_volume_id(-1)
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     , m_toolbar_action_running(false)
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     , m_legend_texture_enabled(false)
     , m_picking_enabled(false)
     , m_moving_enabled(false)
@@ -4041,6 +4053,9 @@ void GLCanvas3D::allow_multisample(bool allow)
     m_multisample_allowed = allow;
 }
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 void GLCanvas3D::enable_toolbar_item(const std::string& name, bool enable)
 {
     if (enable)
@@ -4053,6 +4068,9 @@ bool GLCanvas3D::is_toolbar_item_pressed(const std::string& name) const
 {
     return m_toolbar.is_item_pressed(name);
 }
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 void GLCanvas3D::zoom_to_bed()
 {
@@ -4106,6 +4124,9 @@ void GLCanvas3D::update_volumes_colors_by_extruder()
         m_volumes.update_colors_by_extruder(m_config);
 }
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 void GLCanvas3D::update_toolbar_items_visibility()
 {
     ConfigOptionMode mode = wxGetApp().get_mode();
@@ -4114,6 +4135,9 @@ void GLCanvas3D::update_toolbar_items_visibility()
     m_toolbar.set_item_visible("splitvolumes", mode != comSimple);
     m_dirty = true;
 }
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 // Returns a Rect object denoting size and position of the Reset button used by a gizmo.
 // Returns in either screen or viewport coords.
@@ -4790,6 +4814,13 @@ void GLCanvas3D::on_size(wxSizeEvent& evt)
 
 void GLCanvas3D::on_idle(wxIdleEvent& evt)
 {
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    m_dirty |= m_toolbar.update_items_state();
+    m_dirty |= m_view_toolbar.update_items_state();
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
     if (!m_dirty)
         return;
 
@@ -5074,6 +5105,22 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
 #endif /* SLIC3R_DEBUG_MOUSE_EVENTS */
 	}
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+//    if (!evt.Entering() && !evt.Leaving())
+//    {
+        bool processed_by_toolbar = m_toolbar.on_mouse(evt, *this);
+        processed_by_toolbar |= m_view_toolbar.on_mouse(evt, *this);
+
+        if (processed_by_toolbar)
+        {
+            m_mouse.set_start_position_3D_as_invalid();
+            return;
+        }
+//    }
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
     if (m_picking_enabled)
         _set_current();
 
@@ -5081,8 +5128,14 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
     int layer_editing_object_idx = is_layers_editing_enabled() ? selected_object_idx : -1;
     m_layers_editing.select_object(*m_model, layer_editing_object_idx);
     bool gizmos_overlay_contains_mouse = m_gizmos.overlay_contains_mouse(*this, m_mouse.position);
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     int toolbar_contains_mouse = m_toolbar.contains_mouse(m_mouse.position, *this);
     int view_toolbar_contains_mouse = m_view_toolbar.contains_mouse(m_mouse.position, *this);
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 #if ENABLE_MOVE_MIN_THRESHOLD
     if (m_mouse.drag.move_requires_threshold && m_mouse.is_move_start_threshold_position_2D_defined() && m_mouse.is_move_threshold_met(pos))
@@ -5124,23 +5177,41 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
     {
         // to remove hover on objects when the mouse goes out of this canvas
         m_mouse.position = Vec2d(-1.0, -1.0);
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         // ensure m_mouse.left_down is reset (it may happen when switching canvas)
         m_mouse.left_down = false;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         m_dirty = true;
     }
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     else if (evt.LeftDClick() && (toolbar_contains_mouse != -1))
     {
         m_toolbar_action_running = true;
         m_mouse.set_start_position_3D_as_invalid();
         m_toolbar.do_action((unsigned int)toolbar_contains_mouse, *this);
     }
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     else if (evt.LeftDClick() && (m_gizmos.get_current_type() != Gizmos::Undefined))
     {
         m_mouse.ignore_up_event = true;
     }
     else if (evt.LeftDown() || evt.RightDown())
     {
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         m_mouse.left_down = evt.LeftDown();
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
         // If user pressed left or right button we first check whether this happened
         // on a volume or not.
@@ -5193,6 +5264,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
         {
             // event was taken care of by the SlaSupports gizmo
         }
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         else if (evt.LeftDown() && (view_toolbar_contains_mouse != -1))
             m_view_toolbar.do_action((unsigned int)view_toolbar_contains_mouse, *this);
         else if (evt.LeftDown() && (toolbar_contains_mouse != -1))
@@ -5202,6 +5276,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
             m_toolbar.do_action((unsigned int)toolbar_contains_mouse, *this);
             m_mouse.left_down = false;
         }
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         else
         {
             // Select volume in this 3D canvas.
@@ -5403,7 +5480,15 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
         m_dirty = true;
     }
     // do not process dragging if the mouse is into any of the HUD elements
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    else if (evt.Dragging() && !gizmos_overlay_contains_mouse)
+#else
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     else if (evt.Dragging() && !gizmos_overlay_contains_mouse && (toolbar_contains_mouse == -1) && (view_toolbar_contains_mouse == -1))
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     {
         m_mouse.dragging = true;
 
@@ -5413,7 +5498,15 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
                 _perform_layer_editing_action(&evt);
         }
         // do not process the dragging if the left mouse was set down in another canvas
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+        else if (evt.LeftIsDown())
+#else
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         else if (m_mouse.left_down && evt.LeftIsDown())
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         {
             // if dragging over blank area with left button, rotate
 #if ENABLE_MOVE_MIN_THRESHOLD
@@ -5474,7 +5567,15 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
             // that's why the mouse_event function was called so that the gizmo can refuse the deselection in manual editing mode
 
             // deselect and propagate event through callback
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+            if (!evt.ShiftDown() && m_picking_enabled && !m_mouse.ignore_up_event)
+#else
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
             if (!evt.ShiftDown() && m_picking_enabled && !m_toolbar_action_running && !m_mouse.ignore_up_event)
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
             {
                 m_selection.clear();
                 m_selection.set_mode(Selection::Instance);
@@ -5523,8 +5624,14 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
         m_mouse.set_start_position_3D_as_invalid();
         m_mouse.set_start_position_2D_as_invalid();
         m_mouse.dragging = false;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         m_mouse.left_down = false;
         m_toolbar_action_running = false;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         m_dirty = true;
 
         if (m_canvas->HasCapture())
@@ -5540,6 +5647,15 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
         if (m_selection.is_empty())
             m_gizmos.reset_all_states();
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+        if (tooltip.empty())
+            tooltip = m_toolbar.get_tooltip();
+
+        if (tooltip.empty())
+            tooltip = m_view_toolbar.get_tooltip();
+#else
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         // updates toolbar overlay
         if (tooltip.empty())
             tooltip = m_toolbar.update_hover_state(m_mouse.position, *this);
@@ -5551,6 +5667,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
             if (!tooltip.empty())
                 m_dirty = true;
         }
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
         set_tooltip(tooltip);
 
@@ -5954,7 +6073,15 @@ bool GLCanvas3D::_init_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("Add...") + " [" + GUI::shortkey_ctrl_prefix() + "I]";
     item.sprite_id = 0;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_ADD)); };
+#else
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     item.action_event = EVT_GLTOOLBAR_ADD;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -5964,7 +6091,16 @@ bool GLCanvas3D::_init_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("Delete") + " [Del]";
     item.sprite_id = 1;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_DELETE)); };
+    item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_delete(); };
+#else
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     item.action_event = EVT_GLTOOLBAR_DELETE;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -5974,7 +6110,16 @@ bool GLCanvas3D::_init_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("Delete all") + " [" + GUI::shortkey_ctrl_prefix() + "Del]";
     item.sprite_id = 2;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_DELETE_ALL)); };
+    item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_delete_all(); };
+#else
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     item.action_event = EVT_GLTOOLBAR_DELETE_ALL;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -5984,7 +6129,16 @@ bool GLCanvas3D::_init_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("Arrange [A]");
     item.sprite_id = 3;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_ARRANGE)); };
+    item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_arrange(); };
+#else
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     item.action_event = EVT_GLTOOLBAR_ARRANGE;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -5997,7 +6151,17 @@ bool GLCanvas3D::_init_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("Add instance [+]");
     item.sprite_id = 4;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_MORE)); };
+    item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; };
+    item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_increase_instances(); };
+#else
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     item.action_event = EVT_GLTOOLBAR_MORE;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -6007,7 +6171,17 @@ bool GLCanvas3D::_init_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("Remove instance [-]");
     item.sprite_id = 5;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_FEWER)); };
+    item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; };
+    item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_decrease_instances(); };
+#else
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     item.action_event = EVT_GLTOOLBAR_FEWER;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -6020,7 +6194,17 @@ bool GLCanvas3D::_init_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("Split to objects");
     item.sprite_id = 6;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_OBJECTS)); };
+    item.visibility_callback = GLToolbarItem::Default_Visibility_Callback;
+    item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_split_to_objects(); };
+#else
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     item.action_event = EVT_GLTOOLBAR_SPLIT_OBJECTS;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -6030,7 +6214,17 @@ bool GLCanvas3D::_init_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("Split to parts");
     item.sprite_id = 7;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_VOLUMES)); };
+    item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; };
+    item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_split_to_volumes(); };
+#else
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     item.action_event = EVT_GLTOOLBAR_SPLIT_VOLUMES;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -6044,13 +6238,29 @@ bool GLCanvas3D::_init_toolbar()
     item.tooltip = GUI::L_str("Layers editing");
     item.sprite_id = 8;
     item.is_toggable = true;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_LAYERSEDITING)); };
+    item.visibility_callback = GLToolbarItem::Default_Visibility_Callback;
+    item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_layers_editing(); };
+#else
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     item.action_event = EVT_GLTOOLBAR_LAYERSEDITING;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     if (!m_toolbar.add_item(item))
         return false;
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     enable_toolbar_item("add", true);
 
     update_toolbar_items_visibility();
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     return true;
 }
@@ -6255,7 +6465,15 @@ void GLCanvas3D::_picking_pass() const
 {
     const Vec2d& pos = m_mouse.position;
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    if (m_picking_enabled && !m_mouse.dragging && (pos != Vec2d(DBL_MAX, DBL_MAX)))
+#else
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     if (m_picking_enabled && !m_mouse.dragging && !m_mouse.left_down && (pos != Vec2d(DBL_MAX, DBL_MAX)))
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     {
         // Render the object for picking.
         // FIXME This cannot possibly work in a multi - sampled context as the color gets mangled by the anti - aliasing.
diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp
index 07b3907a3..808e958c7 100644
--- a/src/slic3r/GUI/GLCanvas3D.hpp
+++ b/src/slic3r/GUI/GLCanvas3D.hpp
@@ -314,7 +314,13 @@ class GLCanvas3D
         };
 
         bool dragging;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         bool left_down;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         Vec2d position;
         Vec3d scene_position;
         Drag drag;
@@ -876,7 +882,13 @@ private:
     bool m_use_VBOs;
     bool m_apply_zoom_to_volumes_filter;
     mutable int m_hover_volume_id;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     bool m_toolbar_action_running;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     bool m_warning_texture_enabled;
     bool m_legend_texture_enabled;
     bool m_picking_enabled;
@@ -959,8 +971,14 @@ public:
     void enable_dynamic_background(bool enable);
     void allow_multisample(bool allow);
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     void enable_toolbar_item(const std::string& name, bool enable);
     bool is_toolbar_item_pressed(const std::string& name) const;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     void zoom_to_bed();
     void zoom_to_volumes();
@@ -969,7 +987,13 @@ public:
 
     void update_volumes_colors_by_extruder();
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     void update_toolbar_items_visibility();
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 #if !ENABLE_IMGUI
     Rect get_gizmo_reset_rect(const GLCanvas3D& canvas, bool viewport) const;
diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp
index 1b8ccc165..9678776c8 100644
--- a/src/slic3r/GUI/GLToolbar.cpp
+++ b/src/slic3r/GUI/GLToolbar.cpp
@@ -30,6 +30,14 @@ wxDEFINE_EVENT(EVT_GLTOOLBAR_LAYERSEDITING, SimpleEvent);
 wxDEFINE_EVENT(EVT_GLVIEWTOOLBAR_3D, SimpleEvent);
 wxDEFINE_EVENT(EVT_GLVIEWTOOLBAR_PREVIEW, SimpleEvent);
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+const GLToolbarItem::ActionCallback GLToolbarItem::Default_Action_Callback = [](){};
+const GLToolbarItem::VisibilityCallback GLToolbarItem::Default_Visibility_Callback = []()->bool { return true; };
+const GLToolbarItem::EnabledStateCallback GLToolbarItem::Default_Enabled_State_Callback = []()->bool { return true; };
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
 GLToolbarItem::Data::Data()
     : name("")
 #if ENABLE_SVG_ICONS
@@ -39,20 +47,65 @@ GLToolbarItem::Data::Data()
     , sprite_id(-1)
     , is_toggable(false)
     , visible(true)
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    , action_callback(Default_Action_Callback)
+    , visibility_callback(Default_Visibility_Callback)
+    , enabled_state_callback(Default_Enabled_State_Callback)
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 {
 }
 
 GLToolbarItem::GLToolbarItem(GLToolbarItem::EType type, const GLToolbarItem::Data& data)
     : m_type(type)
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    , m_state(Normal)
+#else
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     , m_state(Disabled)
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     , m_data(data)
 {
 }
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 void GLToolbarItem::do_action(wxEvtHandler *target)
 {
     wxPostEvent(target, SimpleEvent(m_data.action_event));
 }
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+bool GLToolbarItem::update_visibility()
+{
+    bool visible = m_data.visibility_callback();
+    bool ret = (m_data.visible != visible);
+    if (ret)
+        m_data.visible = visible;
+
+    return ret;
+}
+
+bool GLToolbarItem::update_enabled_state()
+{
+    bool enabled = m_data.enabled_state_callback();
+    bool ret = (is_enabled() != enabled);
+    if (ret)
+        m_state = enabled ? GLToolbarItem::Normal : GLToolbarItem::Disabled;
+
+    return ret;
+}
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 void GLToolbarItem::render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const
 {
@@ -135,6 +188,12 @@ GLToolbar::GLToolbar(GLToolbar::EType type)
 #if ENABLE_SVG_ICONS
     , m_icons_texture_dirty(true)
 #endif // ENABLE_SVG_ICONS
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    , m_mouse_capture({false, false, false})
+    , m_tooltip("")
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 {
 }
 
@@ -299,6 +358,9 @@ float GLToolbar::get_height() const
     return m_layout.height;
 }
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 void GLToolbar::enable_item(const std::string& name)
 {
     for (GLToolbarItem* item : m_items)
@@ -322,6 +384,9 @@ void GLToolbar::disable_item(const std::string& name)
         }
     }
 }
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 void GLToolbar::select_item(const std::string& name)
 {
@@ -371,6 +436,9 @@ bool GLToolbar::is_item_visible(const std::string& name) const
     return false;
 }
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 void GLToolbar::set_item_visible(const std::string& name, bool visible)
 {
     for (GLToolbarItem* item : m_items)
@@ -395,9 +463,26 @@ void GLToolbar::set_item_visible(const std::string& name, bool visible)
             any_item_visible = false;
         }
     }
-
 }
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+bool GLToolbar::update_items_state()
+{
+    bool ret = false;
+    ret |= update_items_visibility();
+    ret |= update_items_enabled_state();
+    return ret;
+}
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 std::string GLToolbar::update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent)
 {
     if (!m_enabled)
@@ -461,6 +546,9 @@ void GLToolbar::do_action(unsigned int item_id, GLCanvas3D& parent)
         }
     }
 }
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 void GLToolbar::render(const GLCanvas3D& parent) const
 {
@@ -487,6 +575,57 @@ void GLToolbar::render(const GLCanvas3D& parent) const
     ::glPopMatrix();
 }
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent)
+{
+    Vec2d mouse_pos((double)evt.GetX(), (double)evt.GetY());
+    bool processed = false;
+
+    // mouse anywhere
+    if (evt.Moving())
+        m_tooltip = update_hover_state(mouse_pos, parent);
+    else if (evt.LeftUp())
+        m_mouse_capture.left = false;
+    else if (evt.MiddleUp())
+        m_mouse_capture.middle = false;
+    else if (evt.RightUp())
+        m_mouse_capture.right = false;
+    else if (m_mouse_capture.any() && evt.Dragging())
+        processed = true;
+
+    int item_id = contains_mouse(mouse_pos, parent);
+    if (item_id == -1)
+    {
+        // mouse is outside the toolbar
+        m_tooltip = "";
+    }
+    else
+    {
+        // mouse inside toolbar only
+        if (evt.LeftDown() || evt.LeftDClick())
+        {
+            m_mouse_capture.left = true;
+            if ((item_id != -2) && !m_items[item_id]->is_separator())
+            {
+                // mouse is inside an icon
+                do_action((unsigned int)item_id, parent);
+                processed = true;
+            }
+        }
+        else if (evt.MiddleDown())
+            m_mouse_capture.middle = true;
+        else if (evt.RightDown())
+            m_mouse_capture.right = true;
+        else if (evt.LeftUp())
+            processed = true;
+    }
+
+    return processed;
+}
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
 void GLToolbar::calc_layout() const
 {
     switch (m_layout.type)
@@ -576,6 +715,61 @@ float GLToolbar::get_main_size() const
     return size;
 }
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+void GLToolbar::do_action(unsigned int item_id, GLCanvas3D& parent)
+{
+    if (item_id < (unsigned int)m_items.size())
+    {
+        GLToolbarItem* item = m_items[item_id];
+        if ((item != nullptr) && !item->is_separator() && item->is_hovered())
+        {
+            if (item->is_toggable())
+            {
+                GLToolbarItem::EState state = item->get_state();
+                if (state == GLToolbarItem::Hover)
+                    item->set_state(GLToolbarItem::HoverPressed);
+                else if (state == GLToolbarItem::HoverPressed)
+                    item->set_state(GLToolbarItem::Hover);
+
+                parent.render();
+                item->do_action();
+            }
+            else
+            {
+                if (m_type == Radio)
+                    select_item(item->get_name());
+                else
+                    item->set_state(GLToolbarItem::HoverPressed);
+
+                parent.render();
+                item->do_action();
+                if ((m_type == Normal) && (item->get_state() != GLToolbarItem::Disabled))
+                {
+                    // the item may get disabled during the action, if not, set it back to hover state
+                    item->set_state(GLToolbarItem::Hover);
+                    parent.render();
+                }
+            }
+        }
+    }
+}
+
+std::string GLToolbar::update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent)
+{
+    if (!m_enabled)
+        return "";
+
+    switch (m_layout.type)
+    {
+    default:
+    case Layout::Horizontal: { return update_hover_state_horizontal(mouse_pos, parent); }
+    case Layout::Vertical: { return update_hover_state_vertical(mouse_pos, parent); }
+    }
+}
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
 std::string GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLCanvas3D& parent)
 {
     // NB: mouse_pos is already scaled appropriately
@@ -785,6 +979,23 @@ std::string GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCan
     return tooltip;
 }
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+int GLToolbar::contains_mouse(const Vec2d& mouse_pos, const GLCanvas3D& parent) const
+{
+    if (!m_enabled)
+        return -1;
+
+    switch (m_layout.type)
+    {
+    default:
+    case Layout::Horizontal: { return contains_mouse_horizontal(mouse_pos, parent); }
+    case Layout::Vertical: { return contains_mouse_vertical(mouse_pos, parent); }
+    }
+}
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
 int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3D& parent) const
 {
     // NB: mouse_pos is already scaled appropriately
@@ -808,8 +1019,14 @@ int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3
     float scaled_separator_size = m_layout.separator_size * factor;
     float scaled_gap_size = m_layout.gap_size * factor;
     float scaled_border = m_layout.border * factor;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     float separator_stride = scaled_separator_size + scaled_gap_size;
     float icon_stride = scaled_icons_size + scaled_gap_size;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     float left = m_layout.left + scaled_border;
     float top = m_layout.top - scaled_border;
@@ -824,16 +1041,62 @@ int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3
             continue;
 
         if (item->is_separator())
-            left += separator_stride;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+        {
+            float right = left + scaled_separator_size;
+            float bottom = top - scaled_icons_size;
+
+            // mouse inside the separator
+            if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
+                return id;
+
+            left = right;
+            right += scaled_gap_size;
+
+            if (id < m_items.size() - 1)
+            {
+                // mouse inside the gap
+                if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
+                    return -2;
+            }
+
+            left = right;
+        }
+#else
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+        left += separator_stride;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         else
         {
             float right = left + scaled_icons_size;
             float bottom = top - scaled_icons_size;
 
+            // mouse inside the icon
             if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
                 return id;
             
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+            left = right;
+            right += scaled_gap_size;
+
+            if (id < m_items.size() - 1)
+            {
+                // mouse inside the gap
+                if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
+                    return -2;
+            }
+
+            left = right;
+#else
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
             left += icon_stride;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         }
     }
     
@@ -863,9 +1126,14 @@ int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D&
     float scaled_separator_size = m_layout.separator_size * factor;
     float scaled_gap_size = m_layout.gap_size * factor;
     float scaled_border = m_layout.border * factor;
-
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     float separator_stride = scaled_separator_size + scaled_gap_size;
     float icon_stride = scaled_icons_size + scaled_gap_size;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     float left = m_layout.left + scaled_border;
     float top = m_layout.top - scaled_border;
@@ -880,16 +1148,62 @@ int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D&
             continue;
 
         if (item->is_separator())
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+        {
+            float right = left + scaled_icons_size;
+            float bottom = top - scaled_separator_size;
+
+            // mouse inside the separator
+            if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
+                return id;
+
+            top = bottom;
+            bottom -= scaled_gap_size;
+
+            if (id < m_items.size() - 1)
+            {
+                // mouse inside the gap
+                if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
+                    return -2;
+            }
+
+            top = bottom;
+        }
+#else
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
             top -= separator_stride;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         else
         {
             float right = left + scaled_icons_size;
             float bottom = top - scaled_icons_size;
 
+            // mouse inside the icon
             if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
                 return id;
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+            top = bottom;
+            bottom -= scaled_gap_size;
+
+            if (id < m_items.size() - 1)
+            {
+                // mouse inside the gap
+                if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
+                    return -2;
+            }
+
+            top = bottom;
+#else
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
             top -= icon_stride;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         }
     }
 
@@ -1244,5 +1558,52 @@ bool GLToolbar::generate_icons_texture() const
 }
 #endif // ENABLE_SVG_ICONS
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+bool GLToolbar::update_items_visibility()
+{
+    bool ret = false;
+
+    for (GLToolbarItem* item : m_items)
+    {
+        ret |= item->update_visibility();
+    }
+
+    if (ret)
+        m_layout.dirty = true;
+
+    // updates separators visibility to avoid having two of them consecutive
+    bool any_item_visible = false;
+    for (GLToolbarItem* item : m_items)
+    {
+        if (!item->is_separator())
+            any_item_visible |= item->is_visible();
+        else
+        {
+            item->set_visible(any_item_visible);
+            any_item_visible = false;
+        }
+    }
+
+    return ret;
+}
+
+bool GLToolbar::update_items_enabled_state()
+{
+    bool ret = false;
+
+    for (GLToolbarItem* item : m_items)
+    {
+        ret |= item->update_enabled_state();
+    }
+
+    if (ret)
+        m_layout.dirty = true;
+
+    return ret;
+}
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
 } // namespace GUI
 } // namespace Slic3r
diff --git a/src/slic3r/GUI/GLToolbar.hpp b/src/slic3r/GUI/GLToolbar.hpp
index 4ca72fc4a..e6ef051d6 100644
--- a/src/slic3r/GUI/GLToolbar.hpp
+++ b/src/slic3r/GUI/GLToolbar.hpp
@@ -31,6 +31,14 @@ wxDECLARE_EVENT(EVT_GLVIEWTOOLBAR_PREVIEW, SimpleEvent);
 class GLToolbarItem
 {
 public:
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    typedef std::function<void()> ActionCallback;
+    typedef std::function<bool()> VisibilityCallback;
+    typedef std::function<bool()> EnabledStateCallback;
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
     enum EType : unsigned char
     {
         Action,
@@ -57,12 +65,33 @@ public:
         std::string tooltip;
         unsigned int sprite_id;
         bool is_toggable;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         wxEventType action_event;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         bool visible;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+        ActionCallback action_callback;
+        VisibilityCallback visibility_callback;
+        EnabledStateCallback enabled_state_callback;
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
         Data();
     };
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    static const ActionCallback Default_Action_Callback;
+    static const VisibilityCallback Default_Visibility_Callback;
+    static const EnabledStateCallback Default_Enabled_State_Callback;
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
 private:
     EType m_type;
     EState m_state;
@@ -80,7 +109,15 @@ public:
 #endif // ENABLE_SVG_ICONS
     const std::string& get_tooltip() const { return m_data.tooltip; }
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    void do_action() { m_data.action_callback(); }
+#else
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     void do_action(wxEvtHandler *target);
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     bool is_enabled() const { return m_state != Disabled; }
     bool is_disabled() const { return m_state == Disabled; }
@@ -89,13 +126,35 @@ public:
 
     bool is_toggable() const { return m_data.is_toggable; }
     bool is_visible() const { return m_data.visible; }
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     void set_visible(bool visible) { m_data.visible = visible; }
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     bool is_separator() const { return m_type == Separator; }
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    // returns true if the state changes
+    bool update_visibility();
+    // returns true if the state changes
+    bool update_enabled_state();
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
     void render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const;
 
 private:
     GLTexture::Quad_UVs get_uvs(unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    void set_visible(bool visible) { m_data.visible = visible; }
+
+    friend class GLToolbar;
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 };
 
 #if !ENABLE_SVG_ICONS
@@ -213,6 +272,21 @@ private:
     mutable Layout m_layout;
 
     ItemsList m_items;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    struct MouseCapture
+    {
+        bool left;
+        bool middle;
+        bool right;
+
+        bool any() const { return left || middle || right; }
+    };
+
+    MouseCapture m_mouse_capture;
+    std::string m_tooltip;
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 public:
 #if ENABLE_SVG_ICONS
@@ -253,24 +327,59 @@ public:
     float get_width() const;
     float get_height() const;
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     void enable_item(const std::string& name);
     void disable_item(const std::string& name);
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     void select_item(const std::string& name);
 
     bool is_item_pressed(const std::string& name) const;
     bool is_item_disabled(const std::string& name) const;
     bool is_item_visible(const std::string& name) const;
-    void set_item_visible(const std::string& name, bool visible);
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    const std::string& get_tooltip() const { return m_tooltip; }
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
+
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    // returns true if any item changed its state
+    bool update_items_state();
+#else
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+    void set_item_visible(const std::string& name, bool visible);
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     std::string update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent);
 
     // returns the id of the item under the given mouse position or -1 if none
     int contains_mouse(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;
 
     void do_action(unsigned int item_id, GLCanvas3D& parent);
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     void render(const GLCanvas3D& parent) const;    
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    bool on_mouse(wxMouseEvent& evt, GLCanvas3D& parent);
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
 private:
     void calc_layout() const;
     float get_width_horizontal() const;
@@ -278,8 +387,20 @@ private:
     float get_height_horizontal() const;
     float get_height_vertical() const;
     float get_main_size() const;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    void do_action(unsigned int item_id, GLCanvas3D& parent);
+    std::string update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent);
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     std::string update_hover_state_horizontal(const Vec2d& mouse_pos, GLCanvas3D& parent);
     std::string update_hover_state_vertical(const Vec2d& mouse_pos, GLCanvas3D& parent);
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    // returns the id of the item under the given mouse position or -1 if none
+    int contains_mouse(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     int contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;
     int contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;
 
@@ -289,6 +410,15 @@ private:
 #if ENABLE_SVG_ICONS
     bool generate_icons_texture() const;
 #endif // ENABLE_SVG_ICONS
+
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    // returns true if any item changed its state
+    bool update_items_visibility();
+    // returns true if any item changed its state
+    bool update_items_enabled_state();
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 };
 
 } // namespace GUI
diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp
index 6f177d8b4..553978972 100644
--- a/src/slic3r/GUI/GUI_Preview.cpp
+++ b/src/slic3r/GUI/GUI_Preview.cpp
@@ -122,6 +122,9 @@ void View3D::mirror_selection(Axis axis)
         m_canvas->mirror_selection(axis);
 }
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 void View3D::update_toolbar_items_visibility()
 {
     if (m_canvas != nullptr)
@@ -133,6 +136,9 @@ void View3D::enable_toolbar_item(const std::string& name, bool enable)
     if (m_canvas != nullptr)
         m_canvas->enable_toolbar_item(name, enable);
 }
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 int View3D::check_volumes_outside_state() const
 {
diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp
index c15aad3b3..61d789247 100644
--- a/src/slic3r/GUI/GUI_Preview.hpp
+++ b/src/slic3r/GUI/GUI_Preview.hpp
@@ -54,8 +54,14 @@ public:
     void delete_selected();
     void mirror_selection(Axis axis);
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     void update_toolbar_items_visibility();
     void enable_toolbar_item(const std::string& name, bool enable);
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     int check_volumes_outside_state() const;
 
     bool is_layers_editing_enabled() const;
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index 64d189859..85349a52a 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -1217,6 +1217,19 @@ struct Plater::priv
     // Sets m_bed.m_polygon to limit the object placement.
     void set_bed_shape(const Pointfs& shape);
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    bool can_delete() const;
+    bool can_delete_all() const;
+    bool can_increase_instances() const;
+    bool can_decrease_instances() const;
+    bool can_split_to_objects() const;
+    bool can_split_to_volumes() const;
+    bool can_arrange() const;
+    bool can_layers_editing() const;
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
 private:
     bool init_object_menu();
     bool init_common_menu(wxMenu* menu, const bool is_part = false);
@@ -1225,16 +1238,34 @@ private:
     bool complit_init_part_menu();
     void init_view_toolbar();
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     bool can_delete_object() const;
     bool can_increase_instances() const;
     bool can_decrease_instances() const;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     bool can_set_instance_to_object() const;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     bool can_split_to_objects() const;
     bool can_split_to_volumes() const;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     bool can_split() const;
     bool layers_height_allowed() const;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     bool can_delete_all() const;
     bool can_arrange() const;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     bool can_mirror() const;
 
     void update_fff_scene();
@@ -1794,11 +1825,17 @@ int Plater::priv::get_selected_volume_idx() const
 
 void Plater::priv::selection_changed()
 {
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     view3D->enable_toolbar_item("delete", can_delete_object());
     view3D->enable_toolbar_item("more", can_increase_instances());
     view3D->enable_toolbar_item("fewer", can_decrease_instances());
     view3D->enable_toolbar_item("splitobjects", can_split());
     view3D->enable_toolbar_item("splitvolumes", printer_technology == ptFFF && can_split());
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     // if the selection is not valid to allow for layer editing, we need to turn off the tool if it is running
     bool enable_layer_editing = layers_height_allowed();
@@ -1807,7 +1844,13 @@ void Plater::priv::selection_changed()
         on_action_layersediting(evt);
     }
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     view3D->enable_toolbar_item("layersediting", enable_layer_editing);
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     // forces a frame render to update the view (to avoid a missed update if, for example, the context menu appears)
     view3D->render();
@@ -1815,9 +1858,15 @@ void Plater::priv::selection_changed()
 
 void Plater::priv::object_list_changed()
 {
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     // Enable/disable buttons depending on whether there are any objects on the platter.
     view3D->enable_toolbar_item("deleteall", can_delete_all());
     view3D->enable_toolbar_item("arrange", can_arrange());
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     const bool export_in_progress = this->background_process.is_export_scheduled(); // || ! send_gcode_file.empty());
     // XXX: is this right?
@@ -1897,8 +1946,14 @@ void Plater::priv::arrange()
 
     wxBusyCursor wait;
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     // Disable the arrange button (to prevent reentrancies, we will call wxYied)
     view3D->enable_toolbar_item("arrange", can_arrange());
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     this->background_process.stop();
     unsigned count = 0;
@@ -1970,8 +2025,14 @@ void Plater::priv::arrange()
     statusbar()->set_cancel_callback(); // remove cancel button
     arranging.store(false);
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     // We enable back the arrange button
     view3D->enable_toolbar_item("arrange", can_arrange());
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     // Do a full refresh of scene tree, including regenerating all the GLVolumes.
     //FIXME The update function shall just reload the modified matrices.
@@ -2527,10 +2588,16 @@ void Plater::priv::on_process_completed(wxCommandEvent &evt)
 void Plater::priv::on_layer_editing_toggled(bool enable)
 {
     view3D->enable_layers_editing(enable);
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     if (enable && !view3D->is_layers_editing_enabled()) {
         // Initialization of the OpenGL shaders failed. Disable the tool.
         view3D->enable_toolbar_item("layersediting", false);
     }
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     view3D->set_as_dirty();
 }
 
@@ -2552,10 +2619,18 @@ void Plater::priv::on_action_split_volumes(SimpleEvent&)
 
 void Plater::priv::on_action_layersediting(SimpleEvent&)
 {
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    view3D->enable_layers_editing(!view3D->is_layers_editing_enabled());
+#else
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     bool enable = !view3D->is_layers_editing_enabled();
     view3D->enable_layers_editing(enable);
     if (enable && !view3D->is_layers_editing_enabled())
         view3D->enable_toolbar_item("layersediting", false);
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 }
 
 void Plater::priv::on_object_select(SimpleEvent& evt)
@@ -2680,7 +2755,15 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
     if (q != nullptr)
     {
         q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_mirror()); }, item_mirror->GetId());
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+        q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete()); }, item_delete->GetId());
+#else
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete_object()); }, item_delete->GetId());
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     }
 
     return true;
@@ -2785,7 +2868,15 @@ void Plater::priv::init_view_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("3D editor view") + " [" + GUI::shortkey_ctrl_prefix() + "5]";
     item.sprite_id = 0;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    item.action_callback = [this]() { if (this->q != nullptr) wxPostEvent(this->q, SimpleEvent(EVT_GLVIEWTOOLBAR_3D)); };
+#else
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     item.action_event = EVT_GLVIEWTOOLBAR_3D;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     item.is_toggable = false;
     if (!view_toolbar.add_item(item))
         return;
@@ -2796,18 +2887,35 @@ void Plater::priv::init_view_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("Preview") + " [" + GUI::shortkey_ctrl_prefix() + "6]";
     item.sprite_id = 1;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    item.action_callback = [this]() { if (this->q != nullptr) wxPostEvent(this->q, SimpleEvent(EVT_GLVIEWTOOLBAR_PREVIEW)); };
+#else
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     item.action_event = EVT_GLVIEWTOOLBAR_PREVIEW;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     item.is_toggable = false;
     if (!view_toolbar.add_item(item))
         return;
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     view_toolbar.enable_item("3D");
     view_toolbar.enable_item("Preview");
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     view_toolbar.select_item("3D");
     view_toolbar.set_enabled(true);
 }
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 bool Plater::priv::can_delete_object() const
 {
     int obj_idx = get_selected_object_idx();
@@ -2819,6 +2927,9 @@ bool Plater::priv::can_increase_instances() const
     int obj_idx = get_selected_object_idx();
     return (0 <= obj_idx) && (obj_idx < (int)model.objects.size());
 }
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 bool Plater::priv::can_set_instance_to_object() const
 {
@@ -2826,6 +2937,9 @@ bool Plater::priv::can_set_instance_to_object() const
     return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && (model.objects[obj_idx]->instances.size() > 1);
 }
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 bool Plater::priv::can_decrease_instances() const
 {
     int obj_idx = get_selected_object_idx();
@@ -2846,6 +2960,9 @@ bool Plater::priv::can_split_to_volumes() const
 //     return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && !model.objects[obj_idx]->is_multiparts();
     return sidebar->obj_list()->is_splittable();
 }
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 bool Plater::priv::can_split() const
 {
@@ -2858,6 +2975,9 @@ bool Plater::priv::layers_height_allowed() const
     return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && config->opt_bool("variable_layer_height") && view3D->is_layers_editing_allowed();
 }
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 bool Plater::priv::can_delete_all() const
 {
     return !model.objects.empty();
@@ -2867,6 +2987,9 @@ bool Plater::priv::can_arrange() const
 {
     return !model.objects.empty() && !arranging.load();
 }
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 bool Plater::priv::can_mirror() const
 {
@@ -2883,11 +3006,63 @@ void Plater::priv::set_bed_shape(const Pointfs& shape)
     }
 }
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+bool Plater::priv::can_delete() const
+{
+    return !get_selection().is_empty();
+}
+
+bool Plater::priv::can_delete_all() const
+{
+    return !model.objects.empty();
+}
+
+bool Plater::priv::can_increase_instances() const
+{
+    int obj_idx = get_selected_object_idx();
+    return (0 <= obj_idx) && (obj_idx < (int)model.objects.size());
+}
+
+bool Plater::priv::can_decrease_instances() const
+{
+    int obj_idx = get_selected_object_idx();
+    return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && (model.objects[obj_idx]->instances.size() > 1);
+}
+
+bool Plater::priv::can_split_to_objects() const
+{
+    return can_split();
+}
+
+bool Plater::priv::can_split_to_volumes() const
+{
+    return (printer_technology != ptSLA) && can_split();
+}
+
+bool Plater::priv::can_arrange() const
+{
+    return !model.objects.empty() && !arranging.load();
+}
+
+bool Plater::priv::can_layers_editing() const
+{
+    return layers_height_allowed();
+}
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
 void Plater::priv::update_object_menu()
 {
     sidebar->obj_list()->append_menu_items_add_volume(&object_menu);
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     if (view3D != nullptr)
         view3D->update_toolbar_items_visibility();
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 }
 
 void Plater::priv::show_action_buttons(const bool is_ready_to_slice) const 
@@ -3370,14 +3545,26 @@ void Plater::on_config_change(const DynamicPrintConfig &config)
         } 
         else if(opt_key == "variable_layer_height") {
             if (p->config->opt_bool("variable_layer_height") != true) {
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
                 p->view3D->enable_toolbar_item("layersediting", false);
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
                 p->view3D->enable_layers_editing(false);
                 p->view3D->set_as_dirty();
             }
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
             else if (p->view3D->is_layers_editing_allowed()) {
                 p->view3D->enable_toolbar_item("layersediting", true);
             }
-        } 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#endif // !ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+        }
         else if(opt_key == "extruder_colour") {
             update_scheduled = true;
             p->preview->set_number_extruders(p->config->option<ConfigOptionStrings>(opt_key)->values.size());
@@ -3498,4 +3685,17 @@ void Plater::fix_through_netfabb(const int obj_idx, const int vol_idx/* = -1*/)
 
 void Plater::update_object_menu() { p->update_object_menu(); }
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+bool Plater::can_delete() const { return p->can_delete(); }
+bool Plater::can_delete_all() const { return p->can_delete_all(); }
+bool Plater::can_increase_instances() const { return p->can_increase_instances(); }
+bool Plater::can_decrease_instances() const { return p->can_decrease_instances(); }
+bool Plater::can_split_to_objects() const { return p->can_split_to_objects(); }
+bool Plater::can_split_to_volumes() const { return p->can_split_to_volumes(); }
+bool Plater::can_arrange() const { return p->can_arrange(); }
+bool Plater::can_layers_editing() const { return p->can_layers_editing(); }
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
 }}    // namespace Slic3r::GUI
diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp
index 4261dbae2..b8bd7d907 100644
--- a/src/slic3r/GUI/Plater.hpp
+++ b/src/slic3r/GUI/Plater.hpp
@@ -178,6 +178,19 @@ public:
     PrinterTechnology   printer_technology() const;
     void                set_printer_technology(PrinterTechnology printer_technology);
 
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+#if ENABLE_CANVAS_GUI_REFACTORING
+    bool can_delete() const;
+    bool can_delete_all() const;
+    bool can_increase_instances() const;
+    bool can_decrease_instances() const;
+    bool can_split_to_objects() const;
+    bool can_split_to_volumes() const;
+    bool can_arrange() const;
+    bool can_layers_editing() const;
+#endif // ENABLE_CANVAS_GUI_REFACTORING
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
 private:
     struct priv;
     std::unique_ptr<priv> p;

From 42939e76a335319d391dce846eb210d780dc261c Mon Sep 17 00:00:00 2001
From: Enrico Turri <enricoturri@seznam.cz>
Date: Tue, 19 Mar 2019 09:21:27 +0100
Subject: [PATCH 2/8] Code cleanup

---
 src/libslic3r/Technologies.hpp |   2 -
 src/slic3r/GUI/GLCanvas3D.cpp  | 122 ++-------------------------------
 src/slic3r/GUI/GLCanvas3D.hpp  |  16 -----
 src/slic3r/GUI/GLToolbar.cpp   |  62 -----------------
 src/slic3r/GUI/GLToolbar.hpp   |  46 -------------
 src/slic3r/GUI/GUI_Preview.cpp |   4 --
 src/slic3r/GUI/GUI_Preview.hpp |   4 --
 src/slic3r/GUI/Plater.cpp      |  86 -----------------------
 src/slic3r/GUI/Plater.hpp      |   2 -
 9 files changed, 7 insertions(+), 337 deletions(-)

diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp
index bbf746cda..bf869b99d 100644
--- a/src/libslic3r/Technologies.hpp
+++ b/src/libslic3r/Technologies.hpp
@@ -59,8 +59,6 @@
 #define ENABLE_SVG_ICONS (1 && ENABLE_1_42_0_ALPHA8 && ENABLE_TEXTURES_FROM_SVG)
 
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #define ENABLE_CANVAS_GUI_REFACTORING 1
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 #endif // _technologies_h_
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index c152b0bf2..8dcb58cbb 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -733,13 +733,9 @@ GLCanvas3D::Mouse::Drag::Drag()
 
 GLCanvas3D::Mouse::Mouse()
     : dragging(false)
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     , left_down(false)
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     , position(DBL_MAX, DBL_MAX)
     , scene_position(DBL_MAX, DBL_MAX, DBL_MAX)
     , ignore_up_event(false)
@@ -3721,13 +3717,9 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar
     , m_use_VBOs(false)
     , m_apply_zoom_to_volumes_filter(false)
     , m_hover_volume_id(-1)
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     , m_toolbar_action_running(false)
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     , m_legend_texture_enabled(false)
     , m_picking_enabled(false)
     , m_moving_enabled(false)
@@ -4031,9 +4023,7 @@ void GLCanvas3D::allow_multisample(bool allow)
     m_multisample_allowed = allow;
 }
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 void GLCanvas3D::enable_toolbar_item(const std::string& name, bool enable)
 {
     if (enable)
@@ -4046,9 +4036,7 @@ bool GLCanvas3D::is_toolbar_item_pressed(const std::string& name) const
 {
     return m_toolbar.is_item_pressed(name);
 }
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 void GLCanvas3D::zoom_to_bed()
 {
@@ -4102,9 +4090,7 @@ void GLCanvas3D::update_volumes_colors_by_extruder()
         m_volumes.update_colors_by_extruder(m_config);
 }
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 void GLCanvas3D::update_toolbar_items_visibility()
 {
     ConfigOptionMode mode = wxGetApp().get_mode();
@@ -4113,10 +4099,7 @@ void GLCanvas3D::update_toolbar_items_visibility()
     m_toolbar.set_item_visible("splitvolumes", mode != comSimple);
     m_dirty = true;
 }
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
-
 
 void GLCanvas3D::render()
 {
@@ -4770,12 +4753,10 @@ void GLCanvas3D::on_size(wxSizeEvent& evt)
 
 void GLCanvas3D::on_idle(wxIdleEvent& evt)
 {
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     m_dirty |= m_toolbar.update_items_state();
     m_dirty |= m_view_toolbar.update_items_state();
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     if (!m_dirty)
         return;
@@ -5055,21 +5036,16 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
 #endif /* SLIC3R_DEBUG_MOUSE_EVENTS */
 	}
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
-//    if (!evt.Entering() && !evt.Leaving())
-//    {
-        bool processed_by_toolbar = m_toolbar.on_mouse(evt, *this);
-        processed_by_toolbar |= m_view_toolbar.on_mouse(evt, *this);
+    bool processed_by_toolbar = m_toolbar.on_mouse(evt, *this);
+    processed_by_toolbar |= m_view_toolbar.on_mouse(evt, *this);
 
-        if (processed_by_toolbar)
-        {
-            m_mouse.set_start_position_3D_as_invalid();
-            return;
-        }
-//    }
+    if (processed_by_toolbar)
+    {
+        m_mouse.set_start_position_3D_as_invalid();
+        return;
+    }
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     if (m_picking_enabled)
         _set_current();
@@ -5078,14 +5054,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
     int layer_editing_object_idx = is_layers_editing_enabled() ? selected_object_idx : -1;
     m_layers_editing.select_object(*m_model, layer_editing_object_idx);
     bool gizmos_overlay_contains_mouse = m_gizmos.overlay_contains_mouse(*this, m_mouse.position);
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     int toolbar_contains_mouse = m_toolbar.contains_mouse(m_mouse.position, *this);
     int view_toolbar_contains_mouse = m_view_toolbar.contains_mouse(m_mouse.position, *this);
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 #if ENABLE_MOVE_MIN_THRESHOLD
     if (m_mouse.drag.move_requires_threshold && m_mouse.is_move_start_threshold_position_2D_defined() && m_mouse.is_move_threshold_met(pos))
@@ -5127,41 +5099,29 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
     {
         // to remove hover on objects when the mouse goes out of this canvas
         m_mouse.position = Vec2d(-1.0, -1.0);
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         // ensure m_mouse.left_down is reset (it may happen when switching canvas)
         m_mouse.left_down = false;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         m_dirty = true;
     }
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     else if (evt.LeftDClick() && (toolbar_contains_mouse != -1))
     {
         m_toolbar_action_running = true;
         m_mouse.set_start_position_3D_as_invalid();
         m_toolbar.do_action((unsigned int)toolbar_contains_mouse, *this);
     }
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     else if (evt.LeftDClick() && (m_gizmos.get_current_type() != Gizmos::Undefined))
     {
         m_mouse.ignore_up_event = true;
     }
     else if (evt.LeftDown() || evt.RightDown())
     {
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         m_mouse.left_down = evt.LeftDown();
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
         // If user pressed left or right button we first check whether this happened
         // on a volume or not.
@@ -5214,9 +5174,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
         {
             // event was taken care of by the SlaSupports gizmo
         }
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         else if (evt.LeftDown() && (view_toolbar_contains_mouse != -1))
             m_view_toolbar.do_action((unsigned int)view_toolbar_contains_mouse, *this);
         else if (evt.LeftDown() && (toolbar_contains_mouse != -1))
@@ -5226,9 +5184,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
             m_toolbar.do_action((unsigned int)toolbar_contains_mouse, *this);
             m_mouse.left_down = false;
         }
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         else
         {
             // Select volume in this 3D canvas.
@@ -5394,15 +5350,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
         m_dirty = true;
     }
     // do not process dragging if the mouse is into any of the HUD elements
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     else if (evt.Dragging() && !gizmos_overlay_contains_mouse)
 #else
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     else if (evt.Dragging() && !gizmos_overlay_contains_mouse && (toolbar_contains_mouse == -1) && (view_toolbar_contains_mouse == -1))
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     {
         m_mouse.dragging = true;
 
@@ -5412,15 +5364,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
                 _perform_layer_editing_action(&evt);
         }
         // do not process the dragging if the left mouse was set down in another canvas
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
         else if (evt.LeftIsDown())
 #else
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         else if (m_mouse.left_down && evt.LeftIsDown())
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         {
             // if dragging over blank area with left button, rotate
 #if ENABLE_MOVE_MIN_THRESHOLD
@@ -5481,15 +5429,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
             // that's why the mouse_event function was called so that the gizmo can refuse the deselection in manual editing mode
 
             // deselect and propagate event through callback
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
             if (!evt.ShiftDown() && m_picking_enabled && !m_mouse.ignore_up_event)
 #else
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
             if (!evt.ShiftDown() && m_picking_enabled && !m_toolbar_action_running && !m_mouse.ignore_up_event)
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
             {
                 m_selection.clear();
                 m_selection.set_mode(Selection::Instance);
@@ -5569,14 +5513,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
         m_mouse.set_start_position_3D_as_invalid();
         m_mouse.set_start_position_2D_as_invalid();
         m_mouse.dragging = false;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         m_mouse.left_down = false;
         m_toolbar_action_running = false;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         m_dirty = true;
 
         if (m_canvas->HasCapture())
@@ -5592,7 +5532,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
         if (m_selection.is_empty())
             m_gizmos.reset_all_states();
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
         if (tooltip.empty())
             tooltip = m_toolbar.get_tooltip();
@@ -5600,7 +5539,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
         if (tooltip.empty())
             tooltip = m_view_toolbar.get_tooltip();
 #else
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         // updates toolbar overlay
         if (tooltip.empty())
             tooltip = m_toolbar.update_hover_state(m_mouse.position, *this);
@@ -5612,9 +5550,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
             if (!tooltip.empty())
                 m_dirty = true;
         }
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
         set_tooltip(tooltip);
 
@@ -6012,15 +5948,11 @@ bool GLCanvas3D::_init_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("Add...") + " [" + GUI::shortkey_ctrl_prefix() + "I]";
     item.sprite_id = 0;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_ADD)); };
 #else
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     item.action_event = EVT_GLTOOLBAR_ADD;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -6030,16 +5962,12 @@ bool GLCanvas3D::_init_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("Delete") + " [Del]";
     item.sprite_id = 1;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_DELETE)); };
     item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_delete(); };
 #else
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     item.action_event = EVT_GLTOOLBAR_DELETE;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -6049,16 +5977,12 @@ bool GLCanvas3D::_init_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("Delete all") + " [" + GUI::shortkey_ctrl_prefix() + "Del]";
     item.sprite_id = 2;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_DELETE_ALL)); };
     item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_delete_all(); };
 #else
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     item.action_event = EVT_GLTOOLBAR_DELETE_ALL;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -6068,16 +5992,12 @@ bool GLCanvas3D::_init_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("Arrange [A]");
     item.sprite_id = 3;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_ARRANGE)); };
     item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_arrange(); };
 #else
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     item.action_event = EVT_GLTOOLBAR_ARRANGE;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -6090,17 +6010,13 @@ bool GLCanvas3D::_init_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("Add instance [+]");
     item.sprite_id = 4;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_MORE)); };
     item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; };
     item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_increase_instances(); };
 #else
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     item.action_event = EVT_GLTOOLBAR_MORE;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -6110,17 +6026,13 @@ bool GLCanvas3D::_init_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("Remove instance [-]");
     item.sprite_id = 5;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_FEWER)); };
     item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; };
     item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_decrease_instances(); };
 #else
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     item.action_event = EVT_GLTOOLBAR_FEWER;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -6133,17 +6045,13 @@ bool GLCanvas3D::_init_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("Split to objects");
     item.sprite_id = 6;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_OBJECTS)); };
     item.visibility_callback = GLToolbarItem::Default_Visibility_Callback;
     item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_split_to_objects(); };
 #else
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     item.action_event = EVT_GLTOOLBAR_SPLIT_OBJECTS;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -6153,17 +6061,13 @@ bool GLCanvas3D::_init_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("Split to parts");
     item.sprite_id = 7;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_VOLUMES)); };
     item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; };
     item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_split_to_volumes(); };
 #else
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     item.action_event = EVT_GLTOOLBAR_SPLIT_VOLUMES;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -6177,29 +6081,21 @@ bool GLCanvas3D::_init_toolbar()
     item.tooltip = GUI::L_str("Layers editing");
     item.sprite_id = 8;
     item.is_toggable = true;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_LAYERSEDITING)); };
     item.visibility_callback = GLToolbarItem::Default_Visibility_Callback;
     item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_layers_editing(); };
 #else
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     item.action_event = EVT_GLTOOLBAR_LAYERSEDITING;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     if (!m_toolbar.add_item(item))
         return false;
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     enable_toolbar_item("add", true);
 
     update_toolbar_items_visibility();
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     return true;
 }
@@ -6402,15 +6298,11 @@ void GLCanvas3D::_picking_pass() const
 {
     const Vec2d& pos = m_mouse.position;
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     if (m_picking_enabled && !m_mouse.dragging && (pos != Vec2d(DBL_MAX, DBL_MAX)))
 #else
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     if (m_picking_enabled && !m_mouse.dragging && !m_mouse.left_down && (pos != Vec2d(DBL_MAX, DBL_MAX)))
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     {
         // Render the object for picking.
         // FIXME This cannot possibly work in a multi - sampled context as the color gets mangled by the anti - aliasing.
diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp
index b293857c5..229d70b4e 100644
--- a/src/slic3r/GUI/GLCanvas3D.hpp
+++ b/src/slic3r/GUI/GLCanvas3D.hpp
@@ -314,13 +314,9 @@ class GLCanvas3D
         };
 
         bool dragging;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         bool left_down;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         Vec2d position;
         Vec3d scene_position;
         Drag drag;
@@ -878,13 +874,9 @@ private:
     bool m_use_VBOs;
     bool m_apply_zoom_to_volumes_filter;
     mutable int m_hover_volume_id;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     bool m_toolbar_action_running;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     bool m_warning_texture_enabled;
     bool m_legend_texture_enabled;
     bool m_picking_enabled;
@@ -963,14 +955,10 @@ public:
     void enable_dynamic_background(bool enable);
     void allow_multisample(bool allow);
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     void enable_toolbar_item(const std::string& name, bool enable);
     bool is_toolbar_item_pressed(const std::string& name) const;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     void zoom_to_bed();
     void zoom_to_volumes();
@@ -979,13 +967,9 @@ public:
 
     void update_volumes_colors_by_extruder();
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     void update_toolbar_items_visibility();
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     bool is_dragging() const { return m_gizmos.is_dragging() || m_moving; }
 
diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp
index 9678776c8..715eb7442 100644
--- a/src/slic3r/GUI/GLToolbar.cpp
+++ b/src/slic3r/GUI/GLToolbar.cpp
@@ -30,13 +30,11 @@ wxDEFINE_EVENT(EVT_GLTOOLBAR_LAYERSEDITING, SimpleEvent);
 wxDEFINE_EVENT(EVT_GLVIEWTOOLBAR_3D, SimpleEvent);
 wxDEFINE_EVENT(EVT_GLVIEWTOOLBAR_PREVIEW, SimpleEvent);
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
 const GLToolbarItem::ActionCallback GLToolbarItem::Default_Action_Callback = [](){};
 const GLToolbarItem::VisibilityCallback GLToolbarItem::Default_Visibility_Callback = []()->bool { return true; };
 const GLToolbarItem::EnabledStateCallback GLToolbarItem::Default_Enabled_State_Callback = []()->bool { return true; };
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 GLToolbarItem::Data::Data()
     : name("")
@@ -47,43 +45,32 @@ GLToolbarItem::Data::Data()
     , sprite_id(-1)
     , is_toggable(false)
     , visible(true)
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     , action_callback(Default_Action_Callback)
     , visibility_callback(Default_Visibility_Callback)
     , enabled_state_callback(Default_Enabled_State_Callback)
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 {
 }
 
 GLToolbarItem::GLToolbarItem(GLToolbarItem::EType type, const GLToolbarItem::Data& data)
     : m_type(type)
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     , m_state(Normal)
 #else
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     , m_state(Disabled)
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     , m_data(data)
 {
 }
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 void GLToolbarItem::do_action(wxEvtHandler *target)
 {
     wxPostEvent(target, SimpleEvent(m_data.action_event));
 }
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
 bool GLToolbarItem::update_visibility()
 {
@@ -105,7 +92,6 @@ bool GLToolbarItem::update_enabled_state()
     return ret;
 }
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 void GLToolbarItem::render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const
 {
@@ -188,12 +174,10 @@ GLToolbar::GLToolbar(GLToolbar::EType type)
 #if ENABLE_SVG_ICONS
     , m_icons_texture_dirty(true)
 #endif // ENABLE_SVG_ICONS
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     , m_mouse_capture({false, false, false})
     , m_tooltip("")
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 {
 }
 
@@ -358,9 +342,7 @@ float GLToolbar::get_height() const
     return m_layout.height;
 }
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 void GLToolbar::enable_item(const std::string& name)
 {
     for (GLToolbarItem* item : m_items)
@@ -384,9 +366,7 @@ void GLToolbar::disable_item(const std::string& name)
         }
     }
 }
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 void GLToolbar::select_item(const std::string& name)
 {
@@ -436,9 +416,7 @@ bool GLToolbar::is_item_visible(const std::string& name) const
     return false;
 }
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 void GLToolbar::set_item_visible(const std::string& name, bool visible)
 {
     for (GLToolbarItem* item : m_items)
@@ -464,11 +442,8 @@ void GLToolbar::set_item_visible(const std::string& name, bool visible)
         }
     }
 }
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
 bool GLToolbar::update_items_state()
 {
@@ -478,11 +453,8 @@ bool GLToolbar::update_items_state()
     return ret;
 }
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 std::string GLToolbar::update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent)
 {
     if (!m_enabled)
@@ -546,9 +518,7 @@ void GLToolbar::do_action(unsigned int item_id, GLCanvas3D& parent)
         }
     }
 }
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 void GLToolbar::render(const GLCanvas3D& parent) const
 {
@@ -575,7 +545,6 @@ void GLToolbar::render(const GLCanvas3D& parent) const
     ::glPopMatrix();
 }
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
 bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent)
 {
@@ -624,7 +593,6 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent)
     return processed;
 }
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 void GLToolbar::calc_layout() const
 {
@@ -715,7 +683,6 @@ float GLToolbar::get_main_size() const
     return size;
 }
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
 void GLToolbar::do_action(unsigned int item_id, GLCanvas3D& parent)
 {
@@ -768,7 +735,6 @@ std::string GLToolbar::update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& pa
     }
 }
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 std::string GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLCanvas3D& parent)
 {
@@ -979,7 +945,6 @@ std::string GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCan
     return tooltip;
 }
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
 int GLToolbar::contains_mouse(const Vec2d& mouse_pos, const GLCanvas3D& parent) const
 {
@@ -994,7 +959,6 @@ int GLToolbar::contains_mouse(const Vec2d& mouse_pos, const GLCanvas3D& parent)
     }
 }
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3D& parent) const
 {
@@ -1019,14 +983,10 @@ int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3
     float scaled_separator_size = m_layout.separator_size * factor;
     float scaled_gap_size = m_layout.gap_size * factor;
     float scaled_border = m_layout.border * factor;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     float separator_stride = scaled_separator_size + scaled_gap_size;
     float icon_stride = scaled_icons_size + scaled_gap_size;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     float left = m_layout.left + scaled_border;
     float top = m_layout.top - scaled_border;
@@ -1041,7 +1001,6 @@ int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3
             continue;
 
         if (item->is_separator())
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
         {
             float right = left + scaled_separator_size;
@@ -1064,11 +1023,8 @@ int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3
             left = right;
         }
 #else
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         left += separator_stride;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         else
         {
             float right = left + scaled_icons_size;
@@ -1078,7 +1034,6 @@ int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3
             if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
                 return id;
             
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
             left = right;
             right += scaled_gap_size;
@@ -1092,11 +1047,8 @@ int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3
 
             left = right;
 #else
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
             left += icon_stride;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         }
     }
     
@@ -1126,14 +1078,10 @@ int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D&
     float scaled_separator_size = m_layout.separator_size * factor;
     float scaled_gap_size = m_layout.gap_size * factor;
     float scaled_border = m_layout.border * factor;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     float separator_stride = scaled_separator_size + scaled_gap_size;
     float icon_stride = scaled_icons_size + scaled_gap_size;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     float left = m_layout.left + scaled_border;
     float top = m_layout.top - scaled_border;
@@ -1148,7 +1096,6 @@ int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D&
             continue;
 
         if (item->is_separator())
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
         {
             float right = left + scaled_icons_size;
@@ -1171,11 +1118,8 @@ int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D&
             top = bottom;
         }
 #else
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
             top -= separator_stride;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         else
         {
             float right = left + scaled_icons_size;
@@ -1185,7 +1129,6 @@ int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D&
             if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
                 return id;
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
             top = bottom;
             bottom -= scaled_gap_size;
@@ -1199,11 +1142,8 @@ int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D&
 
             top = bottom;
 #else
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
             top -= icon_stride;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         }
     }
 
@@ -1558,7 +1498,6 @@ bool GLToolbar::generate_icons_texture() const
 }
 #endif // ENABLE_SVG_ICONS
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
 bool GLToolbar::update_items_visibility()
 {
@@ -1603,7 +1542,6 @@ bool GLToolbar::update_items_enabled_state()
     return ret;
 }
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 } // namespace GUI
 } // namespace Slic3r
diff --git a/src/slic3r/GUI/GLToolbar.hpp b/src/slic3r/GUI/GLToolbar.hpp
index e6ef051d6..cd5d3f83f 100644
--- a/src/slic3r/GUI/GLToolbar.hpp
+++ b/src/slic3r/GUI/GLToolbar.hpp
@@ -31,13 +31,11 @@ wxDECLARE_EVENT(EVT_GLVIEWTOOLBAR_PREVIEW, SimpleEvent);
 class GLToolbarItem
 {
 public:
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     typedef std::function<void()> ActionCallback;
     typedef std::function<bool()> VisibilityCallback;
     typedef std::function<bool()> EnabledStateCallback;
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     enum EType : unsigned char
     {
@@ -65,32 +63,24 @@ public:
         std::string tooltip;
         unsigned int sprite_id;
         bool is_toggable;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         wxEventType action_event;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         bool visible;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
         ActionCallback action_callback;
         VisibilityCallback visibility_callback;
         EnabledStateCallback enabled_state_callback;
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
         Data();
     };
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     static const ActionCallback Default_Action_Callback;
     static const VisibilityCallback Default_Visibility_Callback;
     static const EnabledStateCallback Default_Enabled_State_Callback;
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 private:
     EType m_type;
@@ -109,15 +99,11 @@ public:
 #endif // ENABLE_SVG_ICONS
     const std::string& get_tooltip() const { return m_data.tooltip; }
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     void do_action() { m_data.action_callback(); }
 #else
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     void do_action(wxEvtHandler *target);
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     bool is_enabled() const { return m_state != Disabled; }
     bool is_disabled() const { return m_state == Disabled; }
@@ -126,35 +112,27 @@ public:
 
     bool is_toggable() const { return m_data.is_toggable; }
     bool is_visible() const { return m_data.visible; }
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     void set_visible(bool visible) { m_data.visible = visible; }
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     bool is_separator() const { return m_type == Separator; }
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     // returns true if the state changes
     bool update_visibility();
     // returns true if the state changes
     bool update_enabled_state();
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     void render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const;
 
 private:
     GLTexture::Quad_UVs get_uvs(unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     void set_visible(bool visible) { m_data.visible = visible; }
 
     friend class GLToolbar;
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 };
 
 #if !ENABLE_SVG_ICONS
@@ -272,7 +250,6 @@ private:
     mutable Layout m_layout;
 
     ItemsList m_items;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     struct MouseCapture
     {
@@ -286,7 +263,6 @@ private:
     MouseCapture m_mouse_capture;
     std::string m_tooltip;
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 public:
 #if ENABLE_SVG_ICONS
@@ -327,58 +303,42 @@ public:
     float get_width() const;
     float get_height() const;
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     void enable_item(const std::string& name);
     void disable_item(const std::string& name);
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     void select_item(const std::string& name);
 
     bool is_item_pressed(const std::string& name) const;
     bool is_item_disabled(const std::string& name) const;
     bool is_item_visible(const std::string& name) const;
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     const std::string& get_tooltip() const { return m_tooltip; }
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     // returns true if any item changed its state
     bool update_items_state();
 #else
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     void set_item_visible(const std::string& name, bool visible);
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     std::string update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent);
 
     // returns the id of the item under the given mouse position or -1 if none
     int contains_mouse(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;
 
     void do_action(unsigned int item_id, GLCanvas3D& parent);
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     void render(const GLCanvas3D& parent) const;    
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     bool on_mouse(wxMouseEvent& evt, GLCanvas3D& parent);
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 private:
     void calc_layout() const;
@@ -387,20 +347,16 @@ private:
     float get_height_horizontal() const;
     float get_height_vertical() const;
     float get_main_size() const;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     void do_action(unsigned int item_id, GLCanvas3D& parent);
     std::string update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent);
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     std::string update_hover_state_horizontal(const Vec2d& mouse_pos, GLCanvas3D& parent);
     std::string update_hover_state_vertical(const Vec2d& mouse_pos, GLCanvas3D& parent);
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     // returns the id of the item under the given mouse position or -1 if none
     int contains_mouse(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     int contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;
     int contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;
 
@@ -411,14 +367,12 @@ private:
     bool generate_icons_texture() const;
 #endif // ENABLE_SVG_ICONS
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     // returns true if any item changed its state
     bool update_items_visibility();
     // returns true if any item changed its state
     bool update_items_enabled_state();
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 };
 
 } // namespace GUI
diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp
index dba51d06f..546815288 100644
--- a/src/slic3r/GUI/GUI_Preview.cpp
+++ b/src/slic3r/GUI/GUI_Preview.cpp
@@ -110,9 +110,7 @@ void View3D::mirror_selection(Axis axis)
         m_canvas->mirror_selection(axis);
 }
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 void View3D::update_toolbar_items_visibility()
 {
     if (m_canvas != nullptr)
@@ -124,9 +122,7 @@ void View3D::enable_toolbar_item(const std::string& name, bool enable)
     if (m_canvas != nullptr)
         m_canvas->enable_toolbar_item(name, enable);
 }
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 int View3D::check_volumes_outside_state() const
 {
diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp
index 2191cd263..6c413ca17 100644
--- a/src/slic3r/GUI/GUI_Preview.hpp
+++ b/src/slic3r/GUI/GUI_Preview.hpp
@@ -50,14 +50,10 @@ public:
     void delete_selected();
     void mirror_selection(Axis axis);
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     void update_toolbar_items_visibility();
     void enable_toolbar_item(const std::string& name, bool enable);
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     int check_volumes_outside_state() const;
 
     bool is_layers_editing_enabled() const;
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index 098a647d5..cbe6a8178 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -1217,7 +1217,6 @@ struct Plater::priv
     // Sets m_bed.m_polygon to limit the object placement.
     void set_bed_shape(const Pointfs& shape);
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     bool can_delete() const;
     bool can_delete_all() const;
@@ -1228,7 +1227,6 @@ struct Plater::priv
     bool can_arrange() const;
     bool can_layers_editing() const;
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 private:
     bool init_object_menu();
@@ -1238,34 +1236,22 @@ private:
     bool complit_init_part_menu();
     void init_view_toolbar();
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     bool can_delete_object() const;
     bool can_increase_instances() const;
     bool can_decrease_instances() const;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     bool can_set_instance_to_object() const;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     bool can_split_to_objects() const;
     bool can_split_to_volumes() const;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     bool can_split() const;
     bool layers_height_allowed() const;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     bool can_delete_all() const;
     bool can_arrange() const;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     bool can_mirror() const;
 
     void update_fff_scene();
@@ -1825,17 +1811,13 @@ int Plater::priv::get_selected_volume_idx() const
 
 void Plater::priv::selection_changed()
 {
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     view3D->enable_toolbar_item("delete", can_delete_object());
     view3D->enable_toolbar_item("more", can_increase_instances());
     view3D->enable_toolbar_item("fewer", can_decrease_instances());
     view3D->enable_toolbar_item("splitobjects", can_split());
     view3D->enable_toolbar_item("splitvolumes", printer_technology == ptFFF && can_split());
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     // if the selection is not valid to allow for layer editing, we need to turn off the tool if it is running
     bool enable_layer_editing = layers_height_allowed();
@@ -1844,13 +1826,9 @@ void Plater::priv::selection_changed()
         on_action_layersediting(evt);
     }
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     view3D->enable_toolbar_item("layersediting", enable_layer_editing);
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     // forces a frame render to update the view (to avoid a missed update if, for example, the context menu appears)
     view3D->render();
@@ -1858,15 +1836,11 @@ void Plater::priv::selection_changed()
 
 void Plater::priv::object_list_changed()
 {
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     // Enable/disable buttons depending on whether there are any objects on the platter.
     view3D->enable_toolbar_item("deleteall", can_delete_all());
     view3D->enable_toolbar_item("arrange", can_arrange());
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     const bool export_in_progress = this->background_process.is_export_scheduled(); // || ! send_gcode_file.empty());
     // XXX: is this right?
@@ -1946,14 +1920,10 @@ void Plater::priv::arrange()
 
     wxBusyCursor wait;
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     // Disable the arrange button (to prevent reentrancies, we will call wxYied)
     view3D->enable_toolbar_item("arrange", can_arrange());
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     this->background_process.stop();
     unsigned count = 0;
@@ -2025,14 +1995,10 @@ void Plater::priv::arrange()
     statusbar()->set_cancel_callback(); // remove cancel button
     arranging.store(false);
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     // We enable back the arrange button
     view3D->enable_toolbar_item("arrange", can_arrange());
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     // Do a full refresh of scene tree, including regenerating all the GLVolumes.
     //FIXME The update function shall just reload the modified matrices.
@@ -2594,16 +2560,12 @@ void Plater::priv::on_process_completed(wxCommandEvent &evt)
 void Plater::priv::on_layer_editing_toggled(bool enable)
 {
     view3D->enable_layers_editing(enable);
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     if (enable && !view3D->is_layers_editing_enabled()) {
         // Initialization of the OpenGL shaders failed. Disable the tool.
         view3D->enable_toolbar_item("layersediting", false);
     }
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     view3D->set_as_dirty();
 }
 
@@ -2625,18 +2587,14 @@ void Plater::priv::on_action_split_volumes(SimpleEvent&)
 
 void Plater::priv::on_action_layersediting(SimpleEvent&)
 {
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     view3D->enable_layers_editing(!view3D->is_layers_editing_enabled());
 #else
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     bool enable = !view3D->is_layers_editing_enabled();
     view3D->enable_layers_editing(enable);
     if (enable && !view3D->is_layers_editing_enabled())
         view3D->enable_toolbar_item("layersediting", false);
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 }
 
 void Plater::priv::on_object_select(SimpleEvent& evt)
@@ -2761,15 +2719,11 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
     if (q != nullptr)
     {
         q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_mirror()); }, item_mirror->GetId());
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
         q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete()); }, item_delete->GetId());
 #else
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete_object()); }, item_delete->GetId());
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     }
 
     return true;
@@ -2874,15 +2828,11 @@ void Plater::priv::init_view_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("3D editor view") + " [" + GUI::shortkey_ctrl_prefix() + "5]";
     item.sprite_id = 0;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     item.action_callback = [this]() { if (this->q != nullptr) wxPostEvent(this->q, SimpleEvent(EVT_GLVIEWTOOLBAR_3D)); };
 #else
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     item.action_event = EVT_GLVIEWTOOLBAR_3D;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     item.is_toggable = false;
     if (!view_toolbar.add_item(item))
         return;
@@ -2893,35 +2843,25 @@ void Plater::priv::init_view_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("Preview") + " [" + GUI::shortkey_ctrl_prefix() + "6]";
     item.sprite_id = 1;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     item.action_callback = [this]() { if (this->q != nullptr) wxPostEvent(this->q, SimpleEvent(EVT_GLVIEWTOOLBAR_PREVIEW)); };
 #else
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     item.action_event = EVT_GLVIEWTOOLBAR_PREVIEW;
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     item.is_toggable = false;
     if (!view_toolbar.add_item(item))
         return;
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     view_toolbar.enable_item("3D");
     view_toolbar.enable_item("Preview");
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
     view_toolbar.select_item("3D");
     view_toolbar.set_enabled(true);
 }
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 bool Plater::priv::can_delete_object() const
 {
     int obj_idx = get_selected_object_idx();
@@ -2933,9 +2873,7 @@ bool Plater::priv::can_increase_instances() const
     int obj_idx = get_selected_object_idx();
     return (0 <= obj_idx) && (obj_idx < (int)model.objects.size());
 }
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 bool Plater::priv::can_set_instance_to_object() const
 {
@@ -2943,9 +2881,7 @@ bool Plater::priv::can_set_instance_to_object() const
     return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && (model.objects[obj_idx]->instances.size() > 1);
 }
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 bool Plater::priv::can_decrease_instances() const
 {
     int obj_idx = get_selected_object_idx();
@@ -2966,9 +2902,7 @@ bool Plater::priv::can_split_to_volumes() const
 //     return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && !model.objects[obj_idx]->is_multiparts();
     return sidebar->obj_list()->is_splittable();
 }
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 bool Plater::priv::can_split() const
 {
@@ -2981,9 +2915,7 @@ bool Plater::priv::layers_height_allowed() const
     return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && config->opt_bool("variable_layer_height") && view3D->is_layers_editing_allowed();
 }
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 bool Plater::priv::can_delete_all() const
 {
     return !model.objects.empty();
@@ -2993,9 +2925,7 @@ bool Plater::priv::can_arrange() const
 {
     return !model.objects.empty() && !arranging.load();
 }
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 bool Plater::priv::can_mirror() const
 {
@@ -3012,7 +2942,6 @@ void Plater::priv::set_bed_shape(const Pointfs& shape)
     }
 }
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
 bool Plater::priv::can_delete() const
 {
@@ -3056,19 +2985,14 @@ bool Plater::priv::can_layers_editing() const
     return layers_height_allowed();
 }
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 void Plater::priv::update_object_menu()
 {
     sidebar->obj_list()->append_menu_items_add_volume(&object_menu);
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     if (view3D != nullptr)
         view3D->update_toolbar_items_visibility();
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 }
 
 void Plater::priv::show_action_buttons(const bool is_ready_to_slice) const 
@@ -3551,25 +3475,17 @@ void Plater::on_config_change(const DynamicPrintConfig &config)
         } 
         else if(opt_key == "variable_layer_height") {
             if (p->config->opt_bool("variable_layer_height") != true) {
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
                 p->view3D->enable_toolbar_item("layersediting", false);
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
                 p->view3D->enable_layers_editing(false);
                 p->view3D->set_as_dirty();
             }
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
             else if (p->view3D->is_layers_editing_allowed()) {
                 p->view3D->enable_toolbar_item("layersediting", true);
             }
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
         }
         else if(opt_key == "extruder_colour") {
             update_scheduled = true;
@@ -3691,7 +3607,6 @@ void Plater::fix_through_netfabb(const int obj_idx, const int vol_idx/* = -1*/)
 
 void Plater::update_object_menu() { p->update_object_menu(); }
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
 bool Plater::can_delete() const { return p->can_delete(); }
 bool Plater::can_delete_all() const { return p->can_delete_all(); }
@@ -3702,6 +3617,5 @@ bool Plater::can_split_to_volumes() const { return p->can_split_to_volumes(); }
 bool Plater::can_arrange() const { return p->can_arrange(); }
 bool Plater::can_layers_editing() const { return p->can_layers_editing(); }
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 }}    // namespace Slic3r::GUI
diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp
index eede860ca..8746c1eef 100644
--- a/src/slic3r/GUI/Plater.hpp
+++ b/src/slic3r/GUI/Plater.hpp
@@ -176,7 +176,6 @@ public:
     PrinterTechnology   printer_technology() const;
     void                set_printer_technology(PrinterTechnology printer_technology);
 
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 #if ENABLE_CANVAS_GUI_REFACTORING
     bool can_delete() const;
     bool can_delete_all() const;
@@ -187,7 +186,6 @@ public:
     bool can_arrange() const;
     bool can_layers_editing() const;
 #endif // ENABLE_CANVAS_GUI_REFACTORING
-//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 private:
     struct priv;

From 334b5a82a630f5423cd971d2eecfa8a3be46ed21 Mon Sep 17 00:00:00 2001
From: Enrico Turri <enricoturri@seznam.cz>
Date: Tue, 19 Mar 2019 10:04:19 +0100
Subject: [PATCH 3/8] Tech ENABLE_MOVE_MIN_THRESHOLD set as default

---
 src/libslic3r/Technologies.hpp |  2 --
 src/slic3r/GUI/GLCanvas3D.cpp  | 16 ----------------
 src/slic3r/GUI/GLCanvas3D.hpp  |  8 --------
 3 files changed, 26 deletions(-)

diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp
index bf869b99d..156a225bf 100644
--- a/src/libslic3r/Technologies.hpp
+++ b/src/libslic3r/Technologies.hpp
@@ -33,8 +33,6 @@
 
 // Changed algorithm to extract euler angles from rotation matrix
 #define ENABLE_NEW_EULER_ANGLES (1 && ENABLE_1_42_0_ALPHA4)
-// Added minimum threshold for click and drag movements
-#define ENABLE_MOVE_MIN_THRESHOLD (1 && ENABLE_1_42_0_ALPHA4)
 // Modified initial default placement of generic subparts
 #define ENABLE_GENERIC_SUBPARTS_PLACEMENT (1 && ENABLE_1_42_0_ALPHA4)
 // Bunch of fixes related to volumes centering
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index 8dcb58cbb..2f7ed8c38 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -716,18 +716,14 @@ float GLCanvas3D::LayersEditing::reset_button_height(const GLCanvas3D &canvas)
 
 const Point GLCanvas3D::Mouse::Drag::Invalid_2D_Point(INT_MAX, INT_MAX);
 const Vec3d GLCanvas3D::Mouse::Drag::Invalid_3D_Point(DBL_MAX, DBL_MAX, DBL_MAX);
-#if ENABLE_MOVE_MIN_THRESHOLD
 const int GLCanvas3D::Mouse::Drag::MoveThresholdPx = 5;
-#endif // ENABLE_MOVE_MIN_THRESHOLD
 
 GLCanvas3D::Mouse::Drag::Drag()
     : start_position_2D(Invalid_2D_Point)
     , start_position_3D(Invalid_3D_Point)
     , move_volume_idx(-1)
-#if ENABLE_MOVE_MIN_THRESHOLD
     , move_requires_threshold(false)
     , move_start_threshold_position_2D(Invalid_2D_Point)
-#endif // ENABLE_MOVE_MIN_THRESHOLD
 {
 }
 
@@ -5059,13 +5055,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
     int view_toolbar_contains_mouse = m_view_toolbar.contains_mouse(m_mouse.position, *this);
 #endif // !ENABLE_CANVAS_GUI_REFACTORING
 
-#if ENABLE_MOVE_MIN_THRESHOLD
     if (m_mouse.drag.move_requires_threshold && m_mouse.is_move_start_threshold_position_2D_defined() && m_mouse.is_move_threshold_met(pos))
     {
         m_mouse.drag.move_requires_threshold = false;
         m_mouse.set_move_start_threshold_position_2D_as_invalid();
     }
-#endif // ENABLE_MOVE_MIN_THRESHOLD
 
     if (evt.ButtonDown() && wxWindow::FindFocus() != this->m_canvas)
         // Grab keyboard focus on any mouse click event.
@@ -5206,13 +5200,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
                     {
                         bool add_as_single = !already_selected && !shift_down;
                         m_selection.add(m_hover_volume_id, add_as_single);
-#if ENABLE_MOVE_MIN_THRESHOLD
                         m_mouse.drag.move_requires_threshold = !already_selected;
                         if (already_selected)
                             m_mouse.set_move_start_threshold_position_2D_as_invalid();
                         else
                             m_mouse.drag.move_start_threshold_position_2D = pos;
-#endif // ENABLE_MOVE_MIN_THRESHOLD
                     }
 
                     if (curr_idxs != m_selection.get_volume_idxs())
@@ -5249,10 +5241,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
     else if (evt.Dragging() && evt.LeftIsDown() && !gizmos_overlay_contains_mouse && (m_layers_editing.state == LayersEditing::Unknown)
           && (m_mouse.drag.move_volume_idx != -1) && m_gizmos.get_current_type() != Gizmos::SlaSupports /* don't allow dragging objects with the Sla gizmo on */)
     {
-#if ENABLE_MOVE_MIN_THRESHOLD
         if (!m_mouse.drag.move_requires_threshold)
         {
-#endif // ENABLE_MOVE_MIN_THRESHOLD
             m_mouse.dragging = true;
 
             Vec3d cur_pos = m_mouse.drag.start_position_3D;
@@ -5300,9 +5290,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
             wxGetApp().obj_manipul()->update_settings_value(m_selection);
 
             m_dirty = true;
-#if ENABLE_MOVE_MIN_THRESHOLD
         }
-#endif // ENABLE_MOVE_MIN_THRESHOLD
     }
     else if (evt.Dragging() && m_gizmos.is_dragging())
     {
@@ -5371,11 +5359,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
 #endif // ENABLE_CANVAS_GUI_REFACTORING
         {
             // if dragging over blank area with left button, rotate
-#if ENABLE_MOVE_MIN_THRESHOLD
             if ((m_hover_volume_id == -1) && m_mouse.is_start_position_3D_defined())
-#else
-            if (m_mouse.is_start_position_3D_defined())
-#endif // ENABLE_MOVE_MIN_THRESHOLD
             {
                 const Vec3d& orig = m_mouse.drag.start_position_3D;
                 m_camera.phi += (((float)pos(0) - (float)orig(0)) * TRACKBALLSIZE);
diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp
index 229d70b4e..639d10120 100644
--- a/src/slic3r/GUI/GLCanvas3D.hpp
+++ b/src/slic3r/GUI/GLCanvas3D.hpp
@@ -297,17 +297,13 @@ class GLCanvas3D
         {
             static const Point Invalid_2D_Point;
             static const Vec3d Invalid_3D_Point;
-#if ENABLE_MOVE_MIN_THRESHOLD
             static const int MoveThresholdPx;
-#endif // ENABLE_MOVE_MIN_THRESHOLD
 
             Point start_position_2D;
             Vec3d start_position_3D;
             int move_volume_idx;
-#if ENABLE_MOVE_MIN_THRESHOLD
             bool move_requires_threshold;
             Point move_start_threshold_position_2D;
-#endif // ENABLE_MOVE_MIN_THRESHOLD
 
         public:
             Drag();
@@ -326,19 +322,15 @@ class GLCanvas3D
 
         void set_start_position_2D_as_invalid() { drag.start_position_2D = Drag::Invalid_2D_Point; }
         void set_start_position_3D_as_invalid() { drag.start_position_3D = Drag::Invalid_3D_Point; }
-#if ENABLE_MOVE_MIN_THRESHOLD
         void set_move_start_threshold_position_2D_as_invalid() { drag.move_start_threshold_position_2D = Drag::Invalid_2D_Point; }
-#endif // ENABLE_MOVE_MIN_THRESHOLD
 
         bool is_start_position_2D_defined() const { return (drag.start_position_2D != Drag::Invalid_2D_Point); }
         bool is_start_position_3D_defined() const { return (drag.start_position_3D != Drag::Invalid_3D_Point); }
-#if ENABLE_MOVE_MIN_THRESHOLD
         bool is_move_start_threshold_position_2D_defined() const { return (drag.move_start_threshold_position_2D != Drag::Invalid_2D_Point); }
         bool is_move_threshold_met(const Point& mouse_pos) const {
             return (std::abs(mouse_pos(0) - drag.move_start_threshold_position_2D(0)) > Drag::MoveThresholdPx)
                 || (std::abs(mouse_pos(1) - drag.move_start_threshold_position_2D(1)) > Drag::MoveThresholdPx);
         }
-#endif // ENABLE_MOVE_MIN_THRESHOLD
     };
 
 public:

From 80c1a8d8e4fe3611f1bc2ca47fac136ffe6a1892 Mon Sep 17 00:00:00 2001
From: Enrico Turri <enricoturri@seznam.cz>
Date: Tue, 19 Mar 2019 13:30:21 +0100
Subject: [PATCH 4/8] GLCanvas3D::Selection as a standalone class

---
 src/slic3r/CMakeLists.txt                    |    2 +
 src/slic3r/GUI/GLCanvas3D.cpp                | 1669 +----------------
 src/slic3r/GUI/GLCanvas3D.hpp                |  289 +--
 src/slic3r/GUI/GUI_ObjectList.cpp            |   15 +-
 src/slic3r/GUI/GUI_ObjectManipulation.cpp    |   16 +-
 src/slic3r/GUI/GUI_ObjectManipulation.hpp    |    4 +-
 src/slic3r/GUI/Gizmos/GLGizmoBase.cpp        |    4 +-
 src/slic3r/GUI/Gizmos/GLGizmoBase.hpp        |   25 +-
 src/slic3r/GUI/Gizmos/GLGizmoCut.cpp         |   16 +-
 src/slic3r/GUI/Gizmos/GLGizmoCut.hpp         |   16 +-
 src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp     |    8 +-
 src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp     |   10 +-
 src/slic3r/GUI/Gizmos/GLGizmoMove.cpp        |   10 +-
 src/slic3r/GUI/Gizmos/GLGizmoMove.hpp        |   10 +-
 src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp      |   18 +-
 src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp      |   24 +-
 src/slic3r/GUI/Gizmos/GLGizmoScale.cpp       |   12 +-
 src/slic3r/GUI/Gizmos/GLGizmoScale.hpp       |   12 +-
 src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp |   22 +-
 src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp |   16 +-
 src/slic3r/GUI/Plater.cpp                    |   11 +-
 src/slic3r/GUI/Selection.cpp                 | 1670 ++++++++++++++++++
 src/slic3r/GUI/Selection.hpp                 |  301 ++++
 23 files changed, 2111 insertions(+), 2069 deletions(-)
 create mode 100644 src/slic3r/GUI/Selection.cpp
 create mode 100644 src/slic3r/GUI/Selection.hpp

diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt
index 219f17082..ef60ab3fa 100644
--- a/src/slic3r/CMakeLists.txt
+++ b/src/slic3r/CMakeLists.txt
@@ -28,6 +28,8 @@ set(SLIC3R_GUI_SOURCES
     GUI/GLCanvas3D.cpp
     GUI/GLCanvas3DManager.hpp
     GUI/GLCanvas3DManager.cpp
+    GUI/Selection.hpp
+    GUI/Selection.cpp    
     GUI/Gizmos/GLGizmoBase.cpp
     GUI/Gizmos/GLGizmoBase.hpp
     GUI/Gizmos/GLGizmoMove.cpp
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index 68b343ba5..1236ee7b4 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -1,9 +1,9 @@
+#include "libslic3r/libslic3r.h"
 #include "slic3r/GUI/Gizmos/GLGizmos.hpp"
 #include "GLCanvas3D.hpp"
 
 #include "admesh/stl.h"
 #include "polypartition.h"
-#include "libslic3r/libslic3r.h"
 #include "libslic3r/ClipperUtils.hpp"
 #include "libslic3r/PrintConfig.hpp"
 #include "libslic3r/GCode/PreviewData.hpp"
@@ -76,7 +76,6 @@ static const float DEFAULT_BG_DARK_COLOR[3] = { 0.478f, 0.478f, 0.478f };
 static const float DEFAULT_BG_LIGHT_COLOR[3] = { 0.753f, 0.753f, 0.753f };
 static const float ERROR_BG_DARK_COLOR[3] = { 0.478f, 0.192f, 0.039f };
 static const float ERROR_BG_LIGHT_COLOR[3] = { 0.753f, 0.192f, 0.039f };
-static const float UNIFORM_SCALE_COLOR[3] = { 1.0f, 0.38f, 0.0f };
 //static const float AXES_COLOR[3][3] = { { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f } };
 
 namespace Slic3r {
@@ -738,1654 +737,6 @@ GLCanvas3D::Mouse::Mouse()
 {
 }
 
-GLCanvas3D::Selection::VolumeCache::TransformCache::TransformCache()
-    : position(Vec3d::Zero())
-    , rotation(Vec3d::Zero())
-    , scaling_factor(Vec3d::Ones())
-    , mirror(Vec3d::Ones())
-    , rotation_matrix(Transform3d::Identity())
-    , scale_matrix(Transform3d::Identity())
-    , mirror_matrix(Transform3d::Identity())
-    , full_matrix(Transform3d::Identity())
-{
-}
-
-GLCanvas3D::Selection::VolumeCache::TransformCache::TransformCache(const Geometry::Transformation& transform)
-    : position(transform.get_offset())
-    , rotation(transform.get_rotation())
-    , scaling_factor(transform.get_scaling_factor())
-    , mirror(transform.get_mirror())
-    , full_matrix(transform.get_matrix())
-{
-    rotation_matrix = Geometry::assemble_transform(Vec3d::Zero(), rotation);
-    scale_matrix = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), scaling_factor);
-    mirror_matrix = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), Vec3d::Ones(), mirror);
-}
-
-GLCanvas3D::Selection::VolumeCache::VolumeCache(const Geometry::Transformation& volume_transform, const Geometry::Transformation& instance_transform)
-    : m_volume(volume_transform)
-    , m_instance(instance_transform)
-{
-}
-
-GLCanvas3D::Selection::Selection()
-    : m_volumes(nullptr)
-    , m_model(nullptr)
-    , m_mode(Instance)
-    , m_type(Empty)
-    , m_valid(false)
-    , m_bounding_box_dirty(true)
-    , m_curved_arrow(16)
-    , m_scale_factor(1.0f)
-{
-#if ENABLE_RENDER_SELECTION_CENTER
-    m_quadric = ::gluNewQuadric();
-    if (m_quadric != nullptr)
-        ::gluQuadricDrawStyle(m_quadric, GLU_FILL);
-#endif // ENABLE_RENDER_SELECTION_CENTER
-}
-
-#if ENABLE_RENDER_SELECTION_CENTER
-GLCanvas3D::Selection::~Selection()
-{
-    if (m_quadric != nullptr)
-        ::gluDeleteQuadric(m_quadric);
-}
-#endif // ENABLE_RENDER_SELECTION_CENTER
-
-void GLCanvas3D::Selection::set_volumes(GLVolumePtrs* volumes)
-{
-    m_volumes = volumes;
-    _update_valid();
-}
-
-bool GLCanvas3D::Selection::init(bool useVBOs)
-{
-    if (!m_arrow.init(useVBOs))
-        return false;
-
-    m_arrow.set_scale(5.0 * Vec3d::Ones());
-
-    if (!m_curved_arrow.init(useVBOs))
-        return false;
-
-    m_curved_arrow.set_scale(5.0 * Vec3d::Ones());
-    return true;
-}
-
-void GLCanvas3D::Selection::set_model(Model* model)
-{
-    m_model = model;
-    _update_valid();
-}
-
-void GLCanvas3D::Selection::add(unsigned int volume_idx, bool as_single_selection)
-{
-    if (!m_valid || ((unsigned int)m_volumes->size() <= volume_idx))
-        return;
-
-    const GLVolume* volume = (*m_volumes)[volume_idx];
-    // wipe tower is already selected
-    if (is_wipe_tower() && volume->is_wipe_tower)
-        return;
-
-    // resets the current list if needed
-    bool needs_reset = as_single_selection;
-    needs_reset |= volume->is_wipe_tower;
-    needs_reset |= is_wipe_tower() && !volume->is_wipe_tower;
-    needs_reset |= !is_modifier() && volume->is_modifier;
-    needs_reset |= is_modifier() && !volume->is_modifier;
-
-    if (needs_reset)
-        clear();
-
-    if (volume->is_modifier)
-        m_mode = Volume;
-    else if (!contains_volume(volume_idx))
-        m_mode = Instance;
-    // else -> keep current mode
-
-    switch (m_mode)
-    {
-    case Volume:
-    {
-        if (volume->volume_idx() >= 0 && (is_empty() || (volume->instance_idx() == get_instance_idx())))
-            _add_volume(volume_idx);
-
-        break;
-    }
-    case Instance:
-    {
-        _add_instance(volume->object_idx(), volume->instance_idx());
-        break;
-    }
-    }
-
-    _update_type();
-    m_bounding_box_dirty = true;
-}
-
-void GLCanvas3D::Selection::remove(unsigned int volume_idx)
-{
-    if (!m_valid || ((unsigned int)m_volumes->size() <= volume_idx))
-        return;
-
-    GLVolume* volume = (*m_volumes)[volume_idx];
-
-    switch (m_mode)
-    {
-    case Volume:
-    {
-        _remove_volume(volume_idx);
-        break;
-    }
-    case Instance:
-    {
-        _remove_instance(volume->object_idx(), volume->instance_idx());
-        break;
-    }
-    }
-
-    _update_type();
-    m_bounding_box_dirty = true;
-}
-
-void GLCanvas3D::Selection::add_object(unsigned int object_idx, bool as_single_selection)
-{
-    if (!m_valid)
-        return;
-
-    // resets the current list if needed
-    if (as_single_selection)
-        clear();
-
-    m_mode = Instance;
-
-    _add_object(object_idx);
-
-    _update_type();
-    m_bounding_box_dirty = true;
-}
-
-void GLCanvas3D::Selection::remove_object(unsigned int object_idx)
-{
-    if (!m_valid)
-        return;
-
-    _remove_object(object_idx);
-
-    _update_type();
-    m_bounding_box_dirty = true;
-}
-
-void GLCanvas3D::Selection::add_instance(unsigned int object_idx, unsigned int instance_idx, bool as_single_selection)
-{
-    if (!m_valid)
-        return;
-
-    // resets the current list if needed
-    if (as_single_selection)
-        clear();
-
-    m_mode = Instance;
-
-    _add_instance(object_idx, instance_idx);
-
-    _update_type();
-    m_bounding_box_dirty = true;
-}
-
-void GLCanvas3D::Selection::remove_instance(unsigned int object_idx, unsigned int instance_idx)
-{
-    if (!m_valid)
-        return;
-
-    _remove_instance(object_idx, instance_idx);
-
-    _update_type();
-    m_bounding_box_dirty = true;
-}
-
-void GLCanvas3D::Selection::add_volume(unsigned int object_idx, unsigned int volume_idx, int instance_idx, bool as_single_selection)
-{
-    if (!m_valid)
-        return;
-
-    // resets the current list if needed
-    if (as_single_selection)
-        clear();
-
-    m_mode = Volume;
-
-    for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
-    {
-        GLVolume* v = (*m_volumes)[i];
-        if ((v->object_idx() == object_idx) && (v->volume_idx() == volume_idx))
-        {
-            if ((instance_idx != -1) && (v->instance_idx() == instance_idx))
-                _add_volume(i);
-        }
-    }
-
-    _update_type();
-    m_bounding_box_dirty = true;
-}
-
-void GLCanvas3D::Selection::remove_volume(unsigned int object_idx, unsigned int volume_idx)
-{
-    if (!m_valid)
-        return;
-
-    for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
-    {
-        GLVolume* v = (*m_volumes)[i];
-        if ((v->object_idx() == object_idx) && (v->volume_idx() == volume_idx))
-            _remove_volume(i);
-    }
-
-    _update_type();
-    m_bounding_box_dirty = true;
-}
-
-void GLCanvas3D::Selection::add_all()
-{
-    if (!m_valid)
-        return;
-
-    m_mode = Instance;
-    clear();
-
-    for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
-    {
-        if (!(*m_volumes)[i]->is_wipe_tower)
-            _add_volume(i);
-    }
-
-    _update_type();
-    m_bounding_box_dirty = true;
-}
-
-void GLCanvas3D::Selection::clear()
-{
-    if (!m_valid)
-        return;
-
-    for (unsigned int i : m_list)
-    {
-        (*m_volumes)[i]->selected = false;
-    }
-
-    m_list.clear();
-
-    _update_type();
-    m_bounding_box_dirty = true;
-
-    // resets the cache in the sidebar
-    wxGetApp().obj_manipul()->reset_cache();
-}
-
-// Update the selection based on the map from old indices to new indices after m_volumes changed.
-// If the current selection is by instance, this call may select newly added volumes, if they belong to already selected instances.
-void GLCanvas3D::Selection::volumes_changed(const std::vector<size_t> &map_volume_old_to_new)
-{
-    assert(m_valid);
-
-    // 1) Update the selection set.
-    IndicesList list_new;
-    std::vector<std::pair<unsigned int, unsigned int>> model_instances;
-    for (unsigned int idx : m_list) {
-		if (map_volume_old_to_new[idx] != size_t(-1)) {
-			unsigned int new_idx = (unsigned int)map_volume_old_to_new[idx];
-			list_new.insert(new_idx);
-			if (m_mode == Instance) {
-                // Save the object_idx / instance_idx pair of selected old volumes,
-                // so we may add the newly added volumes of the same object_idx / instance_idx pair
-                // to the selection.
-				const GLVolume *volume = (*m_volumes)[new_idx];
-				model_instances.emplace_back(volume->object_idx(), volume->instance_idx());
-			}
-        }
-    }
-	m_list = std::move(list_new);
-
-    if (! model_instances.empty()) {
-        // Instance selection mode. Add the newly added volumes of the same object_idx / instance_idx pair
-        // to the selection.
-        assert(m_mode == Instance);
-        sort_remove_duplicates(model_instances);
-        for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++ i) {
-			const GLVolume* volume = (*m_volumes)[i];
-            for (const std::pair<int, int> &model_instance : model_instances)
-				if (volume->object_idx() == model_instance.first && volume->instance_idx() == model_instance.second)
-                    this->_add_volume(i);
-        }
-    }
-
-    _update_type();
-    m_bounding_box_dirty = true;
-}
-
-bool GLCanvas3D::Selection::is_single_full_instance() const
-{
-    if (m_type == SingleFullInstance)
-        return true;
-
-    if (m_type == SingleFullObject)
-        return get_instance_idx() != -1;
-
-    if (m_list.empty() || m_volumes->empty())
-        return false;
-
-    int object_idx = m_valid ? get_object_idx() : -1;
-    if ((object_idx < 0) || ((int)m_model->objects.size() <= object_idx))
-        return false;
-
-    int instance_idx = (*m_volumes)[*m_list.begin()]->instance_idx();
-
-    std::set<int> volumes_idxs;
-    for (unsigned int i : m_list)
-    {
-        const GLVolume* v = (*m_volumes)[i];
-        if ((object_idx != v->object_idx()) || (instance_idx != v->instance_idx()))
-            return false;
-
-        int volume_idx = v->volume_idx();
-        if (volume_idx >= 0)
-            volumes_idxs.insert(volume_idx);
-    }
-
-    return m_model->objects[object_idx]->volumes.size() == volumes_idxs.size();
-}
-
-bool GLCanvas3D::Selection::is_from_single_object() const
-{
-    int idx = get_object_idx();
-    return (0 <= idx) && (idx < 1000);
-}
-
-bool GLCanvas3D::Selection::requires_uniform_scale() const
-{
-    if (is_single_full_instance() || is_single_modifier() || is_single_volume())
-        return false;
-
-    return true;
-}
-
-int GLCanvas3D::Selection::get_object_idx() const
-{
-    return (m_cache.content.size() == 1) ? m_cache.content.begin()->first : -1;
-}
-
-int GLCanvas3D::Selection::get_instance_idx() const
-{
-    if (m_cache.content.size() == 1)
-    {
-        const InstanceIdxsList& idxs = m_cache.content.begin()->second;
-        if (idxs.size() == 1)
-            return *idxs.begin();
-    }
-
-    return -1;
-}
-
-const GLCanvas3D::Selection::InstanceIdxsList& GLCanvas3D::Selection::get_instance_idxs() const
-{
-    assert(m_cache.content.size() == 1);
-    return m_cache.content.begin()->second;
-}
-
-const GLVolume* GLCanvas3D::Selection::get_volume(unsigned int volume_idx) const
-{
-    return (m_valid && (volume_idx < (unsigned int)m_volumes->size())) ? (*m_volumes)[volume_idx] : nullptr;
-}
-
-const BoundingBoxf3& GLCanvas3D::Selection::get_bounding_box() const
-{
-    if (m_bounding_box_dirty)
-        _calc_bounding_box();
-
-    return m_bounding_box;
-}
-
-void GLCanvas3D::Selection::start_dragging()
-{
-    if (!m_valid)
-        return;
-
-    _set_caches();
-}
-
-void GLCanvas3D::Selection::translate(const Vec3d& displacement, bool local)
-{
-    if (!m_valid)
-        return;
-
-    for (unsigned int i : m_list)
-    {
-    if ((m_mode == Volume) || (*m_volumes)[i]->is_wipe_tower)
-    {
-        if (local)
-            (*m_volumes)[i]->set_volume_offset(m_cache.volumes_data[i].get_volume_position() + displacement);
-        else
-        {
-            Vec3d local_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() * m_cache.volumes_data[i].get_instance_mirror_matrix()).inverse() * displacement;
-            (*m_volumes)[i]->set_volume_offset(m_cache.volumes_data[i].get_volume_position() + local_displacement);
-        }
-    }
-    else if (m_mode == Instance)
-        (*m_volumes)[i]->set_instance_offset(m_cache.volumes_data[i].get_instance_position() + displacement);
-    }
-
-#if !DISABLE_INSTANCES_SYNCH
-    if (m_mode == Instance)
-        _synchronize_unselected_instances(SYNC_ROTATION_NONE);
-    else if (m_mode == Volume)
-        _synchronize_unselected_volumes();
-#endif // !DISABLE_INSTANCES_SYNCH
-
-    m_bounding_box_dirty = true;
-}
-
-static Eigen::Quaterniond rotation_xyz_diff(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
-{
-    return
-        // From the current coordinate system to world.
-        Eigen::AngleAxisd(rot_xyz_to(2), Vec3d::UnitZ()) * Eigen::AngleAxisd(rot_xyz_to(1), Vec3d::UnitY()) * Eigen::AngleAxisd(rot_xyz_to(0), Vec3d::UnitX()) *
-        // From world to the initial coordinate system.
-        Eigen::AngleAxisd(-rot_xyz_from(0), Vec3d::UnitX()) * Eigen::AngleAxisd(-rot_xyz_from(1), Vec3d::UnitY()) * Eigen::AngleAxisd(-rot_xyz_from(2), Vec3d::UnitZ());
-}
-
-// This should only be called if it is known, that the two rotations only differ in rotation around the Z axis.
-static double rotation_diff_z(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
-{
-    Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to));
-    Vec3d  axis  = angle_axis.axis();
-    double angle = angle_axis.angle();
-#ifndef NDEBUG
-	if (std::abs(angle) > 1e-8) {
-		assert(std::abs(axis.x()) < 1e-8);
-		assert(std::abs(axis.y()) < 1e-8);
-	}
-#endif /* NDEBUG */
-	return (axis.z() < 0) ? -angle : angle;
-}
-
-// Rotate an object around one of the axes. Only one rotation component is expected to be changing.
-void GLCanvas3D::Selection::rotate(const Vec3d& rotation, GLCanvas3D::TransformationType transformation_type)
-{
-    if (!m_valid)
-        return;
-
-    // Only relative rotation values are allowed in the world coordinate system.
-    assert(! transformation_type.world() || transformation_type.relative());
-
-    int rot_axis_max = 0;
-    if (rotation.isApprox(Vec3d::Zero()))
-    {
-        for (unsigned int i : m_list)
-        {
-            GLVolume &volume = *(*m_volumes)[i];
-            if (m_mode == Instance)
-            {
-                volume.set_instance_rotation(m_cache.volumes_data[i].get_instance_rotation());
-                volume.set_instance_offset(m_cache.volumes_data[i].get_instance_position());
-            }
-            else if (m_mode == Volume)
-            {
-                volume.set_volume_rotation(m_cache.volumes_data[i].get_volume_rotation());
-                volume.set_volume_offset(m_cache.volumes_data[i].get_volume_position());
-            }
-        }
-    }
-    else
-    {
-        //FIXME this does not work for absolute rotations (transformation_type.absolute() is true)
-        rotation.cwiseAbs().maxCoeff(&rot_axis_max);
-
-	    // For generic rotation, we want to rotate the first volume in selection, and then to synchronize the other volumes with it.
-	    std::vector<int> object_instance_first(m_model->objects.size(), -1);
-	    auto rotate_instance = [this, &rotation, &object_instance_first, rot_axis_max, transformation_type](GLVolume &volume, int i) {
-            int first_volume_idx = object_instance_first[volume.object_idx()];
-            if (rot_axis_max != 2 && first_volume_idx != -1) {
-                // Generic rotation, but no rotation around the Z axis.
-                // Always do a local rotation (do not consider the selection to be a rigid body).
-                assert(is_approx(rotation.z(), 0.0));
-                const GLVolume &first_volume = *(*m_volumes)[first_volume_idx];
-                const Vec3d    &rotation     = first_volume.get_instance_rotation();
-                double z_diff = rotation_diff_z(m_cache.volumes_data[first_volume_idx].get_instance_rotation(), m_cache.volumes_data[i].get_instance_rotation());
-                volume.set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2) + z_diff));
-            } else {
-                // extracts rotations from the composed transformation
-			    Vec3d new_rotation = transformation_type.world() ?
-				    Geometry::extract_euler_angles(Geometry::assemble_transform(Vec3d::Zero(), rotation) * m_cache.volumes_data[i].get_instance_rotation_matrix()) :
-				    transformation_type.absolute() ? rotation : rotation + m_cache.volumes_data[i].get_instance_rotation();
-                if (rot_axis_max == 2 && transformation_type.joint()) {
-                    // Only allow rotation of multiple instances as a single rigid body when rotating around the Z axis.
-                    Vec3d offset = Geometry::assemble_transform(Vec3d::Zero(), Vec3d(0.0, 0.0, new_rotation(2) - m_cache.volumes_data[i].get_instance_rotation()(2))) * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center);
-                    volume.set_instance_offset(m_cache.dragging_center + offset);
-                }
-                volume.set_instance_rotation(new_rotation);
-                object_instance_first[volume.object_idx()] = i;
-            }
-        };
-
-        for (unsigned int i : m_list)
-        {
-            GLVolume &volume = *(*m_volumes)[i];
-            if (is_single_full_instance())
-                rotate_instance(volume, i);
-            else if (is_single_volume() || is_single_modifier())
-            {
-                if (transformation_type.independent())
-                    volume.set_volume_rotation(volume.get_volume_rotation() + rotation);
-                else
-                {
-                    Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation);
-                    Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_volume_rotation_matrix());
-                    volume.set_volume_rotation(new_rotation);
-                }
-            }
-            else
-            {
-                if (m_mode == Instance)
-                    rotate_instance(volume, i);
-                else if (m_mode == Volume)
-                {
-                    // extracts rotations from the composed transformation
-                    Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation);
-                    Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_volume_rotation_matrix());
-                    if (transformation_type.joint())
-                    {
-                        Vec3d local_pivot = m_cache.volumes_data[i].get_instance_full_matrix().inverse() * m_cache.dragging_center;
-                        Vec3d offset = m * (m_cache.volumes_data[i].get_volume_position() - local_pivot);
-                        volume.set_volume_offset(local_pivot + offset);
-                    }
-                    volume.set_volume_rotation(new_rotation);
-                }
-            }
-        }
-    }
-
-#if !DISABLE_INSTANCES_SYNCH
-    if (m_mode == Instance)
-        _synchronize_unselected_instances((rot_axis_max == 2) ? SYNC_ROTATION_NONE : SYNC_ROTATION_GENERAL);
-    else if (m_mode == Volume)
-        _synchronize_unselected_volumes();
-#endif // !DISABLE_INSTANCES_SYNCH
-
-    m_bounding_box_dirty = true;
-}
-
-void GLCanvas3D::Selection::flattening_rotate(const Vec3d& normal)
-{
-    // We get the normal in untransformed coordinates. We must transform it using the instance matrix, find out
-    // how to rotate the instance so it faces downwards and do the rotation. All that for all selected instances.
-    // The function assumes that is_from_single_object() holds.
-
-    if (!m_valid)
-        return;
-
-    for (unsigned int i : m_list)
-    {
-        Transform3d wst = m_cache.volumes_data[i].get_instance_scale_matrix();
-        Vec3d scaling_factor = Vec3d(1./wst(0,0), 1./wst(1,1), 1./wst(2,2));
-
-        Transform3d wmt = m_cache.volumes_data[i].get_instance_mirror_matrix();
-        Vec3d mirror(wmt(0,0), wmt(1,1), wmt(2,2));
-
-        Vec3d rotation = Geometry::extract_euler_angles(m_cache.volumes_data[i].get_instance_rotation_matrix());
-        Vec3d transformed_normal = Geometry::assemble_transform(Vec3d::Zero(), rotation, scaling_factor, mirror) * normal;
-        transformed_normal.normalize();
-
-        Vec3d axis = transformed_normal(2) > 0.999f ? Vec3d(1., 0., 0.) : Vec3d(transformed_normal.cross(Vec3d(0., 0., -1.)));
-        axis.normalize();
-
-        Transform3d extra_rotation = Transform3d::Identity();
-        extra_rotation.rotate(Eigen::AngleAxisd(acos(-transformed_normal(2)), axis));
-
-        Vec3d new_rotation = Geometry::extract_euler_angles(extra_rotation * m_cache.volumes_data[i].get_instance_rotation_matrix() );
-        (*m_volumes)[i]->set_instance_rotation(new_rotation);
-    }
-
-#if !DISABLE_INSTANCES_SYNCH
-    // we want to synchronize z-rotation as well, otherwise the flattening behaves funny
-    // when applied on one of several identical instances
-    if (m_mode == Instance)
-        _synchronize_unselected_instances(SYNC_ROTATION_FULL);
-#endif // !DISABLE_INSTANCES_SYNCH
-
-    m_bounding_box_dirty = true;
-}
-
-void GLCanvas3D::Selection::scale(const Vec3d& scale, bool local)
-{
-    if (!m_valid)
-        return;
-
-    for (unsigned int i : m_list)
-    {
-        if (is_single_full_instance())
-            (*m_volumes)[i]->set_instance_scaling_factor(scale);
-        else if (is_single_volume() || is_single_modifier())
-            (*m_volumes)[i]->set_volume_scaling_factor(scale);
-        else
-        {
-            Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), scale);
-            if (m_mode == Instance)
-            {
-                Eigen::Matrix<double, 3, 3, Eigen::DontAlign> new_matrix = (m * m_cache.volumes_data[i].get_instance_scale_matrix()).matrix().block(0, 0, 3, 3);
-                // extracts scaling factors from the composed transformation
-                Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm());
-                if (!local)
-                    (*m_volumes)[i]->set_instance_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center));
-
-                (*m_volumes)[i]->set_instance_scaling_factor(new_scale);
-            }
-            else if (m_mode == Volume)
-            {
-                Eigen::Matrix<double, 3, 3, Eigen::DontAlign> new_matrix = (m * m_cache.volumes_data[i].get_volume_scale_matrix()).matrix().block(0, 0, 3, 3);
-                // extracts scaling factors from the composed transformation
-                Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm());
-                if (!local)
-                {
-                    Vec3d offset = m * (m_cache.volumes_data[i].get_volume_position() + m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center);
-                    (*m_volumes)[i]->set_volume_offset(m_cache.dragging_center - m_cache.volumes_data[i].get_instance_position() + offset);
-                }
-                (*m_volumes)[i]->set_volume_scaling_factor(new_scale);
-            }
-        }
-    }
-
-#if !DISABLE_INSTANCES_SYNCH
-    if (m_mode == Instance)
-        _synchronize_unselected_instances(SYNC_ROTATION_NONE);
-    else if (m_mode == Volume)
-        _synchronize_unselected_volumes();
-#endif // !DISABLE_INSTANCES_SYNCH
-
-    _ensure_on_bed();
-
-    m_bounding_box_dirty = true;
-}
-
-void GLCanvas3D::Selection::mirror(Axis axis)
-{
-    if (!m_valid)
-        return;
-
-    bool single_full_instance = is_single_full_instance();
-
-    for (unsigned int i : m_list)
-    {
-        if (single_full_instance)
-            (*m_volumes)[i]->set_instance_mirror(axis, -(*m_volumes)[i]->get_instance_mirror(axis));
-        else if (m_mode == Volume)
-            (*m_volumes)[i]->set_volume_mirror(axis, -(*m_volumes)[i]->get_volume_mirror(axis));
-    }
-
-#if !DISABLE_INSTANCES_SYNCH
-    if (m_mode == Instance)
-        _synchronize_unselected_instances(SYNC_ROTATION_NONE);
-    else if (m_mode == Volume)
-        _synchronize_unselected_volumes();
-#endif // !DISABLE_INSTANCES_SYNCH
-
-    m_bounding_box_dirty = true;
-}
-
-void GLCanvas3D::Selection::translate(unsigned int object_idx, const Vec3d& displacement)
-{
-    if (!m_valid)
-        return;
-
-    for (unsigned int i : m_list)
-    {
-        GLVolume* v = (*m_volumes)[i];
-        if (v->object_idx() == object_idx)
-            v->set_instance_offset(v->get_instance_offset() + displacement);
-    }
-
-    std::set<unsigned int> done;  // prevent processing volumes twice
-    done.insert(m_list.begin(), m_list.end());
-
-    for (unsigned int i : m_list)
-    {
-        if (done.size() == m_volumes->size())
-            break;
-
-        int object_idx = (*m_volumes)[i]->object_idx();
-        if (object_idx >= 1000)
-            continue;
-
-        // Process unselected volumes of the object.
-        for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j)
-        {
-            if (done.size() == m_volumes->size())
-                break;
-
-            if (done.find(j) != done.end())
-                continue;
-
-            GLVolume* v = (*m_volumes)[j];
-            if (v->object_idx() != object_idx)
-                continue;
-
-            v->set_instance_offset(v->get_instance_offset() + displacement);
-            done.insert(j);
-        }
-    }
-
-    m_bounding_box_dirty = true;
-}
-
-void GLCanvas3D::Selection::translate(unsigned int object_idx, unsigned int instance_idx, const Vec3d& displacement)
-{
-    if (!m_valid)
-        return;
-
-    for (unsigned int i : m_list)
-    {
-        GLVolume* v = (*m_volumes)[i];
-        if ((v->object_idx() == object_idx) && (v->instance_idx() == instance_idx))
-            v->set_instance_offset(v->get_instance_offset() + displacement);
-    }
-
-    std::set<unsigned int> done;  // prevent processing volumes twice
-    done.insert(m_list.begin(), m_list.end());
-
-    for (unsigned int i : m_list)
-    {
-        if (done.size() == m_volumes->size())
-            break;
-
-        int object_idx = (*m_volumes)[i]->object_idx();
-        if (object_idx >= 1000)
-            continue;
-
-        // Process unselected volumes of the object.
-        for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j)
-        {
-            if (done.size() == m_volumes->size())
-                break;
-
-            if (done.find(j) != done.end())
-                continue;
-
-            GLVolume* v = (*m_volumes)[j];
-            if ((v->object_idx() != object_idx) || (v->instance_idx() != instance_idx))
-                continue;
-
-            v->set_instance_offset(v->get_instance_offset() + displacement);
-            done.insert(j);
-        }
-    }
-
-    m_bounding_box_dirty = true;
-}
-
-void GLCanvas3D::Selection::erase()
-{
-    if (!m_valid)
-        return;
-
-    if (is_single_full_object())
-        wxGetApp().obj_list()->delete_from_model_and_list(ItemType::itObject, get_object_idx(), 0);
-    else if (is_multiple_full_object())
-    {
-        std::vector<ItemForDelete> items;
-        items.reserve(m_cache.content.size());
-        for (ObjectIdxsToInstanceIdxsMap::iterator it = m_cache.content.begin(); it != m_cache.content.end(); ++it)
-        {
-            items.emplace_back(ItemType::itObject, it->first, 0);
-        }
-        wxGetApp().obj_list()->delete_from_model_and_list(items);
-    }
-    else if (is_multiple_full_instance())
-    {
-        std::set<std::pair<int, int>> instances_idxs;
-        for (ObjectIdxsToInstanceIdxsMap::iterator obj_it = m_cache.content.begin(); obj_it != m_cache.content.end(); ++obj_it)
-        {
-            for (InstanceIdxsList::reverse_iterator inst_it = obj_it->second.rbegin(); inst_it != obj_it->second.rend(); ++inst_it)
-            {
-                instances_idxs.insert(std::make_pair(obj_it->first, *inst_it));
-            }
-        }
-
-        std::vector<ItemForDelete> items;
-        items.reserve(instances_idxs.size());
-        for (const std::pair<int, int>& i : instances_idxs)
-        {
-            items.emplace_back(ItemType::itInstance, i.first, i.second);
-        }
-        wxGetApp().obj_list()->delete_from_model_and_list(items);
-    }
-    else if (is_single_full_instance())
-        wxGetApp().obj_list()->delete_from_model_and_list(ItemType::itInstance, get_object_idx(), get_instance_idx());
-    else if (is_mixed())
-    {
-        std::set<ItemForDelete> items_set;
-        std::map<int, int> volumes_in_obj;
-
-        for (auto i : m_list) {
-            const auto gl_vol = (*m_volumes)[i];
-            const auto glv_obj_idx = gl_vol->object_idx();
-            const auto model_object = m_model->objects[glv_obj_idx];
-
-            if (model_object->instances.size() == 1) {
-                if (model_object->volumes.size() == 1)
-                    items_set.insert(ItemForDelete(ItemType::itObject, glv_obj_idx, -1));
-                else {
-                    items_set.insert(ItemForDelete(ItemType::itVolume, glv_obj_idx, gl_vol->volume_idx()));
-                    int idx = (volumes_in_obj.find(glv_obj_idx) == volumes_in_obj.end()) ? 0 : volumes_in_obj.at(glv_obj_idx);
-                    volumes_in_obj[glv_obj_idx] = ++idx;
-                }
-                continue;
-            }
-
-            const auto glv_ins_idx = gl_vol->instance_idx();
-
-            for (auto obj_ins : m_cache.content) {
-                if (obj_ins.first == glv_obj_idx) {
-                    if (obj_ins.second.find(glv_ins_idx) != obj_ins.second.end()) {
-                        if (obj_ins.second.size() == model_object->instances.size())
-                            items_set.insert(ItemForDelete(ItemType::itVolume, glv_obj_idx, gl_vol->volume_idx()));
-                        else
-                            items_set.insert(ItemForDelete(ItemType::itInstance, glv_obj_idx, glv_ins_idx));
-
-                        break;
-                    }
-                }
-            }
-        }
-
-        std::vector<ItemForDelete> items;
-        items.reserve(items_set.size());
-        for (const ItemForDelete& i : items_set) {
-            if (i.type == ItemType::itVolume ) {
-                const int vol_in_obj_cnt = volumes_in_obj.find(i.obj_idx) == volumes_in_obj.end() ? 0 : volumes_in_obj.at(i.obj_idx);
-                if (vol_in_obj_cnt == m_model->objects[i.obj_idx]->volumes.size()) {
-                    if (i.sub_obj_idx == vol_in_obj_cnt - 1)
-                        items.emplace_back(ItemType::itObject, i.obj_idx, 0);
-                    continue;
-                }
-            }
-            items.emplace_back(i.type, i.obj_idx, i.sub_obj_idx);
-        }
-
-        wxGetApp().obj_list()->delete_from_model_and_list(items);
-    }
-    else
-    {
-        std::set<std::pair<int, int>> volumes_idxs;
-        for (unsigned int i : m_list)
-        {
-            const GLVolume* v = (*m_volumes)[i];
-			// Only remove volumes associated with ModelVolumes from the object list.
-			// Temporary meshes (SLA supports or pads) are not managed by the object list.
-			if (v->volume_idx() >= 0)
-	            volumes_idxs.insert(std::make_pair(v->object_idx(), v->volume_idx()));
-        }
-
-        std::vector<ItemForDelete> items;
-        items.reserve(volumes_idxs.size());
-        for (const std::pair<int, int>& v : volumes_idxs)
-        {
-            items.emplace_back(ItemType::itVolume, v.first, v.second);
-        }
-
-        wxGetApp().obj_list()->delete_from_model_and_list(items);
-    }
-}
-
-void GLCanvas3D::Selection::render(float scale_factor) const
-{
-    if (!m_valid || is_empty())
-        return;
-
-    m_scale_factor = scale_factor;
-
-    // render cumulative bounding box of selected volumes
-    _render_selected_volumes();
-    _render_synchronized_volumes();
-}
-
-#if ENABLE_RENDER_SELECTION_CENTER
-void GLCanvas3D::Selection::render_center() const
-{
-    if (!m_valid || is_empty() || (m_quadric == nullptr))
-        return;
-
-    const Vec3d& center = get_bounding_box().center();
-
-    ::glDisable(GL_DEPTH_TEST);
-
-    ::glEnable(GL_LIGHTING);
-
-    ::glColor3f(1.0f, 1.0f, 1.0f);
-    ::glPushMatrix();
-    ::glTranslated(center(0), center(1), center(2));
-    ::gluSphere(m_quadric, 0.75, 32, 32);
-    ::glPopMatrix();
-
-    ::glDisable(GL_LIGHTING);
-}
-#endif // ENABLE_RENDER_SELECTION_CENTER
-
-void GLCanvas3D::Selection::render_sidebar_hints(const std::string& sidebar_field) const
-{
-    if (sidebar_field.empty())
-        return;
-
-    ::glClear(GL_DEPTH_BUFFER_BIT);
-    ::glEnable(GL_DEPTH_TEST);
-
-    ::glEnable(GL_LIGHTING);
-
-    ::glPushMatrix();
-
-    const Vec3d& center = get_bounding_box().center();
-
-    if (is_single_full_instance())
-    {
-        ::glTranslated(center(0), center(1), center(2));
-        if (!boost::starts_with(sidebar_field, "position"))
-        {
-            Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true);
-            ::glMultMatrixd(orient_matrix.data());
-        }
-    }
-    else if (is_single_volume() || is_single_modifier())
-    {
-        ::glTranslated(center(0), center(1), center(2));
-        Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true);
-        if (!boost::starts_with(sidebar_field, "position"))
-            orient_matrix = orient_matrix * (*m_volumes)[*m_list.begin()]->get_volume_transformation().get_matrix(true, false, true, true);
-
-        ::glMultMatrixd(orient_matrix.data());
-    }
-    else
-    {
-        ::glTranslated(center(0), center(1), center(2));
-        if (requires_local_axes())
-        {
-            Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true);
-            ::glMultMatrixd(orient_matrix.data());
-        }
-    }
-
-    if (boost::starts_with(sidebar_field, "position"))
-        _render_sidebar_position_hints(sidebar_field);
-    else if (boost::starts_with(sidebar_field, "rotation"))
-        _render_sidebar_rotation_hints(sidebar_field);
-    else if (boost::starts_with(sidebar_field, "scale"))
-        _render_sidebar_scale_hints(sidebar_field);
-    else if (boost::starts_with(sidebar_field, "size"))
-        _render_sidebar_size_hints(sidebar_field);
-
-    ::glPopMatrix();
-
-    ::glDisable(GL_LIGHTING);
-}
-
-bool GLCanvas3D::Selection::requires_local_axes() const
-{
-    return (m_mode == Volume) && is_from_single_instance();
-}
-
-void GLCanvas3D::Selection::_update_valid()
-{
-    m_valid = (m_volumes != nullptr) && (m_model != nullptr);
-}
-
-void GLCanvas3D::Selection::_update_type()
-{
-    m_cache.content.clear();
-    m_type = Mixed;
-
-    for (unsigned int i : m_list)
-    {
-        const GLVolume* volume = (*m_volumes)[i];
-        int obj_idx = volume->object_idx();
-        int inst_idx = volume->instance_idx();
-        ObjectIdxsToInstanceIdxsMap::iterator obj_it = m_cache.content.find(obj_idx);
-        if (obj_it == m_cache.content.end())
-            obj_it = m_cache.content.insert(ObjectIdxsToInstanceIdxsMap::value_type(obj_idx, InstanceIdxsList())).first;
-
-        obj_it->second.insert(inst_idx);
-    }
-
-    bool requires_disable = false;
-
-    if (!m_valid)
-        m_type = Invalid;
-    else
-    {
-        if (m_list.empty())
-            m_type = Empty;
-        else if (m_list.size() == 1)
-        {
-            const GLVolume* first = (*m_volumes)[*m_list.begin()];
-            if (first->is_wipe_tower)
-                m_type = WipeTower;
-            else if (first->is_modifier)
-            {
-                m_type = SingleModifier;
-                requires_disable = true;
-            }
-            else
-            {
-                const ModelObject* model_object = m_model->objects[first->object_idx()];
-                unsigned int volumes_count = (unsigned int)model_object->volumes.size();
-                unsigned int instances_count = (unsigned int)model_object->instances.size();
-                if (volumes_count * instances_count == 1)
-                {
-                    m_type = SingleFullObject;
-                    // ensures the correct mode is selected
-                    m_mode = Instance;
-                }
-                else if (volumes_count == 1) // instances_count > 1
-                {
-                    m_type = SingleFullInstance;
-                    // ensures the correct mode is selected
-                    m_mode = Instance;
-                }
-                else
-                {
-                    m_type = SingleVolume;
-                    requires_disable = true;
-                }
-            }
-        }
-        else
-        {
-            if (m_cache.content.size() == 1) // single object
-            {
-                const ModelObject* model_object = m_model->objects[m_cache.content.begin()->first];
-                unsigned int model_volumes_count = (unsigned int)model_object->volumes.size();
-                unsigned int sla_volumes_count = 0;
-                for (unsigned int i : m_list)
-                {
-                    if ((*m_volumes)[i]->volume_idx() < 0)
-                        ++sla_volumes_count;
-                }
-                unsigned int volumes_count = model_volumes_count + sla_volumes_count;
-                unsigned int instances_count = (unsigned int)model_object->instances.size();
-                unsigned int selected_instances_count = (unsigned int)m_cache.content.begin()->second.size();
-                if (volumes_count * instances_count == (unsigned int)m_list.size())
-                {
-                    m_type = SingleFullObject;
-                    // ensures the correct mode is selected
-                    m_mode = Instance;
-                }
-                else if (selected_instances_count == 1)
-                {
-                    if (volumes_count == (unsigned int)m_list.size())
-                    {
-                        m_type = SingleFullInstance;
-                        // ensures the correct mode is selected
-                        m_mode = Instance;
-                    }
-                    else
-                    {
-                        unsigned int modifiers_count = 0;
-                        for (unsigned int i : m_list)
-                        {
-                            if ((*m_volumes)[i]->is_modifier)
-                                ++modifiers_count;
-                        }
-
-                        if (modifiers_count == 0)
-                        {
-                            m_type = MultipleVolume;
-                            requires_disable = true;
-                        }
-                        else if (modifiers_count == (unsigned int)m_list.size())
-                        {
-                            m_type = MultipleModifier;
-                            requires_disable = true;
-                        }
-                    }
-                }
-                else if ((selected_instances_count > 1) && (selected_instances_count * volumes_count == (unsigned int)m_list.size()))
-                {
-                    m_type = MultipleFullInstance;
-                    // ensures the correct mode is selected
-                    m_mode = Instance;
-                }
-            }
-            else
-            {
-                int sels_cntr = 0;
-                for (ObjectIdxsToInstanceIdxsMap::iterator it = m_cache.content.begin(); it != m_cache.content.end(); ++it)
-                {
-                    const ModelObject* model_object = m_model->objects[it->first];
-                    unsigned int volumes_count = (unsigned int)model_object->volumes.size();
-                    unsigned int instances_count = (unsigned int)model_object->instances.size();
-                        sels_cntr += volumes_count * instances_count;
-                }
-                if (sels_cntr == (unsigned int)m_list.size())
-                {
-                    m_type = MultipleFullObject;
-                    // ensures the correct mode is selected
-                    m_mode = Instance;
-                }
-            }
-        }
-    }
-
-    int object_idx = get_object_idx();
-    int instance_idx = get_instance_idx();
-    for (GLVolume* v : *m_volumes)
-    {
-        v->disabled = requires_disable ? (v->object_idx() != object_idx) || (v->instance_idx() != instance_idx) : false;
-    }
-
-#if ENABLE_SELECTION_DEBUG_OUTPUT
-    std::cout << "Selection: ";
-    std::cout << "mode: ";
-    switch (m_mode)
-    {
-    case Volume:
-    {
-        std::cout << "Volume";
-        break;
-    }
-    case Instance:
-    {
-        std::cout << "Instance";
-        break;
-    }
-    }
-
-    std::cout << " - type: ";
-
-    switch (m_type)
-    {
-    case Invalid:
-    {
-        std::cout << "Invalid" << std::endl;
-        break;
-    }
-    case Empty:
-    {
-        std::cout << "Empty" << std::endl;
-        break;
-    }
-    case WipeTower:
-    {
-        std::cout << "WipeTower" << std::endl;
-        break;
-    }
-    case SingleModifier:
-    {
-        std::cout << "SingleModifier" << std::endl;
-        break;
-    }
-    case MultipleModifier:
-    {
-        std::cout << "MultipleModifier" << std::endl;
-        break;
-    }
-    case SingleVolume:
-    {
-        std::cout << "SingleVolume" << std::endl;
-        break;
-    }
-    case MultipleVolume:
-    {
-        std::cout << "MultipleVolume" << std::endl;
-        break;
-    }
-    case SingleFullObject:
-    {
-        std::cout << "SingleFullObject" << std::endl;
-        break;
-    }
-    case MultipleFullObject:
-    {
-        std::cout << "MultipleFullObject" << std::endl;
-        break;
-    }
-    case SingleFullInstance:
-    {
-        std::cout << "SingleFullInstance" << std::endl;
-        break;
-    }
-    case MultipleFullInstance:
-    {
-        std::cout << "MultipleFullInstance" << std::endl;
-        break;
-    }
-    case Mixed:
-    {
-        std::cout << "Mixed" << std::endl;
-        break;
-    }
-    }
-#endif // ENABLE_SELECTION_DEBUG_OUTPUT
-}
-
-void GLCanvas3D::Selection::_set_caches()
-{
-    m_cache.volumes_data.clear();
-    for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
-    {
-        const GLVolume* v = (*m_volumes)[i];
-        m_cache.volumes_data.emplace(i, VolumeCache(v->get_volume_transformation(), v->get_instance_transformation()));
-    }
-    m_cache.dragging_center = get_bounding_box().center();
-}
-
-void GLCanvas3D::Selection::_add_volume(unsigned int volume_idx)
-{
-    m_list.insert(volume_idx);
-    (*m_volumes)[volume_idx]->selected = true;
-}
-
-void GLCanvas3D::Selection::_add_instance(unsigned int object_idx, unsigned int instance_idx)
-{
-    for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
-    {
-        GLVolume* v = (*m_volumes)[i];
-        if ((v->object_idx() == object_idx) && (v->instance_idx() == instance_idx))
-            _add_volume(i);
-    }
-}
-
-void GLCanvas3D::Selection::_add_object(unsigned int object_idx)
-{
-    for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
-    {
-        GLVolume* v = (*m_volumes)[i];
-        if (v->object_idx() == object_idx)
-            _add_volume(i);
-    }
-}
-
-void GLCanvas3D::Selection::_remove_volume(unsigned int volume_idx)
-{
-    IndicesList::iterator v_it = m_list.find(volume_idx);
-    if (v_it == m_list.end())
-        return;
-
-    m_list.erase(v_it);
-
-    (*m_volumes)[volume_idx]->selected = false;
-}
-
-void GLCanvas3D::Selection::_remove_instance(unsigned int object_idx, unsigned int instance_idx)
-{
-    for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
-    {
-        GLVolume* v = (*m_volumes)[i];
-        if ((v->object_idx() == object_idx) && (v->instance_idx() == instance_idx))
-            _remove_volume(i);
-    }
-}
-
-void GLCanvas3D::Selection::_remove_object(unsigned int object_idx)
-{
-    for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
-    {
-        GLVolume* v = (*m_volumes)[i];
-        if (v->object_idx() == object_idx)
-            _remove_volume(i);
-    }
-}
-
-void GLCanvas3D::Selection::_calc_bounding_box() const
-{
-    m_bounding_box = BoundingBoxf3();
-    if (m_valid)
-    {
-        for (unsigned int i : m_list)
-        {
-            m_bounding_box.merge((*m_volumes)[i]->transformed_convex_hull_bounding_box());
-        }
-    }
-    m_bounding_box_dirty = false;
-}
-
-void GLCanvas3D::Selection::_render_selected_volumes() const
-{
-    float color[3] = { 1.0f, 1.0f, 1.0f };
-    _render_bounding_box(get_bounding_box(), color);
-}
-
-void GLCanvas3D::Selection::_render_synchronized_volumes() const
-{
-    if (m_mode == Instance)
-        return;
-
-    float color[3] = { 1.0f, 1.0f, 0.0f };
-
-    for (unsigned int i : m_list)
-    {
-        const GLVolume* volume = (*m_volumes)[i];
-        int object_idx = volume->object_idx();
-        int instance_idx = volume->instance_idx();
-        int volume_idx = volume->volume_idx();
-        for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j)
-        {
-            if (i == j)
-                continue;
-
-            const GLVolume* v = (*m_volumes)[j];
-            if ((v->object_idx() != object_idx) || (v->volume_idx() != volume_idx))
-                continue;
-
-            _render_bounding_box(v->transformed_convex_hull_bounding_box(), color);
-        }
-    }
-}
-
-void GLCanvas3D::Selection::_render_bounding_box(const BoundingBoxf3& box, float* color) const
-{
-    if (color == nullptr)
-        return;
-
-    Vec3f b_min = box.min.cast<float>();
-    Vec3f b_max = box.max.cast<float>();
-    Vec3f size = 0.2f * box.size().cast<float>();
-
-    ::glEnable(GL_DEPTH_TEST);
-
-    ::glColor3fv(color);
-    ::glLineWidth(2.0f * m_scale_factor);
-
-    ::glBegin(GL_LINES);
-
-    ::glVertex3f(b_min(0), b_min(1), b_min(2)); ::glVertex3f(b_min(0) + size(0), b_min(1), b_min(2));
-    ::glVertex3f(b_min(0), b_min(1), b_min(2)); ::glVertex3f(b_min(0), b_min(1) + size(1), b_min(2));
-    ::glVertex3f(b_min(0), b_min(1), b_min(2)); ::glVertex3f(b_min(0), b_min(1), b_min(2) + size(2));
-
-    ::glVertex3f(b_max(0), b_min(1), b_min(2)); ::glVertex3f(b_max(0) - size(0), b_min(1), b_min(2));
-    ::glVertex3f(b_max(0), b_min(1), b_min(2)); ::glVertex3f(b_max(0), b_min(1) + size(1), b_min(2));
-    ::glVertex3f(b_max(0), b_min(1), b_min(2)); ::glVertex3f(b_max(0), b_min(1), b_min(2) + size(2));
-
-    ::glVertex3f(b_max(0), b_max(1), b_min(2)); ::glVertex3f(b_max(0) - size(0), b_max(1), b_min(2));
-    ::glVertex3f(b_max(0), b_max(1), b_min(2)); ::glVertex3f(b_max(0), b_max(1) - size(1), b_min(2));
-    ::glVertex3f(b_max(0), b_max(1), b_min(2)); ::glVertex3f(b_max(0), b_max(1), b_min(2) + size(2));
-
-    ::glVertex3f(b_min(0), b_max(1), b_min(2)); ::glVertex3f(b_min(0) + size(0), b_max(1), b_min(2));
-    ::glVertex3f(b_min(0), b_max(1), b_min(2)); ::glVertex3f(b_min(0), b_max(1) - size(1), b_min(2));
-    ::glVertex3f(b_min(0), b_max(1), b_min(2)); ::glVertex3f(b_min(0), b_max(1), b_min(2) + size(2));
-
-    ::glVertex3f(b_min(0), b_min(1), b_max(2)); ::glVertex3f(b_min(0) + size(0), b_min(1), b_max(2));
-    ::glVertex3f(b_min(0), b_min(1), b_max(2)); ::glVertex3f(b_min(0), b_min(1) + size(1), b_max(2));
-    ::glVertex3f(b_min(0), b_min(1), b_max(2)); ::glVertex3f(b_min(0), b_min(1), b_max(2) - size(2));
-
-    ::glVertex3f(b_max(0), b_min(1), b_max(2)); ::glVertex3f(b_max(0) - size(0), b_min(1), b_max(2));
-    ::glVertex3f(b_max(0), b_min(1), b_max(2)); ::glVertex3f(b_max(0), b_min(1) + size(1), b_max(2));
-    ::glVertex3f(b_max(0), b_min(1), b_max(2)); ::glVertex3f(b_max(0), b_min(1), b_max(2) - size(2));
-
-    ::glVertex3f(b_max(0), b_max(1), b_max(2)); ::glVertex3f(b_max(0) - size(0), b_max(1), b_max(2));
-    ::glVertex3f(b_max(0), b_max(1), b_max(2)); ::glVertex3f(b_max(0), b_max(1) - size(1), b_max(2));
-    ::glVertex3f(b_max(0), b_max(1), b_max(2)); ::glVertex3f(b_max(0), b_max(1), b_max(2) - size(2));
-
-    ::glVertex3f(b_min(0), b_max(1), b_max(2)); ::glVertex3f(b_min(0) + size(0), b_max(1), b_max(2));
-    ::glVertex3f(b_min(0), b_max(1), b_max(2)); ::glVertex3f(b_min(0), b_max(1) - size(1), b_max(2));
-    ::glVertex3f(b_min(0), b_max(1), b_max(2)); ::glVertex3f(b_min(0), b_max(1), b_max(2) - size(2));
-
-    ::glEnd();
-}
-
-void GLCanvas3D::Selection::_render_sidebar_position_hints(const std::string& sidebar_field) const
-{
-    if (boost::ends_with(sidebar_field, "x"))
-    {
-        ::glRotated(-90.0, 0.0, 0.0, 1.0);
-        _render_sidebar_position_hint(X);
-    }
-    else if (boost::ends_with(sidebar_field, "y"))
-        _render_sidebar_position_hint(Y);
-    else if (boost::ends_with(sidebar_field, "z"))
-    {
-        ::glRotated(90.0, 1.0, 0.0, 0.0);
-        _render_sidebar_position_hint(Z);
-    }
-}
-
-void GLCanvas3D::Selection::_render_sidebar_rotation_hints(const std::string& sidebar_field) const
-{
-    if (boost::ends_with(sidebar_field, "x"))
-    {
-        ::glRotated(90.0, 0.0, 1.0, 0.0);
-        _render_sidebar_rotation_hint(X);
-    }
-    else if (boost::ends_with(sidebar_field, "y"))
-    {
-        ::glRotated(-90.0, 1.0, 0.0, 0.0);
-        _render_sidebar_rotation_hint(Y);
-    }
-    else if (boost::ends_with(sidebar_field, "z"))
-        _render_sidebar_rotation_hint(Z);
-}
-
-void GLCanvas3D::Selection::_render_sidebar_scale_hints(const std::string& sidebar_field) const
-{
-    bool uniform_scale = requires_uniform_scale() || wxGetApp().obj_manipul()->get_uniform_scaling();
-
-    if (boost::ends_with(sidebar_field, "x") || uniform_scale)
-    {
-        ::glPushMatrix();
-        ::glRotated(-90.0, 0.0, 0.0, 1.0);
-        _render_sidebar_scale_hint(X);
-        ::glPopMatrix();
-    }
-
-    if (boost::ends_with(sidebar_field, "y") || uniform_scale)
-    {
-        ::glPushMatrix();
-        _render_sidebar_scale_hint(Y);
-        ::glPopMatrix();
-    }
-
-    if (boost::ends_with(sidebar_field, "z") || uniform_scale)
-    {
-        ::glPushMatrix();
-        ::glRotated(90.0, 1.0, 0.0, 0.0);
-        _render_sidebar_scale_hint(Z);
-        ::glPopMatrix();
-    }
-}
-
-void GLCanvas3D::Selection::_render_sidebar_size_hints(const std::string& sidebar_field) const
-{
-    _render_sidebar_scale_hints(sidebar_field);
-}
-
-void GLCanvas3D::Selection::_render_sidebar_position_hint(Axis axis) const
-{
-    m_arrow.set_color(AXES_COLOR[axis], 3);
-    m_arrow.render();
-}
-
-void GLCanvas3D::Selection::_render_sidebar_rotation_hint(Axis axis) const
-{
-    m_curved_arrow.set_color(AXES_COLOR[axis], 3);
-    m_curved_arrow.render();
-
-    ::glRotated(180.0, 0.0, 0.0, 1.0);
-    m_curved_arrow.render();
-}
-
-void GLCanvas3D::Selection::_render_sidebar_scale_hint(Axis axis) const
-{
-    m_arrow.set_color(((requires_uniform_scale() || wxGetApp().obj_manipul()->get_uniform_scaling()) ? UNIFORM_SCALE_COLOR : AXES_COLOR[axis]), 3);
-
-    ::glTranslated(0.0, 5.0, 0.0);
-    m_arrow.render();
-
-    ::glTranslated(0.0, -10.0, 0.0);
-    ::glRotated(180.0, 0.0, 0.0, 1.0);
-    m_arrow.render();
-}
-
-void GLCanvas3D::Selection::_render_sidebar_size_hint(Axis axis, double length) const
-{
-}
-
-#ifndef NDEBUG
-static bool is_rotation_xy_synchronized(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
-{
-	Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to));
-	Vec3d  axis = angle_axis.axis();
-	double angle = angle_axis.angle();
-	if (std::abs(angle) < 1e-8)
-		return true;
-	assert(std::abs(axis.x()) < 1e-8);
-	assert(std::abs(axis.y()) < 1e-8);
-	assert(std::abs(std::abs(axis.z()) - 1.) < 1e-8);
-	return std::abs(axis.x()) < 1e-8 && std::abs(axis.y()) < 1e-8 && std::abs(std::abs(axis.z()) - 1.) < 1e-8;
-}
-static void verify_instances_rotation_synchronized(const Model &model, const GLVolumePtrs &volumes)
-{
-    for (size_t idx_object = 0; idx_object < model.objects.size(); ++ idx_object) {
-        int idx_volume_first = -1;
-        for (int i = 0; i < (int)volumes.size(); ++ i) {
-			if (volumes[i]->object_idx() == idx_object) {
-                idx_volume_first = i;
-                break;
-            }
-        }
-        assert(idx_volume_first != -1); // object without instances?
-        if (idx_volume_first == -1)
-            continue;
-        const Vec3d &rotation0 = volumes[idx_volume_first]->get_instance_rotation();
-        for (int i = idx_volume_first + 1; i < (int)volumes.size(); ++ i)
-			if (volumes[i]->object_idx() == idx_object) {
-                const Vec3d &rotation = volumes[i]->get_instance_rotation();
-				assert(is_rotation_xy_synchronized(rotation, rotation0));
-            }
-    }
-}
-#endif /* NDEBUG */
-
-void GLCanvas3D::Selection::_synchronize_unselected_instances(SyncRotationType sync_rotation_type)
-{
-    std::set<unsigned int> done;  // prevent processing volumes twice
-    done.insert(m_list.begin(), m_list.end());
-
-    for (unsigned int i : m_list)
-    {
-        if (done.size() == m_volumes->size())
-            break;
-
-        const GLVolume* volume = (*m_volumes)[i];
-        int object_idx = volume->object_idx();
-        if (object_idx >= 1000)
-            continue;
-
-        int instance_idx = volume->instance_idx();
-		const Vec3d& rotation = volume->get_instance_rotation();
-        const Vec3d& scaling_factor = volume->get_instance_scaling_factor();
-        const Vec3d& mirror = volume->get_instance_mirror();
-
-        // Process unselected instances.
-        for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j)
-        {
-            if (done.size() == m_volumes->size())
-                break;
-
-            if (done.find(j) != done.end())
-                continue;
-
-            GLVolume* v = (*m_volumes)[j];
-            if ((v->object_idx() != object_idx) || (v->instance_idx() == instance_idx))
-                continue;
-
-            assert(is_rotation_xy_synchronized(m_cache.volumes_data[i].get_instance_rotation(), m_cache.volumes_data[j].get_instance_rotation()));
-            switch (sync_rotation_type) {
-			case SYNC_ROTATION_NONE:
-				// z only rotation -> keep instance z
-				// The X,Y rotations should be synchronized from start to end of the rotation.
-				assert(is_rotation_xy_synchronized(rotation, v->get_instance_rotation()));
-				break;
-			case SYNC_ROTATION_FULL:
-                // rotation comes from place on face -> force given z
-                v->set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2)));
-                break;
-            case SYNC_ROTATION_GENERAL:
-				// generic rotation -> update instance z with the delta of the rotation.
-                double z_diff = rotation_diff_z(m_cache.volumes_data[i].get_instance_rotation(), m_cache.volumes_data[j].get_instance_rotation());
-				v->set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2) + z_diff));
-                break;
-			}
-
-            v->set_instance_scaling_factor(scaling_factor);
-            v->set_instance_mirror(mirror);
-
-            done.insert(j);
-        }
-    }
-
-#ifndef NDEBUG
-    verify_instances_rotation_synchronized(*m_model, *m_volumes);
-#endif /* NDEBUG */
-}
-
-void GLCanvas3D::Selection::_synchronize_unselected_volumes()
-{
-    for (unsigned int i : m_list)
-    {
-        const GLVolume* volume = (*m_volumes)[i];
-        int object_idx = volume->object_idx();
-        if (object_idx >= 1000)
-            continue;
-
-        int volume_idx = volume->volume_idx();
-        const Vec3d& offset = volume->get_volume_offset();
-        const Vec3d& rotation = volume->get_volume_rotation();
-        const Vec3d& scaling_factor = volume->get_volume_scaling_factor();
-        const Vec3d& mirror = volume->get_volume_mirror();
-
-        // Process unselected volumes.
-        for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j)
-        {
-            if (j == i)
-                continue;
-
-            GLVolume* v = (*m_volumes)[j];
-            if ((v->object_idx() != object_idx) || (v->volume_idx() != volume_idx))
-                continue;
-
-            v->set_volume_offset(offset);
-            v->set_volume_rotation(rotation);
-            v->set_volume_scaling_factor(scaling_factor);
-            v->set_volume_mirror(mirror);
-        }
-    }
-}
-
-void GLCanvas3D::Selection::_ensure_on_bed()
-{
-    typedef std::map<std::pair<int, int>, double> InstancesToZMap;
-    InstancesToZMap instances_min_z;
-
-    for (GLVolume* volume : *m_volumes)
-    {
-        if (!volume->is_wipe_tower && !volume->is_modifier)
-        {
-            double min_z = volume->transformed_convex_hull_bounding_box().min(2);
-            std::pair<int, int> instance = std::make_pair(volume->object_idx(), volume->instance_idx());
-            InstancesToZMap::iterator it = instances_min_z.find(instance);
-            if (it == instances_min_z.end())
-                it = instances_min_z.insert(InstancesToZMap::value_type(instance, DBL_MAX)).first;
-
-            it->second = std::min(it->second, min_z);
-        }
-    }
-
-    for (GLVolume* volume : *m_volumes)
-    {
-        std::pair<int, int> instance = std::make_pair(volume->object_idx(), volume->instance_idx());
-        InstancesToZMap::iterator it = instances_min_z.find(instance);
-        if (it != instances_min_z.end())
-            volume->set_instance_offset(Z, volume->get_instance_offset(Z) - it->second);
-    }
-}
-
 #if ENABLE_SVG_ICONS
 const float GLCanvas3D::Gizmos::Default_Icons_Size = 64;
 #endif // ENABLE_SVG_ICONS
@@ -2574,7 +925,7 @@ void GLCanvas3D::Gizmos::set_overlay_scale(float scale)
 #endif // ENABLE_SVG_ICONS
 }
 
-std::string GLCanvas3D::Gizmos::update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const GLCanvas3D::Selection& selection)
+std::string GLCanvas3D::Gizmos::update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection)
 {
     std::string name = "";
 
@@ -2620,7 +971,7 @@ std::string GLCanvas3D::Gizmos::update_hover_state(const GLCanvas3D& canvas, con
     return name;
 }
 
-void GLCanvas3D::Gizmos::update_on_off_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const GLCanvas3D::Selection& selection)
+void GLCanvas3D::Gizmos::update_on_off_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection)
 {
     if (!m_enabled)
         return;
@@ -2858,7 +1209,7 @@ bool GLCanvas3D::Gizmos::is_dragging() const
     return (curr != nullptr) ? curr->is_dragging() : false;
 }
 
-void GLCanvas3D::Gizmos::start_dragging(const GLCanvas3D::Selection& selection)
+void GLCanvas3D::Gizmos::start_dragging(const Selection& selection)
 {
     if (!m_enabled)
         return;
@@ -2944,7 +1295,7 @@ void GLCanvas3D::Gizmos::set_flattening_data(const ModelObject* model_object)
         reinterpret_cast<GLGizmoFlatten*>(it->second)->set_flattening_data(model_object);
 }
 
-void GLCanvas3D::Gizmos::set_sla_support_data(ModelObject* model_object, const GLCanvas3D::Selection& selection)
+void GLCanvas3D::Gizmos::set_sla_support_data(ModelObject* model_object, const Selection& selection)
 {
     if (!m_enabled)
         return;
@@ -2968,7 +1319,7 @@ bool GLCanvas3D::Gizmos::mouse_event(SLAGizmoEventType action, const Vec2d& mous
     return false;
 }
 
-void GLCanvas3D::Gizmos::render_current_gizmo(const GLCanvas3D::Selection& selection) const
+void GLCanvas3D::Gizmos::render_current_gizmo(const Selection& selection) const
 {
     if (!m_enabled)
         return;
@@ -2976,7 +1327,7 @@ void GLCanvas3D::Gizmos::render_current_gizmo(const GLCanvas3D::Selection& selec
     do_render_current_gizmo(selection);
 }
 
-void GLCanvas3D::Gizmos::render_current_gizmo_for_picking_pass(const GLCanvas3D::Selection& selection) const
+void GLCanvas3D::Gizmos::render_current_gizmo_for_picking_pass(const Selection& selection) const
 {
     if (!m_enabled)
         return;
@@ -2986,7 +1337,7 @@ void GLCanvas3D::Gizmos::render_current_gizmo_for_picking_pass(const GLCanvas3D:
         curr->render_for_picking(selection);
 }
 
-void GLCanvas3D::Gizmos::render_overlay(const GLCanvas3D& canvas, const GLCanvas3D::Selection& selection) const
+void GLCanvas3D::Gizmos::render_overlay(const GLCanvas3D& canvas, const Selection& selection) const
 {
     if (!m_enabled)
         return;
@@ -3018,7 +1369,7 @@ void GLCanvas3D::Gizmos::reset()
     m_gizmos.clear();
 }
 
-void GLCanvas3D::Gizmos::do_render_overlay(const GLCanvas3D& canvas, const GLCanvas3D::Selection& selection) const
+void GLCanvas3D::Gizmos::do_render_overlay(const GLCanvas3D& canvas, const Selection& selection) const
 {
     if (m_gizmos.empty())
         return;
@@ -3178,7 +1529,7 @@ void GLCanvas3D::Gizmos::do_render_overlay(const GLCanvas3D& canvas, const GLCan
     }
 }
 
-void GLCanvas3D::Gizmos::do_render_current_gizmo(const GLCanvas3D::Selection& selection) const
+void GLCanvas3D::Gizmos::do_render_current_gizmo(const Selection& selection) const
 {
     GLGizmoBase* curr = get_current();
     if (curr != nullptr)
diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp
index 639d10120..9653b138b 100644
--- a/src/slic3r/GUI/GLCanvas3D.hpp
+++ b/src/slic3r/GUI/GLCanvas3D.hpp
@@ -4,12 +4,12 @@
 #include <stddef.h>
 #include <memory>
 
-#include "libslic3r/Technologies.hpp"
 #include "3DScene.hpp"
 #include "GLToolbar.hpp"
 #include "Event.hpp"
 #include "3DBed.hpp"
 #include "Camera.hpp"
+#include "Selection.hpp"
 
 #include <float.h>
 
@@ -334,293 +334,6 @@ class GLCanvas3D
     };
 
 public:
-    class TransformationType
-    {
-	public:
-		enum Enum {
-			// Transforming in a world coordinate system
-			World = 0,
-			// Transforming in a local coordinate system
-			Local = 1,
-			// Absolute transformations, allowed in local coordinate system only.
-			Absolute = 0,
-			// Relative transformations, allowed in both local and world coordinate system.
-			Relative = 2,
-			// For group selection, the transformation is performed as if the group made a single solid body.
-			Joint = 0,
-			// For group selection, the transformation is performed on each object independently.
-			Independent = 4,
-
-			World_Relative_Joint = World | Relative | Joint,
-			World_Relative_Independent = World | Relative | Independent,
-			Local_Absolute_Joint = Local | Absolute | Joint,
-			Local_Absolute_Independent = Local | Absolute | Independent,
-			Local_Relative_Joint = Local | Relative | Joint,
-			Local_Relative_Independent = Local | Relative | Independent,
-		};
-		
-		TransformationType() : m_value(World) {}
-        TransformationType(Enum value) : m_value(value) {}
-        TransformationType& operator=(Enum value) { m_value = value; return *this; }
-
-        Enum operator()() const { return m_value; }
-        bool has(Enum v) const { return ((unsigned int)m_value & (unsigned int)v) != 0; }
-
-        void set_world()        { this->remove(Local); }
-        void set_local()        { this->add(Local); }
-        void set_absolute()     { this->remove(Relative); }
-        void set_relative()     { this->add(Relative); }
-        void set_joint()        { this->remove(Independent); }
-        void set_independent()  { this->add(Independent); }
-
-        bool world()        const { return ! this->has(Local); }
-		bool local()        const { return this->has(Local); }
-		bool absolute()     const { return ! this->has(Relative); }
-		bool relative()     const { return this->has(Relative); }
-		bool joint()        const { return ! this->has(Independent); }
-		bool independent()  const { return this->has(Independent); }
-
-    private:
-        void add(Enum v) { m_value = Enum((unsigned int)m_value | (unsigned int)v); }
-        void remove(Enum v) { m_value = Enum((unsigned int)m_value & (~(unsigned int)v)); }
-
-        Enum    m_value;
-    };
-
-    class Selection
-    {
-    public:
-        typedef std::set<unsigned int> IndicesList;
-
-        enum EMode : unsigned char
-        {
-            Volume,
-            Instance
-        };
-
-        enum EType : unsigned char
-        {
-            Invalid,
-            Empty,
-            WipeTower,
-            SingleModifier,
-            MultipleModifier,
-            SingleVolume,
-            MultipleVolume,
-            SingleFullObject,
-            MultipleFullObject,
-            SingleFullInstance,
-            MultipleFullInstance,
-            Mixed
-        };
-
-    private:
-        struct VolumeCache
-        {
-        private:
-            struct TransformCache
-            {
-                Vec3d position;
-                Vec3d rotation;
-                Vec3d scaling_factor;
-                Vec3d mirror;
-                Transform3d rotation_matrix;
-                Transform3d scale_matrix;
-                Transform3d mirror_matrix;
-                Transform3d full_matrix;
-
-                TransformCache();
-                explicit TransformCache(const Geometry::Transformation& transform);
-            };
-
-            TransformCache m_volume;
-            TransformCache m_instance;
-
-        public:
-            VolumeCache() {}
-            VolumeCache(const Geometry::Transformation& volume_transform, const Geometry::Transformation& instance_transform);
-
-            const Vec3d& get_volume_position() const { return m_volume.position; }
-            const Vec3d& get_volume_rotation() const { return m_volume.rotation; }
-            const Vec3d& get_volume_scaling_factor() const { return m_volume.scaling_factor; }
-            const Vec3d& get_volume_mirror() const { return m_volume.mirror; }
-            const Transform3d& get_volume_rotation_matrix() const { return m_volume.rotation_matrix; }
-            const Transform3d& get_volume_scale_matrix() const { return m_volume.scale_matrix; }
-            const Transform3d& get_volume_mirror_matrix() const { return m_volume.mirror_matrix; }
-            const Transform3d& get_volume_full_matrix() const { return m_volume.full_matrix; }
-
-            const Vec3d& get_instance_position() const { return m_instance.position; }
-            const Vec3d& get_instance_rotation() const { return m_instance.rotation; }
-            const Vec3d& get_instance_scaling_factor() const { return m_instance.scaling_factor; }
-            const Vec3d& get_instance_mirror() const { return m_instance.mirror; }
-            const Transform3d& get_instance_rotation_matrix() const { return m_instance.rotation_matrix; }
-            const Transform3d& get_instance_scale_matrix() const { return m_instance.scale_matrix; }
-            const Transform3d& get_instance_mirror_matrix() const { return m_instance.mirror_matrix; }
-            const Transform3d& get_instance_full_matrix() const { return m_instance.full_matrix; }
-        };
-
-        typedef std::map<unsigned int, VolumeCache> VolumesCache;
-        typedef std::set<int> InstanceIdxsList;
-        typedef std::map<int, InstanceIdxsList> ObjectIdxsToInstanceIdxsMap;
-
-        struct Cache
-        {
-            // Cache of GLVolume derived transformation matrices, valid during mouse dragging.
-            VolumesCache volumes_data;
-            // Center of the dragged selection, valid during mouse dragging.
-            Vec3d dragging_center;
-            // Map from indices of ModelObject instances in Model::objects
-            // to a set of indices of ModelVolume instances in ModelObject::instances
-            // Here the index means a position inside the respective std::vector, not ModelID.
-            ObjectIdxsToInstanceIdxsMap content;
-        };
-
-        // Volumes owned by GLCanvas3D.
-        GLVolumePtrs* m_volumes;
-        // Model, not owned.
-        Model* m_model;
-
-        bool m_valid;
-        EMode m_mode;
-        EType m_type;
-        // set of indices to m_volumes
-        IndicesList m_list;
-        Cache m_cache;
-        mutable BoundingBoxf3 m_bounding_box;
-        mutable bool m_bounding_box_dirty;
-
-#if ENABLE_RENDER_SELECTION_CENTER
-        GLUquadricObj* m_quadric;
-#endif // ENABLE_RENDER_SELECTION_CENTER
-        mutable GLArrow m_arrow;
-        mutable GLCurvedArrow m_curved_arrow;
-
-        mutable float m_scale_factor;
-
-    public:
-        Selection();
-#if ENABLE_RENDER_SELECTION_CENTER
-        ~Selection();
-#endif // ENABLE_RENDER_SELECTION_CENTER
-
-        void set_volumes(GLVolumePtrs* volumes);
-        bool init(bool useVBOs);
-
-        Model* get_model() const { return m_model; }
-        void set_model(Model* model);
-
-        EMode get_mode() const { return m_mode; }
-        void set_mode(EMode mode) { m_mode = mode; }
-
-        void add(unsigned int volume_idx, bool as_single_selection = true);
-        void remove(unsigned int volume_idx);
-
-        void add_object(unsigned int object_idx, bool as_single_selection = true);
-        void remove_object(unsigned int object_idx);
-
-        void add_instance(unsigned int object_idx, unsigned int instance_idx, bool as_single_selection = true);
-        void remove_instance(unsigned int object_idx, unsigned int instance_idx);
-
-        void add_volume(unsigned int object_idx, unsigned int volume_idx, int instance_idx, bool as_single_selection = true);
-        void remove_volume(unsigned int object_idx, unsigned int volume_idx);
-
-        void add_all();
-
-        // Update the selection based on the map from old indices to new indices after m_volumes changed.
-        // If the current selection is by instance, this call may select newly added volumes, if they belong to already selected instances.
-        void volumes_changed(const std::vector<size_t> &map_volume_old_to_new);
-        void clear();
-
-        bool is_empty() const { return m_type == Empty; }
-        bool is_wipe_tower() const { return m_type == WipeTower; }
-        bool is_modifier() const { return (m_type == SingleModifier) || (m_type == MultipleModifier); }
-        bool is_single_modifier() const { return m_type == SingleModifier; }
-        bool is_multiple_modifier() const { return m_type == MultipleModifier; }
-        bool is_single_full_instance() const;
-        bool is_multiple_full_instance() const { return m_type == MultipleFullInstance; }
-        bool is_single_full_object() const { return m_type == SingleFullObject; }
-        bool is_multiple_full_object() const { return m_type == MultipleFullObject; }
-        bool is_single_volume() const { return m_type == SingleVolume; }
-        bool is_multiple_volume() const { return m_type == MultipleVolume; }
-        bool is_mixed() const { return m_type == Mixed; }
-        bool is_from_single_instance() const { return get_instance_idx() != -1; }
-        bool is_from_single_object() const;
-
-        bool contains_volume(unsigned int volume_idx) const { return std::find(m_list.begin(), m_list.end(), volume_idx) != m_list.end(); }
-        bool requires_uniform_scale() const;
-
-        // Returns the the object id if the selection is from a single object, otherwise is -1
-        int get_object_idx() const;
-        // Returns the instance id if the selection is from a single object and from a single instance, otherwise is -1
-        int get_instance_idx() const;
-        // Returns the indices of selected instances.
-        // Can only be called if selection is from a single object.
-        const InstanceIdxsList& get_instance_idxs() const;
-
-        const IndicesList& get_volume_idxs() const { return m_list; }
-        const GLVolume* get_volume(unsigned int volume_idx) const;
-
-        const ObjectIdxsToInstanceIdxsMap& get_content() const { return m_cache.content; }
-
-        unsigned int volumes_count() const { return (unsigned int)m_list.size(); }
-        const BoundingBoxf3& get_bounding_box() const;
-
-        void start_dragging();
-
-        void translate(const Vec3d& displacement, bool local = false);
-        void rotate(const Vec3d& rotation, TransformationType transformation_type);
-        void flattening_rotate(const Vec3d& normal);
-        void scale(const Vec3d& scale, bool local);
-        void mirror(Axis axis);
-
-        void translate(unsigned int object_idx, const Vec3d& displacement);
-        void translate(unsigned int object_idx, unsigned int instance_idx, const Vec3d& displacement);
-
-        void erase();
-
-        void render(float scale_factor = 1.0) const;
-#if ENABLE_RENDER_SELECTION_CENTER
-        void render_center() const;
-#endif // ENABLE_RENDER_SELECTION_CENTER
-        void render_sidebar_hints(const std::string& sidebar_field) const;
-
-        bool requires_local_axes() const;
-
-    private:
-        void _update_valid();
-        void _update_type();
-        void _set_caches();
-        void _add_volume(unsigned int volume_idx);
-        void _add_instance(unsigned int object_idx, unsigned int instance_idx);
-        void _add_object(unsigned int object_idx);
-        void _remove_volume(unsigned int volume_idx);
-        void _remove_instance(unsigned int object_idx, unsigned int instance_idx);
-        void _remove_object(unsigned int object_idx);
-        void _calc_bounding_box() const;
-        void _render_selected_volumes() const;
-        void _render_synchronized_volumes() const;
-        void _render_bounding_box(const BoundingBoxf3& box, float* color) const;
-        void _render_sidebar_position_hints(const std::string& sidebar_field) const;
-        void _render_sidebar_rotation_hints(const std::string& sidebar_field) const;
-        void _render_sidebar_scale_hints(const std::string& sidebar_field) const;
-        void _render_sidebar_size_hints(const std::string& sidebar_field) const;
-        void _render_sidebar_position_hint(Axis axis) const;
-        void _render_sidebar_rotation_hint(Axis axis) const;
-        void _render_sidebar_scale_hint(Axis axis) const;
-        void _render_sidebar_size_hint(Axis axis, double length) const;
-		enum SyncRotationType {
-			// Do not synchronize rotation. Either not rotating at all, or rotating by world Z axis.
-			SYNC_ROTATION_NONE = 0,
-			// Synchronize fully. Used from "place on bed" feature.
-			SYNC_ROTATION_FULL = 1,
-			// Synchronize after rotation by an axis not parallel with Z.
-			SYNC_ROTATION_GENERAL = 2,
-		};
-        void _synchronize_unselected_instances(SyncRotationType sync_rotation_type);
-        void _synchronize_unselected_volumes();
-        void _ensure_on_bed();
-    };
-
     class ClippingPlane
     {
         double m_data[4];
diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp
index 183820aed..2dda6b7cd 100644
--- a/src/slic3r/GUI/GUI_ObjectList.cpp
+++ b/src/slic3r/GUI/GUI_ObjectList.cpp
@@ -10,6 +10,7 @@
 #include "libslic3r/Model.hpp"
 #include "LambdaObjectDialog.hpp"
 #include "GLCanvas3D.hpp"
+#include "Selection.hpp"
 
 #include <boost/algorithm/string.hpp>
 #include "slic3r/Utils/FixModelByWin10.hpp"
@@ -1275,7 +1276,7 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode
     if (obj_idx < 0) 
         return;
 
-    const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
+    const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
     assert(obj_idx == selection.get_object_idx());
 
     /** Any changes of the Object's composition is duplicated for all Object's Instances
@@ -1563,7 +1564,7 @@ bool ObjectList::selected_instances_of_same_object()
 
 bool ObjectList::can_split_instances()
 {
-    const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
+    const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
     return selection.is_multiple_full_instance() || selection.is_single_full_instance();
 }
 
@@ -1873,7 +1874,7 @@ bool ObjectList::multiple_selection() const
 
 void ObjectList::update_selections()
 {
-    const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
+    const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
     wxDataViewItemArray sels;
 
     // We doesn't update selection if SettingsItem for the current object/part is selected
@@ -1971,7 +1972,7 @@ void ObjectList::update_selections()
 
 void ObjectList::update_selections_on_canvas()
 {
-    GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
+    Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
 
     const int sel_cnt = GetSelectedItemsCount();
     if (sel_cnt == 0) {
@@ -1980,8 +1981,8 @@ void ObjectList::update_selections_on_canvas()
         return;
     }
 
-    auto add_to_selection = [this](const wxDataViewItem& item, GLCanvas3D::Selection& selection, bool as_single_selection)
-    {        
+    auto add_to_selection = [this](const wxDataViewItem& item, Selection& selection, bool as_single_selection)
+    {
         if (m_objects_model->GetParent(item) == wxDataViewItem(0)) {
             selection.add_object(m_objects_model->GetIdByItem(item), as_single_selection);
             return;
@@ -2240,7 +2241,7 @@ void ObjectList::instances_to_separated_object(const int obj_idx, const std::set
 
 void ObjectList::split_instances()
 {
-    const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
+    const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
     const int obj_idx = selection.get_object_idx();
     if (obj_idx == -1)
         return;
diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp
index ab83df05d..d186f7057 100644
--- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp
+++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp
@@ -7,6 +7,8 @@
 #include "PresetBundle.hpp"
 #include "libslic3r/Model.hpp"
 #include "libslic3r/Geometry.hpp"
+#include "GLCanvas3D.hpp"
+#include "Selection.hpp"
 
 #include <boost/algorithm/string.hpp>
 
@@ -155,7 +157,7 @@ void ObjectManipulation::UpdateAndShow(const bool show)
     OG_Settings::UpdateAndShow(show);
 }
 
-void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& selection)
+void ObjectManipulation::update_settings_value(const Selection& selection)
 {
 	m_new_move_label_string   = L("Position");
     m_new_rotate_label_string = L("Rotation");
@@ -348,7 +350,7 @@ void ObjectManipulation::reset_settings_value()
 void ObjectManipulation::change_position_value(const Vec3d& position)
 {
     auto canvas = wxGetApp().plater()->canvas3D();
-    GLCanvas3D::Selection& selection = canvas->get_selection();
+    Selection& selection = canvas->get_selection();
     selection.start_dragging();
     selection.translate(position - m_cache.position, selection.requires_local_axes());
     canvas->do_move();
@@ -359,10 +361,10 @@ void ObjectManipulation::change_position_value(const Vec3d& position)
 void ObjectManipulation::change_rotation_value(const Vec3d& rotation)
 {
     GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
-    const GLCanvas3D::Selection& selection = canvas->get_selection();
+    const Selection& selection = canvas->get_selection();
 
-	GLCanvas3D::TransformationType transformation_type(GLCanvas3D::TransformationType::World_Relative_Joint);
-	if (selection.is_single_full_instance() || selection.requires_local_axes())
+    TransformationType transformation_type(TransformationType::World_Relative_Joint);
+    if (selection.is_single_full_instance() || selection.requires_local_axes())
 		transformation_type.set_independent();
 	if (selection.is_single_full_instance()) {
         //FIXME GLCanvas3D::Selection::rotate() does not process absoulte rotations correctly: It does not recognize the axis index, which was changed.
@@ -384,7 +386,7 @@ void ObjectManipulation::change_rotation_value(const Vec3d& rotation)
 void ObjectManipulation::change_scale_value(const Vec3d& scale)
 {
     Vec3d scaling_factor = scale;
-    const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
+    const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
     if (m_uniform_scale || selection.requires_uniform_scale())
     {
         Vec3d abs_scale_diff = (scale - m_cache.scale).cwiseAbs();
@@ -418,7 +420,7 @@ void ObjectManipulation::change_scale_value(const Vec3d& scale)
 
 void ObjectManipulation::change_size_value(const Vec3d& size)
 {
-    const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
+    const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
 
     Vec3d ref_size = m_cache.size;
     if (selection.is_single_volume() || selection.is_single_modifier())
diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp
index 16160c84d..46e8cec81 100644
--- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp
+++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp
@@ -4,7 +4,6 @@
 #include <memory>
 
 #include "GUI_ObjectSettings.hpp"
-#include "GLCanvas3D.hpp"
 
 class wxStaticText;
 class PrusaLockButton;
@@ -12,6 +11,7 @@ class PrusaLockButton;
 namespace Slic3r {
 namespace GUI {
 
+class Selection;
 
 class ObjectManipulation : public OG_Settings
 {
@@ -90,7 +90,7 @@ public:
     bool        IsShown() override;
     void        UpdateAndShow(const bool show) override;
 
-    void        update_settings_value(const GLCanvas3D::Selection& selection);
+    void        update_settings_value(const Selection& selection);
 
 	// Called from the App to update the UI if dirty.
 	void		update_if_dirty();
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp
index 290541a18..1e12674ec 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp
@@ -184,7 +184,7 @@ void GLGizmoBase::disable_grabber(unsigned int id)
     on_disable_grabber(id);
 }
 
-void GLGizmoBase::start_dragging(const GLCanvas3D::Selection& selection)
+void GLGizmoBase::start_dragging(const Selection& selection)
 {
     m_dragging = true;
 
@@ -208,7 +208,7 @@ void GLGizmoBase::stop_dragging()
     on_stop_dragging();
 }
 
-void GLGizmoBase::update(const UpdateData& data, const GLCanvas3D::Selection& selection)
+void GLGizmoBase::update(const UpdateData& data, const Selection& selection)
 {
     if (m_hover_id != -1)
         on_update(data, selection);
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp
index e8328bcd4..b70c1f8df 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp
@@ -5,6 +5,7 @@
 
 #include "slic3r/GUI/GLCanvas3D.hpp"
 #include "slic3r/GUI/I18N.hpp"
+#include "slic3r/GUI/Selection.hpp"
 
 
 class wxWindow;
@@ -126,7 +127,7 @@ public:
     const std::string& get_icon_filename() const { return m_icon_filename; }
 #endif // ENABLE_SVG_ICONS
 
-    bool is_activable(const GLCanvas3D::Selection& selection) const { return on_is_activable(selection); }
+    bool is_activable(const Selection& selection) const { return on_is_activable(selection); }
     bool is_selectable() const { return on_is_selectable(); }
 
     unsigned int get_sprite_id() const { return m_sprite_id; }
@@ -139,31 +140,31 @@ public:
     void enable_grabber(unsigned int id);
     void disable_grabber(unsigned int id);
 
-    void start_dragging(const GLCanvas3D::Selection& selection);
+    void start_dragging(const Selection& selection);
     void stop_dragging();
     bool is_dragging() const { return m_dragging; }
 
-    void update(const UpdateData& data, const GLCanvas3D::Selection& selection);
+    void update(const UpdateData& data, const Selection& selection);
 
-    void render(const GLCanvas3D::Selection& selection) const { on_render(selection); }
-    void render_for_picking(const GLCanvas3D::Selection& selection) const { on_render_for_picking(selection); }
-    void render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) { on_render_input_window(x, y, bottom_limit, selection); }
+    void render(const Selection& selection) const { on_render(selection); }
+    void render_for_picking(const Selection& selection) const { on_render_for_picking(selection); }
+    void render_input_window(float x, float y, float bottom_limit, const Selection& selection) { on_render_input_window(x, y, bottom_limit, selection); }
 
 protected:
     virtual bool on_init() = 0;
     virtual std::string on_get_name() const = 0;
     virtual void on_set_state() {}
     virtual void on_set_hover_id() {}
-    virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const { return true; }
+    virtual bool on_is_activable(const Selection& selection) const { return true; }
     virtual bool on_is_selectable() const { return true; }
     virtual void on_enable_grabber(unsigned int id) {}
     virtual void on_disable_grabber(unsigned int id) {}
-    virtual void on_start_dragging(const GLCanvas3D::Selection& selection) {}
+    virtual void on_start_dragging(const Selection& selection) {}
     virtual void on_stop_dragging() {}
-    virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) = 0;
-    virtual void on_render(const GLCanvas3D::Selection& selection) const = 0;
-    virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const = 0;
-    virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) {}
+    virtual void on_update(const UpdateData& data, const Selection& selection) = 0;
+    virtual void on_render(const Selection& selection) const = 0;
+    virtual void on_render_for_picking(const Selection& selection) const = 0;
+    virtual void on_render_input_window(float x, float y, float bottom_limit, const Selection& selection) {}
 
     // Returns the picking color for the given id, based on the BASE_ID constant
     // No check is made for clashing with other picking color (i.e. GLVolumes)
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp
index 54a39c6d5..e228706c0 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp
@@ -101,12 +101,12 @@ void GLGizmoCut::on_set_state()
     }
 }
 
-bool GLGizmoCut::on_is_activable(const GLCanvas3D::Selection& selection) const
+bool GLGizmoCut::on_is_activable(const Selection& selection) const
 {
     return selection.is_single_full_instance() && !selection.is_wipe_tower();
 }
 
-void GLGizmoCut::on_start_dragging(const GLCanvas3D::Selection& selection)
+void GLGizmoCut::on_start_dragging(const Selection& selection)
 {
     if (m_hover_id == -1) { return; }
 
@@ -118,14 +118,14 @@ void GLGizmoCut::on_start_dragging(const GLCanvas3D::Selection& selection)
     m_drag_center(2) = m_cut_z;
 }
 
-void GLGizmoCut::on_update(const UpdateData& data, const GLCanvas3D::Selection& selection)
+void GLGizmoCut::on_update(const UpdateData& data, const Selection& selection)
 {
     if (m_hover_id != -1) {
         set_cut_z(m_start_z + calc_projection(data.mouse_ray));
     }
 }
 
-void GLGizmoCut::on_render(const GLCanvas3D::Selection& selection) const
+void GLGizmoCut::on_render(const Selection& selection) const
 {
     if (m_grabbers[0].dragging) {
         set_tooltip("Z: " + format(m_cut_z, 2));
@@ -176,14 +176,14 @@ void GLGizmoCut::on_render(const GLCanvas3D::Selection& selection) const
     m_grabbers[0].render(m_hover_id == 0, box.max_size());
 }
 
-void GLGizmoCut::on_render_for_picking(const GLCanvas3D::Selection& selection) const
+void GLGizmoCut::on_render_for_picking(const Selection& selection) const
 {
     ::glDisable(GL_DEPTH_TEST);
 
     render_grabbers_for_picking(selection.get_bounding_box());
 }
 
-void GLGizmoCut::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection)
+void GLGizmoCut::on_render_input_window(float x, float y, float bottom_limit, const Selection& selection)
 {
     m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
     m_imgui->set_next_window_bg_alpha(0.5f);
@@ -207,7 +207,7 @@ void GLGizmoCut::on_render_input_window(float x, float y, float bottom_limit, co
     }
 }
 
-void GLGizmoCut::update_max_z(const GLCanvas3D::Selection& selection) const
+void GLGizmoCut::update_max_z(const Selection& selection) const
 {
     m_max_z = selection.get_bounding_box().size()(2);
     set_cut_z(m_cut_z);
@@ -219,7 +219,7 @@ void GLGizmoCut::set_cut_z(double cut_z) const
     m_cut_z = std::max(0.0, std::min(m_max_z, cut_z));
 }
 
-void GLGizmoCut::perform_cut(const GLCanvas3D::Selection& selection)
+void GLGizmoCut::perform_cut(const Selection& selection)
 {
     const auto instance_idx = selection.get_instance_idx();
     const auto object_idx = selection.get_object_idx();
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp
index beec6d1da..fd4e8d8dc 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp
@@ -33,17 +33,17 @@ protected:
     virtual bool on_init();
     virtual std::string on_get_name() const;
     virtual void on_set_state();
-    virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const;
-    virtual void on_start_dragging(const GLCanvas3D::Selection& selection);
-    virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection);
-    virtual void on_render(const GLCanvas3D::Selection& selection) const;
-    virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const;
-    virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection);
+    virtual bool on_is_activable(const Selection& selection) const;
+    virtual void on_start_dragging(const Selection& selection);
+    virtual void on_update(const UpdateData& data, const Selection& selection);
+    virtual void on_render(const Selection& selection) const;
+    virtual void on_render_for_picking(const Selection& selection) const;
+    virtual void on_render_input_window(float x, float y, float bottom_limit, const Selection& selection);
 
 private:
-    void update_max_z(const GLCanvas3D::Selection& selection) const;
+    void update_max_z(const Selection& selection) const;
     void set_cut_z(double cut_z) const;
-    void perform_cut(const GLCanvas3D::Selection& selection);
+    void perform_cut(const Selection& selection);
     double calc_projection(const Linef3& mouse_ray) const;
 };
 
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp
index d72dc4913..2ed048677 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp
@@ -32,12 +32,12 @@ std::string GLGizmoFlatten::on_get_name() const
     return L("Place on face [F]");
 }
 
-bool GLGizmoFlatten::on_is_activable(const GLCanvas3D::Selection& selection) const
+bool GLGizmoFlatten::on_is_activable(const Selection& selection) const
 {
     return selection.is_single_full_instance();
 }
 
-void GLGizmoFlatten::on_start_dragging(const GLCanvas3D::Selection& selection)
+void GLGizmoFlatten::on_start_dragging(const Selection& selection)
 {
     if (m_hover_id != -1)
     {
@@ -47,7 +47,7 @@ void GLGizmoFlatten::on_start_dragging(const GLCanvas3D::Selection& selection)
     }
 }
 
-void GLGizmoFlatten::on_render(const GLCanvas3D::Selection& selection) const
+void GLGizmoFlatten::on_render(const Selection& selection) const
 {
     ::glClear(GL_DEPTH_BUFFER_BIT);
 
@@ -83,7 +83,7 @@ void GLGizmoFlatten::on_render(const GLCanvas3D::Selection& selection) const
     ::glDisable(GL_BLEND);
 }
 
-void GLGizmoFlatten::on_render_for_picking(const GLCanvas3D::Selection& selection) const
+void GLGizmoFlatten::on_render_for_picking(const Selection& selection) const
 {
     ::glDisable(GL_DEPTH_TEST);
     ::glDisable(GL_BLEND);
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp
index c91924c5a..1bd17e5ef 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp
@@ -49,11 +49,11 @@ public:
 protected:
     virtual bool on_init();
     virtual std::string on_get_name() const;
-    virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const;
-    virtual void on_start_dragging(const GLCanvas3D::Selection& selection);
-    virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) {}
-    virtual void on_render(const GLCanvas3D::Selection& selection) const;
-    virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const;
+    virtual bool on_is_activable(const Selection& selection) const;
+    virtual void on_start_dragging(const Selection& selection);
+    virtual void on_update(const UpdateData& data, const Selection& selection) {}
+    virtual void on_render(const Selection& selection) const;
+    virtual void on_render_for_picking(const Selection& selection) const;
     virtual void on_set_state()
     {
         if (m_state == On && is_plane_update_necessary())
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp
index d18d71c83..03151c433 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp
@@ -51,7 +51,7 @@ std::string GLGizmoMove3D::on_get_name() const
     return L("Move [M]");
 }
 
-void GLGizmoMove3D::on_start_dragging(const GLCanvas3D::Selection& selection)
+void GLGizmoMove3D::on_start_dragging(const Selection& selection)
 {
     if (m_hover_id != -1)
     {
@@ -69,7 +69,7 @@ void GLGizmoMove3D::on_stop_dragging()
     m_displacement = Vec3d::Zero();
 }
 
-void GLGizmoMove3D::on_update(const UpdateData& data, const GLCanvas3D::Selection& selection)
+void GLGizmoMove3D::on_update(const UpdateData& data, const Selection& selection)
 {
     if (m_hover_id == 0)
         m_displacement(0) = calc_projection(data);
@@ -79,7 +79,7 @@ void GLGizmoMove3D::on_update(const UpdateData& data, const GLCanvas3D::Selectio
         m_displacement(2) = calc_projection(data);
 }
 
-void GLGizmoMove3D::on_render(const GLCanvas3D::Selection& selection) const
+void GLGizmoMove3D::on_render(const Selection& selection) const
 {
     bool show_position = selection.is_single_full_instance();
     const Vec3d& position = selection.get_bounding_box().center();
@@ -155,7 +155,7 @@ void GLGizmoMove3D::on_render(const GLCanvas3D::Selection& selection) const
     }
 }
 
-void GLGizmoMove3D::on_render_for_picking(const GLCanvas3D::Selection& selection) const
+void GLGizmoMove3D::on_render_for_picking(const Selection& selection) const
 {
     ::glDisable(GL_DEPTH_TEST);
 
@@ -166,7 +166,7 @@ void GLGizmoMove3D::on_render_for_picking(const GLCanvas3D::Selection& selection
     render_grabber_extension(Z, box, true);
 }
 
-void GLGizmoMove3D::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection)
+void GLGizmoMove3D::on_render_input_window(float x, float y, float bottom_limit, const Selection& selection)
 {
 #if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
     bool show_position = selection.is_single_full_instance();
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp
index d4d97de7f..ddab2b777 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp
@@ -37,12 +37,12 @@ public:
 protected:
     virtual bool on_init();
     virtual std::string on_get_name() const;
-    virtual void on_start_dragging(const GLCanvas3D::Selection& selection);
+    virtual void on_start_dragging(const Selection& selection);
     virtual void on_stop_dragging();
-    virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection);
-    virtual void on_render(const GLCanvas3D::Selection& selection) const;
-    virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const;
-    virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection);
+    virtual void on_update(const UpdateData& data, const Selection& selection);
+    virtual void on_render(const Selection& selection) const;
+    virtual void on_render_for_picking(const Selection& selection) const;
+    virtual void on_render_input_window(float x, float y, float bottom_limit, const Selection& selection);
 
 private:
     double calc_projection(const UpdateData& data) const;
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp
index 4c6f66f4c..72b9ad18a 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp
@@ -80,7 +80,7 @@ bool GLGizmoRotate::on_init()
     return true;
 }
 
-void GLGizmoRotate::on_start_dragging(const GLCanvas3D::Selection& selection)
+void GLGizmoRotate::on_start_dragging(const Selection& selection)
 {
     const BoundingBoxf3& box = selection.get_bounding_box();
     m_center = box.center();
@@ -91,7 +91,7 @@ void GLGizmoRotate::on_start_dragging(const GLCanvas3D::Selection& selection)
     m_snap_fine_out_radius = m_snap_fine_in_radius + m_radius * ScaleLongTooth;
 }
 
-void GLGizmoRotate::on_update(const UpdateData& data, const GLCanvas3D::Selection& selection)
+void GLGizmoRotate::on_update(const UpdateData& data, const Selection& selection)
 {
     Vec2d mouse_pos = to_2d(mouse_position_in_local_plane(data.mouse_ray, selection));
 
@@ -126,7 +126,7 @@ void GLGizmoRotate::on_update(const UpdateData& data, const GLCanvas3D::Selectio
     m_angle = theta;
 }
 
-void GLGizmoRotate::on_render(const GLCanvas3D::Selection& selection) const
+void GLGizmoRotate::on_render(const Selection& selection) const
 {
     if (!m_grabbers[0].enabled)
         return;
@@ -183,7 +183,7 @@ void GLGizmoRotate::on_render(const GLCanvas3D::Selection& selection) const
     ::glPopMatrix();
 }
 
-void GLGizmoRotate::on_render_for_picking(const GLCanvas3D::Selection& selection) const
+void GLGizmoRotate::on_render_for_picking(const Selection& selection) const
 {
     ::glDisable(GL_DEPTH_TEST);
 
@@ -347,7 +347,7 @@ void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool pick
         ::glDisable(GL_LIGHTING);
 }
 
-void GLGizmoRotate::transform_to_local(const GLCanvas3D::Selection& selection) const
+void GLGizmoRotate::transform_to_local(const Selection& selection) const
 {
     ::glTranslated(m_center(0), m_center(1), m_center(2));
 
@@ -380,7 +380,7 @@ void GLGizmoRotate::transform_to_local(const GLCanvas3D::Selection& selection) c
     }
 }
 
-Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray, const GLCanvas3D::Selection& selection) const
+Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray, const Selection& selection) const
 {
     double half_pi = 0.5 * (double)PI;
 
@@ -457,7 +457,7 @@ std::string GLGizmoRotate3D::on_get_name() const
     return L("Rotate [R]");
 }
 
-void GLGizmoRotate3D::on_start_dragging(const GLCanvas3D::Selection& selection)
+void GLGizmoRotate3D::on_start_dragging(const Selection& selection)
 {
     if ((0 <= m_hover_id) && (m_hover_id < 3))
         m_gizmos[m_hover_id].start_dragging(selection);
@@ -469,7 +469,7 @@ void GLGizmoRotate3D::on_stop_dragging()
         m_gizmos[m_hover_id].stop_dragging();
 }
 
-void GLGizmoRotate3D::on_render(const GLCanvas3D::Selection& selection) const
+void GLGizmoRotate3D::on_render(const Selection& selection) const
 {
     ::glClear(GL_DEPTH_BUFFER_BIT);
 
@@ -483,7 +483,7 @@ void GLGizmoRotate3D::on_render(const GLCanvas3D::Selection& selection) const
         m_gizmos[Z].render(selection);
 }
 
-void GLGizmoRotate3D::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection)
+void GLGizmoRotate3D::on_render_input_window(float x, float y, float bottom_limit, const Selection& selection)
 {
 #if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
     Vec3d rotation(Geometry::rad2deg(m_gizmos[0].get_angle()), Geometry::rad2deg(m_gizmos[1].get_angle()), Geometry::rad2deg(m_gizmos[2].get_angle()));
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp
index aca64c94e..f5946aa56 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp
@@ -52,10 +52,10 @@ public:
 protected:
     virtual bool on_init();
     virtual std::string on_get_name() const { return ""; }
-    virtual void on_start_dragging(const GLCanvas3D::Selection& selection);
-    virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection);
-    virtual void on_render(const GLCanvas3D::Selection& selection) const;
-    virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const;
+    virtual void on_start_dragging(const Selection& selection);
+    virtual void on_update(const UpdateData& data, const Selection& selection);
+    virtual void on_render(const Selection& selection) const;
+    virtual void on_render_for_picking(const Selection& selection) const;
 
 private:
     void render_circle() const;
@@ -66,9 +66,9 @@ private:
     void render_grabber(const BoundingBoxf3& box) const;
     void render_grabber_extension(const BoundingBoxf3& box, bool picking) const;
 
-    void transform_to_local(const GLCanvas3D::Selection& selection) const;
+    void transform_to_local(const Selection& selection) const;
     // returns the intersection of the mouse ray with the plane perpendicular to the gizmo axis, in local coordinate
-    Vec3d mouse_position_in_local_plane(const Linef3& mouse_ray, const GLCanvas3D::Selection& selection) const;
+    Vec3d mouse_position_in_local_plane(const Linef3& mouse_ray, const Selection& selection) const;
 };
 
 class GLGizmoRotate3D : public GLGizmoBase
@@ -102,7 +102,7 @@ protected:
             m_gizmos[i].set_hover_id((m_hover_id == i) ? 0 : -1);
         }
     }
-    virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const { return !selection.is_wipe_tower(); }
+    virtual bool on_is_activable(const Selection& selection) const { return !selection.is_wipe_tower(); }
     virtual void on_enable_grabber(unsigned int id)
     {
         if ((0 <= id) && (id < 3))
@@ -113,17 +113,17 @@ protected:
         if ((0 <= id) && (id < 3))
             m_gizmos[id].disable_grabber(0);
     }
-    virtual void on_start_dragging(const GLCanvas3D::Selection& selection);
+    virtual void on_start_dragging(const Selection& selection);
     virtual void on_stop_dragging();
-    virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection)
+    virtual void on_update(const UpdateData& data, const Selection& selection)
     {
         for (GLGizmoRotate& g : m_gizmos)
         {
             g.update(data, selection);
         }
     }
-    virtual void on_render(const GLCanvas3D::Selection& selection) const;
-    virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const
+    virtual void on_render(const Selection& selection) const;
+    virtual void on_render_for_picking(const Selection& selection) const
     {
         for (const GLGizmoRotate& g : m_gizmos)
         {
@@ -131,7 +131,7 @@ protected:
         }
     }
 
-    virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection);
+    virtual void on_render_input_window(float x, float y, float bottom_limit, const Selection& selection);
 };
 
 
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp
index acc44e00d..43152b56c 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp
@@ -51,7 +51,7 @@ std::string GLGizmoScale3D::on_get_name() const
     return L("Scale [S]");
 }
 
-void GLGizmoScale3D::on_start_dragging(const GLCanvas3D::Selection& selection)
+void GLGizmoScale3D::on_start_dragging(const Selection& selection)
 {
     if (m_hover_id != -1)
     {
@@ -60,7 +60,7 @@ void GLGizmoScale3D::on_start_dragging(const GLCanvas3D::Selection& selection)
     }
 }
 
-void GLGizmoScale3D::on_update(const UpdateData& data, const GLCanvas3D::Selection& selection)
+void GLGizmoScale3D::on_update(const UpdateData& data, const Selection& selection)
 {
     if ((m_hover_id == 0) || (m_hover_id == 1))
         do_scale_x(data);
@@ -72,7 +72,7 @@ void GLGizmoScale3D::on_update(const UpdateData& data, const GLCanvas3D::Selecti
         do_scale_uniform(data);
 }
 
-void GLGizmoScale3D::on_render(const GLCanvas3D::Selection& selection) const
+void GLGizmoScale3D::on_render(const Selection& selection) const
 {
     bool single_instance = selection.is_single_full_instance();
     bool single_volume = selection.is_single_modifier() || selection.is_single_volume();
@@ -121,7 +121,7 @@ void GLGizmoScale3D::on_render(const GLCanvas3D::Selection& selection) const
     if (single_instance)
     {
         // calculate bounding box in instance local reference system
-        const GLCanvas3D::Selection::IndicesList& idxs = selection.get_volume_idxs();
+        const Selection::IndicesList& idxs = selection.get_volume_idxs();
         for (unsigned int idx : idxs)
         {
             const GLVolume* vol = selection.get_volume(idx);
@@ -267,14 +267,14 @@ void GLGizmoScale3D::on_render(const GLCanvas3D::Selection& selection) const
     }
 }
 
-void GLGizmoScale3D::on_render_for_picking(const GLCanvas3D::Selection& selection) const
+void GLGizmoScale3D::on_render_for_picking(const Selection& selection) const
 {
     ::glDisable(GL_DEPTH_TEST);
 
     render_grabbers_for_picking(selection.get_bounding_box());
 }
 
-void GLGizmoScale3D::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection)
+void GLGizmoScale3D::on_render_input_window(float x, float y, float bottom_limit, const Selection& selection)
 {
 #if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI
     bool single_instance = selection.is_single_full_instance();
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp
index 8554e57a7..6e14a361e 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp
@@ -37,12 +37,12 @@ public:
 protected:
     virtual bool on_init();
     virtual std::string on_get_name() const;
-    virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const { return !selection.is_wipe_tower(); }
-    virtual void on_start_dragging(const GLCanvas3D::Selection& selection);
-    virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection);
-    virtual void on_render(const GLCanvas3D::Selection& selection) const;
-    virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const;
-    virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection);
+    virtual bool on_is_activable(const Selection& selection) const { return !selection.is_wipe_tower(); }
+    virtual void on_start_dragging(const Selection& selection);
+    virtual void on_update(const UpdateData& data, const Selection& selection);
+    virtual void on_render(const Selection& selection) const;
+    virtual void on_render_for_picking(const Selection& selection) const;
+    virtual void on_render_input_window(float x, float y, float bottom_limit, const Selection& selection);
 
 private:
     void render_grabbers_connection(unsigned int id_1, unsigned int id_2) const;
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
index 695564971..cd7e3b985 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
@@ -42,7 +42,7 @@ bool GLGizmoSlaSupports::on_init()
     return true;
 }
 
-void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const GLCanvas3D::Selection& selection)
+void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const Selection& selection)
 {
     m_starting_center = Vec3d::Zero();
     m_old_model_object = m_model_object;
@@ -72,7 +72,7 @@ void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const G
     }
 }
 
-void GLGizmoSlaSupports::on_render(const GLCanvas3D::Selection& selection) const
+void GLGizmoSlaSupports::on_render(const Selection& selection) const
 {
     ::glEnable(GL_BLEND);
     ::glEnable(GL_DEPTH_TEST);
@@ -123,14 +123,14 @@ void GLGizmoSlaSupports::render_selection_rectangle() const
     ::glPopAttrib();                // restore former MatrixMode
 }
 
-void GLGizmoSlaSupports::on_render_for_picking(const GLCanvas3D::Selection& selection) const
+void GLGizmoSlaSupports::on_render_for_picking(const Selection& selection) const
 {
     ::glEnable(GL_DEPTH_TEST);
 
     render_points(selection, true);
 }
 
-void GLGizmoSlaSupports::render_points(const GLCanvas3D::Selection& selection, bool picking) const
+void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) const
 {
     if (m_quadric == nullptr || !selection.is_from_single_instance())
         return;
@@ -276,7 +276,7 @@ std::pair<Vec3f, Vec3f> GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse
 
     igl::Hit hit;
 
-    const GLCanvas3D::Selection& selection = m_parent.get_selection();
+    const Selection& selection = m_parent.get_selection();
     const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
     double z_offset = volume->get_sla_shift_z();
 
@@ -380,7 +380,7 @@ bool GLGizmoSlaSupports::mouse_event(SLAGizmoEventType action, const Vec2d& mous
             GLdouble projection_matrix[16];
             ::glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix);
 
-            const GLCanvas3D::Selection& selection = m_parent.get_selection();
+            const Selection& selection = m_parent.get_selection();
             const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
             double z_offset = volume->get_sla_shift_z();
 
@@ -484,7 +484,7 @@ void GLGizmoSlaSupports::delete_selected_points(bool force)
     //m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
 }
 
-void GLGizmoSlaSupports::on_update(const UpdateData& data, const GLCanvas3D::Selection& selection)
+void GLGizmoSlaSupports::on_update(const UpdateData& data, const Selection& selection)
 {
     if (m_editing_mode && m_hover_id != -1 && data.mouse_pos && (!m_editing_mode_cache[m_hover_id].support_point.is_new_island || !m_lock_unique_islands)) {
         std::pair<Vec3f, Vec3f> pos_and_normal;
@@ -542,7 +542,7 @@ void GLGizmoSlaSupports::update_cache_entry_normal(unsigned int i) const
 
 
 
-void GLGizmoSlaSupports::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection)
+void GLGizmoSlaSupports::on_render_input_window(float x, float y, float bottom_limit, const Selection& selection)
 {
     if (!m_model_object)
         return;
@@ -686,14 +686,14 @@ RENDER_AGAIN:
         m_parent.set_as_dirty();
 }
 
-bool GLGizmoSlaSupports::on_is_activable(const GLCanvas3D::Selection& selection) const
+bool GLGizmoSlaSupports::on_is_activable(const Selection& selection) const
 {
     if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA
         || !selection.is_from_single_instance())
             return false;
 
     // Check that none of the selected volumes is outside.
-    const GLCanvas3D::Selection::IndicesList& list = selection.get_volume_idxs();
+    const Selection::IndicesList& list = selection.get_volume_idxs();
     for (const auto& idx : list)
         if (selection.get_volume(idx)->is_outside)
             return false;
@@ -750,7 +750,7 @@ void GLGizmoSlaSupports::on_set_state()
 
 
 
-void GLGizmoSlaSupports::on_start_dragging(const GLCanvas3D::Selection& selection)
+void GLGizmoSlaSupports::on_start_dragging(const Selection& selection)
 {
     if (m_hover_id != -1) {
         select_point(NoPoints);
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp
index 492bb85ca..c27ff0b6d 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp
@@ -58,19 +58,19 @@ public:
     GLGizmoSlaSupports(GLCanvas3D& parent, unsigned int sprite_id);
 #endif // ENABLE_SVG_ICONS
     virtual ~GLGizmoSlaSupports();
-    void set_sla_support_data(ModelObject* model_object, const GLCanvas3D::Selection& selection);
+    void set_sla_support_data(ModelObject* model_object, const Selection& selection);
     bool mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down);
     void delete_selected_points(bool force = false);
     std::pair<float, float> get_sla_clipping_plane() const;
 
 private:
     bool on_init();
-    void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection);
-    virtual void on_render(const GLCanvas3D::Selection& selection) const;
-    virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const;
+    void on_update(const UpdateData& data, const Selection& selection);
+    virtual void on_render(const Selection& selection) const;
+    virtual void on_render_for_picking(const Selection& selection) const;
 
     void render_selection_rectangle() const;
-    void render_points(const GLCanvas3D::Selection& selection, bool picking = false) const;
+    void render_points(const Selection& selection, bool picking = false) const;
     bool is_mesh_update_necessary() const;
     void update_mesh();
     void update_cache_entry_normal(unsigned int i) const;
@@ -113,11 +113,11 @@ private:
 
 protected:
     void on_set_state() override;
-    void on_start_dragging(const GLCanvas3D::Selection& selection) override;
-    virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) override;
+    void on_start_dragging(const Selection& selection) override;
+    virtual void on_render_input_window(float x, float y, float bottom_limit, const Selection& selection) override;
 
     virtual std::string on_get_name() const;
-    virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const;
+    virtual bool on_is_activable(const Selection& selection) const;
     virtual bool on_is_selectable() const;
 };
 
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index 6ddb4c837..630586bb5 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -47,6 +47,7 @@
 #include "MainFrame.hpp"
 #include "3DScene.hpp"
 #include "GLCanvas3D.hpp"
+#include "Selection.hpp"
 #include "GLToolbar.hpp"
 #include "GUI_Preview.hpp"
 #include "3DBed.hpp"
@@ -1153,8 +1154,8 @@ struct Plater::priv
     std::vector<size_t> load_model_objects(const ModelObjectPtrs &model_objects);
     std::unique_ptr<CheckboxFileDialog> get_export_file(GUI::FileType file_type);
 
-    const GLCanvas3D::Selection& get_selection() const;
-    GLCanvas3D::Selection& get_selection();
+    const Selection& get_selection() const;
+    Selection& get_selection();
     int get_selected_object_idx() const;
     int get_selected_volume_idx() const;
     void selection_changed();
@@ -1641,7 +1642,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
     // automatic selection of added objects
     if (!obj_idxs.empty() && (view3D != nullptr))
     {
-        GLCanvas3D::Selection& selection = view3D->get_canvas3d()->get_selection();
+        Selection& selection = view3D->get_canvas3d()->get_selection();
         selection.clear();
         for (size_t idx : obj_idxs)
         {
@@ -1790,12 +1791,12 @@ std::unique_ptr<CheckboxFileDialog> Plater::priv::get_export_file(GUI::FileType
     return dlg;
 }
 
-const GLCanvas3D::Selection& Plater::priv::get_selection() const
+const Selection& Plater::priv::get_selection() const
 {
     return view3D->get_canvas3d()->get_selection();
 }
 
-GLCanvas3D::Selection& Plater::priv::get_selection()
+Selection& Plater::priv::get_selection()
 {
     return view3D->get_canvas3d()->get_selection();
 }
diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp
new file mode 100644
index 000000000..e5d221a5f
--- /dev/null
+++ b/src/slic3r/GUI/Selection.cpp
@@ -0,0 +1,1670 @@
+#include "libslic3r/libslic3r.h"
+#include "Selection.hpp"
+
+#include "GLCanvas3D.hpp"
+#include "GUI_App.hpp"
+#include "GUI_ObjectManipulation.hpp"
+#include "GUI_ObjectList.hpp"
+#include "Gizmos/GLGizmoBase.hpp"
+
+#include <GL/glew.h>
+
+#include <boost/algorithm/string/predicate.hpp>
+
+static const float UNIFORM_SCALE_COLOR[3] = { 1.0f, 0.38f, 0.0f };
+
+namespace Slic3r {
+namespace GUI {
+
+Selection::VolumeCache::TransformCache::TransformCache()
+    : position(Vec3d::Zero())
+    , rotation(Vec3d::Zero())
+    , scaling_factor(Vec3d::Ones())
+    , mirror(Vec3d::Ones())
+    , rotation_matrix(Transform3d::Identity())
+    , scale_matrix(Transform3d::Identity())
+    , mirror_matrix(Transform3d::Identity())
+    , full_matrix(Transform3d::Identity())
+{
+}
+
+Selection::VolumeCache::TransformCache::TransformCache(const Geometry::Transformation& transform)
+    : position(transform.get_offset())
+    , rotation(transform.get_rotation())
+    , scaling_factor(transform.get_scaling_factor())
+    , mirror(transform.get_mirror())
+    , full_matrix(transform.get_matrix())
+{
+    rotation_matrix = Geometry::assemble_transform(Vec3d::Zero(), rotation);
+    scale_matrix = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), scaling_factor);
+    mirror_matrix = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), Vec3d::Ones(), mirror);
+}
+
+Selection::VolumeCache::VolumeCache(const Geometry::Transformation& volume_transform, const Geometry::Transformation& instance_transform)
+    : m_volume(volume_transform)
+    , m_instance(instance_transform)
+{
+}
+
+Selection::Selection()
+    : m_volumes(nullptr)
+    , m_model(nullptr)
+    , m_mode(Instance)
+    , m_type(Empty)
+    , m_valid(false)
+    , m_bounding_box_dirty(true)
+    , m_curved_arrow(16)
+    , m_scale_factor(1.0f)
+{
+#if ENABLE_RENDER_SELECTION_CENTER
+    m_quadric = ::gluNewQuadric();
+    if (m_quadric != nullptr)
+        ::gluQuadricDrawStyle(m_quadric, GLU_FILL);
+#endif // ENABLE_RENDER_SELECTION_CENTER
+}
+
+#if ENABLE_RENDER_SELECTION_CENTER
+Selection::~Selection()
+{
+    if (m_quadric != nullptr)
+        ::gluDeleteQuadric(m_quadric);
+}
+#endif // ENABLE_RENDER_SELECTION_CENTER
+
+void Selection::set_volumes(GLVolumePtrs* volumes)
+{
+    m_volumes = volumes;
+    _update_valid();
+}
+
+bool Selection::init(bool useVBOs)
+{
+    if (!m_arrow.init(useVBOs))
+        return false;
+
+    m_arrow.set_scale(5.0 * Vec3d::Ones());
+
+    if (!m_curved_arrow.init(useVBOs))
+        return false;
+
+    m_curved_arrow.set_scale(5.0 * Vec3d::Ones());
+    return true;
+}
+
+void Selection::set_model(Model* model)
+{
+    m_model = model;
+    _update_valid();
+}
+
+void Selection::add(unsigned int volume_idx, bool as_single_selection)
+{
+    if (!m_valid || ((unsigned int)m_volumes->size() <= volume_idx))
+        return;
+
+    const GLVolume* volume = (*m_volumes)[volume_idx];
+    // wipe tower is already selected
+    if (is_wipe_tower() && volume->is_wipe_tower)
+        return;
+
+    // resets the current list if needed
+    bool needs_reset = as_single_selection;
+    needs_reset |= volume->is_wipe_tower;
+    needs_reset |= is_wipe_tower() && !volume->is_wipe_tower;
+    needs_reset |= !is_modifier() && volume->is_modifier;
+    needs_reset |= is_modifier() && !volume->is_modifier;
+
+    if (needs_reset)
+        clear();
+
+    if (volume->is_modifier)
+        m_mode = Volume;
+    else if (!contains_volume(volume_idx))
+        m_mode = Instance;
+    // else -> keep current mode
+
+    switch (m_mode)
+    {
+    case Volume:
+    {
+        if (volume->volume_idx() >= 0 && (is_empty() || (volume->instance_idx() == get_instance_idx())))
+            _add_volume(volume_idx);
+
+        break;
+    }
+    case Instance:
+    {
+        _add_instance(volume->object_idx(), volume->instance_idx());
+        break;
+    }
+    }
+
+    _update_type();
+    m_bounding_box_dirty = true;
+}
+
+void Selection::remove(unsigned int volume_idx)
+{
+    if (!m_valid || ((unsigned int)m_volumes->size() <= volume_idx))
+        return;
+
+    GLVolume* volume = (*m_volumes)[volume_idx];
+
+    switch (m_mode)
+    {
+    case Volume:
+    {
+        _remove_volume(volume_idx);
+        break;
+    }
+    case Instance:
+    {
+        _remove_instance(volume->object_idx(), volume->instance_idx());
+        break;
+    }
+    }
+
+    _update_type();
+    m_bounding_box_dirty = true;
+}
+
+void Selection::add_object(unsigned int object_idx, bool as_single_selection)
+{
+    if (!m_valid)
+        return;
+
+    // resets the current list if needed
+    if (as_single_selection)
+        clear();
+
+    m_mode = Instance;
+
+    _add_object(object_idx);
+
+    _update_type();
+    m_bounding_box_dirty = true;
+}
+
+void Selection::remove_object(unsigned int object_idx)
+{
+    if (!m_valid)
+        return;
+
+    _remove_object(object_idx);
+
+    _update_type();
+    m_bounding_box_dirty = true;
+}
+
+void Selection::add_instance(unsigned int object_idx, unsigned int instance_idx, bool as_single_selection)
+{
+    if (!m_valid)
+        return;
+
+    // resets the current list if needed
+    if (as_single_selection)
+        clear();
+
+    m_mode = Instance;
+
+    _add_instance(object_idx, instance_idx);
+
+    _update_type();
+    m_bounding_box_dirty = true;
+}
+
+void Selection::remove_instance(unsigned int object_idx, unsigned int instance_idx)
+{
+    if (!m_valid)
+        return;
+
+    _remove_instance(object_idx, instance_idx);
+
+    _update_type();
+    m_bounding_box_dirty = true;
+}
+
+void Selection::add_volume(unsigned int object_idx, unsigned int volume_idx, int instance_idx, bool as_single_selection)
+{
+    if (!m_valid)
+        return;
+
+    // resets the current list if needed
+    if (as_single_selection)
+        clear();
+
+    m_mode = Volume;
+
+    for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
+    {
+        GLVolume* v = (*m_volumes)[i];
+        if ((v->object_idx() == object_idx) && (v->volume_idx() == volume_idx))
+        {
+            if ((instance_idx != -1) && (v->instance_idx() == instance_idx))
+                _add_volume(i);
+        }
+    }
+
+    _update_type();
+    m_bounding_box_dirty = true;
+}
+
+void Selection::remove_volume(unsigned int object_idx, unsigned int volume_idx)
+{
+    if (!m_valid)
+        return;
+
+    for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
+    {
+        GLVolume* v = (*m_volumes)[i];
+        if ((v->object_idx() == object_idx) && (v->volume_idx() == volume_idx))
+            _remove_volume(i);
+    }
+
+    _update_type();
+    m_bounding_box_dirty = true;
+}
+
+void Selection::add_all()
+{
+    if (!m_valid)
+        return;
+
+    m_mode = Instance;
+    clear();
+
+    for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
+    {
+        if (!(*m_volumes)[i]->is_wipe_tower)
+            _add_volume(i);
+    }
+
+    _update_type();
+    m_bounding_box_dirty = true;
+}
+
+void Selection::clear()
+{
+    if (!m_valid)
+        return;
+
+    for (unsigned int i : m_list)
+    {
+        (*m_volumes)[i]->selected = false;
+    }
+
+    m_list.clear();
+
+    _update_type();
+    m_bounding_box_dirty = true;
+
+    // resets the cache in the sidebar
+    wxGetApp().obj_manipul()->reset_cache();
+}
+
+// Update the selection based on the map from old indices to new indices after m_volumes changed.
+// If the current selection is by instance, this call may select newly added volumes, if they belong to already selected instances.
+void Selection::volumes_changed(const std::vector<size_t> &map_volume_old_to_new)
+{
+    assert(m_valid);
+
+    // 1) Update the selection set.
+    IndicesList list_new;
+    std::vector<std::pair<unsigned int, unsigned int>> model_instances;
+    for (unsigned int idx : m_list) {
+        if (map_volume_old_to_new[idx] != size_t(-1)) {
+            unsigned int new_idx = (unsigned int)map_volume_old_to_new[idx];
+            list_new.insert(new_idx);
+            if (m_mode == Instance) {
+                // Save the object_idx / instance_idx pair of selected old volumes,
+                // so we may add the newly added volumes of the same object_idx / instance_idx pair
+                // to the selection.
+                const GLVolume *volume = (*m_volumes)[new_idx];
+                model_instances.emplace_back(volume->object_idx(), volume->instance_idx());
+            }
+        }
+    }
+    m_list = std::move(list_new);
+
+    if (!model_instances.empty()) {
+        // Instance selection mode. Add the newly added volumes of the same object_idx / instance_idx pair
+        // to the selection.
+        assert(m_mode == Instance);
+        sort_remove_duplicates(model_instances);
+        for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) {
+            const GLVolume* volume = (*m_volumes)[i];
+            for (const std::pair<int, int> &model_instance : model_instances)
+                if (volume->object_idx() == model_instance.first && volume->instance_idx() == model_instance.second)
+                    this->_add_volume(i);
+        }
+    }
+
+    _update_type();
+    m_bounding_box_dirty = true;
+}
+
+bool Selection::is_single_full_instance() const
+{
+    if (m_type == SingleFullInstance)
+        return true;
+
+    if (m_type == SingleFullObject)
+        return get_instance_idx() != -1;
+
+    if (m_list.empty() || m_volumes->empty())
+        return false;
+
+    int object_idx = m_valid ? get_object_idx() : -1;
+    if ((object_idx < 0) || ((int)m_model->objects.size() <= object_idx))
+        return false;
+
+    int instance_idx = (*m_volumes)[*m_list.begin()]->instance_idx();
+
+    std::set<int> volumes_idxs;
+    for (unsigned int i : m_list)
+    {
+        const GLVolume* v = (*m_volumes)[i];
+        if ((object_idx != v->object_idx()) || (instance_idx != v->instance_idx()))
+            return false;
+
+        int volume_idx = v->volume_idx();
+        if (volume_idx >= 0)
+            volumes_idxs.insert(volume_idx);
+    }
+
+    return m_model->objects[object_idx]->volumes.size() == volumes_idxs.size();
+}
+
+bool Selection::is_from_single_object() const
+{
+    int idx = get_object_idx();
+    return (0 <= idx) && (idx < 1000);
+}
+
+bool Selection::requires_uniform_scale() const
+{
+    if (is_single_full_instance() || is_single_modifier() || is_single_volume())
+        return false;
+
+    return true;
+}
+
+int Selection::get_object_idx() const
+{
+    return (m_cache.content.size() == 1) ? m_cache.content.begin()->first : -1;
+}
+
+int Selection::get_instance_idx() const
+{
+    if (m_cache.content.size() == 1)
+    {
+        const InstanceIdxsList& idxs = m_cache.content.begin()->second;
+        if (idxs.size() == 1)
+            return *idxs.begin();
+    }
+
+    return -1;
+}
+
+const Selection::InstanceIdxsList& Selection::get_instance_idxs() const
+{
+    assert(m_cache.content.size() == 1);
+    return m_cache.content.begin()->second;
+}
+
+const GLVolume* Selection::get_volume(unsigned int volume_idx) const
+{
+    return (m_valid && (volume_idx < (unsigned int)m_volumes->size())) ? (*m_volumes)[volume_idx] : nullptr;
+}
+
+const BoundingBoxf3& Selection::get_bounding_box() const
+{
+    if (m_bounding_box_dirty)
+        _calc_bounding_box();
+
+    return m_bounding_box;
+}
+
+void Selection::start_dragging()
+{
+    if (!m_valid)
+        return;
+
+    _set_caches();
+}
+
+void Selection::translate(const Vec3d& displacement, bool local)
+{
+    if (!m_valid)
+        return;
+
+    for (unsigned int i : m_list)
+    {
+        if ((m_mode == Volume) || (*m_volumes)[i]->is_wipe_tower)
+        {
+            if (local)
+                (*m_volumes)[i]->set_volume_offset(m_cache.volumes_data[i].get_volume_position() + displacement);
+            else
+            {
+                Vec3d local_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() * m_cache.volumes_data[i].get_instance_mirror_matrix()).inverse() * displacement;
+                (*m_volumes)[i]->set_volume_offset(m_cache.volumes_data[i].get_volume_position() + local_displacement);
+            }
+        }
+        else if (m_mode == Instance)
+            (*m_volumes)[i]->set_instance_offset(m_cache.volumes_data[i].get_instance_position() + displacement);
+    }
+
+#if !DISABLE_INSTANCES_SYNCH
+    if (m_mode == Instance)
+        _synchronize_unselected_instances(SYNC_ROTATION_NONE);
+    else if (m_mode == Volume)
+        _synchronize_unselected_volumes();
+#endif // !DISABLE_INSTANCES_SYNCH
+
+    m_bounding_box_dirty = true;
+}
+
+static Eigen::Quaterniond rotation_xyz_diff(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
+{
+    return
+        // From the current coordinate system to world.
+        Eigen::AngleAxisd(rot_xyz_to(2), Vec3d::UnitZ()) * Eigen::AngleAxisd(rot_xyz_to(1), Vec3d::UnitY()) * Eigen::AngleAxisd(rot_xyz_to(0), Vec3d::UnitX()) *
+        // From world to the initial coordinate system.
+        Eigen::AngleAxisd(-rot_xyz_from(0), Vec3d::UnitX()) * Eigen::AngleAxisd(-rot_xyz_from(1), Vec3d::UnitY()) * Eigen::AngleAxisd(-rot_xyz_from(2), Vec3d::UnitZ());
+}
+
+// This should only be called if it is known, that the two rotations only differ in rotation around the Z axis.
+static double rotation_diff_z(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
+{
+    Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to));
+    Vec3d  axis = angle_axis.axis();
+    double angle = angle_axis.angle();
+#ifndef NDEBUG
+    if (std::abs(angle) > 1e-8) {
+        assert(std::abs(axis.x()) < 1e-8);
+        assert(std::abs(axis.y()) < 1e-8);
+    }
+#endif /* NDEBUG */
+    return (axis.z() < 0) ? -angle : angle;
+}
+
+// Rotate an object around one of the axes. Only one rotation component is expected to be changing.
+void Selection::rotate(const Vec3d& rotation, TransformationType transformation_type)
+{
+    if (!m_valid)
+        return;
+
+    // Only relative rotation values are allowed in the world coordinate system.
+    assert(!transformation_type.world() || transformation_type.relative());
+
+    int rot_axis_max = 0;
+    if (rotation.isApprox(Vec3d::Zero()))
+    {
+        for (unsigned int i : m_list)
+        {
+            GLVolume &volume = *(*m_volumes)[i];
+            if (m_mode == Instance)
+            {
+                volume.set_instance_rotation(m_cache.volumes_data[i].get_instance_rotation());
+                volume.set_instance_offset(m_cache.volumes_data[i].get_instance_position());
+            }
+            else if (m_mode == Volume)
+            {
+                volume.set_volume_rotation(m_cache.volumes_data[i].get_volume_rotation());
+                volume.set_volume_offset(m_cache.volumes_data[i].get_volume_position());
+            }
+        }
+    }
+    else
+    {
+        //FIXME this does not work for absolute rotations (transformation_type.absolute() is true)
+        rotation.cwiseAbs().maxCoeff(&rot_axis_max);
+
+        // For generic rotation, we want to rotate the first volume in selection, and then to synchronize the other volumes with it.
+        std::vector<int> object_instance_first(m_model->objects.size(), -1);
+        auto rotate_instance = [this, &rotation, &object_instance_first, rot_axis_max, transformation_type](GLVolume &volume, int i) {
+            int first_volume_idx = object_instance_first[volume.object_idx()];
+            if (rot_axis_max != 2 && first_volume_idx != -1) {
+                // Generic rotation, but no rotation around the Z axis.
+                // Always do a local rotation (do not consider the selection to be a rigid body).
+                assert(is_approx(rotation.z(), 0.0));
+                const GLVolume &first_volume = *(*m_volumes)[first_volume_idx];
+                const Vec3d    &rotation = first_volume.get_instance_rotation();
+                double z_diff = rotation_diff_z(m_cache.volumes_data[first_volume_idx].get_instance_rotation(), m_cache.volumes_data[i].get_instance_rotation());
+                volume.set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2) + z_diff));
+            }
+            else {
+                // extracts rotations from the composed transformation
+                Vec3d new_rotation = transformation_type.world() ?
+                    Geometry::extract_euler_angles(Geometry::assemble_transform(Vec3d::Zero(), rotation) * m_cache.volumes_data[i].get_instance_rotation_matrix()) :
+                    transformation_type.absolute() ? rotation : rotation + m_cache.volumes_data[i].get_instance_rotation();
+                if (rot_axis_max == 2 && transformation_type.joint()) {
+                    // Only allow rotation of multiple instances as a single rigid body when rotating around the Z axis.
+                    Vec3d offset = Geometry::assemble_transform(Vec3d::Zero(), Vec3d(0.0, 0.0, new_rotation(2) - m_cache.volumes_data[i].get_instance_rotation()(2))) * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center);
+                    volume.set_instance_offset(m_cache.dragging_center + offset);
+                }
+                volume.set_instance_rotation(new_rotation);
+                object_instance_first[volume.object_idx()] = i;
+            }
+        };
+
+        for (unsigned int i : m_list)
+        {
+            GLVolume &volume = *(*m_volumes)[i];
+            if (is_single_full_instance())
+                rotate_instance(volume, i);
+            else if (is_single_volume() || is_single_modifier())
+            {
+                if (transformation_type.independent())
+                    volume.set_volume_rotation(volume.get_volume_rotation() + rotation);
+                else
+                {
+                    Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation);
+                    Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_volume_rotation_matrix());
+                    volume.set_volume_rotation(new_rotation);
+                }
+            }
+            else
+            {
+                if (m_mode == Instance)
+                    rotate_instance(volume, i);
+                else if (m_mode == Volume)
+                {
+                    // extracts rotations from the composed transformation
+                    Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation);
+                    Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_volume_rotation_matrix());
+                    if (transformation_type.joint())
+                    {
+                        Vec3d local_pivot = m_cache.volumes_data[i].get_instance_full_matrix().inverse() * m_cache.dragging_center;
+                        Vec3d offset = m * (m_cache.volumes_data[i].get_volume_position() - local_pivot);
+                        volume.set_volume_offset(local_pivot + offset);
+                    }
+                    volume.set_volume_rotation(new_rotation);
+                }
+            }
+        }
+    }
+
+#if !DISABLE_INSTANCES_SYNCH
+    if (m_mode == Instance)
+        _synchronize_unselected_instances((rot_axis_max == 2) ? SYNC_ROTATION_NONE : SYNC_ROTATION_GENERAL);
+    else if (m_mode == Volume)
+        _synchronize_unselected_volumes();
+#endif // !DISABLE_INSTANCES_SYNCH
+
+    m_bounding_box_dirty = true;
+}
+
+void Selection::flattening_rotate(const Vec3d& normal)
+{
+    // We get the normal in untransformed coordinates. We must transform it using the instance matrix, find out
+    // how to rotate the instance so it faces downwards and do the rotation. All that for all selected instances.
+    // The function assumes that is_from_single_object() holds.
+
+    if (!m_valid)
+        return;
+
+    for (unsigned int i : m_list)
+    {
+        Transform3d wst = m_cache.volumes_data[i].get_instance_scale_matrix();
+        Vec3d scaling_factor = Vec3d(1. / wst(0, 0), 1. / wst(1, 1), 1. / wst(2, 2));
+
+        Transform3d wmt = m_cache.volumes_data[i].get_instance_mirror_matrix();
+        Vec3d mirror(wmt(0, 0), wmt(1, 1), wmt(2, 2));
+
+        Vec3d rotation = Geometry::extract_euler_angles(m_cache.volumes_data[i].get_instance_rotation_matrix());
+        Vec3d transformed_normal = Geometry::assemble_transform(Vec3d::Zero(), rotation, scaling_factor, mirror) * normal;
+        transformed_normal.normalize();
+
+        Vec3d axis = transformed_normal(2) > 0.999f ? Vec3d(1., 0., 0.) : Vec3d(transformed_normal.cross(Vec3d(0., 0., -1.)));
+        axis.normalize();
+
+        Transform3d extra_rotation = Transform3d::Identity();
+        extra_rotation.rotate(Eigen::AngleAxisd(acos(-transformed_normal(2)), axis));
+
+        Vec3d new_rotation = Geometry::extract_euler_angles(extra_rotation * m_cache.volumes_data[i].get_instance_rotation_matrix());
+        (*m_volumes)[i]->set_instance_rotation(new_rotation);
+    }
+
+#if !DISABLE_INSTANCES_SYNCH
+    // we want to synchronize z-rotation as well, otherwise the flattening behaves funny
+    // when applied on one of several identical instances
+    if (m_mode == Instance)
+        _synchronize_unselected_instances(SYNC_ROTATION_FULL);
+#endif // !DISABLE_INSTANCES_SYNCH
+
+    m_bounding_box_dirty = true;
+}
+
+void Selection::scale(const Vec3d& scale, bool local)
+{
+    if (!m_valid)
+        return;
+
+    for (unsigned int i : m_list)
+    {
+        if (is_single_full_instance())
+            (*m_volumes)[i]->set_instance_scaling_factor(scale);
+        else if (is_single_volume() || is_single_modifier())
+            (*m_volumes)[i]->set_volume_scaling_factor(scale);
+        else
+        {
+            Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), scale);
+            if (m_mode == Instance)
+            {
+                Eigen::Matrix<double, 3, 3, Eigen::DontAlign> new_matrix = (m * m_cache.volumes_data[i].get_instance_scale_matrix()).matrix().block(0, 0, 3, 3);
+                // extracts scaling factors from the composed transformation
+                Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm());
+                if (!local)
+                    (*m_volumes)[i]->set_instance_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center));
+
+                (*m_volumes)[i]->set_instance_scaling_factor(new_scale);
+            }
+            else if (m_mode == Volume)
+            {
+                Eigen::Matrix<double, 3, 3, Eigen::DontAlign> new_matrix = (m * m_cache.volumes_data[i].get_volume_scale_matrix()).matrix().block(0, 0, 3, 3);
+                // extracts scaling factors from the composed transformation
+                Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm());
+                if (!local)
+                {
+                    Vec3d offset = m * (m_cache.volumes_data[i].get_volume_position() + m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center);
+                    (*m_volumes)[i]->set_volume_offset(m_cache.dragging_center - m_cache.volumes_data[i].get_instance_position() + offset);
+                }
+                (*m_volumes)[i]->set_volume_scaling_factor(new_scale);
+            }
+        }
+    }
+
+#if !DISABLE_INSTANCES_SYNCH
+    if (m_mode == Instance)
+        _synchronize_unselected_instances(SYNC_ROTATION_NONE);
+    else if (m_mode == Volume)
+        _synchronize_unselected_volumes();
+#endif // !DISABLE_INSTANCES_SYNCH
+
+    _ensure_on_bed();
+
+    m_bounding_box_dirty = true;
+}
+
+void Selection::mirror(Axis axis)
+{
+    if (!m_valid)
+        return;
+
+    bool single_full_instance = is_single_full_instance();
+
+    for (unsigned int i : m_list)
+    {
+        if (single_full_instance)
+            (*m_volumes)[i]->set_instance_mirror(axis, -(*m_volumes)[i]->get_instance_mirror(axis));
+        else if (m_mode == Volume)
+            (*m_volumes)[i]->set_volume_mirror(axis, -(*m_volumes)[i]->get_volume_mirror(axis));
+    }
+
+#if !DISABLE_INSTANCES_SYNCH
+    if (m_mode == Instance)
+        _synchronize_unselected_instances(SYNC_ROTATION_NONE);
+    else if (m_mode == Volume)
+        _synchronize_unselected_volumes();
+#endif // !DISABLE_INSTANCES_SYNCH
+
+    m_bounding_box_dirty = true;
+}
+
+void Selection::translate(unsigned int object_idx, const Vec3d& displacement)
+{
+    if (!m_valid)
+        return;
+
+    for (unsigned int i : m_list)
+    {
+        GLVolume* v = (*m_volumes)[i];
+        if (v->object_idx() == object_idx)
+            v->set_instance_offset(v->get_instance_offset() + displacement);
+    }
+
+    std::set<unsigned int> done;  // prevent processing volumes twice
+    done.insert(m_list.begin(), m_list.end());
+
+    for (unsigned int i : m_list)
+    {
+        if (done.size() == m_volumes->size())
+            break;
+
+        int object_idx = (*m_volumes)[i]->object_idx();
+        if (object_idx >= 1000)
+            continue;
+
+        // Process unselected volumes of the object.
+        for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j)
+        {
+            if (done.size() == m_volumes->size())
+                break;
+
+            if (done.find(j) != done.end())
+                continue;
+
+            GLVolume* v = (*m_volumes)[j];
+            if (v->object_idx() != object_idx)
+                continue;
+
+            v->set_instance_offset(v->get_instance_offset() + displacement);
+            done.insert(j);
+        }
+    }
+
+    m_bounding_box_dirty = true;
+}
+
+void Selection::translate(unsigned int object_idx, unsigned int instance_idx, const Vec3d& displacement)
+{
+    if (!m_valid)
+        return;
+
+    for (unsigned int i : m_list)
+    {
+        GLVolume* v = (*m_volumes)[i];
+        if ((v->object_idx() == object_idx) && (v->instance_idx() == instance_idx))
+            v->set_instance_offset(v->get_instance_offset() + displacement);
+    }
+
+    std::set<unsigned int> done;  // prevent processing volumes twice
+    done.insert(m_list.begin(), m_list.end());
+
+    for (unsigned int i : m_list)
+    {
+        if (done.size() == m_volumes->size())
+            break;
+
+        int object_idx = (*m_volumes)[i]->object_idx();
+        if (object_idx >= 1000)
+            continue;
+
+        // Process unselected volumes of the object.
+        for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j)
+        {
+            if (done.size() == m_volumes->size())
+                break;
+
+            if (done.find(j) != done.end())
+                continue;
+
+            GLVolume* v = (*m_volumes)[j];
+            if ((v->object_idx() != object_idx) || (v->instance_idx() != instance_idx))
+                continue;
+
+            v->set_instance_offset(v->get_instance_offset() + displacement);
+            done.insert(j);
+        }
+    }
+
+    m_bounding_box_dirty = true;
+}
+
+void Selection::erase()
+{
+    if (!m_valid)
+        return;
+
+    if (is_single_full_object())
+        wxGetApp().obj_list()->delete_from_model_and_list(ItemType::itObject, get_object_idx(), 0);
+    else if (is_multiple_full_object())
+    {
+        std::vector<ItemForDelete> items;
+        items.reserve(m_cache.content.size());
+        for (ObjectIdxsToInstanceIdxsMap::iterator it = m_cache.content.begin(); it != m_cache.content.end(); ++it)
+        {
+            items.emplace_back(ItemType::itObject, it->first, 0);
+        }
+        wxGetApp().obj_list()->delete_from_model_and_list(items);
+    }
+    else if (is_multiple_full_instance())
+    {
+        std::set<std::pair<int, int>> instances_idxs;
+        for (ObjectIdxsToInstanceIdxsMap::iterator obj_it = m_cache.content.begin(); obj_it != m_cache.content.end(); ++obj_it)
+        {
+            for (InstanceIdxsList::reverse_iterator inst_it = obj_it->second.rbegin(); inst_it != obj_it->second.rend(); ++inst_it)
+            {
+                instances_idxs.insert(std::make_pair(obj_it->first, *inst_it));
+            }
+        }
+
+        std::vector<ItemForDelete> items;
+        items.reserve(instances_idxs.size());
+        for (const std::pair<int, int>& i : instances_idxs)
+        {
+            items.emplace_back(ItemType::itInstance, i.first, i.second);
+        }
+        wxGetApp().obj_list()->delete_from_model_and_list(items);
+    }
+    else if (is_single_full_instance())
+        wxGetApp().obj_list()->delete_from_model_and_list(ItemType::itInstance, get_object_idx(), get_instance_idx());
+    else if (is_mixed())
+    {
+        std::set<ItemForDelete> items_set;
+        std::map<int, int> volumes_in_obj;
+
+        for (auto i : m_list) {
+            const auto gl_vol = (*m_volumes)[i];
+            const auto glv_obj_idx = gl_vol->object_idx();
+            const auto model_object = m_model->objects[glv_obj_idx];
+
+            if (model_object->instances.size() == 1) {
+                if (model_object->volumes.size() == 1)
+                    items_set.insert(ItemForDelete(ItemType::itObject, glv_obj_idx, -1));
+                else {
+                    items_set.insert(ItemForDelete(ItemType::itVolume, glv_obj_idx, gl_vol->volume_idx()));
+                    int idx = (volumes_in_obj.find(glv_obj_idx) == volumes_in_obj.end()) ? 0 : volumes_in_obj.at(glv_obj_idx);
+                    volumes_in_obj[glv_obj_idx] = ++idx;
+                }
+                continue;
+            }
+
+            const auto glv_ins_idx = gl_vol->instance_idx();
+
+            for (auto obj_ins : m_cache.content) {
+                if (obj_ins.first == glv_obj_idx) {
+                    if (obj_ins.second.find(glv_ins_idx) != obj_ins.second.end()) {
+                        if (obj_ins.second.size() == model_object->instances.size())
+                            items_set.insert(ItemForDelete(ItemType::itVolume, glv_obj_idx, gl_vol->volume_idx()));
+                        else
+                            items_set.insert(ItemForDelete(ItemType::itInstance, glv_obj_idx, glv_ins_idx));
+
+                        break;
+                    }
+                }
+            }
+        }
+
+        std::vector<ItemForDelete> items;
+        items.reserve(items_set.size());
+        for (const ItemForDelete& i : items_set) {
+            if (i.type == ItemType::itVolume) {
+                const int vol_in_obj_cnt = volumes_in_obj.find(i.obj_idx) == volumes_in_obj.end() ? 0 : volumes_in_obj.at(i.obj_idx);
+                if (vol_in_obj_cnt == m_model->objects[i.obj_idx]->volumes.size()) {
+                    if (i.sub_obj_idx == vol_in_obj_cnt - 1)
+                        items.emplace_back(ItemType::itObject, i.obj_idx, 0);
+                    continue;
+                }
+            }
+            items.emplace_back(i.type, i.obj_idx, i.sub_obj_idx);
+        }
+
+        wxGetApp().obj_list()->delete_from_model_and_list(items);
+    }
+    else
+    {
+        std::set<std::pair<int, int>> volumes_idxs;
+        for (unsigned int i : m_list)
+        {
+            const GLVolume* v = (*m_volumes)[i];
+            // Only remove volumes associated with ModelVolumes from the object list.
+            // Temporary meshes (SLA supports or pads) are not managed by the object list.
+            if (v->volume_idx() >= 0)
+                volumes_idxs.insert(std::make_pair(v->object_idx(), v->volume_idx()));
+        }
+
+        std::vector<ItemForDelete> items;
+        items.reserve(volumes_idxs.size());
+        for (const std::pair<int, int>& v : volumes_idxs)
+        {
+            items.emplace_back(ItemType::itVolume, v.first, v.second);
+        }
+
+        wxGetApp().obj_list()->delete_from_model_and_list(items);
+    }
+}
+
+void Selection::render(float scale_factor) const
+{
+    if (!m_valid || is_empty())
+        return;
+
+    m_scale_factor = scale_factor;
+
+    // render cumulative bounding box of selected volumes
+    _render_selected_volumes();
+    _render_synchronized_volumes();
+}
+
+#if ENABLE_RENDER_SELECTION_CENTER
+void Selection::render_center() const
+{
+    if (!m_valid || is_empty() || (m_quadric == nullptr))
+        return;
+
+    const Vec3d& center = get_bounding_box().center();
+
+    ::glDisable(GL_DEPTH_TEST);
+
+    ::glEnable(GL_LIGHTING);
+
+    ::glColor3f(1.0f, 1.0f, 1.0f);
+    ::glPushMatrix();
+    ::glTranslated(center(0), center(1), center(2));
+    ::gluSphere(m_quadric, 0.75, 32, 32);
+    ::glPopMatrix();
+
+    ::glDisable(GL_LIGHTING);
+}
+#endif // ENABLE_RENDER_SELECTION_CENTER
+
+void Selection::render_sidebar_hints(const std::string& sidebar_field) const
+{
+    if (sidebar_field.empty())
+        return;
+
+    ::glClear(GL_DEPTH_BUFFER_BIT);
+    ::glEnable(GL_DEPTH_TEST);
+
+    ::glEnable(GL_LIGHTING);
+
+    ::glPushMatrix();
+
+    const Vec3d& center = get_bounding_box().center();
+
+    if (is_single_full_instance())
+    {
+        ::glTranslated(center(0), center(1), center(2));
+        if (!boost::starts_with(sidebar_field, "position"))
+        {
+            Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true);
+            ::glMultMatrixd(orient_matrix.data());
+        }
+    }
+    else if (is_single_volume() || is_single_modifier())
+    {
+        ::glTranslated(center(0), center(1), center(2));
+        Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true);
+        if (!boost::starts_with(sidebar_field, "position"))
+            orient_matrix = orient_matrix * (*m_volumes)[*m_list.begin()]->get_volume_transformation().get_matrix(true, false, true, true);
+
+        ::glMultMatrixd(orient_matrix.data());
+    }
+    else
+    {
+        ::glTranslated(center(0), center(1), center(2));
+        if (requires_local_axes())
+        {
+            Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true);
+            ::glMultMatrixd(orient_matrix.data());
+        }
+    }
+
+    if (boost::starts_with(sidebar_field, "position"))
+        _render_sidebar_position_hints(sidebar_field);
+    else if (boost::starts_with(sidebar_field, "rotation"))
+        _render_sidebar_rotation_hints(sidebar_field);
+    else if (boost::starts_with(sidebar_field, "scale"))
+        _render_sidebar_scale_hints(sidebar_field);
+    else if (boost::starts_with(sidebar_field, "size"))
+        _render_sidebar_size_hints(sidebar_field);
+
+    ::glPopMatrix();
+
+    ::glDisable(GL_LIGHTING);
+}
+
+bool Selection::requires_local_axes() const
+{
+    return (m_mode == Volume) && is_from_single_instance();
+}
+
+void Selection::_update_valid()
+{
+    m_valid = (m_volumes != nullptr) && (m_model != nullptr);
+}
+
+void Selection::_update_type()
+{
+    m_cache.content.clear();
+    m_type = Mixed;
+
+    for (unsigned int i : m_list)
+    {
+        const GLVolume* volume = (*m_volumes)[i];
+        int obj_idx = volume->object_idx();
+        int inst_idx = volume->instance_idx();
+        ObjectIdxsToInstanceIdxsMap::iterator obj_it = m_cache.content.find(obj_idx);
+        if (obj_it == m_cache.content.end())
+            obj_it = m_cache.content.insert(ObjectIdxsToInstanceIdxsMap::value_type(obj_idx, InstanceIdxsList())).first;
+
+        obj_it->second.insert(inst_idx);
+    }
+
+    bool requires_disable = false;
+
+    if (!m_valid)
+        m_type = Invalid;
+    else
+    {
+        if (m_list.empty())
+            m_type = Empty;
+        else if (m_list.size() == 1)
+        {
+            const GLVolume* first = (*m_volumes)[*m_list.begin()];
+            if (first->is_wipe_tower)
+                m_type = WipeTower;
+            else if (first->is_modifier)
+            {
+                m_type = SingleModifier;
+                requires_disable = true;
+            }
+            else
+            {
+                const ModelObject* model_object = m_model->objects[first->object_idx()];
+                unsigned int volumes_count = (unsigned int)model_object->volumes.size();
+                unsigned int instances_count = (unsigned int)model_object->instances.size();
+                if (volumes_count * instances_count == 1)
+                {
+                    m_type = SingleFullObject;
+                    // ensures the correct mode is selected
+                    m_mode = Instance;
+                }
+                else if (volumes_count == 1) // instances_count > 1
+                {
+                    m_type = SingleFullInstance;
+                    // ensures the correct mode is selected
+                    m_mode = Instance;
+                }
+                else
+                {
+                    m_type = SingleVolume;
+                    requires_disable = true;
+                }
+            }
+        }
+        else
+        {
+            if (m_cache.content.size() == 1) // single object
+            {
+                const ModelObject* model_object = m_model->objects[m_cache.content.begin()->first];
+                unsigned int model_volumes_count = (unsigned int)model_object->volumes.size();
+                unsigned int sla_volumes_count = 0;
+                for (unsigned int i : m_list)
+                {
+                    if ((*m_volumes)[i]->volume_idx() < 0)
+                        ++sla_volumes_count;
+                }
+                unsigned int volumes_count = model_volumes_count + sla_volumes_count;
+                unsigned int instances_count = (unsigned int)model_object->instances.size();
+                unsigned int selected_instances_count = (unsigned int)m_cache.content.begin()->second.size();
+                if (volumes_count * instances_count == (unsigned int)m_list.size())
+                {
+                    m_type = SingleFullObject;
+                    // ensures the correct mode is selected
+                    m_mode = Instance;
+                }
+                else if (selected_instances_count == 1)
+                {
+                    if (volumes_count == (unsigned int)m_list.size())
+                    {
+                        m_type = SingleFullInstance;
+                        // ensures the correct mode is selected
+                        m_mode = Instance;
+                    }
+                    else
+                    {
+                        unsigned int modifiers_count = 0;
+                        for (unsigned int i : m_list)
+                        {
+                            if ((*m_volumes)[i]->is_modifier)
+                                ++modifiers_count;
+                        }
+
+                        if (modifiers_count == 0)
+                        {
+                            m_type = MultipleVolume;
+                            requires_disable = true;
+                        }
+                        else if (modifiers_count == (unsigned int)m_list.size())
+                        {
+                            m_type = MultipleModifier;
+                            requires_disable = true;
+                        }
+                    }
+                }
+                else if ((selected_instances_count > 1) && (selected_instances_count * volumes_count == (unsigned int)m_list.size()))
+                {
+                    m_type = MultipleFullInstance;
+                    // ensures the correct mode is selected
+                    m_mode = Instance;
+                }
+            }
+            else
+            {
+                int sels_cntr = 0;
+                for (ObjectIdxsToInstanceIdxsMap::iterator it = m_cache.content.begin(); it != m_cache.content.end(); ++it)
+                {
+                    const ModelObject* model_object = m_model->objects[it->first];
+                    unsigned int volumes_count = (unsigned int)model_object->volumes.size();
+                    unsigned int instances_count = (unsigned int)model_object->instances.size();
+                    sels_cntr += volumes_count * instances_count;
+                }
+                if (sels_cntr == (unsigned int)m_list.size())
+                {
+                    m_type = MultipleFullObject;
+                    // ensures the correct mode is selected
+                    m_mode = Instance;
+                }
+            }
+        }
+    }
+
+    int object_idx = get_object_idx();
+    int instance_idx = get_instance_idx();
+    for (GLVolume* v : *m_volumes)
+    {
+        v->disabled = requires_disable ? (v->object_idx() != object_idx) || (v->instance_idx() != instance_idx) : false;
+    }
+
+#if ENABLE_SELECTION_DEBUG_OUTPUT
+    std::cout << "Selection: ";
+    std::cout << "mode: ";
+    switch (m_mode)
+    {
+    case Volume:
+    {
+        std::cout << "Volume";
+        break;
+    }
+    case Instance:
+    {
+        std::cout << "Instance";
+        break;
+    }
+    }
+
+    std::cout << " - type: ";
+
+    switch (m_type)
+    {
+    case Invalid:
+    {
+        std::cout << "Invalid" << std::endl;
+        break;
+    }
+    case Empty:
+    {
+        std::cout << "Empty" << std::endl;
+        break;
+    }
+    case WipeTower:
+    {
+        std::cout << "WipeTower" << std::endl;
+        break;
+    }
+    case SingleModifier:
+    {
+        std::cout << "SingleModifier" << std::endl;
+        break;
+    }
+    case MultipleModifier:
+    {
+        std::cout << "MultipleModifier" << std::endl;
+        break;
+    }
+    case SingleVolume:
+    {
+        std::cout << "SingleVolume" << std::endl;
+        break;
+    }
+    case MultipleVolume:
+    {
+        std::cout << "MultipleVolume" << std::endl;
+        break;
+    }
+    case SingleFullObject:
+    {
+        std::cout << "SingleFullObject" << std::endl;
+        break;
+    }
+    case MultipleFullObject:
+    {
+        std::cout << "MultipleFullObject" << std::endl;
+        break;
+    }
+    case SingleFullInstance:
+    {
+        std::cout << "SingleFullInstance" << std::endl;
+        break;
+    }
+    case MultipleFullInstance:
+    {
+        std::cout << "MultipleFullInstance" << std::endl;
+        break;
+    }
+    case Mixed:
+    {
+        std::cout << "Mixed" << std::endl;
+        break;
+    }
+    }
+#endif // ENABLE_SELECTION_DEBUG_OUTPUT
+}
+
+void Selection::_set_caches()
+{
+    m_cache.volumes_data.clear();
+    for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
+    {
+        const GLVolume* v = (*m_volumes)[i];
+        m_cache.volumes_data.emplace(i, VolumeCache(v->get_volume_transformation(), v->get_instance_transformation()));
+    }
+    m_cache.dragging_center = get_bounding_box().center();
+}
+
+void Selection::_add_volume(unsigned int volume_idx)
+{
+    m_list.insert(volume_idx);
+    (*m_volumes)[volume_idx]->selected = true;
+}
+
+void Selection::_add_instance(unsigned int object_idx, unsigned int instance_idx)
+{
+    for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
+    {
+        GLVolume* v = (*m_volumes)[i];
+        if ((v->object_idx() == object_idx) && (v->instance_idx() == instance_idx))
+            _add_volume(i);
+    }
+}
+
+void Selection::_add_object(unsigned int object_idx)
+{
+    for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
+    {
+        GLVolume* v = (*m_volumes)[i];
+        if (v->object_idx() == object_idx)
+            _add_volume(i);
+    }
+}
+
+void Selection::_remove_volume(unsigned int volume_idx)
+{
+    IndicesList::iterator v_it = m_list.find(volume_idx);
+    if (v_it == m_list.end())
+        return;
+
+    m_list.erase(v_it);
+
+    (*m_volumes)[volume_idx]->selected = false;
+}
+
+void Selection::_remove_instance(unsigned int object_idx, unsigned int instance_idx)
+{
+    for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
+    {
+        GLVolume* v = (*m_volumes)[i];
+        if ((v->object_idx() == object_idx) && (v->instance_idx() == instance_idx))
+            _remove_volume(i);
+    }
+}
+
+void Selection::_remove_object(unsigned int object_idx)
+{
+    for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
+    {
+        GLVolume* v = (*m_volumes)[i];
+        if (v->object_idx() == object_idx)
+            _remove_volume(i);
+    }
+}
+
+void Selection::_calc_bounding_box() const
+{
+    m_bounding_box = BoundingBoxf3();
+    if (m_valid)
+    {
+        for (unsigned int i : m_list)
+        {
+            m_bounding_box.merge((*m_volumes)[i]->transformed_convex_hull_bounding_box());
+        }
+    }
+    m_bounding_box_dirty = false;
+}
+
+void Selection::_render_selected_volumes() const
+{
+    float color[3] = { 1.0f, 1.0f, 1.0f };
+    _render_bounding_box(get_bounding_box(), color);
+}
+
+void Selection::_render_synchronized_volumes() const
+{
+    if (m_mode == Instance)
+        return;
+
+    float color[3] = { 1.0f, 1.0f, 0.0f };
+
+    for (unsigned int i : m_list)
+    {
+        const GLVolume* volume = (*m_volumes)[i];
+        int object_idx = volume->object_idx();
+        int instance_idx = volume->instance_idx();
+        int volume_idx = volume->volume_idx();
+        for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j)
+        {
+            if (i == j)
+                continue;
+
+            const GLVolume* v = (*m_volumes)[j];
+            if ((v->object_idx() != object_idx) || (v->volume_idx() != volume_idx))
+                continue;
+
+            _render_bounding_box(v->transformed_convex_hull_bounding_box(), color);
+        }
+    }
+}
+
+void Selection::_render_bounding_box(const BoundingBoxf3& box, float* color) const
+{
+    if (color == nullptr)
+        return;
+
+    Vec3f b_min = box.min.cast<float>();
+    Vec3f b_max = box.max.cast<float>();
+    Vec3f size = 0.2f * box.size().cast<float>();
+
+    ::glEnable(GL_DEPTH_TEST);
+
+    ::glColor3fv(color);
+    ::glLineWidth(2.0f * m_scale_factor);
+
+    ::glBegin(GL_LINES);
+
+    ::glVertex3f(b_min(0), b_min(1), b_min(2)); ::glVertex3f(b_min(0) + size(0), b_min(1), b_min(2));
+    ::glVertex3f(b_min(0), b_min(1), b_min(2)); ::glVertex3f(b_min(0), b_min(1) + size(1), b_min(2));
+    ::glVertex3f(b_min(0), b_min(1), b_min(2)); ::glVertex3f(b_min(0), b_min(1), b_min(2) + size(2));
+
+    ::glVertex3f(b_max(0), b_min(1), b_min(2)); ::glVertex3f(b_max(0) - size(0), b_min(1), b_min(2));
+    ::glVertex3f(b_max(0), b_min(1), b_min(2)); ::glVertex3f(b_max(0), b_min(1) + size(1), b_min(2));
+    ::glVertex3f(b_max(0), b_min(1), b_min(2)); ::glVertex3f(b_max(0), b_min(1), b_min(2) + size(2));
+
+    ::glVertex3f(b_max(0), b_max(1), b_min(2)); ::glVertex3f(b_max(0) - size(0), b_max(1), b_min(2));
+    ::glVertex3f(b_max(0), b_max(1), b_min(2)); ::glVertex3f(b_max(0), b_max(1) - size(1), b_min(2));
+    ::glVertex3f(b_max(0), b_max(1), b_min(2)); ::glVertex3f(b_max(0), b_max(1), b_min(2) + size(2));
+
+    ::glVertex3f(b_min(0), b_max(1), b_min(2)); ::glVertex3f(b_min(0) + size(0), b_max(1), b_min(2));
+    ::glVertex3f(b_min(0), b_max(1), b_min(2)); ::glVertex3f(b_min(0), b_max(1) - size(1), b_min(2));
+    ::glVertex3f(b_min(0), b_max(1), b_min(2)); ::glVertex3f(b_min(0), b_max(1), b_min(2) + size(2));
+
+    ::glVertex3f(b_min(0), b_min(1), b_max(2)); ::glVertex3f(b_min(0) + size(0), b_min(1), b_max(2));
+    ::glVertex3f(b_min(0), b_min(1), b_max(2)); ::glVertex3f(b_min(0), b_min(1) + size(1), b_max(2));
+    ::glVertex3f(b_min(0), b_min(1), b_max(2)); ::glVertex3f(b_min(0), b_min(1), b_max(2) - size(2));
+
+    ::glVertex3f(b_max(0), b_min(1), b_max(2)); ::glVertex3f(b_max(0) - size(0), b_min(1), b_max(2));
+    ::glVertex3f(b_max(0), b_min(1), b_max(2)); ::glVertex3f(b_max(0), b_min(1) + size(1), b_max(2));
+    ::glVertex3f(b_max(0), b_min(1), b_max(2)); ::glVertex3f(b_max(0), b_min(1), b_max(2) - size(2));
+
+    ::glVertex3f(b_max(0), b_max(1), b_max(2)); ::glVertex3f(b_max(0) - size(0), b_max(1), b_max(2));
+    ::glVertex3f(b_max(0), b_max(1), b_max(2)); ::glVertex3f(b_max(0), b_max(1) - size(1), b_max(2));
+    ::glVertex3f(b_max(0), b_max(1), b_max(2)); ::glVertex3f(b_max(0), b_max(1), b_max(2) - size(2));
+
+    ::glVertex3f(b_min(0), b_max(1), b_max(2)); ::glVertex3f(b_min(0) + size(0), b_max(1), b_max(2));
+    ::glVertex3f(b_min(0), b_max(1), b_max(2)); ::glVertex3f(b_min(0), b_max(1) - size(1), b_max(2));
+    ::glVertex3f(b_min(0), b_max(1), b_max(2)); ::glVertex3f(b_min(0), b_max(1), b_max(2) - size(2));
+
+    ::glEnd();
+}
+
+void Selection::_render_sidebar_position_hints(const std::string& sidebar_field) const
+{
+    if (boost::ends_with(sidebar_field, "x"))
+    {
+        ::glRotated(-90.0, 0.0, 0.0, 1.0);
+        _render_sidebar_position_hint(X);
+    }
+    else if (boost::ends_with(sidebar_field, "y"))
+        _render_sidebar_position_hint(Y);
+    else if (boost::ends_with(sidebar_field, "z"))
+    {
+        ::glRotated(90.0, 1.0, 0.0, 0.0);
+        _render_sidebar_position_hint(Z);
+    }
+}
+
+void Selection::_render_sidebar_rotation_hints(const std::string& sidebar_field) const
+{
+    if (boost::ends_with(sidebar_field, "x"))
+    {
+        ::glRotated(90.0, 0.0, 1.0, 0.0);
+        _render_sidebar_rotation_hint(X);
+    }
+    else if (boost::ends_with(sidebar_field, "y"))
+    {
+        ::glRotated(-90.0, 1.0, 0.0, 0.0);
+        _render_sidebar_rotation_hint(Y);
+    }
+    else if (boost::ends_with(sidebar_field, "z"))
+        _render_sidebar_rotation_hint(Z);
+}
+
+void Selection::_render_sidebar_scale_hints(const std::string& sidebar_field) const
+{
+    bool uniform_scale = requires_uniform_scale() || wxGetApp().obj_manipul()->get_uniform_scaling();
+
+    if (boost::ends_with(sidebar_field, "x") || uniform_scale)
+    {
+        ::glPushMatrix();
+        ::glRotated(-90.0, 0.0, 0.0, 1.0);
+        _render_sidebar_scale_hint(X);
+        ::glPopMatrix();
+    }
+
+    if (boost::ends_with(sidebar_field, "y") || uniform_scale)
+    {
+        ::glPushMatrix();
+        _render_sidebar_scale_hint(Y);
+        ::glPopMatrix();
+    }
+
+    if (boost::ends_with(sidebar_field, "z") || uniform_scale)
+    {
+        ::glPushMatrix();
+        ::glRotated(90.0, 1.0, 0.0, 0.0);
+        _render_sidebar_scale_hint(Z);
+        ::glPopMatrix();
+    }
+}
+
+void Selection::_render_sidebar_size_hints(const std::string& sidebar_field) const
+{
+    _render_sidebar_scale_hints(sidebar_field);
+}
+
+void Selection::_render_sidebar_position_hint(Axis axis) const
+{
+    m_arrow.set_color(AXES_COLOR[axis], 3);
+    m_arrow.render();
+}
+
+void Selection::_render_sidebar_rotation_hint(Axis axis) const
+{
+    m_curved_arrow.set_color(AXES_COLOR[axis], 3);
+    m_curved_arrow.render();
+
+    ::glRotated(180.0, 0.0, 0.0, 1.0);
+    m_curved_arrow.render();
+}
+
+void Selection::_render_sidebar_scale_hint(Axis axis) const
+{
+    m_arrow.set_color(((requires_uniform_scale() || wxGetApp().obj_manipul()->get_uniform_scaling()) ? UNIFORM_SCALE_COLOR : AXES_COLOR[axis]), 3);
+
+    ::glTranslated(0.0, 5.0, 0.0);
+    m_arrow.render();
+
+    ::glTranslated(0.0, -10.0, 0.0);
+    ::glRotated(180.0, 0.0, 0.0, 1.0);
+    m_arrow.render();
+}
+
+void Selection::_render_sidebar_size_hint(Axis axis, double length) const
+{
+}
+
+#ifndef NDEBUG
+static bool is_rotation_xy_synchronized(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
+{
+    Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to));
+    Vec3d  axis = angle_axis.axis();
+    double angle = angle_axis.angle();
+    if (std::abs(angle) < 1e-8)
+        return true;
+    assert(std::abs(axis.x()) < 1e-8);
+    assert(std::abs(axis.y()) < 1e-8);
+    assert(std::abs(std::abs(axis.z()) - 1.) < 1e-8);
+    return std::abs(axis.x()) < 1e-8 && std::abs(axis.y()) < 1e-8 && std::abs(std::abs(axis.z()) - 1.) < 1e-8;
+}
+
+static void verify_instances_rotation_synchronized(const Model &model, const GLVolumePtrs &volumes)
+{
+    for (size_t idx_object = 0; idx_object < model.objects.size(); ++idx_object) {
+        int idx_volume_first = -1;
+        for (int i = 0; i < (int)volumes.size(); ++i) {
+            if (volumes[i]->object_idx() == idx_object) {
+                idx_volume_first = i;
+                break;
+            }
+        }
+        assert(idx_volume_first != -1); // object without instances?
+        if (idx_volume_first == -1)
+            continue;
+        const Vec3d &rotation0 = volumes[idx_volume_first]->get_instance_rotation();
+        for (int i = idx_volume_first + 1; i < (int)volumes.size(); ++i)
+            if (volumes[i]->object_idx() == idx_object) {
+                const Vec3d &rotation = volumes[i]->get_instance_rotation();
+                assert(is_rotation_xy_synchronized(rotation, rotation0));
+            }
+    }
+}
+#endif /* NDEBUG */
+
+void Selection::_synchronize_unselected_instances(SyncRotationType sync_rotation_type)
+{
+    std::set<unsigned int> done;  // prevent processing volumes twice
+    done.insert(m_list.begin(), m_list.end());
+
+    for (unsigned int i : m_list)
+    {
+        if (done.size() == m_volumes->size())
+            break;
+
+        const GLVolume* volume = (*m_volumes)[i];
+        int object_idx = volume->object_idx();
+        if (object_idx >= 1000)
+            continue;
+
+        int instance_idx = volume->instance_idx();
+        const Vec3d& rotation = volume->get_instance_rotation();
+        const Vec3d& scaling_factor = volume->get_instance_scaling_factor();
+        const Vec3d& mirror = volume->get_instance_mirror();
+
+        // Process unselected instances.
+        for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j)
+        {
+            if (done.size() == m_volumes->size())
+                break;
+
+            if (done.find(j) != done.end())
+                continue;
+
+            GLVolume* v = (*m_volumes)[j];
+            if ((v->object_idx() != object_idx) || (v->instance_idx() == instance_idx))
+                continue;
+
+            assert(is_rotation_xy_synchronized(m_cache.volumes_data[i].get_instance_rotation(), m_cache.volumes_data[j].get_instance_rotation()));
+            switch (sync_rotation_type) {
+            case SYNC_ROTATION_NONE:
+                // z only rotation -> keep instance z
+                // The X,Y rotations should be synchronized from start to end of the rotation.
+                assert(is_rotation_xy_synchronized(rotation, v->get_instance_rotation()));
+                break;
+            case SYNC_ROTATION_FULL:
+                // rotation comes from place on face -> force given z
+                v->set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2)));
+                break;
+            case SYNC_ROTATION_GENERAL:
+                // generic rotation -> update instance z with the delta of the rotation.
+                double z_diff = rotation_diff_z(m_cache.volumes_data[i].get_instance_rotation(), m_cache.volumes_data[j].get_instance_rotation());
+                v->set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2) + z_diff));
+                break;
+            }
+
+            v->set_instance_scaling_factor(scaling_factor);
+            v->set_instance_mirror(mirror);
+
+            done.insert(j);
+        }
+    }
+
+#ifndef NDEBUG
+    verify_instances_rotation_synchronized(*m_model, *m_volumes);
+#endif /* NDEBUG */
+}
+
+void Selection::_synchronize_unselected_volumes()
+{
+    for (unsigned int i : m_list)
+    {
+        const GLVolume* volume = (*m_volumes)[i];
+        int object_idx = volume->object_idx();
+        if (object_idx >= 1000)
+            continue;
+
+        int volume_idx = volume->volume_idx();
+        const Vec3d& offset = volume->get_volume_offset();
+        const Vec3d& rotation = volume->get_volume_rotation();
+        const Vec3d& scaling_factor = volume->get_volume_scaling_factor();
+        const Vec3d& mirror = volume->get_volume_mirror();
+
+        // Process unselected volumes.
+        for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j)
+        {
+            if (j == i)
+                continue;
+
+            GLVolume* v = (*m_volumes)[j];
+            if ((v->object_idx() != object_idx) || (v->volume_idx() != volume_idx))
+                continue;
+
+            v->set_volume_offset(offset);
+            v->set_volume_rotation(rotation);
+            v->set_volume_scaling_factor(scaling_factor);
+            v->set_volume_mirror(mirror);
+        }
+    }
+}
+
+void Selection::_ensure_on_bed()
+{
+    typedef std::map<std::pair<int, int>, double> InstancesToZMap;
+    InstancesToZMap instances_min_z;
+
+    for (GLVolume* volume : *m_volumes)
+    {
+        if (!volume->is_wipe_tower && !volume->is_modifier)
+        {
+            double min_z = volume->transformed_convex_hull_bounding_box().min(2);
+            std::pair<int, int> instance = std::make_pair(volume->object_idx(), volume->instance_idx());
+            InstancesToZMap::iterator it = instances_min_z.find(instance);
+            if (it == instances_min_z.end())
+                it = instances_min_z.insert(InstancesToZMap::value_type(instance, DBL_MAX)).first;
+
+            it->second = std::min(it->second, min_z);
+        }
+    }
+
+    for (GLVolume* volume : *m_volumes)
+    {
+        std::pair<int, int> instance = std::make_pair(volume->object_idx(), volume->instance_idx());
+        InstancesToZMap::iterator it = instances_min_z.find(instance);
+        if (it != instances_min_z.end())
+            volume->set_instance_offset(Z, volume->get_instance_offset(Z) - it->second);
+    }
+}
+
+} // namespace GUI
+} // namespace Slic3r
diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp
new file mode 100644
index 000000000..3a21122df
--- /dev/null
+++ b/src/slic3r/GUI/Selection.hpp
@@ -0,0 +1,301 @@
+#ifndef slic3r_GUI_Selection_hpp_
+#define slic3r_GUI_Selection_hpp_
+
+#include <set>
+#include "libslic3r/Geometry.hpp"
+#include "3DScene.hpp"
+
+namespace Slic3r {
+namespace GUI {
+
+class TransformationType
+{
+public:
+    enum Enum {
+        // Transforming in a world coordinate system
+        World = 0,
+        // Transforming in a local coordinate system
+        Local = 1,
+        // Absolute transformations, allowed in local coordinate system only.
+        Absolute = 0,
+        // Relative transformations, allowed in both local and world coordinate system.
+        Relative = 2,
+        // For group selection, the transformation is performed as if the group made a single solid body.
+        Joint = 0,
+        // For group selection, the transformation is performed on each object independently.
+        Independent = 4,
+
+        World_Relative_Joint = World | Relative | Joint,
+        World_Relative_Independent = World | Relative | Independent,
+        Local_Absolute_Joint = Local | Absolute | Joint,
+        Local_Absolute_Independent = Local | Absolute | Independent,
+        Local_Relative_Joint = Local | Relative | Joint,
+        Local_Relative_Independent = Local | Relative | Independent,
+    };
+
+    TransformationType() : m_value(World) {}
+    TransformationType(Enum value) : m_value(value) {}
+    TransformationType& operator=(Enum value) { m_value = value; return *this; }
+
+    Enum operator()() const { return m_value; }
+    bool has(Enum v) const { return ((unsigned int)m_value & (unsigned int)v) != 0; }
+
+    void set_world()        { this->remove(Local); }
+    void set_local()        { this->add(Local); }
+    void set_absolute()     { this->remove(Relative); }
+    void set_relative()     { this->add(Relative); }
+    void set_joint()        { this->remove(Independent); }
+    void set_independent()  { this->add(Independent); }
+
+    bool world()        const { return !this->has(Local); }
+    bool local()        const { return this->has(Local); }
+    bool absolute()     const { return !this->has(Relative); }
+    bool relative()     const { return this->has(Relative); }
+    bool joint()        const { return !this->has(Independent); }
+    bool independent()  const { return this->has(Independent); }
+
+private:
+    void add(Enum v) { m_value = Enum((unsigned int)m_value | (unsigned int)v); }
+    void remove(Enum v) { m_value = Enum((unsigned int)m_value & (~(unsigned int)v)); }
+
+    Enum    m_value;
+};
+
+class Selection
+{
+public:
+    typedef std::set<unsigned int> IndicesList;
+
+    enum EMode : unsigned char
+    {
+        Volume,
+        Instance
+    };
+
+    enum EType : unsigned char
+    {
+        Invalid,
+        Empty,
+        WipeTower,
+        SingleModifier,
+        MultipleModifier,
+        SingleVolume,
+        MultipleVolume,
+        SingleFullObject,
+        MultipleFullObject,
+        SingleFullInstance,
+        MultipleFullInstance,
+        Mixed
+    };
+
+private:
+    struct VolumeCache
+    {
+    private:
+        struct TransformCache
+        {
+            Vec3d position;
+            Vec3d rotation;
+            Vec3d scaling_factor;
+            Vec3d mirror;
+            Transform3d rotation_matrix;
+            Transform3d scale_matrix;
+            Transform3d mirror_matrix;
+            Transform3d full_matrix;
+
+            TransformCache();
+            explicit TransformCache(const Geometry::Transformation& transform);
+        };
+
+        TransformCache m_volume;
+        TransformCache m_instance;
+
+    public:
+        VolumeCache() {}
+        VolumeCache(const Geometry::Transformation& volume_transform, const Geometry::Transformation& instance_transform);
+
+        const Vec3d& get_volume_position() const { return m_volume.position; }
+        const Vec3d& get_volume_rotation() const { return m_volume.rotation; }
+        const Vec3d& get_volume_scaling_factor() const { return m_volume.scaling_factor; }
+        const Vec3d& get_volume_mirror() const { return m_volume.mirror; }
+        const Transform3d& get_volume_rotation_matrix() const { return m_volume.rotation_matrix; }
+        const Transform3d& get_volume_scale_matrix() const { return m_volume.scale_matrix; }
+        const Transform3d& get_volume_mirror_matrix() const { return m_volume.mirror_matrix; }
+        const Transform3d& get_volume_full_matrix() const { return m_volume.full_matrix; }
+
+        const Vec3d& get_instance_position() const { return m_instance.position; }
+        const Vec3d& get_instance_rotation() const { return m_instance.rotation; }
+        const Vec3d& get_instance_scaling_factor() const { return m_instance.scaling_factor; }
+        const Vec3d& get_instance_mirror() const { return m_instance.mirror; }
+        const Transform3d& get_instance_rotation_matrix() const { return m_instance.rotation_matrix; }
+        const Transform3d& get_instance_scale_matrix() const { return m_instance.scale_matrix; }
+        const Transform3d& get_instance_mirror_matrix() const { return m_instance.mirror_matrix; }
+        const Transform3d& get_instance_full_matrix() const { return m_instance.full_matrix; }
+    };
+
+    typedef std::map<unsigned int, VolumeCache> VolumesCache;
+    typedef std::set<int> InstanceIdxsList;
+    typedef std::map<int, InstanceIdxsList> ObjectIdxsToInstanceIdxsMap;
+
+    struct Cache
+    {
+        // Cache of GLVolume derived transformation matrices, valid during mouse dragging.
+        VolumesCache volumes_data;
+        // Center of the dragged selection, valid during mouse dragging.
+        Vec3d dragging_center;
+        // Map from indices of ModelObject instances in Model::objects
+        // to a set of indices of ModelVolume instances in ModelObject::instances
+        // Here the index means a position inside the respective std::vector, not ModelID.
+        ObjectIdxsToInstanceIdxsMap content;
+    };
+
+    // Volumes owned by GLCanvas3D.
+    GLVolumePtrs* m_volumes;
+    // Model, not owned.
+    Model* m_model;
+
+    bool m_valid;
+    EMode m_mode;
+    EType m_type;
+    // set of indices to m_volumes
+    IndicesList m_list;
+    Cache m_cache;
+    mutable BoundingBoxf3 m_bounding_box;
+    mutable bool m_bounding_box_dirty;
+
+#if ENABLE_RENDER_SELECTION_CENTER
+    GLUquadricObj* m_quadric;
+#endif // ENABLE_RENDER_SELECTION_CENTER
+    mutable GLArrow m_arrow;
+    mutable GLCurvedArrow m_curved_arrow;
+
+    mutable float m_scale_factor;
+
+public:
+    Selection();
+#if ENABLE_RENDER_SELECTION_CENTER
+    ~Selection();
+#endif // ENABLE_RENDER_SELECTION_CENTER
+
+    void set_volumes(GLVolumePtrs* volumes);
+    bool init(bool useVBOs);
+
+    Model* get_model() const { return m_model; }
+    void set_model(Model* model);
+
+    EMode get_mode() const { return m_mode; }
+    void set_mode(EMode mode) { m_mode = mode; }
+
+    void add(unsigned int volume_idx, bool as_single_selection = true);
+    void remove(unsigned int volume_idx);
+
+    void add_object(unsigned int object_idx, bool as_single_selection = true);
+    void remove_object(unsigned int object_idx);
+
+    void add_instance(unsigned int object_idx, unsigned int instance_idx, bool as_single_selection = true);
+    void remove_instance(unsigned int object_idx, unsigned int instance_idx);
+
+    void add_volume(unsigned int object_idx, unsigned int volume_idx, int instance_idx, bool as_single_selection = true);
+    void remove_volume(unsigned int object_idx, unsigned int volume_idx);
+
+    void add_all();
+
+    // Update the selection based on the map from old indices to new indices after m_volumes changed.
+    // If the current selection is by instance, this call may select newly added volumes, if they belong to already selected instances.
+    void volumes_changed(const std::vector<size_t> &map_volume_old_to_new);
+    void clear();
+
+    bool is_empty() const { return m_type == Empty; }
+    bool is_wipe_tower() const { return m_type == WipeTower; }
+    bool is_modifier() const { return (m_type == SingleModifier) || (m_type == MultipleModifier); }
+    bool is_single_modifier() const { return m_type == SingleModifier; }
+    bool is_multiple_modifier() const { return m_type == MultipleModifier; }
+    bool is_single_full_instance() const;
+    bool is_multiple_full_instance() const { return m_type == MultipleFullInstance; }
+    bool is_single_full_object() const { return m_type == SingleFullObject; }
+    bool is_multiple_full_object() const { return m_type == MultipleFullObject; }
+    bool is_single_volume() const { return m_type == SingleVolume; }
+    bool is_multiple_volume() const { return m_type == MultipleVolume; }
+    bool is_mixed() const { return m_type == Mixed; }
+    bool is_from_single_instance() const { return get_instance_idx() != -1; }
+    bool is_from_single_object() const;
+
+    bool contains_volume(unsigned int volume_idx) const { return std::find(m_list.begin(), m_list.end(), volume_idx) != m_list.end(); }
+    bool requires_uniform_scale() const;
+
+    // Returns the the object id if the selection is from a single object, otherwise is -1
+    int get_object_idx() const;
+    // Returns the instance id if the selection is from a single object and from a single instance, otherwise is -1
+    int get_instance_idx() const;
+    // Returns the indices of selected instances.
+    // Can only be called if selection is from a single object.
+    const InstanceIdxsList& get_instance_idxs() const;
+
+    const IndicesList& get_volume_idxs() const { return m_list; }
+    const GLVolume* get_volume(unsigned int volume_idx) const;
+
+    const ObjectIdxsToInstanceIdxsMap& get_content() const { return m_cache.content; }
+
+    unsigned int volumes_count() const { return (unsigned int)m_list.size(); }
+    const BoundingBoxf3& get_bounding_box() const;
+
+    void start_dragging();
+
+    void translate(const Vec3d& displacement, bool local = false);
+    void rotate(const Vec3d& rotation, TransformationType transformation_type);
+    void flattening_rotate(const Vec3d& normal);
+    void scale(const Vec3d& scale, bool local);
+    void mirror(Axis axis);
+
+    void translate(unsigned int object_idx, const Vec3d& displacement);
+    void translate(unsigned int object_idx, unsigned int instance_idx, const Vec3d& displacement);
+
+    void erase();
+
+    void render(float scale_factor = 1.0) const;
+#if ENABLE_RENDER_SELECTION_CENTER
+    void render_center() const;
+#endif // ENABLE_RENDER_SELECTION_CENTER
+    void render_sidebar_hints(const std::string& sidebar_field) const;
+
+    bool requires_local_axes() const;
+
+private:
+    void _update_valid();
+    void _update_type();
+    void _set_caches();
+    void _add_volume(unsigned int volume_idx);
+    void _add_instance(unsigned int object_idx, unsigned int instance_idx);
+    void _add_object(unsigned int object_idx);
+    void _remove_volume(unsigned int volume_idx);
+    void _remove_instance(unsigned int object_idx, unsigned int instance_idx);
+    void _remove_object(unsigned int object_idx);
+    void _calc_bounding_box() const;
+    void _render_selected_volumes() const;
+    void _render_synchronized_volumes() const;
+    void _render_bounding_box(const BoundingBoxf3& box, float* color) const;
+    void _render_sidebar_position_hints(const std::string& sidebar_field) const;
+    void _render_sidebar_rotation_hints(const std::string& sidebar_field) const;
+    void _render_sidebar_scale_hints(const std::string& sidebar_field) const;
+    void _render_sidebar_size_hints(const std::string& sidebar_field) const;
+    void _render_sidebar_position_hint(Axis axis) const;
+    void _render_sidebar_rotation_hint(Axis axis) const;
+    void _render_sidebar_scale_hint(Axis axis) const;
+    void _render_sidebar_size_hint(Axis axis, double length) const;
+    enum SyncRotationType {
+        // Do not synchronize rotation. Either not rotating at all, or rotating by world Z axis.
+        SYNC_ROTATION_NONE = 0,
+        // Synchronize fully. Used from "place on bed" feature.
+        SYNC_ROTATION_FULL = 1,
+        // Synchronize after rotation by an axis not parallel with Z.
+        SYNC_ROTATION_GENERAL = 2,
+    };
+    void _synchronize_unselected_instances(SyncRotationType sync_rotation_type);
+    void _synchronize_unselected_volumes();
+    void _ensure_on_bed();
+};
+
+} // namespace GUI
+} // namespace Slic3r
+
+#endif // slic3r_GUI_Selection_hpp_

From b57f6c9fe0d2f848ed0995870e322004a9850a0e Mon Sep 17 00:00:00 2001
From: Enrico Turri <enricoturri@seznam.cz>
Date: Tue, 19 Mar 2019 15:33:09 +0100
Subject: [PATCH 5/8] Fixed build on Linux and Mac

---
 src/slic3r/GUI/GLCanvas3D.hpp             | 2 +-
 src/slic3r/GUI/GUI_ObjectManipulation.cpp | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp
index 9653b138b..aec8a4a17 100644
--- a/src/slic3r/GUI/GLCanvas3D.hpp
+++ b/src/slic3r/GUI/GLCanvas3D.hpp
@@ -448,7 +448,7 @@ private:
 
         void set_flattening_data(const ModelObject* model_object);
 
-        void set_sla_support_data(ModelObject* model_object, const GLCanvas3D::Selection& selection);
+        void set_sla_support_data(ModelObject* model_object, const Selection& selection);
         bool mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false);
         void delete_current_grabber(bool delete_all = false);
 
diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp
index d186f7057..fb75414ed 100644
--- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp
+++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp
@@ -367,7 +367,7 @@ void ObjectManipulation::change_rotation_value(const Vec3d& rotation)
     if (selection.is_single_full_instance() || selection.requires_local_axes())
 		transformation_type.set_independent();
 	if (selection.is_single_full_instance()) {
-        //FIXME GLCanvas3D::Selection::rotate() does not process absoulte rotations correctly: It does not recognize the axis index, which was changed.
+        //FIXME Selection::rotate() does not process absoulte rotations correctly: It does not recognize the axis index, which was changed.
 		// transformation_type.set_absolute();
 		transformation_type.set_local();
 	}

From 3b31976b0964e4be188a6c514e30b1fb7fe21e3b Mon Sep 17 00:00:00 2001
From: Enrico Turri <enricoturri@seznam.cz>
Date: Tue, 19 Mar 2019 15:58:18 +0100
Subject: [PATCH 6/8] Another fix for Linuz and Mac builds

---
 src/slic3r/GUI/GUI_ObjectManipulation.cpp | 1 -
 src/slic3r/GUI/GUI_ObjectManipulation.hpp | 1 +
 2 files changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp
index fb75414ed..f759250b3 100644
--- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp
+++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp
@@ -7,7 +7,6 @@
 #include "PresetBundle.hpp"
 #include "libslic3r/Model.hpp"
 #include "libslic3r/Geometry.hpp"
-#include "GLCanvas3D.hpp"
 #include "Selection.hpp"
 
 #include <boost/algorithm/string.hpp>
diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp
index 46e8cec81..a5a180a56 100644
--- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp
+++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp
@@ -4,6 +4,7 @@
 #include <memory>
 
 #include "GUI_ObjectSettings.hpp"
+#include "GLCanvas3D.hpp"
 
 class wxStaticText;
 class PrusaLockButton;

From df250039dfb170c420649ec2dadcd2891b2aab27 Mon Sep 17 00:00:00 2001
From: Enrico Turri <enricoturri@seznam.cz>
Date: Wed, 20 Mar 2019 09:33:30 +0100
Subject: [PATCH 7/8] Tech ENABLE_CANVAS_GUI_REFACTORING set as default

---
 src/libslic3r/Technologies.hpp |   2 -
 src/slic3r/GUI/GLCanvas3D.cpp  | 143 ---------------------------
 src/slic3r/GUI/GLCanvas3D.hpp  |  15 ---
 src/slic3r/GUI/GLToolbar.cpp   | 173 ---------------------------------
 src/slic3r/GUI/GLToolbar.hpp   |  50 +---------
 src/slic3r/GUI/GUI_Preview.cpp |  14 ---
 src/slic3r/GUI/GUI_Preview.hpp |   4 -
 src/slic3r/GUI/Plater.cpp      | 138 --------------------------
 src/slic3r/GUI/Plater.hpp      |   2 -
 9 files changed, 1 insertion(+), 540 deletions(-)

diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp
index 156a225bf..ea3d87888 100644
--- a/src/libslic3r/Technologies.hpp
+++ b/src/libslic3r/Technologies.hpp
@@ -57,6 +57,4 @@
 #define ENABLE_SVG_ICONS (1 && ENABLE_1_42_0_ALPHA8 && ENABLE_TEXTURES_FROM_SVG)
 
 
-#define ENABLE_CANVAS_GUI_REFACTORING 1
-
 #endif // _technologies_h_
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index 1236ee7b4..7fb1ad25e 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -728,9 +728,6 @@ GLCanvas3D::Mouse::Drag::Drag()
 
 GLCanvas3D::Mouse::Mouse()
     : dragging(false)
-#if !ENABLE_CANVAS_GUI_REFACTORING
-    , left_down(false)
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
     , position(DBL_MAX, DBL_MAX)
     , scene_position(DBL_MAX, DBL_MAX, DBL_MAX)
     , ignore_up_event(false)
@@ -2067,9 +2064,6 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar
     , m_use_VBOs(false)
     , m_apply_zoom_to_volumes_filter(false)
     , m_hover_volume_id(-1)
-#if !ENABLE_CANVAS_GUI_REFACTORING
-    , m_toolbar_action_running(false)
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
     , m_legend_texture_enabled(false)
     , m_picking_enabled(false)
     , m_moving_enabled(false)
@@ -2373,21 +2367,6 @@ void GLCanvas3D::allow_multisample(bool allow)
     m_multisample_allowed = allow;
 }
 
-#if !ENABLE_CANVAS_GUI_REFACTORING
-void GLCanvas3D::enable_toolbar_item(const std::string& name, bool enable)
-{
-    if (enable)
-        m_toolbar.enable_item(name);
-    else
-        m_toolbar.disable_item(name);
-}
-
-bool GLCanvas3D::is_toolbar_item_pressed(const std::string& name) const
-{
-    return m_toolbar.is_item_pressed(name);
-}
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
-
 void GLCanvas3D::zoom_to_bed()
 {
     _zoom_to_bounding_box(m_bed.get_bounding_box());
@@ -2440,17 +2419,6 @@ void GLCanvas3D::update_volumes_colors_by_extruder()
         m_volumes.update_colors_by_extruder(m_config);
 }
 
-#if !ENABLE_CANVAS_GUI_REFACTORING
-void GLCanvas3D::update_toolbar_items_visibility()
-{
-    ConfigOptionMode mode = wxGetApp().get_mode();
-    m_toolbar.set_item_visible("more", mode != comSimple);
-    m_toolbar.set_item_visible("fewer", mode != comSimple);
-    m_toolbar.set_item_visible("splitvolumes", mode != comSimple);
-    m_dirty = true;
-}
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
-
 void GLCanvas3D::render()
 {
     wxCHECK_RET(!m_in_render, "GLCanvas3D::render() called recursively");
@@ -3103,10 +3071,8 @@ void GLCanvas3D::on_size(wxSizeEvent& evt)
 
 void GLCanvas3D::on_idle(wxIdleEvent& evt)
 {
-#if ENABLE_CANVAS_GUI_REFACTORING
     m_dirty |= m_toolbar.update_items_state();
     m_dirty |= m_view_toolbar.update_items_state();
-#endif // ENABLE_CANVAS_GUI_REFACTORING
 
     if (!m_dirty)
         return;
@@ -3386,7 +3352,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
 #endif /* SLIC3R_DEBUG_MOUSE_EVENTS */
 	}
 
-#if ENABLE_CANVAS_GUI_REFACTORING
     bool processed_by_toolbar = m_toolbar.on_mouse(evt, *this);
     processed_by_toolbar |= m_view_toolbar.on_mouse(evt, *this);
 
@@ -3395,7 +3360,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
         m_mouse.set_start_position_3D_as_invalid();
         return;
     }
-#endif // ENABLE_CANVAS_GUI_REFACTORING
 
     if (m_picking_enabled)
         _set_current();
@@ -3404,10 +3368,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
     int layer_editing_object_idx = is_layers_editing_enabled() ? selected_object_idx : -1;
     m_layers_editing.select_object(*m_model, layer_editing_object_idx);
     bool gizmos_overlay_contains_mouse = m_gizmos.overlay_contains_mouse(*this, m_mouse.position);
-#if !ENABLE_CANVAS_GUI_REFACTORING
-    int toolbar_contains_mouse = m_toolbar.contains_mouse(m_mouse.position, *this);
-    int view_toolbar_contains_mouse = m_view_toolbar.contains_mouse(m_mouse.position, *this);
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
 
     if (m_mouse.drag.move_requires_threshold && m_mouse.is_move_start_threshold_position_2D_defined() && m_mouse.is_move_threshold_met(pos))
     {
@@ -3447,30 +3407,14 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
     {
         // to remove hover on objects when the mouse goes out of this canvas
         m_mouse.position = Vec2d(-1.0, -1.0);
-#if !ENABLE_CANVAS_GUI_REFACTORING
-        // ensure m_mouse.left_down is reset (it may happen when switching canvas)
-        m_mouse.left_down = false;
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
         m_dirty = true;
     }
-#if !ENABLE_CANVAS_GUI_REFACTORING
-    else if (evt.LeftDClick() && (toolbar_contains_mouse != -1))
-    {
-        m_toolbar_action_running = true;
-        m_mouse.set_start_position_3D_as_invalid();
-        m_toolbar.do_action((unsigned int)toolbar_contains_mouse, *this);
-    }
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
     else if (evt.LeftDClick() && (m_gizmos.get_current_type() != Gizmos::Undefined))
     {
         m_mouse.ignore_up_event = true;
     }
     else if (evt.LeftDown() || evt.RightDown())
     {
-#if !ENABLE_CANVAS_GUI_REFACTORING
-        m_mouse.left_down = evt.LeftDown();
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
-
         // If user pressed left or right button we first check whether this happened
         // on a volume or not.
         m_layers_editing.state = LayersEditing::Unknown;
@@ -3522,17 +3466,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
         {
             // event was taken care of by the SlaSupports gizmo
         }
-#if !ENABLE_CANVAS_GUI_REFACTORING
-        else if (evt.LeftDown() && (view_toolbar_contains_mouse != -1))
-            m_view_toolbar.do_action((unsigned int)view_toolbar_contains_mouse, *this);
-        else if (evt.LeftDown() && (toolbar_contains_mouse != -1))
-        {
-            m_toolbar_action_running = true;
-            m_mouse.set_start_position_3D_as_invalid();
-            m_toolbar.do_action((unsigned int)toolbar_contains_mouse, *this);
-            m_mouse.left_down = false;
-        }
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
         else
         {
             // Select volume in this 3D canvas.
@@ -3692,11 +3625,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
         m_dirty = true;
     }
     // do not process dragging if the mouse is into any of the HUD elements
-#if ENABLE_CANVAS_GUI_REFACTORING
     else if (evt.Dragging() && !gizmos_overlay_contains_mouse)
-#else
-    else if (evt.Dragging() && !gizmos_overlay_contains_mouse && (toolbar_contains_mouse == -1) && (view_toolbar_contains_mouse == -1))
-#endif // ENABLE_CANVAS_GUI_REFACTORING
     {
         m_mouse.dragging = true;
 
@@ -3706,11 +3635,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
                 _perform_layer_editing_action(&evt);
         }
         // do not process the dragging if the left mouse was set down in another canvas
-#if ENABLE_CANVAS_GUI_REFACTORING
         else if (evt.LeftIsDown())
-#else
-        else if (m_mouse.left_down && evt.LeftIsDown())
-#endif // ENABLE_CANVAS_GUI_REFACTORING
         {
             // if dragging over blank area with left button, rotate
             if ((m_hover_volume_id == -1) && m_mouse.is_start_position_3D_defined())
@@ -3767,11 +3692,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
             // that's why the mouse_event function was called so that the gizmo can refuse the deselection in manual editing mode
 
             // deselect and propagate event through callback
-#if ENABLE_CANVAS_GUI_REFACTORING
             if (!evt.ShiftDown() && m_picking_enabled && !m_mouse.ignore_up_event)
-#else
-            if (!evt.ShiftDown() && m_picking_enabled && !m_toolbar_action_running && !m_mouse.ignore_up_event)
-#endif // ENABLE_CANVAS_GUI_REFACTORING
             {
                 m_selection.clear();
                 m_selection.set_mode(Selection::Instance);
@@ -3851,10 +3772,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
         m_mouse.set_start_position_3D_as_invalid();
         m_mouse.set_start_position_2D_as_invalid();
         m_mouse.dragging = false;
-#if !ENABLE_CANVAS_GUI_REFACTORING
-        m_mouse.left_down = false;
-        m_toolbar_action_running = false;
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
         m_dirty = true;
 
         if (m_canvas->HasCapture())
@@ -3870,25 +3787,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
         if (m_selection.is_empty())
             m_gizmos.reset_all_states();
 
-#if ENABLE_CANVAS_GUI_REFACTORING
         if (tooltip.empty())
             tooltip = m_toolbar.get_tooltip();
 
         if (tooltip.empty())
             tooltip = m_view_toolbar.get_tooltip();
-#else
-        // updates toolbar overlay
-        if (tooltip.empty())
-            tooltip = m_toolbar.update_hover_state(m_mouse.position, *this);
-
-        // updates view toolbar overlay
-        if (tooltip.empty())
-        {
-            tooltip = m_view_toolbar.update_hover_state(m_mouse.position, *this);
-            if (!tooltip.empty())
-                m_dirty = true;
-        }
-#endif // ENABLE_CANVAS_GUI_REFACTORING
 
         set_tooltip(tooltip);
 
@@ -4286,11 +4189,7 @@ bool GLCanvas3D::_init_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("Add...") + " [" + GUI::shortkey_ctrl_prefix() + "I]";
     item.sprite_id = 0;
-#if ENABLE_CANVAS_GUI_REFACTORING
     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_ADD)); };
-#else
-    item.action_event = EVT_GLTOOLBAR_ADD;
-#endif // ENABLE_CANVAS_GUI_REFACTORING
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -4300,12 +4199,8 @@ bool GLCanvas3D::_init_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("Delete") + " [Del]";
     item.sprite_id = 1;
-#if ENABLE_CANVAS_GUI_REFACTORING
     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_DELETE)); };
     item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_delete(); };
-#else
-    item.action_event = EVT_GLTOOLBAR_DELETE;
-#endif // ENABLE_CANVAS_GUI_REFACTORING
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -4315,12 +4210,8 @@ bool GLCanvas3D::_init_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("Delete all") + " [" + GUI::shortkey_ctrl_prefix() + "Del]";
     item.sprite_id = 2;
-#if ENABLE_CANVAS_GUI_REFACTORING
     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_DELETE_ALL)); };
     item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_delete_all(); };
-#else
-    item.action_event = EVT_GLTOOLBAR_DELETE_ALL;
-#endif // ENABLE_CANVAS_GUI_REFACTORING
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -4330,12 +4221,8 @@ bool GLCanvas3D::_init_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("Arrange [A]");
     item.sprite_id = 3;
-#if ENABLE_CANVAS_GUI_REFACTORING
     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_ARRANGE)); };
     item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_arrange(); };
-#else
-    item.action_event = EVT_GLTOOLBAR_ARRANGE;
-#endif // ENABLE_CANVAS_GUI_REFACTORING
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -4348,13 +4235,9 @@ bool GLCanvas3D::_init_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("Add instance [+]");
     item.sprite_id = 4;
-#if ENABLE_CANVAS_GUI_REFACTORING
     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_MORE)); };
     item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; };
     item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_increase_instances(); };
-#else
-    item.action_event = EVT_GLTOOLBAR_MORE;
-#endif // ENABLE_CANVAS_GUI_REFACTORING
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -4364,13 +4247,9 @@ bool GLCanvas3D::_init_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("Remove instance [-]");
     item.sprite_id = 5;
-#if ENABLE_CANVAS_GUI_REFACTORING
     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_FEWER)); };
     item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; };
     item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_decrease_instances(); };
-#else
-    item.action_event = EVT_GLTOOLBAR_FEWER;
-#endif // ENABLE_CANVAS_GUI_REFACTORING
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -4383,13 +4262,9 @@ bool GLCanvas3D::_init_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("Split to objects");
     item.sprite_id = 6;
-#if ENABLE_CANVAS_GUI_REFACTORING
     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_OBJECTS)); };
     item.visibility_callback = GLToolbarItem::Default_Visibility_Callback;
     item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_split_to_objects(); };
-#else
-    item.action_event = EVT_GLTOOLBAR_SPLIT_OBJECTS;
-#endif // ENABLE_CANVAS_GUI_REFACTORING
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -4399,13 +4274,9 @@ bool GLCanvas3D::_init_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("Split to parts");
     item.sprite_id = 7;
-#if ENABLE_CANVAS_GUI_REFACTORING
     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_VOLUMES)); };
     item.visibility_callback = []()->bool { return wxGetApp().get_mode() != comSimple; };
     item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_split_to_volumes(); };
-#else
-    item.action_event = EVT_GLTOOLBAR_SPLIT_VOLUMES;
-#endif // ENABLE_CANVAS_GUI_REFACTORING
     if (!m_toolbar.add_item(item))
         return false;
 
@@ -4419,22 +4290,12 @@ bool GLCanvas3D::_init_toolbar()
     item.tooltip = GUI::L_str("Layers editing");
     item.sprite_id = 8;
     item.is_toggable = true;
-#if ENABLE_CANVAS_GUI_REFACTORING
     item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_LAYERSEDITING)); };
     item.visibility_callback = GLToolbarItem::Default_Visibility_Callback;
     item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_layers_editing(); };
-#else
-    item.action_event = EVT_GLTOOLBAR_LAYERSEDITING;
-#endif // ENABLE_CANVAS_GUI_REFACTORING
     if (!m_toolbar.add_item(item))
         return false;
 
-#if !ENABLE_CANVAS_GUI_REFACTORING
-    enable_toolbar_item("add", true);
-
-    update_toolbar_items_visibility();
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
-
     return true;
 }
 
@@ -4636,11 +4497,7 @@ void GLCanvas3D::_picking_pass() const
 {
     const Vec2d& pos = m_mouse.position;
 
-#if ENABLE_CANVAS_GUI_REFACTORING
     if (m_picking_enabled && !m_mouse.dragging && (pos != Vec2d(DBL_MAX, DBL_MAX)))
-#else
-    if (m_picking_enabled && !m_mouse.dragging && !m_mouse.left_down && (pos != Vec2d(DBL_MAX, DBL_MAX)))
-#endif // ENABLE_CANVAS_GUI_REFACTORING
     {
         // Render the object for picking.
         // FIXME This cannot possibly work in a multi - sampled context as the color gets mangled by the anti - aliasing.
diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp
index aec8a4a17..4cbabc438 100644
--- a/src/slic3r/GUI/GLCanvas3D.hpp
+++ b/src/slic3r/GUI/GLCanvas3D.hpp
@@ -310,9 +310,6 @@ class GLCanvas3D
         };
 
         bool dragging;
-#if !ENABLE_CANVAS_GUI_REFACTORING
-        bool left_down;
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
         Vec2d position;
         Vec3d scene_position;
         Drag drag;
@@ -579,9 +576,6 @@ private:
     bool m_use_VBOs;
     bool m_apply_zoom_to_volumes_filter;
     mutable int m_hover_volume_id;
-#if !ENABLE_CANVAS_GUI_REFACTORING
-    bool m_toolbar_action_running;
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
     bool m_warning_texture_enabled;
     bool m_legend_texture_enabled;
     bool m_picking_enabled;
@@ -660,11 +654,6 @@ public:
     void enable_dynamic_background(bool enable);
     void allow_multisample(bool allow);
 
-#if !ENABLE_CANVAS_GUI_REFACTORING
-    void enable_toolbar_item(const std::string& name, bool enable);
-    bool is_toolbar_item_pressed(const std::string& name) const;
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
-
     void zoom_to_bed();
     void zoom_to_volumes();
     void zoom_to_selection();
@@ -672,10 +661,6 @@ public:
 
     void update_volumes_colors_by_extruder();
 
-#if !ENABLE_CANVAS_GUI_REFACTORING
-    void update_toolbar_items_visibility();
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
-
     bool is_dragging() const { return m_gizmos.is_dragging() || m_moving; }
 
     void render();
diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp
index 715eb7442..5ac5bf92f 100644
--- a/src/slic3r/GUI/GLToolbar.cpp
+++ b/src/slic3r/GUI/GLToolbar.cpp
@@ -30,11 +30,9 @@ wxDEFINE_EVENT(EVT_GLTOOLBAR_LAYERSEDITING, SimpleEvent);
 wxDEFINE_EVENT(EVT_GLVIEWTOOLBAR_3D, SimpleEvent);
 wxDEFINE_EVENT(EVT_GLVIEWTOOLBAR_PREVIEW, SimpleEvent);
 
-#if ENABLE_CANVAS_GUI_REFACTORING
 const GLToolbarItem::ActionCallback GLToolbarItem::Default_Action_Callback = [](){};
 const GLToolbarItem::VisibilityCallback GLToolbarItem::Default_Visibility_Callback = []()->bool { return true; };
 const GLToolbarItem::EnabledStateCallback GLToolbarItem::Default_Enabled_State_Callback = []()->bool { return true; };
-#endif // ENABLE_CANVAS_GUI_REFACTORING
 
 GLToolbarItem::Data::Data()
     : name("")
@@ -45,33 +43,19 @@ GLToolbarItem::Data::Data()
     , sprite_id(-1)
     , is_toggable(false)
     , visible(true)
-#if ENABLE_CANVAS_GUI_REFACTORING
     , action_callback(Default_Action_Callback)
     , visibility_callback(Default_Visibility_Callback)
     , enabled_state_callback(Default_Enabled_State_Callback)
-#endif // ENABLE_CANVAS_GUI_REFACTORING
 {
 }
 
 GLToolbarItem::GLToolbarItem(GLToolbarItem::EType type, const GLToolbarItem::Data& data)
     : m_type(type)
-#if ENABLE_CANVAS_GUI_REFACTORING
     , m_state(Normal)
-#else
-    , m_state(Disabled)
-#endif // ENABLE_CANVAS_GUI_REFACTORING
     , m_data(data)
 {
 }
 
-#if !ENABLE_CANVAS_GUI_REFACTORING
-void GLToolbarItem::do_action(wxEvtHandler *target)
-{
-    wxPostEvent(target, SimpleEvent(m_data.action_event));
-}
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
-
-#if ENABLE_CANVAS_GUI_REFACTORING
 bool GLToolbarItem::update_visibility()
 {
     bool visible = m_data.visibility_callback();
@@ -91,7 +75,6 @@ bool GLToolbarItem::update_enabled_state()
 
     return ret;
 }
-#endif // ENABLE_CANVAS_GUI_REFACTORING
 
 void GLToolbarItem::render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const
 {
@@ -174,10 +157,8 @@ GLToolbar::GLToolbar(GLToolbar::EType type)
 #if ENABLE_SVG_ICONS
     , m_icons_texture_dirty(true)
 #endif // ENABLE_SVG_ICONS
-#if ENABLE_CANVAS_GUI_REFACTORING
     , m_mouse_capture({false, false, false})
     , m_tooltip("")
-#endif // ENABLE_CANVAS_GUI_REFACTORING
 {
 }
 
@@ -342,32 +323,6 @@ float GLToolbar::get_height() const
     return m_layout.height;
 }
 
-#if !ENABLE_CANVAS_GUI_REFACTORING
-void GLToolbar::enable_item(const std::string& name)
-{
-    for (GLToolbarItem* item : m_items)
-    {
-        if ((item->get_name() == name) && (item->get_state() == GLToolbarItem::Disabled))
-        {
-            item->set_state(GLToolbarItem::Normal);
-            return;
-        }
-    }
-}
-
-void GLToolbar::disable_item(const std::string& name)
-{
-    for (GLToolbarItem* item : m_items)
-    {
-        if (item->get_name() == name)
-        {
-            item->set_state(GLToolbarItem::Disabled);
-            return;
-        }
-    }
-}
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
-
 void GLToolbar::select_item(const std::string& name)
 {
     if (is_item_disabled(name))
@@ -416,35 +371,6 @@ bool GLToolbar::is_item_visible(const std::string& name) const
     return false;
 }
 
-#if !ENABLE_CANVAS_GUI_REFACTORING
-void GLToolbar::set_item_visible(const std::string& name, bool visible)
-{
-    for (GLToolbarItem* item : m_items)
-    {
-        if ((item->get_name() == name) && (item->is_visible() != visible))
-        {
-            item->set_visible(visible);
-            m_layout.dirty = true;
-            break;
-        }
-    }
-
-    // updates separators visibility to avoid having two consecutive
-    bool any_item_visible = false;
-    for (GLToolbarItem* item : m_items)
-    {
-        if (!item->is_separator())
-            any_item_visible |= item->is_visible();
-        else
-        {
-            item->set_visible(any_item_visible);
-            any_item_visible = false;
-        }
-    }
-}
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
-
-#if ENABLE_CANVAS_GUI_REFACTORING
 bool GLToolbar::update_items_state()
 {
     bool ret = false;
@@ -452,73 +378,6 @@ bool GLToolbar::update_items_state()
     ret |= update_items_enabled_state();
     return ret;
 }
-#endif // ENABLE_CANVAS_GUI_REFACTORING
-
-#if !ENABLE_CANVAS_GUI_REFACTORING
-std::string GLToolbar::update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent)
-{
-    if (!m_enabled)
-        return "";
-
-    switch (m_layout.type)
-    {
-    default:
-    case Layout::Horizontal: { return update_hover_state_horizontal(mouse_pos, parent); }
-    case Layout::Vertical: { return update_hover_state_vertical(mouse_pos, parent); }
-    }
-}
-
-int GLToolbar::contains_mouse(const Vec2d& mouse_pos, const GLCanvas3D& parent) const
-{
-    if (!m_enabled)
-        return -1;
-
-    switch (m_layout.type)
-    {
-    default:
-    case Layout::Horizontal: { return contains_mouse_horizontal(mouse_pos, parent); }
-    case Layout::Vertical: { return contains_mouse_vertical(mouse_pos, parent); }
-    }
-}
-
-void GLToolbar::do_action(unsigned int item_id, GLCanvas3D& parent)
-{
-    if (item_id < (unsigned int)m_items.size())
-    {
-        GLToolbarItem* item = m_items[item_id];
-        if ((item != nullptr) && !item->is_separator() && item->is_hovered())
-        {
-            if (item->is_toggable())
-            {
-                GLToolbarItem::EState state = item->get_state();
-                if (state == GLToolbarItem::Hover)
-                    item->set_state(GLToolbarItem::HoverPressed);
-                else if (state == GLToolbarItem::HoverPressed)
-                    item->set_state(GLToolbarItem::Hover);
-
-                parent.render();
-                item->do_action(parent.get_wxglcanvas());
-            }
-            else
-            {
-                if (m_type == Radio)
-                    select_item(item->get_name());
-                else
-                    item->set_state(GLToolbarItem::HoverPressed);
-
-                parent.render();
-                item->do_action(parent.get_wxglcanvas());
-                if ((m_type == Normal) && (item->get_state() != GLToolbarItem::Disabled))
-                {
-                    // the item may get disabled during the action, if not, set it back to hover state
-                    item->set_state(GLToolbarItem::Hover);
-                    parent.render();
-                }
-            }
-        }
-    }
-}
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
 
 void GLToolbar::render(const GLCanvas3D& parent) const
 {
@@ -545,7 +404,6 @@ void GLToolbar::render(const GLCanvas3D& parent) const
     ::glPopMatrix();
 }
 
-#if ENABLE_CANVAS_GUI_REFACTORING
 bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent)
 {
     Vec2d mouse_pos((double)evt.GetX(), (double)evt.GetY());
@@ -592,7 +450,6 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent)
 
     return processed;
 }
-#endif // ENABLE_CANVAS_GUI_REFACTORING
 
 void GLToolbar::calc_layout() const
 {
@@ -683,7 +540,6 @@ float GLToolbar::get_main_size() const
     return size;
 }
 
-#if ENABLE_CANVAS_GUI_REFACTORING
 void GLToolbar::do_action(unsigned int item_id, GLCanvas3D& parent)
 {
     if (item_id < (unsigned int)m_items.size())
@@ -734,7 +590,6 @@ std::string GLToolbar::update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& pa
     case Layout::Vertical: { return update_hover_state_vertical(mouse_pos, parent); }
     }
 }
-#endif // ENABLE_CANVAS_GUI_REFACTORING
 
 std::string GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos, GLCanvas3D& parent)
 {
@@ -945,7 +800,6 @@ std::string GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos, GLCan
     return tooltip;
 }
 
-#if ENABLE_CANVAS_GUI_REFACTORING
 int GLToolbar::contains_mouse(const Vec2d& mouse_pos, const GLCanvas3D& parent) const
 {
     if (!m_enabled)
@@ -958,7 +812,6 @@ int GLToolbar::contains_mouse(const Vec2d& mouse_pos, const GLCanvas3D& parent)
     case Layout::Vertical: { return contains_mouse_vertical(mouse_pos, parent); }
     }
 }
-#endif // ENABLE_CANVAS_GUI_REFACTORING
 
 int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3D& parent) const
 {
@@ -983,10 +836,6 @@ int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3
     float scaled_separator_size = m_layout.separator_size * factor;
     float scaled_gap_size = m_layout.gap_size * factor;
     float scaled_border = m_layout.border * factor;
-#if !ENABLE_CANVAS_GUI_REFACTORING
-    float separator_stride = scaled_separator_size + scaled_gap_size;
-    float icon_stride = scaled_icons_size + scaled_gap_size;
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
 
     float left = m_layout.left + scaled_border;
     float top = m_layout.top - scaled_border;
@@ -1001,7 +850,6 @@ int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3
             continue;
 
         if (item->is_separator())
-#if ENABLE_CANVAS_GUI_REFACTORING
         {
             float right = left + scaled_separator_size;
             float bottom = top - scaled_icons_size;
@@ -1022,9 +870,6 @@ int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3
 
             left = right;
         }
-#else
-        left += separator_stride;
-#endif // ENABLE_CANVAS_GUI_REFACTORING
         else
         {
             float right = left + scaled_icons_size;
@@ -1034,7 +879,6 @@ int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3
             if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
                 return id;
             
-#if ENABLE_CANVAS_GUI_REFACTORING
             left = right;
             right += scaled_gap_size;
 
@@ -1046,9 +890,6 @@ int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3
             }
 
             left = right;
-#else
-            left += icon_stride;
-#endif // ENABLE_CANVAS_GUI_REFACTORING
         }
     }
     
@@ -1078,10 +919,6 @@ int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D&
     float scaled_separator_size = m_layout.separator_size * factor;
     float scaled_gap_size = m_layout.gap_size * factor;
     float scaled_border = m_layout.border * factor;
-#if !ENABLE_CANVAS_GUI_REFACTORING
-    float separator_stride = scaled_separator_size + scaled_gap_size;
-    float icon_stride = scaled_icons_size + scaled_gap_size;
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
 
     float left = m_layout.left + scaled_border;
     float top = m_layout.top - scaled_border;
@@ -1096,7 +933,6 @@ int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D&
             continue;
 
         if (item->is_separator())
-#if ENABLE_CANVAS_GUI_REFACTORING
         {
             float right = left + scaled_icons_size;
             float bottom = top - scaled_separator_size;
@@ -1117,9 +953,6 @@ int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D&
 
             top = bottom;
         }
-#else
-            top -= separator_stride;
-#endif // ENABLE_CANVAS_GUI_REFACTORING
         else
         {
             float right = left + scaled_icons_size;
@@ -1129,7 +962,6 @@ int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D&
             if ((left <= (float)scaled_mouse_pos(0)) && ((float)scaled_mouse_pos(0) <= right) && (bottom <= (float)scaled_mouse_pos(1)) && ((float)scaled_mouse_pos(1) <= top))
                 return id;
 
-#if ENABLE_CANVAS_GUI_REFACTORING
             top = bottom;
             bottom -= scaled_gap_size;
 
@@ -1141,9 +973,6 @@ int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D&
             }
 
             top = bottom;
-#else
-            top -= icon_stride;
-#endif // ENABLE_CANVAS_GUI_REFACTORING
         }
     }
 
@@ -1498,7 +1327,6 @@ bool GLToolbar::generate_icons_texture() const
 }
 #endif // ENABLE_SVG_ICONS
 
-#if ENABLE_CANVAS_GUI_REFACTORING
 bool GLToolbar::update_items_visibility()
 {
     bool ret = false;
@@ -1541,7 +1369,6 @@ bool GLToolbar::update_items_enabled_state()
 
     return ret;
 }
-#endif // ENABLE_CANVAS_GUI_REFACTORING
 
 } // namespace GUI
 } // namespace Slic3r
diff --git a/src/slic3r/GUI/GLToolbar.hpp b/src/slic3r/GUI/GLToolbar.hpp
index cd5d3f83f..07d1fcb92 100644
--- a/src/slic3r/GUI/GLToolbar.hpp
+++ b/src/slic3r/GUI/GLToolbar.hpp
@@ -31,11 +31,9 @@ wxDECLARE_EVENT(EVT_GLVIEWTOOLBAR_PREVIEW, SimpleEvent);
 class GLToolbarItem
 {
 public:
-#if ENABLE_CANVAS_GUI_REFACTORING
     typedef std::function<void()> ActionCallback;
     typedef std::function<bool()> VisibilityCallback;
     typedef std::function<bool()> EnabledStateCallback;
-#endif // ENABLE_CANVAS_GUI_REFACTORING
 
     enum EType : unsigned char
     {
@@ -63,24 +61,17 @@ public:
         std::string tooltip;
         unsigned int sprite_id;
         bool is_toggable;
-#if !ENABLE_CANVAS_GUI_REFACTORING
-        wxEventType action_event;
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
         bool visible;
-#if ENABLE_CANVAS_GUI_REFACTORING
         ActionCallback action_callback;
         VisibilityCallback visibility_callback;
         EnabledStateCallback enabled_state_callback;
-#endif // ENABLE_CANVAS_GUI_REFACTORING
 
         Data();
     };
 
-#if ENABLE_CANVAS_GUI_REFACTORING
     static const ActionCallback Default_Action_Callback;
     static const VisibilityCallback Default_Visibility_Callback;
     static const EnabledStateCallback Default_Enabled_State_Callback;
-#endif // ENABLE_CANVAS_GUI_REFACTORING
 
 private:
     EType m_type;
@@ -99,11 +90,7 @@ public:
 #endif // ENABLE_SVG_ICONS
     const std::string& get_tooltip() const { return m_data.tooltip; }
 
-#if ENABLE_CANVAS_GUI_REFACTORING
     void do_action() { m_data.action_callback(); }
-#else
-    void do_action(wxEvtHandler *target);
-#endif // ENABLE_CANVAS_GUI_REFACTORING
 
     bool is_enabled() const { return m_state != Disabled; }
     bool is_disabled() const { return m_state == Disabled; }
@@ -112,27 +99,20 @@ public:
 
     bool is_toggable() const { return m_data.is_toggable; }
     bool is_visible() const { return m_data.visible; }
-#if !ENABLE_CANVAS_GUI_REFACTORING
-    void set_visible(bool visible) { m_data.visible = visible; }
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
     bool is_separator() const { return m_type == Separator; }
 
-#if ENABLE_CANVAS_GUI_REFACTORING
     // returns true if the state changes
     bool update_visibility();
     // returns true if the state changes
     bool update_enabled_state();
-#endif // ENABLE_CANVAS_GUI_REFACTORING
 
     void render(unsigned int tex_id, float left, float right, float bottom, float top, unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const;
 
 private:
     GLTexture::Quad_UVs get_uvs(unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const;
-#if ENABLE_CANVAS_GUI_REFACTORING
     void set_visible(bool visible) { m_data.visible = visible; }
 
     friend class GLToolbar;
-#endif // ENABLE_CANVAS_GUI_REFACTORING
 };
 
 #if !ENABLE_SVG_ICONS
@@ -250,7 +230,7 @@ private:
     mutable Layout m_layout;
 
     ItemsList m_items;
-#if ENABLE_CANVAS_GUI_REFACTORING
+
     struct MouseCapture
     {
         bool left;
@@ -262,7 +242,6 @@ private:
 
     MouseCapture m_mouse_capture;
     std::string m_tooltip;
-#endif // ENABLE_CANVAS_GUI_REFACTORING
 
 public:
 #if ENABLE_SVG_ICONS
@@ -303,42 +282,21 @@ public:
     float get_width() const;
     float get_height() const;
 
-#if !ENABLE_CANVAS_GUI_REFACTORING
-    void enable_item(const std::string& name);
-    void disable_item(const std::string& name);
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
     void select_item(const std::string& name);
 
     bool is_item_pressed(const std::string& name) const;
     bool is_item_disabled(const std::string& name) const;
     bool is_item_visible(const std::string& name) const;
 
-#if ENABLE_CANVAS_GUI_REFACTORING
     const std::string& get_tooltip() const { return m_tooltip; }
-#endif // ENABLE_CANVAS_GUI_REFACTORING
 
 
-#if ENABLE_CANVAS_GUI_REFACTORING
     // returns true if any item changed its state
     bool update_items_state();
-#else
-    void set_item_visible(const std::string& name, bool visible);
-#endif // ENABLE_CANVAS_GUI_REFACTORING
-
-#if !ENABLE_CANVAS_GUI_REFACTORING
-    std::string update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent);
-
-    // returns the id of the item under the given mouse position or -1 if none
-    int contains_mouse(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;
-
-    void do_action(unsigned int item_id, GLCanvas3D& parent);
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
 
     void render(const GLCanvas3D& parent) const;    
 
-#if ENABLE_CANVAS_GUI_REFACTORING
     bool on_mouse(wxMouseEvent& evt, GLCanvas3D& parent);
-#endif // ENABLE_CANVAS_GUI_REFACTORING
 
 private:
     void calc_layout() const;
@@ -347,16 +305,12 @@ private:
     float get_height_horizontal() const;
     float get_height_vertical() const;
     float get_main_size() const;
-#if ENABLE_CANVAS_GUI_REFACTORING
     void do_action(unsigned int item_id, GLCanvas3D& parent);
     std::string update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent);
-#endif // ENABLE_CANVAS_GUI_REFACTORING
     std::string update_hover_state_horizontal(const Vec2d& mouse_pos, GLCanvas3D& parent);
     std::string update_hover_state_vertical(const Vec2d& mouse_pos, GLCanvas3D& parent);
-#if ENABLE_CANVAS_GUI_REFACTORING
     // returns the id of the item under the given mouse position or -1 if none
     int contains_mouse(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;
-#endif // ENABLE_CANVAS_GUI_REFACTORING
     int contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;
     int contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D& parent) const;
 
@@ -367,12 +321,10 @@ private:
     bool generate_icons_texture() const;
 #endif // ENABLE_SVG_ICONS
 
-#if ENABLE_CANVAS_GUI_REFACTORING
     // returns true if any item changed its state
     bool update_items_visibility();
     // returns true if any item changed its state
     bool update_items_enabled_state();
-#endif // ENABLE_CANVAS_GUI_REFACTORING
 };
 
 } // namespace GUI
diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp
index b76628b8d..be3fad9ec 100644
--- a/src/slic3r/GUI/GUI_Preview.cpp
+++ b/src/slic3r/GUI/GUI_Preview.cpp
@@ -110,20 +110,6 @@ void View3D::mirror_selection(Axis axis)
         m_canvas->mirror_selection(axis);
 }
 
-#if !ENABLE_CANVAS_GUI_REFACTORING
-void View3D::update_toolbar_items_visibility()
-{
-    if (m_canvas != nullptr)
-        m_canvas->update_toolbar_items_visibility();
-}
-
-void View3D::enable_toolbar_item(const std::string& name, bool enable)
-{
-    if (m_canvas != nullptr)
-        m_canvas->enable_toolbar_item(name, enable);
-}
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
-
 int View3D::check_volumes_outside_state() const
 {
     return (m_canvas != nullptr) ? m_canvas->check_volumes_outside_state() : false;
diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp
index 5a244abb7..182eaa952 100644
--- a/src/slic3r/GUI/GUI_Preview.hpp
+++ b/src/slic3r/GUI/GUI_Preview.hpp
@@ -50,10 +50,6 @@ public:
     void delete_selected();
     void mirror_selection(Axis axis);
 
-#if !ENABLE_CANVAS_GUI_REFACTORING
-    void update_toolbar_items_visibility();
-    void enable_toolbar_item(const std::string& name, bool enable);
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
     int check_volumes_outside_state() const;
 
     bool is_layers_editing_enabled() const;
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index 630586bb5..f6efb1d91 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -1227,7 +1227,6 @@ struct Plater::priv
     // Sets m_bed.m_polygon to limit the object placement.
     void set_bed_shape(const Pointfs& shape);
 
-#if ENABLE_CANVAS_GUI_REFACTORING
     bool can_delete() const;
     bool can_delete_all() const;
     bool can_increase_instances() const;
@@ -1236,7 +1235,6 @@ struct Plater::priv
     bool can_split_to_volumes() const;
     bool can_arrange() const;
     bool can_layers_editing() const;
-#endif // ENABLE_CANVAS_GUI_REFACTORING
 
 private:
     bool init_object_menu();
@@ -1246,22 +1244,9 @@ private:
     bool complit_init_part_menu();
     void init_view_toolbar();
 
-#if !ENABLE_CANVAS_GUI_REFACTORING
-    bool can_delete_object() const;
-    bool can_increase_instances() const;
-    bool can_decrease_instances() const;
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
     bool can_set_instance_to_object() const;
-#if !ENABLE_CANVAS_GUI_REFACTORING
-    bool can_split_to_objects() const;
-    bool can_split_to_volumes() const;
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
     bool can_split() const;
     bool layers_height_allowed() const;
-#if !ENABLE_CANVAS_GUI_REFACTORING
-    bool can_delete_all() const;
-    bool can_arrange() const;
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
     bool can_mirror() const;
 
     void update_fff_scene();
@@ -1821,14 +1806,6 @@ int Plater::priv::get_selected_volume_idx() const
 
 void Plater::priv::selection_changed()
 {
-#if !ENABLE_CANVAS_GUI_REFACTORING
-    view3D->enable_toolbar_item("delete", can_delete_object());
-    view3D->enable_toolbar_item("more", can_increase_instances());
-    view3D->enable_toolbar_item("fewer", can_decrease_instances());
-    view3D->enable_toolbar_item("splitobjects", can_split());
-    view3D->enable_toolbar_item("splitvolumes", printer_technology == ptFFF && can_split());
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
-
     // if the selection is not valid to allow for layer editing, we need to turn off the tool if it is running
     bool enable_layer_editing = layers_height_allowed();
     if (!enable_layer_editing && view3D->is_layers_editing_enabled()) {
@@ -1836,22 +1813,12 @@ void Plater::priv::selection_changed()
         on_action_layersediting(evt);
     }
 
-#if !ENABLE_CANVAS_GUI_REFACTORING
-    view3D->enable_toolbar_item("layersediting", enable_layer_editing);
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
-
     // forces a frame render to update the view (to avoid a missed update if, for example, the context menu appears)
     view3D->render();
 }
 
 void Plater::priv::object_list_changed()
 {
-#if !ENABLE_CANVAS_GUI_REFACTORING
-    // Enable/disable buttons depending on whether there are any objects on the platter.
-    view3D->enable_toolbar_item("deleteall", can_delete_all());
-    view3D->enable_toolbar_item("arrange", can_arrange());
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
-
     const bool export_in_progress = this->background_process.is_export_scheduled(); // || ! send_gcode_file.empty());
     // XXX: is this right?
     const bool model_fits = view3D->check_volumes_outside_state() == ModelInstance::PVS_Inside;
@@ -1930,11 +1897,6 @@ void Plater::priv::arrange()
 
     wxBusyCursor wait;
 
-#if !ENABLE_CANVAS_GUI_REFACTORING
-    // Disable the arrange button (to prevent reentrancies, we will call wxYied)
-    view3D->enable_toolbar_item("arrange", can_arrange());
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
-
     this->background_process.stop();
     unsigned count = 0;
     for(auto obj : model.objects) count += obj->instances.size();
@@ -2005,11 +1967,6 @@ void Plater::priv::arrange()
     statusbar()->set_cancel_callback(); // remove cancel button
     arranging.store(false);
 
-#if !ENABLE_CANVAS_GUI_REFACTORING
-    // We enable back the arrange button
-    view3D->enable_toolbar_item("arrange", can_arrange());
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
-
     // Do a full refresh of scene tree, including regenerating all the GLVolumes.
     //FIXME The update function shall just reload the modified matrices.
     update(true);
@@ -2570,12 +2527,6 @@ void Plater::priv::on_process_completed(wxCommandEvent &evt)
 void Plater::priv::on_layer_editing_toggled(bool enable)
 {
     view3D->enable_layers_editing(enable);
-#if !ENABLE_CANVAS_GUI_REFACTORING
-    if (enable && !view3D->is_layers_editing_enabled()) {
-        // Initialization of the OpenGL shaders failed. Disable the tool.
-        view3D->enable_toolbar_item("layersediting", false);
-    }
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
     view3D->set_as_dirty();
 }
 
@@ -2597,14 +2548,7 @@ void Plater::priv::on_action_split_volumes(SimpleEvent&)
 
 void Plater::priv::on_action_layersediting(SimpleEvent&)
 {
-#if ENABLE_CANVAS_GUI_REFACTORING
     view3D->enable_layers_editing(!view3D->is_layers_editing_enabled());
-#else
-    bool enable = !view3D->is_layers_editing_enabled();
-    view3D->enable_layers_editing(enable);
-    if (enable && !view3D->is_layers_editing_enabled())
-        view3D->enable_toolbar_item("layersediting", false);
-#endif // ENABLE_CANVAS_GUI_REFACTORING
 }
 
 void Plater::priv::on_object_select(SimpleEvent& evt)
@@ -2764,11 +2708,7 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
     if (q != nullptr)
     {
         q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_mirror()); }, item_mirror->GetId());
-#if ENABLE_CANVAS_GUI_REFACTORING
         q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete()); }, item_delete->GetId());
-#else
-        q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete_object()); }, item_delete->GetId());
-#endif // ENABLE_CANVAS_GUI_REFACTORING
     }
 
     return true;
@@ -2873,11 +2813,7 @@ void Plater::priv::init_view_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("3D editor view") + " [" + GUI::shortkey_ctrl_prefix() + "5]";
     item.sprite_id = 0;
-#if ENABLE_CANVAS_GUI_REFACTORING
     item.action_callback = [this]() { if (this->q != nullptr) wxPostEvent(this->q, SimpleEvent(EVT_GLVIEWTOOLBAR_3D)); };
-#else
-    item.action_event = EVT_GLVIEWTOOLBAR_3D;
-#endif // ENABLE_CANVAS_GUI_REFACTORING
     item.is_toggable = false;
     if (!view_toolbar.add_item(item))
         return;
@@ -2888,67 +2824,21 @@ void Plater::priv::init_view_toolbar()
 #endif // ENABLE_SVG_ICONS
     item.tooltip = GUI::L_str("Preview") + " [" + GUI::shortkey_ctrl_prefix() + "6]";
     item.sprite_id = 1;
-#if ENABLE_CANVAS_GUI_REFACTORING
     item.action_callback = [this]() { if (this->q != nullptr) wxPostEvent(this->q, SimpleEvent(EVT_GLVIEWTOOLBAR_PREVIEW)); };
-#else
-    item.action_event = EVT_GLVIEWTOOLBAR_PREVIEW;
-#endif // ENABLE_CANVAS_GUI_REFACTORING
     item.is_toggable = false;
     if (!view_toolbar.add_item(item))
         return;
 
-#if !ENABLE_CANVAS_GUI_REFACTORING
-    view_toolbar.enable_item("3D");
-    view_toolbar.enable_item("Preview");
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
-
     view_toolbar.select_item("3D");
     view_toolbar.set_enabled(true);
 }
 
-#if !ENABLE_CANVAS_GUI_REFACTORING
-bool Plater::priv::can_delete_object() const
-{
-    int obj_idx = get_selected_object_idx();
-    return (0 <= obj_idx) && (obj_idx < (int)model.objects.size());
-}
-
-bool Plater::priv::can_increase_instances() const
-{
-    int obj_idx = get_selected_object_idx();
-    return (0 <= obj_idx) && (obj_idx < (int)model.objects.size());
-}
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
-
 bool Plater::priv::can_set_instance_to_object() const
 {
     const int obj_idx = get_selected_object_idx();
     return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && (model.objects[obj_idx]->instances.size() > 1);
 }
 
-#if !ENABLE_CANVAS_GUI_REFACTORING
-bool Plater::priv::can_decrease_instances() const
-{
-    int obj_idx = get_selected_object_idx();
-    return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && (model.objects[obj_idx]->instances.size() > 1);
-}
-
-bool Plater::priv::can_split_to_objects() const
-{
-    int obj_idx = get_selected_object_idx();
-    return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && !model.objects[obj_idx]->is_multiparts();
-}
-
-bool Plater::priv::can_split_to_volumes() const
-{
-    if (printer_technology == ptSLA)
-        return false;
-//     int obj_idx = get_selected_object_idx();
-//     return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && !model.objects[obj_idx]->is_multiparts();
-    return sidebar->obj_list()->is_splittable();
-}
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
-
 bool Plater::priv::can_split() const
 {
     return sidebar->obj_list()->is_splittable();
@@ -2960,18 +2850,6 @@ bool Plater::priv::layers_height_allowed() const
     return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && config->opt_bool("variable_layer_height") && view3D->is_layers_editing_allowed();
 }
 
-#if !ENABLE_CANVAS_GUI_REFACTORING
-bool Plater::priv::can_delete_all() const
-{
-    return !model.objects.empty();
-}
-
-bool Plater::priv::can_arrange() const
-{
-    return !model.objects.empty() && !arranging.load();
-}
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
-
 bool Plater::priv::can_mirror() const
 {
     return get_selection().is_from_single_instance();
@@ -2987,7 +2865,6 @@ void Plater::priv::set_bed_shape(const Pointfs& shape)
     }
 }
 
-#if ENABLE_CANVAS_GUI_REFACTORING
 bool Plater::priv::can_delete() const
 {
     return !get_selection().is_empty();
@@ -3029,15 +2906,10 @@ bool Plater::priv::can_layers_editing() const
 {
     return layers_height_allowed();
 }
-#endif // ENABLE_CANVAS_GUI_REFACTORING
 
 void Plater::priv::update_object_menu()
 {
     sidebar->obj_list()->append_menu_items_add_volume(&object_menu);
-#if !ENABLE_CANVAS_GUI_REFACTORING
-    if (view3D != nullptr)
-        view3D->update_toolbar_items_visibility();
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
 }
 
 void Plater::priv::show_action_buttons(const bool is_ready_to_slice) const 
@@ -3520,17 +3392,9 @@ void Plater::on_config_change(const DynamicPrintConfig &config)
         } 
         else if(opt_key == "variable_layer_height") {
             if (p->config->opt_bool("variable_layer_height") != true) {
-#if !ENABLE_CANVAS_GUI_REFACTORING
-                p->view3D->enable_toolbar_item("layersediting", false);
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
                 p->view3D->enable_layers_editing(false);
                 p->view3D->set_as_dirty();
             }
-#if !ENABLE_CANVAS_GUI_REFACTORING
-            else if (p->view3D->is_layers_editing_allowed()) {
-                p->view3D->enable_toolbar_item("layersediting", true);
-            }
-#endif // !ENABLE_CANVAS_GUI_REFACTORING
         }
         else if(opt_key == "extruder_colour") {
             update_scheduled = true;
@@ -3652,7 +3516,6 @@ void Plater::fix_through_netfabb(const int obj_idx, const int vol_idx/* = -1*/)
 
 void Plater::update_object_menu() { p->update_object_menu(); }
 
-#if ENABLE_CANVAS_GUI_REFACTORING
 bool Plater::can_delete() const { return p->can_delete(); }
 bool Plater::can_delete_all() const { return p->can_delete_all(); }
 bool Plater::can_increase_instances() const { return p->can_increase_instances(); }
@@ -3661,6 +3524,5 @@ bool Plater::can_split_to_objects() const { return p->can_split_to_objects(); }
 bool Plater::can_split_to_volumes() const { return p->can_split_to_volumes(); }
 bool Plater::can_arrange() const { return p->can_arrange(); }
 bool Plater::can_layers_editing() const { return p->can_layers_editing(); }
-#endif // ENABLE_CANVAS_GUI_REFACTORING
 
 }}    // namespace Slic3r::GUI
diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp
index 8746c1eef..dc5a50cf1 100644
--- a/src/slic3r/GUI/Plater.hpp
+++ b/src/slic3r/GUI/Plater.hpp
@@ -176,7 +176,6 @@ public:
     PrinterTechnology   printer_technology() const;
     void                set_printer_technology(PrinterTechnology printer_technology);
 
-#if ENABLE_CANVAS_GUI_REFACTORING
     bool can_delete() const;
     bool can_delete_all() const;
     bool can_increase_instances() const;
@@ -185,7 +184,6 @@ public:
     bool can_split_to_volumes() const;
     bool can_arrange() const;
     bool can_layers_editing() const;
-#endif // ENABLE_CANVAS_GUI_REFACTORING
 
 private:
     struct priv;

From 4ceba39d99c8f46218920954cfc3eeaa7dc530e2 Mon Sep 17 00:00:00 2001
From: Lukas Matena <lukasmatena@seznam.cz>
Date: Wed, 20 Mar 2019 10:13:00 +0100
Subject: [PATCH 8/8] Decreased number of polygons on the SLA support point
 marks for faster rendering

---
 src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
index cd7e3b985..56452ae73 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
@@ -201,12 +201,12 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
             const float cone_height = 0.75f;
             ::glPushMatrix();
             ::glTranslatef(0.f, 0.f, m_editing_mode_cache[i].support_point.head_front_radius * RenderPointScale);
-            ::gluCylinder(m_quadric, 0.f, cone_radius, cone_height, 36, 1);
+            ::gluCylinder(m_quadric, 0.f, cone_radius, cone_height, 24, 1);
             ::glTranslatef(0.f, 0.f, cone_height);
-            ::gluDisk(m_quadric, 0.0, cone_radius, 36, 1);
+            ::gluDisk(m_quadric, 0.0, cone_radius, 24, 1);
             ::glPopMatrix();
         }
-        ::gluSphere(m_quadric, m_editing_mode_cache[i].support_point.head_front_radius * RenderPointScale, 64, 36);
+        ::gluSphere(m_quadric, m_editing_mode_cache[i].support_point.head_front_radius * RenderPointScale, 24, 12);
         ::glPopMatrix();
     }