diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp
index 8de64544c..7bfb73aa3 100644
--- a/src/libslic3r/GCode.cpp
+++ b/src/libslic3r/GCode.cpp
@@ -1050,10 +1050,19 @@ namespace DoExport {
 	    print_statistics.clear();
 	    print_statistics.estimated_normal_print_time = normal_time_estimator.get_time_dhm/*s*/();
 	    print_statistics.estimated_silent_print_time = silent_time_estimator_enabled ? silent_time_estimator.get_time_dhm/*s*/() : "N/A";
-	    print_statistics.estimated_normal_custom_gcode_print_times = normal_time_estimator.get_custom_gcode_times_dhm(true);
-	    if (silent_time_estimator_enabled)
-	        print_statistics.estimated_silent_custom_gcode_print_times = silent_time_estimator.get_custom_gcode_times_dhm(true);
-	    print_statistics.total_toolchanges = std::max(0, wipe_tower_data.number_of_toolchanges);
+#if ENABLE_GCODE_VIEWER
+        print_statistics.estimated_normal_custom_gcode_print_times_str = normal_time_estimator.get_custom_gcode_times_dhm(true);
+        print_statistics.estimated_normal_custom_gcode_print_times = normal_time_estimator.get_custom_gcode_times(true);
+        if (silent_time_estimator_enabled) {
+            print_statistics.estimated_silent_custom_gcode_print_times_str = silent_time_estimator.get_custom_gcode_times_dhm(true);
+            print_statistics.estimated_silent_custom_gcode_print_times = silent_time_estimator.get_custom_gcode_times(true);
+        }
+#else
+        print_statistics.estimated_normal_custom_gcode_print_times = normal_time_estimator.get_custom_gcode_times_dhm(true);
+        if (silent_time_estimator_enabled)
+            print_statistics.estimated_silent_custom_gcode_print_times = silent_time_estimator.get_custom_gcode_times_dhm(true);
+#endif // ENABLE_GCODE_VIEWER
+        print_statistics.total_toolchanges = std::max(0, wipe_tower_data.number_of_toolchanges);
 	    if (! extruders.empty()) {
 	        std::pair<std::string, unsigned int> out_filament_used_mm ("; filament used [mm] = ", 0);
 	        std::pair<std::string, unsigned int> out_filament_used_cm3("; filament used [cm3] = ", 0);
diff --git a/src/libslic3r/GCodeTimeEstimator.cpp b/src/libslic3r/GCodeTimeEstimator.cpp
index 9e8137ef0..d67db8481 100644
--- a/src/libslic3r/GCodeTimeEstimator.cpp
+++ b/src/libslic3r/GCodeTimeEstimator.cpp
@@ -678,6 +678,21 @@ namespace Slic3r {
         return _get_time_minutes(get_time());
     }
 
+#if ENABLE_GCODE_VIEWER
+    std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> GCodeTimeEstimator::get_custom_gcode_times(bool include_remaining) const
+    {
+        std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> ret;
+
+        float total_time = 0.0f;
+        for (const auto& [type, time] : m_custom_gcode_times) {
+            float remaining = include_remaining ? m_time - total_time : 0.0f;
+            ret.push_back({ type, { time, remaining } });
+            total_time += time;
+        }
+
+        return ret;
+    }
+#else
     std::vector<std::pair<CustomGCode::Type, float>> GCodeTimeEstimator::get_custom_gcode_times() const
     {
         return m_custom_gcode_times;
@@ -721,7 +736,24 @@ namespace Slic3r {
         }
         return ret;
     }
+#endif // ENABLE_GCODE_VIEWER
 
+#if ENABLE_GCODE_VIEWER
+    std::vector<std::pair<CustomGCode::Type, std::pair<std::string, std::string>>> GCodeTimeEstimator::get_custom_gcode_times_dhm(bool include_remaining) const
+    {
+        std::vector<std::pair<CustomGCode::Type, std::pair<std::string, std::string>>> ret;
+
+        float total_time = 0.0f;
+        for (const auto& [type, time] : m_custom_gcode_times) {
+            std::string duration = _get_time_dhm(time);
+            std::string remaining = include_remaining ? _get_time_dhm(m_time - total_time) : "";
+            ret.push_back({ type, { duration, remaining } });
+            total_time += time;
+        }
+
+        return ret;
+    }
+#else
     std::vector<std::pair<CustomGCode::Type, std::string>> GCodeTimeEstimator::get_custom_gcode_times_dhm(bool include_remaining) const
     {
         std::vector<std::pair<CustomGCode::Type, std::string>> ret;
@@ -742,6 +774,7 @@ namespace Slic3r {
 
         return ret;
     }
+#endif // ENABLE_GCODE_VIEWER
 
     // Return an estimate of the memory consumed by the time estimator.
 	size_t GCodeTimeEstimator::memory_used() const
diff --git a/src/libslic3r/GCodeTimeEstimator.hpp b/src/libslic3r/GCodeTimeEstimator.hpp
index 63e11c4fa..cfa12b40b 100644
--- a/src/libslic3r/GCodeTimeEstimator.hpp
+++ b/src/libslic3r/GCodeTimeEstimator.hpp
@@ -358,6 +358,9 @@ namespace Slic3r {
         std::string get_time_minutes() const;
 
         // Returns the estimated time, in seconds, for each custom gcode
+#if ENABLE_GCODE_VIEWER
+        std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> get_custom_gcode_times(bool include_remaining) const;
+#else
         std::vector<std::pair<CustomGCode::Type, float>> get_custom_gcode_times() const;
 
         // Returns the estimated time, in format DDd HHh MMm SSs, for each color
@@ -367,10 +370,15 @@ namespace Slic3r {
         // Returns the estimated time, in minutes (integer), for each color
         // If include_remaining==true the strings will be formatted as: "time for color (remaining time at color start)"
         std::vector<std::string> get_color_times_minutes(bool include_remaining) const;
+#endif // ENABLE_GCODE_VIEWER
 
         // Returns the estimated time, in format DDd HHh MMm, for each custom_gcode
         // If include_remaining==true the strings will be formatted as: "time for custom_gcode (remaining time at color start)"
+#if ENABLE_GCODE_VIEWER
+        std::vector<std::pair<CustomGCode::Type, std::pair<std::string, std::string>>> get_custom_gcode_times_dhm(bool include_remaining) const;
+#else
         std::vector<std::pair<CustomGCode::Type, std::string>> get_custom_gcode_times_dhm(bool include_remaining) const;
+#endif // ENABLE_GCODE_VIEWER
 
         // Return an estimate of the memory consumed by the time estimator.
         size_t memory_used() const;
diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp
index e4f4c60f5..eb9a4fb4b 100644
--- a/src/libslic3r/Print.hpp
+++ b/src/libslic3r/Print.hpp
@@ -305,8 +305,15 @@ struct PrintStatistics
     PrintStatistics() { clear(); }
     std::string                     estimated_normal_print_time;
     std::string                     estimated_silent_print_time;
+#if ENABLE_GCODE_VIEWER
+    std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> estimated_normal_custom_gcode_print_times;
+    std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> estimated_silent_custom_gcode_print_times;
+    std::vector<std::pair<CustomGCode::Type, std::pair<std::string, std::string>>> estimated_normal_custom_gcode_print_times_str;
+    std::vector<std::pair<CustomGCode::Type, std::pair<std::string, std::string>>> estimated_silent_custom_gcode_print_times_str;
+#else
     std::vector<std::pair<CustomGCode::Type, std::string>>    estimated_normal_custom_gcode_print_times;
     std::vector<std::pair<CustomGCode::Type, std::string>>    estimated_silent_custom_gcode_print_times;
+#endif // ENABLE_GCODE_VIEWER
     double                          total_used_filament;
     double                          total_extruded_volume;
     double                          total_cost;
@@ -326,8 +333,15 @@ struct PrintStatistics
     void clear() {
         estimated_normal_print_time.clear();
         estimated_silent_print_time.clear();
+#if ENABLE_GCODE_VIEWER
+        estimated_normal_custom_gcode_print_times_str.clear();
+        estimated_silent_custom_gcode_print_times_str.clear();
         estimated_normal_custom_gcode_print_times.clear();
         estimated_silent_custom_gcode_print_times.clear();
+#else
+        estimated_normal_custom_gcode_print_times.clear();
+        estimated_silent_custom_gcode_print_times.clear();
+#endif //ENABLE_GCODE_VIEWER
         total_used_filament    = 0.;
         total_extruded_volume  = 0.;
         total_cost             = 0.;
diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp
index fb84efe5a..b04e78c4e 100644
--- a/src/libslic3r/Technologies.hpp
+++ b/src/libslic3r/Technologies.hpp
@@ -59,8 +59,8 @@
 
 // Enable G-Code viewer
 #define ENABLE_GCODE_VIEWER (1 && ENABLE_2_3_0_ALPHA1)
-#define ENABLE_GCODE_VIEWER_STATISTICS (1 && ENABLE_GCODE_VIEWER)
-#define ENABLE_GCODE_VIEWER_SHADERS_EDITOR (1 && ENABLE_GCODE_VIEWER)
+#define ENABLE_GCODE_VIEWER_STATISTICS (0 && ENABLE_GCODE_VIEWER)
+#define ENABLE_GCODE_VIEWER_SHADERS_EDITOR (0 && ENABLE_GCODE_VIEWER)
 #define ENABLE_GCODE_VIEWER_AS_STATE (1 && ENABLE_GCODE_VIEWER)
 
 
diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp
index 688134f7c..26dc765db 100644
--- a/src/slic3r/GUI/GCodeViewer.cpp
+++ b/src/slic3r/GUI/GCodeViewer.cpp
@@ -4,6 +4,8 @@
 #if ENABLE_GCODE_VIEWER
 #include "libslic3r/Print.hpp"
 #include "libslic3r/Geometry.hpp"
+#include "libslic3r/Model.hpp"
+#include "libslic3r/Utils.hpp"
 #include "GUI_App.hpp"
 #if ENABLE_GCODE_VIEWER_AS_STATE
 #include "MainFrame.hpp"
@@ -17,10 +19,7 @@
 #include "GLCanvas3D.hpp"
 #include "GLToolbar.hpp"
 #include "GUI_Preview.hpp"
-#include "libslic3r/Model.hpp"
-#if ENABLE_GCODE_VIEWER_STATISTICS
 #include <imgui/imgui_internal.h>
-#endif // ENABLE_GCODE_VIEWER_STATISTICS
 
 #include <GL/glew.h>
 #include <boost/log/trivial.hpp>
@@ -187,15 +186,14 @@ void GCodeViewer::SequentialView::Marker::render() const
 
     static float last_window_width = 0.0f;
     static size_t last_text_length = 0;
-    static const ImVec4 ORANGE(1.0f, 0.49f, 0.22f, 1.0f);
 
     ImGuiWrapper& imgui = *wxGetApp().imgui();
     Size cnv_size = wxGetApp().plater()->get_current_canvas3D()->get_canvas_size();
-    imgui.set_next_window_pos(static_cast<float>(cnv_size.get_width()), static_cast<float>(cnv_size.get_height()), ImGuiCond_Always, 1.0f, 1.0f);
+    imgui.set_next_window_pos(0.5f * static_cast<float>(cnv_size.get_width()), static_cast<float>(cnv_size.get_height()), ImGuiCond_Always, 0.5f, 1.0f);
     ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
     ImGui::SetNextWindowBgAlpha(0.25f);
     imgui.begin(std::string("ToolPosition"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove);
-    ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
+    ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT);
     imgui.text(_u8L("Tool position") + ":");
     ImGui::PopStyleColor();
     ImGui::SameLine();
@@ -270,6 +268,7 @@ bool GCodeViewer::init()
     {
         switch (buffer_type(i))
         {
+        default: { break; }
         case GCodeProcessor::EMoveType::Tool_change:
         case GCodeProcessor::EMoveType::Color_change:
         case GCodeProcessor::EMoveType::Pause_Print:
@@ -420,6 +419,7 @@ void GCodeViewer::render() const
     m_sequential_view.marker.render();
     render_shells();
     render_legend();
+    render_time_estimate();
 #if ENABLE_GCODE_VIEWER_STATISTICS
     render_statistics();
 #endif // ENABLE_GCODE_VIEWER_STATISTICS
@@ -458,6 +458,7 @@ unsigned int GCodeViewer::get_options_visibility_flags() const
     flags = set_flag(flags, static_cast<unsigned int>(Preview::OptionType::Shells), m_shells.visible);
     flags = set_flag(flags, static_cast<unsigned int>(Preview::OptionType::ToolMarker), m_sequential_view.marker.is_visible());
     flags = set_flag(flags, static_cast<unsigned int>(Preview::OptionType::Legend), is_legend_enabled());
+    flags = set_flag(flags, static_cast<unsigned int>(Preview::OptionType::TimeEstimate), is_time_estimate_enabled());
     return flags;
 }
 
@@ -477,6 +478,7 @@ void GCodeViewer::set_options_visibility_from_flags(unsigned int flags)
     m_shells.visible = is_flag_set(static_cast<unsigned int>(Preview::OptionType::Shells));
     m_sequential_view.marker.set_visible(is_flag_set(static_cast<unsigned int>(Preview::OptionType::ToolMarker)));
     enable_legend(is_flag_set(static_cast<unsigned int>(Preview::OptionType::Legend)));
+    enable_time_estimate(is_flag_set(static_cast<unsigned int>(Preview::OptionType::TimeEstimate)));
 }
 
 void GCodeViewer::set_layers_z_range(const std::array<double, 2>& layers_z_range)
@@ -591,8 +593,8 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const
             return ret;
         };
 
-        Vec3f v1 = get_vertex(start_id);
-        Vec3f v2 = get_vertex(start_id + 1);
+        Vec3f v1 = get_vertex(start_id) - half_height * Vec3f::UnitZ();
+        Vec3f v2 = get_vertex(start_id + 1) - half_height * Vec3f::UnitZ();
         float length = (v2 - v1).norm();
         const auto&& [dir, right, up] = local_basis(v2 - v1);
         return Segment({ v1, v2, dir, right, up, half_width * right, half_height * up, length });
@@ -605,7 +607,8 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const
         const RenderPath& render_path = buffer.render_paths[i];
         const Path& path = buffer.paths[render_path.path_id];
         float half_width = 0.5f * path.width;
-        float half_height = 0.5f * path.height;
+        // clamp height to avoid artifacts due to z-fighting when importing the obj file into blender and similar
+        float half_height = std::max(0.5f * path.height, 0.005f);
 
         // generates vertices/normals/triangles
         std::vector<Vec3f> out_vertices;
@@ -657,7 +660,7 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const
                             out_triangles.push_back({ base_id + 5, base_id + 3, base_id + 2 });
 
                             // update right vertices
-                            if (disp < prev.length) {
+                            if (disp < prev.length && disp < curr.length) {
                                 base_id = out_vertices.size() - 6;
                                 out_vertices[base_id + 0] -= disp_vec;
                                 out_vertices[base_id + 4] = out_vertices[base_id + 0];
@@ -670,7 +673,7 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const
                             out_triangles.push_back({ base_id + 0, base_id + 3, base_id + 4 });
 
                             // update left vertices
-                            if (disp < prev.length) {
+                            if (disp < prev.length && disp < curr.length) {
                                 base_id = out_vertices.size() - 6;
                                 out_vertices[base_id + 2] -= disp_vec;
                                 out_vertices[base_id + 5] = out_vertices[base_id + 2];
@@ -742,27 +745,25 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const
         }
 
         // save to file
-        fprintf(fp, "\n# vertices path %lld\n", i + 1);
+        fprintf(fp, "\n# vertices path %zu\n", i + 1);
         for (const Vec3f& v : out_vertices) {
             fprintf(fp, "v %g %g %g\n", v[0], v[1], v[2]);
         }
 
-        fprintf(fp, "\n# normals path %lld\n", i + 1);
+        fprintf(fp, "\n# normals path %zu\n", i + 1);
         for (const Vec3f& n : out_normals) {
             fprintf(fp, "vn %g %g %g\n", n[0], n[1], n[2]);
         }
 
-        fprintf(fp, "\n# material path %lld\n", i + 1);
-        fprintf(fp, "usemtl material_%lld\n", i + 1);
+        fprintf(fp, "\n# material path %zu\n", i + 1);
+        fprintf(fp, "usemtl material_%zu\n", i + 1);
 
-        fprintf(fp, "\n# triangles path %lld\n", i + 1);
+        fprintf(fp, "\n# triangles path %zu\n", i + 1);
         for (const Triangle& t : out_triangles) {
-            fprintf(fp, "f %lld//%lld %lld//%lld %lld//%lld\n", t[0], t[0], t[1], t[1], t[2], t[2]);
+            fprintf(fp, "f %zu//%zu %zu//%zu %zu//%zu\n", t[0], t[0], t[1], t[1], t[2], t[2]);
         }
-
     }
 
-//    fprintf(fp, "\n#vertices count %lld\n", out_vertices_count);
     fclose(fp);
 }
 
@@ -775,12 +776,12 @@ void GCodeViewer::init_shaders()
     for (unsigned char i = begin_id; i < end_id; ++i) {
         switch (buffer_type(i))
         {
-        case GCodeProcessor::EMoveType::Tool_change:  { m_buffers[i].shader = is_glsl_120 ? "options_120_solid" : "options_110"; break; }
-        case GCodeProcessor::EMoveType::Color_change: { m_buffers[i].shader = is_glsl_120 ? "options_120_solid" : "options_110"; break; }
-        case GCodeProcessor::EMoveType::Pause_Print:  { m_buffers[i].shader = is_glsl_120 ? "options_120_solid" : "options_110"; break; }
-        case GCodeProcessor::EMoveType::Custom_GCode: { m_buffers[i].shader = is_glsl_120 ? "options_120_solid" : "options_110"; break; }
-        case GCodeProcessor::EMoveType::Retract:      { m_buffers[i].shader = is_glsl_120 ? "options_120_solid" : "options_110"; break; }
-        case GCodeProcessor::EMoveType::Unretract:    { m_buffers[i].shader = is_glsl_120 ? "options_120_solid" : "options_110"; break; }
+        case GCodeProcessor::EMoveType::Tool_change:  { m_buffers[i].shader = is_glsl_120 ? "options_120_flat" : "options_110"; break; }
+        case GCodeProcessor::EMoveType::Color_change: { m_buffers[i].shader = is_glsl_120 ? "options_120_flat" : "options_110"; break; }
+        case GCodeProcessor::EMoveType::Pause_Print:  { m_buffers[i].shader = is_glsl_120 ? "options_120_flat" : "options_110"; break; }
+        case GCodeProcessor::EMoveType::Custom_GCode: { m_buffers[i].shader = is_glsl_120 ? "options_120_flat" : "options_110"; break; }
+        case GCodeProcessor::EMoveType::Retract:      { m_buffers[i].shader = is_glsl_120 ? "options_120_flat" : "options_110"; break; }
+        case GCodeProcessor::EMoveType::Unretract:    { m_buffers[i].shader = is_glsl_120 ? "options_120_flat" : "options_110"; break; }
         case GCodeProcessor::EMoveType::Extrude:      { m_buffers[i].shader = "toolpaths"; break; }
         case GCodeProcessor::EMoveType::Travel:       { m_buffers[i].shader = "toolpaths"; break; }
         default: { break; }
@@ -1137,7 +1138,7 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
     }
 
     // second pass: filter paths by sequential data and collect them by color
-    for (auto&& [buffer, id] : paths) {
+    for (const auto& [buffer, id] : paths) {
         const Path& path = buffer->paths[id];
         if (m_sequential_view.current.last <= path.first.s_id || path.last.s_id <= m_sequential_view.current.first)
             continue;
@@ -1203,8 +1204,8 @@ void GCodeViewer::render_toolpaths() const
         shader.set_uniform("percent_outline_radius", 0.01f * static_cast<float>(m_shaders_editor.points.percent_outline));
         shader.set_uniform("percent_center_radius", 0.01f * static_cast<float>(m_shaders_editor.points.percent_center));
 #else
-        shader.set_uniform("percent_outline_radius", 0.15f);
-        shader.set_uniform("percent_center_radius", 0.15f);
+        shader.set_uniform("percent_outline_radius", 0.0f);
+        shader.set_uniform("percent_center_radius", 0.33f);
 #endif // ENABLE_GCODE_VIEWER_SHADERS_EDITOR
         shader.set_uniform("viewport", viewport);
         shader.set_uniform("inv_proj_matrix", inv_proj);
@@ -1266,6 +1267,7 @@ void GCodeViewer::render_toolpaths() const
 
             switch (buffer_type(i))
             {
+            default: { break; }
             case GCodeProcessor::EMoveType::Tool_change:  { render_as_points(buffer, EOptionsColors::ToolChanges, *shader); break; }
             case GCodeProcessor::EMoveType::Color_change: { render_as_points(buffer, EOptionsColors::ColorChanges, *shader); break; }
             case GCodeProcessor::EMoveType::Pause_Print:  { render_as_points(buffer, EOptionsColors::PausePrints, *shader); break; }
@@ -1320,18 +1322,15 @@ void GCodeViewer::render_shells() const
 //    glsafe(::glDepthMask(GL_TRUE));
 }
 
+#define USE_ICON_HEXAGON 1
+
 void GCodeViewer::render_legend() const
 {
-    static const ImVec4 ORANGE(1.0f, 0.49f, 0.22f, 1.0f);
-    static const ImU32 ICON_BORDER_COLOR = ImGui::GetColorU32(ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
-
     if (!m_legend_enabled)
         return;
 
     ImGuiWrapper& imgui = *wxGetApp().imgui();
 
-#define USE_ICON_HEXAGON 1
-
     imgui.set_next_window_pos(0.0f, 0.0f, ImGuiCond_Always);
     ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
     ImGui::SetNextWindowBgAlpha(0.6f);
@@ -1347,19 +1346,14 @@ void GCodeViewer::render_legend() const
         Line
     };
 
-#if ENABLE_GCODE_VIEWER_SHADERS_EDITOR
     auto add_item = [this, draw_list, &imgui](EItemType type, const Color& color, const std::string& label, std::function<void()> callback = nullptr) {
-#else
-    auto add_item = [draw_list, &imgui](EItemType type, const Color& color, const std::string& label, std::function<void()> callback = nullptr) {
-#endif // ENABLE_GCODE_VIEWER_SHADERS_EDITOR
         float icon_size = ImGui::GetTextLineHeight();
-        ImVec2 pos = ImGui::GetCursorPos();
+        ImVec2 pos = ImGui::GetCursorScreenPos();
         switch (type)
         {
         default:
         case EItemType::Rect:
         {
-            draw_list->AddRect({ pos.x, pos.y }, { pos.x + icon_size, pos.y + icon_size }, ICON_BORDER_COLOR, 0.0f, 0);
             draw_list->AddRectFilled({ pos.x + 1.0f, pos.y + 1.0f }, { pos.x + icon_size - 1.0f, pos.y + icon_size - 1.0f },
                 ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }));
             break;
@@ -1380,37 +1374,26 @@ void GCodeViewer::render_legend() const
             }
             else
                 draw_list->AddCircleFilled(center, 0.5f * icon_size, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 16);
-
-//            ImVec2 center(0.5f * (pos.x + pos.x + icon_size), 0.5f * (pos.y + pos.y + icon_size));
-//            draw_list->AddCircle(center, 0.5f * icon_size, ICON_BORDER_COLOR, 16);
-//            if (m_shaders_editor.shader_version == 1) {
-//                draw_list->AddCircleFilled(center, (0.5f * icon_size) - 2.0f,
-//                    ImGui::GetColorU32({ 0.5f * color[0], 0.5f * color[1], 0.5f * color[2], 1.0f }), 16);
-//                float radius = ((0.5f * icon_size) - 2.0f) * (1.0f - 0.01f * static_cast<float>(m_shaders_editor.percent_outline));
-//                draw_list->AddCircleFilled(center, radius, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 16);
-//                if (m_shaders_editor.percent_center > 0) {
-//                    radius = ((0.5f * icon_size) - 2.0f) * 0.01f * static_cast<float>(m_shaders_editor.percent_center);
-//                    draw_list->AddCircleFilled(center, radius, ImGui::GetColorU32({ 0.5f * color[0], 0.5f * color[1], 0.5f * color[2], 1.0f }), 16);
-//                }
-//            } else
-//                draw_list->AddCircleFilled(center, (0.5f * icon_size) - 2.0f, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 16);
 #else
-            draw_list->AddCircleFilled({ 0.5f * (pos.x + pos.x + icon_size), 0.5f * (pos.y + pos.y + icon_size) }, 0.5f * icon_size,
-                ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 16);
-
-//            draw_list->AddCircle({ 0.5f * (pos.x + pos.x + icon_size), 0.5f * (pos.y + pos.y + icon_size) }, 0.5f * icon_size, ICON_BORDER_COLOR, 16);
-//            draw_list->AddCircleFilled({ 0.5f * (pos.x + pos.x + icon_size), 0.5f * (pos.y + pos.y + icon_size) }, (0.5f * icon_size) - 2.0f,
-//                ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 16);
+            ImVec2 center(0.5f * (pos.x + pos.x + icon_size), 0.5f * (pos.y + pos.y + icon_size));            
+            if (m_buffers[buffer_id(GCodeProcessor::EMoveType::Retract)].shader == "options_120_flat") {
+                draw_list->AddCircleFilled(center, 0.5f * icon_size,
+                    ImGui::GetColorU32({ 0.5f * color[0], 0.5f * color[1], 0.5f * color[2], 1.0f }), 16);
+                float radius = 0.5f * icon_size;
+                draw_list->AddCircleFilled(center, radius, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 16);
+                radius = 0.5f * icon_size * 0.01f * 33.0f;
+                draw_list->AddCircleFilled(center, radius, ImGui::GetColorU32({ 0.5f * color[0], 0.5f * color[1], 0.5f * color[2], 1.0f }), 16);
+            }
+            else
+                draw_list->AddCircleFilled(center, 0.5f * icon_size, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 16);
 #endif // ENABLE_GCODE_VIEWER_SHADERS_EDITOR
+
             break;
         }
         case EItemType::Hexagon:
         {
             ImVec2 center(0.5f * (pos.x + pos.x + icon_size), 0.5f * (pos.y + pos.y + icon_size));
             draw_list->AddNgonFilled(center, 0.5f * icon_size, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 6);
-//            draw_list->AddNgon(center, 0.5f * icon_size, ICON_BORDER_COLOR, 6);
-//            draw_list->AddNgonFilled(center, (0.5f * icon_size) - 2.0f,
-//                ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 6);
             break;
         }
         case EItemType::Line:
@@ -1454,21 +1437,18 @@ void GCodeViewer::render_legend() const
     };
 
     // extrusion paths -> title
-    ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
     switch (m_view_type)
     {
-    case EViewType::FeatureType:    { imgui.text(_u8L("Feature type")); break; }
-    case EViewType::Height:         { imgui.text(_u8L("Height (mm)")); break; }
-    case EViewType::Width:          { imgui.text(_u8L("Width (mm)")); break; }
-    case EViewType::Feedrate:       { imgui.text(_u8L("Speed (mm/s)")); break; }
-    case EViewType::FanSpeed:       { imgui.text(_u8L("Fan Speed (%%)")); break; }
-    case EViewType::VolumetricRate: { imgui.text(_u8L("Volumetric flow rate (mm³/s)")); break; }
-    case EViewType::Tool:           { imgui.text(_u8L("Tool")); break; }
-    case EViewType::ColorPrint:     { imgui.text(_u8L("Color Print")); break; }
-    default:                        { break; }
+    case EViewType::FeatureType:    { imgui.title(_u8L("Feature type")); break; }
+    case EViewType::Height:         { imgui.title(_u8L("Height (mm)")); break; }
+    case EViewType::Width:          { imgui.title(_u8L("Width (mm)")); break; }
+    case EViewType::Feedrate:       { imgui.title(_u8L("Speed (mm/s)")); break; }
+    case EViewType::FanSpeed:       { imgui.title(_u8L("Fan Speed (%%)")); break; }
+    case EViewType::VolumetricRate: { imgui.title(_u8L("Volumetric flow rate (mm³/s)")); break; }
+    case EViewType::Tool:           { imgui.title(_u8L("Tool")); break; }
+    case EViewType::ColorPrint:     { imgui.title(_u8L("Color Print")); break; }
+    default: { break; }
     }
-    ImGui::PopStyleColor();
-    ImGui::Separator();
 
     // extrusion paths -> items
     switch (m_view_type)
@@ -1566,28 +1546,26 @@ void GCodeViewer::render_legend() const
                 else {
                     for (int i = items_cnt; i >= 0; --i) {
                         // create label for color change item
-                        std::string id_str = " (" + std::to_string(i + 1) + ")";
-
                         if (i == 0) {
 #if USE_ICON_HEXAGON
-                            add_item(EItemType::Hexagon, m_tool_colors[i], (boost::format(_u8L("up to %.2f mm")) % cp_values.front().first).str() + id_str);
+                            add_item(EItemType::Hexagon, m_tool_colors[i], (boost::format(_u8L("up to %.2f mm")) % cp_values.front().first).str());
 #else
-                            add_item(EItemType::Rect, m_tool_colors[i], (boost::format(_u8L("up to %.2f mm")) % cp_values.front().first).str() + id_str);
+                            add_item(EItemType::Rect, m_tool_colors[i], (boost::format(_u8L("up to %.2f mm")) % cp_values.front().first).str());
 #endif // USE_ICON_HEXAGON
                             break;
                         }
                         else if (i == items_cnt) {
 #if USE_ICON_HEXAGON
-                            add_item(EItemType::Hexagon, m_tool_colors[i], (boost::format(_u8L("above %.2f mm")) % cp_values[i - 1].second).str() + id_str);
+                            add_item(EItemType::Hexagon, m_tool_colors[i], (boost::format(_u8L("above %.2f mm")) % cp_values[i - 1].second).str());
 #else
-                            add_item(EItemType::Rect, m_tool_colors[i], (boost::format(_u8L("above %.2f mm")) % cp_values[i - 1].second).str() + id_str);
+                            add_item(EItemType::Rect, m_tool_colors[i], (boost::format(_u8L("above %.2f mm")) % cp_values[i - 1].second).str());
 #endif // USE_ICON_HEXAGON
                             continue;
                         }
 #if USE_ICON_HEXAGON
-                        add_item(EItemType::Hexagon, m_tool_colors[i], (boost::format(_u8L("%.2f - %.2f mm")) % cp_values[i - 1].second% cp_values[i].first).str() + id_str);
+                        add_item(EItemType::Hexagon, m_tool_colors[i], (boost::format(_u8L("%.2f - %.2f mm")) % cp_values[i - 1].second % cp_values[i].first).str());
 #else
-                        add_item(EItemType::Rect, m_tool_colors[i], (boost::format(_u8L("%.2f - %.2f mm")) % cp_values[i - 1].second% cp_values[i].first).str() + id_str);
+                        add_item(EItemType::Rect, m_tool_colors[i], (boost::format(_u8L("%.2f - %.2f mm")) % cp_values[i - 1].second % cp_values[i].first).str());
 #endif // USE_ICON_HEXAGON
                     }
                 }
@@ -1609,15 +1587,12 @@ void GCodeViewer::render_legend() const
             size_t last_color_id = m_tool_colors.size() - 1;
             for (int i = static_cast<int>(custom_gcode_per_print_z.size()) - 1; i >= 0; --i) {
                 if (custom_gcode_per_print_z[i].type == ColorChange) {
-                    // create label for color change item
-                    std::string id_str = " (" + std::to_string(color_change_idx--) + ")";
-
 #if USE_ICON_HEXAGON
                     add_item(EItemType::Hexagon, m_tool_colors[last_color_id--],
 #else
                     add_item(EItemType::Rect, m_tool_colors[last_color_id--],
 #endif // USE_ICON_HEXAGON
-                        (boost::format(_u8L("Color change for Extruder %d at %.2f mm")) % custom_gcode_per_print_z[i].extruder % custom_gcode_per_print_z[i].print_z).str() + id_str);
+                        (boost::format(_u8L("Color change for Extruder %d at %.2f mm")) % custom_gcode_per_print_z[i].extruder % custom_gcode_per_print_z[i].print_z).str());
                 }
             }
         }
@@ -1641,11 +1616,7 @@ void GCodeViewer::render_legend() const
         {
             // title
             ImGui::Spacing();
-            ImGui::Spacing();
-            ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
-            imgui.text(_u8L("Travel"));
-            ImGui::PopStyleColor();
-            ImGui::Separator();
+            imgui.title(_u8L("Travel"));
 
             // items
             add_item(EItemType::Line, Travel_Colors[0], _u8L("Movement"));
@@ -1657,13 +1628,18 @@ void GCodeViewer::render_legend() const
         }
     }
 
-    auto any_option_visible = [this]() {
-        return m_buffers[buffer_id(GCodeProcessor::EMoveType::Color_change)].visible ||
-               m_buffers[buffer_id(GCodeProcessor::EMoveType::Custom_GCode)].visible ||
-               m_buffers[buffer_id(GCodeProcessor::EMoveType::Pause_Print)].visible ||
-               m_buffers[buffer_id(GCodeProcessor::EMoveType::Retract)].visible ||
-               m_buffers[buffer_id(GCodeProcessor::EMoveType::Tool_change)].visible ||
-               m_buffers[buffer_id(GCodeProcessor::EMoveType::Unretract)].visible;
+    auto any_option_available = [this]() {
+        auto available = [this](GCodeProcessor::EMoveType type) {
+            const TBuffer& buffer = m_buffers[buffer_id(type)];
+            return buffer.visible && buffer.indices.count > 0;
+        };
+
+        return available(GCodeProcessor::EMoveType::Color_change) ||
+            available(GCodeProcessor::EMoveType::Custom_GCode) ||
+            available(GCodeProcessor::EMoveType::Pause_Print) ||
+            available(GCodeProcessor::EMoveType::Retract) ||
+            available(GCodeProcessor::EMoveType::Tool_change) ||
+            available(GCodeProcessor::EMoveType::Unretract);
     };
 
     auto add_option = [this, add_item](GCodeProcessor::EMoveType move_type, EOptionsColors color, const std::string& text) {
@@ -1677,14 +1653,10 @@ void GCodeViewer::render_legend() const
     };
 
     // options
-    if (any_option_visible()) {
+    if (any_option_available()) {
         // title
         ImGui::Spacing();
-        ImGui::Spacing();
-        ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
-        imgui.text(_u8L("Options"));
-        ImGui::PopStyleColor();
-        ImGui::Separator();
+        imgui.title(_u8L("Options"));
 
         // items
         add_option(GCodeProcessor::EMoveType::Retract, EOptionsColors::Retractions, _u8L("Retractions"));
@@ -1699,10 +1671,175 @@ void GCodeViewer::render_legend() const
     ImGui::PopStyleVar();
 }
 
+void GCodeViewer::render_time_estimate() const
+{
+    static const std::vector<std::string> Columns_Headers = {
+        _u8L("Operation"),
+        _u8L("Remaining"),
+        _u8L("Duration")
+    };
+
+    if (!m_time_estimate_enabled)
+        return;
+
+    const PrintStatistics& ps = wxGetApp().plater()->fff_print().print_statistics();
+    if (ps.estimated_normal_print_time == "N/A" && ps.estimated_silent_print_time == "N/A")
+        return;
+
+    int columns_count = 1;
+    if (ps.estimated_silent_print_time != "N/A")
+        ++columns_count;
+
+    ImGuiWrapper& imgui = *wxGetApp().imgui();
+    Size cnv_size = wxGetApp().plater()->get_current_canvas3D()->get_canvas_size();
+    imgui.set_next_window_pos(static_cast<float>(cnv_size.get_width()), static_cast<float>(cnv_size.get_height()), ImGuiCond_Always, 1.0f, 1.0f);
+    ImGui::SetNextWindowSizeConstraints(ImVec2(0.0f, 0.0f), ImVec2(-1.0f, 0.5f * static_cast<float>(cnv_size.get_height())));
+    ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
+    ImGui::SetNextWindowBgAlpha(0.6f);
+    imgui.begin(std::string("Time_estimate"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove);
+
+    ImDrawList* draw_list = ImGui::GetWindowDrawList();
+    float icon_size = ImGui::GetTextLineHeight();
+
+    using Time = std::pair<float, float>;
+    using TimesList = std::vector<std::pair<CustomGCode::Type, Time>>;
+    using Headers = std::vector<std::string>;
+    using Offsets = std::array<float, 2>;
+
+    auto add_mode = [this, &imgui, icon_size, draw_list](const std::string& mode, const std::string& time, const TimesList& times, const Headers& headers) {
+        auto add_partial_times = [this, &imgui, icon_size, draw_list](const TimesList& times, const Headers& headers) {
+            auto add_color = [this, &imgui, icon_size, draw_list](int id, Offsets& offsets, const Time& time) {
+                ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT);
+                std::string text = _u8L("Color");
+                if (m_view_type != EViewType::ColorPrint)
+                    text += " " + std::to_string(id);
+                imgui.text(text);
+                ImGui::PopStyleColor();
+                ImGui::SameLine();
+
+                if (m_view_type == EViewType::ColorPrint) {
+                    const Color& color = m_tool_colors[id - 1];
+                    ImVec2 pos = ImGui::GetCursorScreenPos();
+#if USE_ICON_HEXAGON
+                    ImVec2 center(0.5f * (pos.x + pos.x + icon_size), 0.5f * (pos.y + pos.y + icon_size));
+                    draw_list->AddNgonFilled(center, 0.5f * icon_size, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 6);
+#else
+                    draw_list->AddRectFilled({ pos.x + 1.0f, pos.y + 1.0f }, { pos.x + icon_size - 1.0f, pos.y + icon_size - 1.0f },
+                        ImGui::GetColorU32({ m_tool_colors[i][0], m_tool_colors[i][1], m_tool_colors[i][2], 1.0f }));
+#endif // USE_ICON_HEXAGON
+                }
+                ImGui::SameLine(offsets[0]);
+                imgui.text(short_time(get_time_dhms(time.second)));
+                ImGui::SameLine(offsets[1]);
+                imgui.text(short_time(get_time_dhms(time.first)));
+            };
+            auto calc_offsets = [this, icon_size](const TimesList& times, const Headers& headers, int color_change_count) {
+                Offsets ret = { ImGui::CalcTextSize(headers[0].c_str()).x, ImGui::CalcTextSize(headers[1].c_str()).x };
+                for (const auto& [type, time] : times) {
+                    std::string label;
+                    switch (type)
+                    {
+                    case CustomGCode::PausePrint:
+                    {
+                        label = _u8L("Pause");
+                        break;
+                    }
+                    case CustomGCode::ColorChange:
+                    {
+                        label = _u8L("Color");
+                        if (m_view_type != EViewType::ColorPrint)
+                            label += " " + std::to_string(color_change_count);
+                        break;
+                    }
+                    default: { break; }
+                    }
+
+                    ret[0] = std::max(ret[0], ImGui::CalcTextSize(label.c_str()).x);
+                    ret[1] = std::max(ret[1], ImGui::CalcTextSize(short_time(get_time_dhms(time.second)).c_str()).x);
+                }
+
+                const ImGuiStyle& style = ImGui::GetStyle();
+                ret[0] += icon_size + style.ItemSpacing.x;
+                ret[1] += ret[0] + style.ItemSpacing.x;
+                return ret;
+            };
+
+            if (times.empty())
+                return;
+
+            int color_change_count = 0;
+            for (auto time : times) {
+                if (time.first == CustomGCode::ColorChange)
+                    ++color_change_count;
+            }
+
+            Offsets offsets = calc_offsets(times, headers, color_change_count);
+
+            ImGui::Spacing();
+            ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT);
+            imgui.text(headers[0]);
+            ImGui::SameLine(offsets[0]);
+            imgui.text(headers[1]);
+            ImGui::SameLine(offsets[1]);
+            imgui.text(headers[2]);
+            ImGui::PopStyleColor();
+
+            int last_color_id = color_change_count;
+
+            for (int i = static_cast<int>(times.size()) - 1; i >= 0; --i) {
+                const auto& [type, time] = times[i];
+
+                switch (type)
+                {
+                case CustomGCode::PausePrint:
+                {
+                    ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT);
+                    imgui.text(_u8L("Pause"));
+                    ImGui::PopStyleColor();
+                    ImGui::SameLine(offsets[0]);
+                    imgui.text(short_time(get_time_dhms(time.second - time.first)));
+
+                    add_color(last_color_id, offsets, time);
+                    break;
+                }
+                case CustomGCode::ColorChange:
+                {
+                    add_color(color_change_count, offsets, time);
+                    last_color_id = color_change_count--;
+                    break;
+                }
+                default: { break; }
+                }
+            }
+        };
+
+        ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT);
+        imgui.text(mode + ":");
+        ImGui::PopStyleColor();
+        ImGui::SameLine();
+        imgui.text(time);
+        add_partial_times(times, headers);
+    };
+
+    // title
+    imgui.title(_u8L("Estimated printing time"));
+
+    // times
+    if (ps.estimated_normal_print_time != "N/A")
+        add_mode(_u8L("Normal mode"), ps.estimated_normal_print_time, ps.estimated_normal_custom_gcode_print_times, Columns_Headers);
+
+    if (ps.estimated_silent_print_time != "N/A") {
+        ImGui::Separator();
+        add_mode(_u8L("Stealth mode"), ps.estimated_silent_print_time, ps.estimated_silent_custom_gcode_print_times, Columns_Headers);
+    }
+
+    imgui.end();
+    ImGui::PopStyleVar();
+}
+
 #if ENABLE_GCODE_VIEWER_STATISTICS
 void GCodeViewer::render_statistics() const
 {
-    static const ImVec4 ORANGE(1.0f, 0.49f, 0.22f, 1.0f);
     static const float offset = 230.0f;
 
     ImGuiWrapper& imgui = *wxGetApp().imgui();
@@ -1711,7 +1848,7 @@ void GCodeViewer::render_statistics() const
     imgui.begin(std::string("GCodeViewer Statistics"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize);
     ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindow());
 
-    ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
+    ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT);
     imgui.text(std::string("GCodeProcessor time:"));
     ImGui::PopStyleColor();
     ImGui::SameLine(offset);
@@ -1719,19 +1856,19 @@ void GCodeViewer::render_statistics() const
 
     ImGui::Separator();
 
-    ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
+    ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT);
     imgui.text(std::string("Load time:"));
     ImGui::PopStyleColor();
     ImGui::SameLine(offset);
     imgui.text(std::to_string(m_statistics.load_time) + " ms");
 
-    ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
+    ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT);
     imgui.text(std::string("Resfresh time:"));
     ImGui::PopStyleColor();
     ImGui::SameLine(offset);
     imgui.text(std::to_string(m_statistics.refresh_time) + " ms");
 
-    ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
+    ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT);
     imgui.text(std::string("Resfresh paths time:"));
     ImGui::PopStyleColor();
     ImGui::SameLine(offset);
@@ -1739,13 +1876,13 @@ void GCodeViewer::render_statistics() const
 
     ImGui::Separator();
 
-    ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
+    ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT);
     imgui.text(std::string("Multi GL_POINTS calls:"));
     ImGui::PopStyleColor();
     ImGui::SameLine(offset);
     imgui.text(std::to_string(m_statistics.gl_multi_points_calls_count));
 
-    ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
+    ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT);
     imgui.text(std::string("Multi GL_LINE_STRIP calls:"));
     ImGui::PopStyleColor();
     ImGui::SameLine(offset);
@@ -1753,7 +1890,7 @@ void GCodeViewer::render_statistics() const
 
     ImGui::Separator();
 
-    ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
+    ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT);
     imgui.text(std::string("GCodeProcessor results:"));
     ImGui::PopStyleColor();
     ImGui::SameLine(offset);
@@ -1761,13 +1898,13 @@ void GCodeViewer::render_statistics() const
 
     ImGui::Separator();
 
-    ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
+    ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT);
     imgui.text(std::string("Paths CPU:"));
     ImGui::PopStyleColor();
     ImGui::SameLine(offset);
     imgui.text(std::to_string(m_statistics.paths_size) + " bytes");
 
-    ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
+    ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT);
     imgui.text(std::string("Render paths CPU:"));
     ImGui::PopStyleColor();
     ImGui::SameLine(offset);
@@ -1775,13 +1912,13 @@ void GCodeViewer::render_statistics() const
 
     ImGui::Separator();
 
-    ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
+    ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT);
     imgui.text(std::string("Vertices GPU:"));
     ImGui::PopStyleColor();
     ImGui::SameLine(offset);
     imgui.text(std::to_string(m_statistics.vertices_gpu_size) + " bytes");
 
-    ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
+    ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT);
     imgui.text(std::string("Indices GPU:"));
     ImGui::PopStyleColor();
     ImGui::SameLine(offset);
@@ -1789,13 +1926,13 @@ void GCodeViewer::render_statistics() const
 
     ImGui::Separator();
 
-    ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
+    ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT);
     imgui.text(std::string("Travel segments:"));
     ImGui::PopStyleColor();
     ImGui::SameLine(offset);
     imgui.text(std::to_string(m_statistics.travel_segments_count));
 
-    ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
+    ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT);
     imgui.text(std::string("Extrude segments:"));
     ImGui::PopStyleColor();
     ImGui::SameLine(offset);
@@ -1816,8 +1953,6 @@ void GCodeViewer::render_shaders_editor() const
         }
     };
 
-    static const ImVec4 ORANGE(1.0f, 0.49f, 0.22f, 1.0f);
-
     ImGuiWrapper& imgui = *wxGetApp().imgui();
 
     Size cnv_size = wxGetApp().plater()->get_current_canvas3D()->get_canvas_size();
@@ -1828,8 +1963,8 @@ void GCodeViewer::render_shaders_editor() const
     if (ImGui::CollapsingHeader("Points", ImGuiTreeNodeFlags_DefaultOpen)) {
         if (ImGui::TreeNode("GLSL version")) {
             ImGui::RadioButton("1.10 (low end PCs)", &m_shaders_editor.points.shader_version, 0);
-            ImGui::RadioButton("1.20 flat (billboards)", &m_shaders_editor.points.shader_version, 1);
-            ImGui::RadioButton("1.20 solid (spheres default)", &m_shaders_editor.points.shader_version, 2);
+            ImGui::RadioButton("1.20 flat (billboards) [default]", &m_shaders_editor.points.shader_version, 1);
+            ImGui::RadioButton("1.20 solid (spheres)", &m_shaders_editor.points.shader_version, 2);
             ImGui::TreePop();
         }
 
diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp
index 137ae89af..90155c728 100644
--- a/src/slic3r/GUI/GCodeViewer.hpp
+++ b/src/slic3r/GUI/GCodeViewer.hpp
@@ -248,7 +248,7 @@ class GCodeViewer
     {
         struct Points
         {
-            int shader_version{ 2 };
+            int shader_version{ 1 };
             float point_size{ 0.8f };
             int percent_outline{ 0 };
             int percent_center{ 33 };
@@ -341,6 +341,7 @@ private:
     Shells m_shells;
     EViewType m_view_type{ EViewType::FeatureType };
     bool m_legend_enabled{ true };
+    bool m_time_estimate_enabled{ true };
 #if ENABLE_GCODE_VIEWER_STATISTICS
     mutable Statistics m_statistics;
 #endif // ENABLE_GCODE_VIEWER_STATISTICS
@@ -396,6 +397,9 @@ public:
     bool is_legend_enabled() const { return m_legend_enabled; }
     void enable_legend(bool enable) { m_legend_enabled = enable; }
 
+    bool is_time_estimate_enabled() const { return m_time_estimate_enabled; }
+    void enable_time_estimate(bool enable) { m_time_estimate_enabled = enable; }
+
     void export_toolpaths_to_obj(const char* filename) const;
 
 private:
@@ -406,6 +410,7 @@ private:
     void render_toolpaths() const;
     void render_shells() const;
     void render_legend() const;
+    void render_time_estimate() const;
 #if ENABLE_GCODE_VIEWER_STATISTICS
     void render_statistics() const;
 #endif // ENABLE_GCODE_VIEWER_STATISTICS
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index f8ff9406f..8c6914248 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -219,8 +219,6 @@ void GLCanvas3D::LayersEditing::render_overlay(const GLCanvas3D& canvas) const
     if (!m_enabled)
         return;
 
-    static const ImVec4 ORANGE(1.0f, 0.49f, 0.22f, 1.0f);
-
     const Size& cnv_size = canvas.get_canvas_size();
     float canvas_w = (float)cnv_size.get_width();
     float canvas_h = (float)cnv_size.get_height();
@@ -228,50 +226,50 @@ void GLCanvas3D::LayersEditing::render_overlay(const GLCanvas3D& canvas) const
     ImGuiWrapper& imgui = *wxGetApp().imgui();
     imgui.set_next_window_pos(canvas_w - imgui.get_style_scaling() * THICKNESS_BAR_WIDTH, canvas_h, ImGuiCond_Always, 1.0f, 1.0f);
 
-    imgui.begin(_(L("Variable layer height")), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse);
+    imgui.begin(_L("Variable layer height"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse);
 
-    ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
-    imgui.text(_(L("Left mouse button:")));
+    ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT);
+    imgui.text(_L("Left mouse button:"));
     ImGui::PopStyleColor();
     ImGui::SameLine();
-    imgui.text(_(L("Add detail")));
+    imgui.text(_L("Add detail"));
 
-    ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
-    imgui.text(_(L("Right mouse button:")));
+    ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT);
+    imgui.text(_L("Right mouse button:"));
     ImGui::PopStyleColor();
     ImGui::SameLine();
-    imgui.text(_(L("Remove detail")));
+    imgui.text(_L("Remove detail"));
 
-    ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
-    imgui.text(_(L("Shift + Left mouse button:")));
+    ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT);
+    imgui.text(_L("Shift + Left mouse button:"));
     ImGui::PopStyleColor();
     ImGui::SameLine();
-    imgui.text(_(L("Reset to base")));
+    imgui.text(_L("Reset to base"));
 
-    ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
-    imgui.text(_(L("Shift + Right mouse button:")));
+    ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT);
+    imgui.text(_L("Shift + Right mouse button:"));
     ImGui::PopStyleColor();
     ImGui::SameLine();
-    imgui.text(_(L("Smoothing")));
+    imgui.text(_L("Smoothing"));
 
-    ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
-    imgui.text(_(L("Mouse wheel:")));
+    ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT);
+    imgui.text(_L("Mouse wheel:"));
     ImGui::PopStyleColor();
     ImGui::SameLine();
-    imgui.text(_(L("Increase/decrease edit area")));
+    imgui.text(_L("Increase/decrease edit area"));
     
     ImGui::Separator();
-    if (imgui.button(_(L("Adaptive"))))
+    if (imgui.button(_L("Adaptive")))
         wxPostEvent((wxEvtHandler*)canvas.get_wxglcanvas(), Event<float>(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, m_adaptive_quality));
 
     ImGui::SameLine();
     float text_align = ImGui::GetCursorPosX();
     ImGui::AlignTextToFramePadding();
-    imgui.text(_(L("Quality / Speed")));
+    imgui.text(_L("Quality / Speed"));
     if (ImGui::IsItemHovered())
     {
         ImGui::BeginTooltip();
-        ImGui::TextUnformatted(_(L("Higher print quality versus higher print speed.")).ToUTF8());
+        ImGui::TextUnformatted(_L("Higher print quality versus higher print speed.").ToUTF8());
         ImGui::EndTooltip();
     }
 
@@ -282,13 +280,13 @@ void GLCanvas3D::LayersEditing::render_overlay(const GLCanvas3D& canvas) const
     ImGui::SliderFloat("", &m_adaptive_quality, 0.0f, 1.f, "%.2f");
 
     ImGui::Separator();
-    if (imgui.button(_(L("Smooth"))))
+    if (imgui.button(_L("Smooth")))
         wxPostEvent((wxEvtHandler*)canvas.get_wxglcanvas(), HeightProfileSmoothEvent(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, m_smooth_params));
 
     ImGui::SameLine();
     ImGui::SetCursorPosX(text_align);
     ImGui::AlignTextToFramePadding();
-    imgui.text(_(L("Radius")));
+    imgui.text(_L("Radius"));
     ImGui::SameLine();
     ImGui::SetCursorPosX(widget_align);
     ImGui::PushItemWidth(imgui.get_style_scaling() * 120.0f);
@@ -298,7 +296,7 @@ void GLCanvas3D::LayersEditing::render_overlay(const GLCanvas3D& canvas) const
 
     ImGui::SetCursorPosX(text_align);
     ImGui::AlignTextToFramePadding();
-    imgui.text(_(L("Keep min")));
+    imgui.text(_L("Keep min"));
     ImGui::SameLine();
     if (ImGui::GetCursorPosX() < widget_align)  // because of line lenght after localization
         ImGui::SetCursorPosX(widget_align);
@@ -307,7 +305,7 @@ void GLCanvas3D::LayersEditing::render_overlay(const GLCanvas3D& canvas) const
     imgui.checkbox("##2", m_smooth_params.keep_min);
 
     ImGui::Separator();
-    if (imgui.button(_(L("Reset"))))
+    if (imgui.button(_L("Reset")))
         wxPostEvent((wxEvtHandler*)canvas.get_wxglcanvas(), SimpleEvent(EVT_GLCANVAS_RESET_LAYER_HEIGHT_PROFILE));
 
     imgui.end();
@@ -3078,8 +3076,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
 #if ENABLE_GCODE_VIEWER
         case 'L':
         case 'l': {
-                    if (!m_main_toolbar.is_enabled())
-                    {
+                    if (!m_main_toolbar.is_enabled()) {
                         m_gcode_viewer.enable_legend(!m_gcode_viewer.is_legend_enabled());
                         m_dirty = true;
                         wxGetApp().plater()->update_preview_bottom_toolbar();
@@ -3090,13 +3087,24 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
         case 'O':
         case 'o': { _update_camera_zoom(-1.0); break; }
 #if ENABLE_RENDER_PICKING_PASS
-        case 'T':
-        case 't': {
+        case 'P':
+        case 'p': {
             m_show_picking_texture = !m_show_picking_texture;
-            m_dirty = true; 
+            m_dirty = true;
             break;
         }
 #endif // ENABLE_RENDER_PICKING_PASS
+#if ENABLE_GCODE_VIEWER
+        case 'T':
+        case 't': {
+            if (!m_main_toolbar.is_enabled()) {
+                m_gcode_viewer.enable_time_estimate(!m_gcode_viewer.is_time_estimate_enabled());
+                m_dirty = true;
+                wxGetApp().plater()->update_preview_bottom_toolbar();
+        }
+            break;
+    }
+#endif // ENABLE_GCODE_VIEWER
         case 'Z':
 #if ENABLE_GCODE_VIEWER
         case 'z':
diff --git a/src/slic3r/GUI/GLShadersManager.cpp b/src/slic3r/GUI/GLShadersManager.cpp
index cb47d7961..e62a81d39 100644
--- a/src/slic3r/GUI/GLShadersManager.cpp
+++ b/src/slic3r/GUI/GLShadersManager.cpp
@@ -69,7 +69,7 @@ GLShaderProgram* GLShadersManager::get_current_shader()
     if (id == 0)
         return nullptr;
 
-    auto it = std::find_if(m_shaders.begin(), m_shaders.end(), [id](std::unique_ptr<GLShaderProgram>& p) { return p->get_id() == id; });
+    auto it = std::find_if(m_shaders.begin(), m_shaders.end(), [id](std::unique_ptr<GLShaderProgram>& p) { return static_cast<GLint>(p->get_id()) == id; });
     return (it != m_shaders.end()) ? it->get() : nullptr;
 }
 
diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp
index 530165001..50a820cfa 100644
--- a/src/slic3r/GUI/GUI_Preview.cpp
+++ b/src/slic3r/GUI/GUI_Preview.cpp
@@ -323,7 +323,8 @@ bool Preview::init(wxWindow* parent, Model* model)
         get_option_type_string(OptionType::CustomGCodes) + "|0|" +
         get_option_type_string(OptionType::Shells) + "|0|" +
         get_option_type_string(OptionType::ToolMarker) + "|0|" +
-        get_option_type_string(OptionType::Legend) + "|1"
+        get_option_type_string(OptionType::Legend) + "|1|" +
+        get_option_type_string(OptionType::TimeEstimate) + "|1"
     );
     Slic3r::GUI::create_combochecklist(m_combochecklist_options, GUI::into_u8(_L("Options")), options_items);
 #else
@@ -1458,10 +1459,10 @@ wxString Preview::get_option_type_string(OptionType type) const
     case OptionType::Shells:        { return _L("Shells"); }
     case OptionType::ToolMarker:    { return _L("Tool marker"); }
     case OptionType::Legend:        { return _L("Legend"); }
+    case OptionType::TimeEstimate:  { return _L("Estimated printing time"); }
     default:                        { return ""; }
     }
 }
-
 #endif // ENABLE_GCODE_VIEWER
 
 } // namespace GUI
diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp
index bf174c2e0..ff3bf4137 100644
--- a/src/slic3r/GUI/GUI_Preview.hpp
+++ b/src/slic3r/GUI/GUI_Preview.hpp
@@ -149,7 +149,8 @@ public:
         CustomGCodes,
         Shells,
         ToolMarker,
-        Legend
+        Legend,
+        TimeEstimate
     };
 
 Preview(wxWindow* parent, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process, 
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp
index cd4285724..9aaded6e3 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp
@@ -650,8 +650,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
         window_width = std::max(window_width, button_width);
 
         auto draw_text_with_caption = [this, &caption_max](const wxString& caption, const wxString& text) {
-            static const ImVec4 ORANGE(1.0f, 0.49f, 0.22f, 1.0f);
-            ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
+            ImGui::PushStyleColor(ImGuiCol_Text, ImGuiWrapper::COL_ORANGE_LIGHT);
             m_imgui->text(caption);
             ImGui::PopStyleColor();
             ImGui::SameLine(caption_max);
diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp
index 51a9a6d4e..2c463dc2a 100644
--- a/src/slic3r/GUI/ImGuiWrapper.cpp
+++ b/src/slic3r/GUI/ImGuiWrapper.cpp
@@ -44,6 +44,12 @@ static const std::map<const char, std::string> font_icons = {
     {ImGui::MaterialIconMarker  , "resin"      }
 };
 
+const ImVec4 ImGuiWrapper::COL_WINDOW_BACKGROND = { 0.133f, 0.133f, 0.133f, 0.8f };
+const ImVec4 ImGuiWrapper::COL_GREY_DARK        = { 0.333f, 0.333f, 0.333f, 1.0f };
+const ImVec4 ImGuiWrapper::COL_GREY_LIGHT       = { 0.4f, 0.4f, 0.4f, 1.0f };
+const ImVec4 ImGuiWrapper::COL_ORANGE_DARK      = { 0.757f, 0.404f, 0.216f, 1.0f };
+const ImVec4 ImGuiWrapper::COL_ORANGE_LIGHT     = { 1.0f, 0.49f, 0.216f, 1.0f };
+
 ImGuiWrapper::ImGuiWrapper()
     : m_glyph_ranges(nullptr)
     , m_font_cjk(false)
@@ -751,6 +757,22 @@ void ImGuiWrapper::search_list(const ImVec2& size_, bool (*items_getter)(int, co
         check_box(_L("Search in English"), view_params.english);
 }
 
+void ImGuiWrapper::title(const std::string& str)
+{
+    ImGuiWindow* window = ImGui::GetCurrentWindow();
+    const float frame_height = ImGui::CalcTextSize(str.c_str(), nullptr, false).y;
+
+    ImRect frame_bb;
+    frame_bb.Min = { window->WorkRect.Min.x, window->DC.CursorPos.y };
+    frame_bb.Max = { window->WorkRect.Max.x, window->DC.CursorPos.y + frame_height };
+
+    frame_bb.Min.x -= IM_FLOOR(window->WindowPadding.x * 0.5f - 1.0f);
+    frame_bb.Max.x += IM_FLOOR(window->WindowPadding.x * 0.5f);
+
+    window->DrawList->AddRectFilled(frame_bb.Min, frame_bb.Max, ImGui::GetColorU32(COL_ORANGE_DARK), 0.0f, 0);
+    text(str);
+}
+
 void ImGuiWrapper::disabled_begin(bool disabled)
 {
     wxCHECK_RET(!m_disabled, "ImGUI: Unbalanced disabled_begin() call");
@@ -970,20 +992,10 @@ void ImGuiWrapper::init_style()
 {
     ImGuiStyle &style = ImGui::GetStyle();
 
-    auto set_color = [&](ImGuiCol_ col, unsigned hex_color) {
-        style.Colors[col] = ImVec4(
-            ((hex_color >> 24) & 0xff) / 255.0f,
-            ((hex_color >> 16) & 0xff) / 255.0f,
-            ((hex_color >> 8) & 0xff) / 255.0f,
-            (hex_color & 0xff) / 255.0f);
+    auto set_color = [&](ImGuiCol_ entity, ImVec4 color) {
+        style.Colors[entity] = color;
     };
 
-    static const unsigned COL_WINDOW_BACKGROND = 0x222222cc;
-    static const unsigned COL_GREY_DARK = 0x555555ff;
-    static const unsigned COL_GREY_LIGHT = 0x666666ff;
-    static const unsigned COL_ORANGE_DARK = 0xc16737ff;
-    static const unsigned COL_ORANGE_LIGHT = 0xff7d38ff;
-
     // Window
     style.WindowRounding = 4.0f;
     set_color(ImGuiCol_WindowBg, COL_WINDOW_BACKGROND);
diff --git a/src/slic3r/GUI/ImGuiWrapper.hpp b/src/slic3r/GUI/ImGuiWrapper.hpp
index bf542e138..f79bd3fbc 100644
--- a/src/slic3r/GUI/ImGuiWrapper.hpp
+++ b/src/slic3r/GUI/ImGuiWrapper.hpp
@@ -80,6 +80,7 @@ public:
     bool undo_redo_list(const ImVec2& size, const bool is_undo, bool (*items_getter)(const bool, int, const char**), int& hovered, int& selected, int& mouse_wheel);
     void search_list(const ImVec2& size, bool (*items_getter)(int, const char** label, const char** tooltip), char* search_str,
                      Search::OptionViewParameters& view_params, int& selected, bool& edited, int& mouse_wheel, bool is_localized);
+    void title(const std::string& str);
 
     void disabled_begin(bool disabled);
     void disabled_end();
@@ -89,6 +90,12 @@ public:
     bool want_text_input() const;
     bool want_any_input() const;
 
+    static const ImVec4 COL_WINDOW_BACKGROND;
+    static const ImVec4 COL_GREY_DARK;
+    static const ImVec4 COL_GREY_LIGHT;
+    static const ImVec4 COL_ORANGE_DARK;
+    static const ImVec4 COL_ORANGE_LIGHT;
+
 private:
     void init_font(bool compress);
     void init_input();
diff --git a/src/slic3r/GUI/KBShortcutsDialog.cpp b/src/slic3r/GUI/KBShortcutsDialog.cpp
index 51ba06ba4..66e5ac487 100644
--- a/src/slic3r/GUI/KBShortcutsDialog.cpp
+++ b/src/slic3r/GUI/KBShortcutsDialog.cpp
@@ -183,7 +183,7 @@ void KBShortcutsDialog::fill_shortcuts()
 #endif // __linux__
 #if ENABLE_RENDER_PICKING_PASS
         // Don't localize debugging texts.
-        { "T", "Toggle picking pass texture rendering on/off" },
+        { "P", "Toggle picking pass texture rendering on/off" },
 #endif // ENABLE_RENDER_PICKING_PASS
     };
 
@@ -203,7 +203,8 @@ void KBShortcutsDialog::fill_shortcuts()
         { L("Arrow Down"), L("Lower Layer") },
         { "U", L("Upper Layer") },
         { "D", L("Lower Layer") },
-        { "L", L("Show/Hide Legend") }
+        { "L", L("Show/Hide Legend") },
+        { "T", L("Show/Hide Estimated printing time") }
     };
 
     m_full_shortcuts.push_back(std::make_pair(_L("Preview"), preview_shortcuts));
diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp
index eba169dc9..59b8e56f3 100644
--- a/src/slic3r/GUI/MainFrame.cpp
+++ b/src/slic3r/GUI/MainFrame.cpp
@@ -355,6 +355,10 @@ void MainFrame::update_layout()
     // Set new settings
     switch (m_layout)
     {
+    case ESettingsLayout::Unknown:
+    {
+        break;
+    }
     case ESettingsLayout::Old:
     {
         m_plater->Reparent(m_tabpanel);
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index 36fa83470..d0b52426c 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -1330,8 +1330,12 @@ void Sidebar::update_sliced_info_sizer()
                 wxString str_color = _L("Color");
                 wxString str_pause = _L("Pause");
 
-                auto fill_labels = [str_color, str_pause](const std::vector<std::pair<CustomGCode::Type, std::string>>& times, 
-                                                          wxString& new_label, wxString& info_text)
+#if ENABLE_GCODE_VIEWER
+                auto fill_labels = [str_color, str_pause](const std::vector<std::pair<CustomGCode::Type, std::pair<std::string, std::string>>>& times,
+#else
+                auto fill_labels = [str_color, str_pause](const std::vector<std::pair<CustomGCode::Type, std::string>>& times,
+#endif // ENABLE_GCODE_VIEWER
+                    wxString& new_label, wxString& info_text)
                 {
                     int color_change_count = 0;
                     for (auto time : times)
@@ -1348,19 +1352,31 @@ void Sidebar::update_sliced_info_sizer()
                         if (i != (int)times.size() - 1 && times[i].first == CustomGCode::PausePrint)
                             new_label += format_wxstr(" -> %1%", str_pause);
 
+#if ENABLE_GCODE_VIEWER
+                        info_text += format_wxstr("\n%1% (%2%)", times[i].second.first, times[i].second.second);
+#else
                         info_text += format_wxstr("\n%1%", times[i].second);
+#endif // ENABLE_GCODE_VIEWER
                     }
                 };
 
                 if (ps.estimated_normal_print_time != "N/A") {
                     new_label += format_wxstr("\n   - %1%", _L("normal mode"));
                     info_text += format_wxstr("\n%1%", ps.estimated_normal_print_time);
+#if ENABLE_GCODE_VIEWER
+                    fill_labels(ps.estimated_normal_custom_gcode_print_times_str, new_label, info_text);
+#else
                     fill_labels(ps.estimated_normal_custom_gcode_print_times, new_label, info_text);
+#endif // ENABLE_GCODE_VIEWER
                 }
                 if (ps.estimated_silent_print_time != "N/A") {
                     new_label += format_wxstr("\n   - %1%", _L("stealth mode"));
                     info_text += format_wxstr("\n%1%", ps.estimated_silent_print_time);
+#if ENABLE_GCODE_VIEWER
+                    fill_labels(ps.estimated_silent_custom_gcode_print_times_str, new_label, info_text);
+#else
                     fill_labels(ps.estimated_silent_custom_gcode_print_times, new_label, info_text);
+#endif // ENABLE_GCODE_VIEWER
                 }
                 p->sliced_info->SetTextAndShow(siEstimatedTime,  info_text,      new_label);
             }
@@ -2709,6 +2725,9 @@ void Plater::priv::reset()
     if (view3D->is_layers_editing_enabled())
         view3D->enable_layers_editing(false);
 
+#if ENABLE_GCODE_VIEWER
+    reset_gcode_toolpaths();
+#endif // ENABLE_GCODE_VIEWER
 #if ENABLE_GCODE_VIEWER_AS_STATE
     gcode_result.reset();
 #endif // ENABLE_GCODE_VIEWER_AS_STATE
@@ -2859,8 +2878,7 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
         // Reset preview canvases. If the print has been invalidated, the preview canvases will be cleared.
         // Otherwise they will be just refreshed.
 #if ENABLE_GCODE_VIEWER
-        if (this->preview != nullptr)
-        {
+        if (this->preview != nullptr) {
             // If the preview is not visible, the following line just invalidates the preview,
             // but the G-code paths or SLA preview are calculated first once the preview is made visible.
             this->preview->get_canvas3d()->reset_gcode_toolpaths();