diff --git a/resources/icons/PrusaSlicer-gcodeviewer_128px.png b/resources/icons/PrusaSlicer-gcodeviewer_128px.png
new file mode 100644
index 000000000..d8e3e438b
Binary files /dev/null and b/resources/icons/PrusaSlicer-gcodeviewer_128px.png differ
diff --git a/resources/icons/PrusaSlicerGCodeViewer_128px.png b/resources/icons/PrusaSlicerGCodeViewer_128px.png
deleted file mode 100644
index 0bf85abbd..000000000
Binary files a/resources/icons/PrusaSlicerGCodeViewer_128px.png and /dev/null differ
diff --git a/resources/icons/splashscreen-gcodeviewer.jpg b/resources/icons/splashscreen-gcodeviewer.jpg
new file mode 100644
index 000000000..f170f390c
Binary files /dev/null and b/resources/icons/splashscreen-gcodeviewer.jpg differ
diff --git a/src/PrusaSlicer.cpp b/src/PrusaSlicer.cpp
index 94996dc92..9874a9d4d 100644
--- a/src/PrusaSlicer.cpp
+++ b/src/PrusaSlicer.cpp
@@ -541,7 +541,11 @@ int CLI::run(int argc, char **argv)
     if (start_gui) {
 #ifdef SLIC3R_GUI
 // #ifdef USE_WX
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+        GUI::GUI_App* gui = new GUI::GUI_App(start_as_gcodeviewer ? GUI::GUI_App::EAppMode::GCodeViewer : GUI::GUI_App::EAppMode::Editor);
+#else
         GUI::GUI_App *gui = new GUI::GUI_App();
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 
 		bool gui_single_instance_setting = gui->app_config->get("single_instance") == "1";
 		if (Slic3r::instance_check(argc, argv, gui_single_instance_setting)) {
diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp
index 8b41bd271..db3bd78dd 100644
--- a/src/libslic3r/AppConfig.cpp
+++ b/src/libslic3r/AppConfig.cpp
@@ -179,6 +179,11 @@ std::string AppConfig::load()
 
 void AppConfig::save()
 {
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    if (!m_save_enabled)
+        return;
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+
     // The config is first written to a file with a PID suffix and then moved
     // to avoid race conditions with multiple instances of Slic3r
     const auto path = config_path();
diff --git a/src/libslic3r/AppConfig.hpp b/src/libslic3r/AppConfig.hpp
index ffd1b9fdf..3f4ce2008 100644
--- a/src/libslic3r/AppConfig.hpp
+++ b/src/libslic3r/AppConfig.hpp
@@ -18,6 +18,9 @@ public:
 	AppConfig() :
 		m_dirty(false),
 		m_orig_version(Semver::invalid()),
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+		m_save_enabled(true),
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 		m_legacy_datadir(false)
 	{
 		this->reset();
@@ -157,6 +160,10 @@ public:
 	bool get_mouse_device_swap_yz(const std::string& name, bool& swap) const
 		{ return get_3dmouse_device_numeric_value(name, "swap_yz", swap); }
 
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+	void enable_save(bool enable) { m_save_enabled = enable; }
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+
 	static const std::string SECTION_FILAMENTS;
     static const std::string SECTION_MATERIALS;
 
@@ -183,6 +190,10 @@ private:
 	bool														m_dirty;
 	// Original version found in the ini file before it was overwritten
 	Semver                                                      m_orig_version;
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+	// Whether or not calls to save() should take effect
+	bool                                                        m_save_enabled;
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 	// Whether the existing version is before system profiles & configuration updating
 	bool                                                        m_legacy_datadir;
 };
diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp
index a0484b259..2dbad472f 100644
--- a/src/libslic3r/Technologies.hpp
+++ b/src/libslic3r/Technologies.hpp
@@ -59,5 +59,6 @@
 #define ENABLE_GCODE_VIEWER_STATISTICS (0 && ENABLE_GCODE_VIEWER)
 #define ENABLE_GCODE_VIEWER_DATA_CHECKING (0 && ENABLE_GCODE_VIEWER)
 #define ENABLE_GCODE_VIEWER_TASKBAR_ICON (0 && ENABLE_GCODE_VIEWER)
+#define ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION (1 && ENABLE_GCODE_VIEWER)
 
 #endif // _prusaslicer_technologies_h_
diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp
index bc424466b..2b9bf8ca4 100644
--- a/src/slic3r/GUI/GCodeViewer.cpp
+++ b/src/slic3r/GUI/GCodeViewer.cpp
@@ -339,7 +339,11 @@ void GCodeViewer::load(const GCodeProcessor::Result& gcode_result, const Print&
     reset();
 
     load_toolpaths(gcode_result);
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    if (wxGetApp().is_editor())
+#else
     if (wxGetApp().mainframe->get_mode() != MainFrame::EMode::GCodeViewer)
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
         load_shells(print, initialized);
     else {
         Pointfs bed_shape;
@@ -875,7 +879,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
 
     for (size_t i = 0; i < m_vertices_count; ++i) {
         const GCodeProcessor::MoveVertex& move = gcode_result.moves[i];
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+        if (wxGetApp().is_gcode_viewer())
+#else
         if (wxGetApp().mainframe->get_mode() == MainFrame::EMode::GCodeViewer)
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
             // for the gcode viewer we need all moves to correctly size the printbed
             m_paths_bounding_box.merge(move.position.cast<double>());
         else {
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index e7f0f094d..2f9f9464c 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -2732,7 +2732,11 @@ static void load_gcode_retractions(const GCodePreviewData::Retraction& retractio
 void GLCanvas3D::load_gcode_preview(const GCodeProcessor::Result& gcode_result)
 {
     m_gcode_viewer.load(gcode_result, *this->fff_print(), m_initialized);
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    if (wxGetApp().is_editor())
+#else
     if (wxGetApp().mainframe->get_mode() != MainFrame::EMode::GCodeViewer)
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
         _show_warning_texture_if_needed(WarningTexture::ToolpathOutside);
 }
 
@@ -4302,7 +4306,11 @@ void GLCanvas3D::update_ui_from_settings()
 #endif // ENABLE_RETINA_GL
 
 #if ENABLE_GCODE_VIEWER
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    if (wxGetApp().is_editor())
+#else
     if (wxGetApp().mainframe != nullptr && wxGetApp().mainframe->get_mode() != MainFrame::EMode::GCodeViewer)
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
         wxGetApp().plater()->get_collapse_toolbar().set_enabled(wxGetApp().app_config->get("show_collapse_button") == "1");
 #else
     bool enable_collapse = wxGetApp().app_config->get("show_collapse_button") == "1";
@@ -5405,7 +5413,11 @@ void GLCanvas3D::_render_background() const
 {
 #if ENABLE_GCODE_VIEWER
     bool use_error_color = false;
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    if (wxGetApp().is_editor()) {
+#else
     if (wxGetApp().mainframe->get_mode() != MainFrame::EMode::GCodeViewer) {
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
         use_error_color = m_dynamic_background_enabled;
         if (!m_volumes.empty())
             use_error_color &= _is_any_volume_outside();
@@ -7134,7 +7146,11 @@ void GLCanvas3D::_show_warning_texture_if_needed(WarningTexture::Warning warning
     if (!m_volumes.empty())
         show = _is_any_volume_outside();
     else {
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+        if (wxGetApp().is_editor()) {
+#else
         if (wxGetApp().mainframe->get_mode() != MainFrame::EMode::GCodeViewer) {
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
             BoundingBoxf3 test_volume = (m_config != nullptr) ? print_volume(*m_config) : BoundingBoxf3();
             const BoundingBoxf3& paths_volume = m_gcode_viewer.get_paths_bounding_box();
             if (test_volume.radius() > 0.0 && paths_volume.radius() > 0.0)
diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp
index 7b6d8c5aa..b313a50eb 100644
--- a/src/slic3r/GUI/GUI_App.cpp
+++ b/src/slic3r/GUI/GUI_App.cpp
@@ -1,3 +1,4 @@
+#include "libslic3r/Technologies.hpp"
 #include "GUI_App.hpp"
 #include "GUI_ObjectList.hpp"
 #include "GUI_ObjectManipulation.hpp"
@@ -434,8 +435,15 @@ static void generic_exception_handle()
 
 IMPLEMENT_APP(GUI_App)
 
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+GUI_App::GUI_App(EAppMode mode)
+#else
 GUI_App::GUI_App()
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
     : wxApp()
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    , m_app_mode(mode)
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
     , m_em_unit(10)
     , m_imgui(new ImGuiWrapper())
     , m_wizard(nullptr)
@@ -491,6 +499,12 @@ void GUI_App::init_app_config()
 	if (!app_config)
 		app_config = new AppConfig();
 
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    if (is_gcode_viewer())
+        // disable config save to avoid to mess it up for the editor
+        app_config->enable_save(false);
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+
 	// load settings
 	app_conf_exists = app_config->exists();
 	if (app_conf_exists) {
@@ -527,18 +541,18 @@ bool GUI_App::on_init_inner()
     wxCHECK_MSG(wxDirExists(resources_dir), false,
         wxString::Format("Resources path does not exist or is not a directory: %s", resources_dir));
 
-     // Enable this to get the default Win32 COMCTRL32 behavior of static boxes.
+    // Enable this to get the default Win32 COMCTRL32 behavior of static boxes.
 //    wxSystemOptions::SetOption("msw.staticbox.optimized-paint", 0);
     // Enable this to disable Windows Vista themes for all wxNotebooks. The themes seem to lead to terrible
     // performance when working on high resolution multi-display setups.
 //    wxSystemOptions::SetOption("msw.notebook.themed-background", 0);
 
 //     Slic3r::debugf "wxWidgets version %s, Wx version %s\n", wxVERSION_STRING, wxVERSION;
-   
+
     std::string msg = Http::tls_global_init();
     std::string ssl_cert_store = app_config->get("tls_accepted_cert_store_location");
     bool ssl_accept = app_config->get("tls_cert_store_accepted") == "yes" && ssl_cert_store == Http::tls_system_cert_store();
-    
+
     if (!msg.empty() && !ssl_accept) {
         wxRichMessageDialog
             dlg(nullptr,
@@ -548,11 +562,11 @@ bool GUI_App::on_init_inner()
         if (dlg.ShowModal() != wxID_YES) return false;
 
         app_config->set("tls_cert_store_accepted",
-                        dlg.IsCheckBoxChecked() ? "yes" : "no");
+            dlg.IsCheckBoxChecked() ? "yes" : "no");
         app_config->set("tls_accepted_cert_store_location",
-                        dlg.IsCheckBoxChecked() ? Http::tls_system_cert_store() : "");
+            dlg.IsCheckBoxChecked() ? Http::tls_system_cert_store() : "");
     }
-    
+
     app_config->set("version", SLIC3R_VERSION);
     app_config->save();
 /*
@@ -564,33 +578,43 @@ bool GUI_App::on_init_inner()
     wxInitAllImageHandlers();
 
     wxBitmap bitmap = create_scaled_bitmap("prusa_slicer_logo", nullptr, 400);
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    wxBitmap bmp(is_editor() ? from_u8(var("splashscreen.jpg")) : from_u8(var("splashscreen-gcodeviewer.jpg")), wxBITMAP_TYPE_JPEG);
+#else
     wxBitmap bmp(from_u8(var("splashscreen.jpg")), wxBITMAP_TYPE_JPEG);
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 
     DecorateSplashScreen(bmp);
 
     SplashScreen* scrn = new SplashScreen(bmp.IsOk() ? bmp : bitmap, wxSPLASH_CENTRE_ON_SCREEN | wxSPLASH_TIMEOUT, 4000, nullptr);
     scrn->SetText(_L("Loading configuration..."));
-    
+
     preset_bundle = new PresetBundle();
-    
+
     // just checking for existence of Slic3r::data_dir is not enough : it may be an empty directory
     // supplied as argument to --datadir; in that case we should still run the wizard
     preset_bundle->setup_directories();
 
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    if (is_editor()) {
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 #ifdef __WXMSW__ 
-    associate_3mf_files();
+        associate_3mf_files();
 #endif // __WXMSW__
 
-    preset_updater = new PresetUpdater();
-    Bind(EVT_SLIC3R_VERSION_ONLINE, [this](const wxCommandEvent &evt) {
-        app_config->set("version_online", into_u8(evt.GetString()));
-        app_config->save();
-		if(this->plater_ != nullptr) {
-			if (*Semver::parse(SLIC3R_VERSION) < * Semver::parse(into_u8(evt.GetString()))) {
-				this->plater_->get_notification_manager()->push_notification(NotificationType::NewAppAviable, *(this->plater_->get_current_canvas3D()));
-			}
-		}
-    });
+        preset_updater = new PresetUpdater();
+        Bind(EVT_SLIC3R_VERSION_ONLINE, [this](const wxCommandEvent& evt) {
+            app_config->set("version_online", into_u8(evt.GetString()));
+            app_config->save();
+            if (this->plater_ != nullptr) {
+                if (*Semver::parse(SLIC3R_VERSION) < *Semver::parse(into_u8(evt.GetString()))) {
+                    this->plater_->get_notification_manager()->push_notification(NotificationType::NewAppAviable, *(this->plater_->get_current_canvas3D()));
+                }
+            }
+            });
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    }
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 
     // initialize label colors and fonts
     init_label_colours();
@@ -618,7 +642,10 @@ bool GUI_App::on_init_inner()
     Slic3r::I18N::set_translate_callback(libslic3r_translate_callback);
 
     // application frame
-    scrn->SetText(_L("Creating settings tabs..."));
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    if (is_editor())
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+        scrn->SetText(_L("Creating settings tabs..."));
 
     mainframe = new MainFrame();
     // hide settings tabs after first Layout
@@ -653,13 +680,20 @@ bool GUI_App::on_init_inner()
         static bool once = true;
         if (once) {
             once = false;
-			check_updates(false);
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+            if (preset_updater != nullptr) {
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+                check_updates(false);
+
+                CallAfter([this] {
+                    config_wizard_startup();
+                    preset_updater->slic3r_update_notify();
+                    preset_updater->sync(preset_bundle);
+                    });
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+            }
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 
-			CallAfter([this] {
-				config_wizard_startup();
-				preset_updater->slic3r_update_notify();
-				preset_updater->sync(preset_bundle);
-				});
 #ifdef _WIN32
 			//sets window property to mainframe so other instances can indentify it
 			OtherInstanceMessageHandler::init_windows_properties(mainframe, m_instance_hash_int);
@@ -667,8 +701,16 @@ bool GUI_App::on_init_inner()
         }
     });
 
-    load_current_presets();
-
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    if (is_gcode_viewer()) {
+        mainframe->update_layout();
+        if (plater_ != nullptr)
+            // ensure the selected technology is ptFFF
+            plater_->set_printer_technology(ptFFF);
+    }
+    else
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+        load_current_presets();
     mainframe->Show(true);
 
     /* Temporary workaround for the correct behavior of the Scrolled sidebar panel:
diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp
index 34114c03c..d63825de3 100644
--- a/src/slic3r/GUI/GUI_App.hpp
+++ b/src/slic3r/GUI/GUI_App.hpp
@@ -94,8 +94,22 @@ static wxString dots("…", wxConvUTF8);
 
 class GUI_App : public wxApp
 {
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+public:
+    enum class EAppMode : unsigned char
+    {
+        Editor,
+        GCodeViewer
+    };
+
+private:
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+
     bool            m_initialized { false };
     bool            app_conf_exists{ false };
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    EAppMode        m_app_mode{ EAppMode::Editor };
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 
     wxColour        m_color_label_modified;
     wxColour        m_color_label_sys;
@@ -125,13 +139,24 @@ class GUI_App : public wxApp
     std::unique_ptr <wxSingleInstanceChecker> m_single_instance_checker;
     std::string m_instance_hash_string;
 	size_t m_instance_hash_int;
+
 public:
     bool            OnInit() override;
     bool            initialized() const { return m_initialized; }
 
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    explicit GUI_App(EAppMode mode = EAppMode::Editor);
+#else
     GUI_App();
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
     ~GUI_App() override;
 
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    EAppMode get_app_mode() const { return m_app_mode; }
+    bool is_editor() const { return m_app_mode == EAppMode::Editor; }
+    bool is_gcode_viewer() const { return m_app_mode == EAppMode::GCodeViewer; }
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+
     static std::string get_gl_info(bool format_as_html, bool extensions);
     wxGLContext* init_glcontext(wxGLCanvas& canvas);
     bool init_opengl();
diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp
index 5dcd26a87..530b3358e 100644
--- a/src/slic3r/GUI/GUI_Preview.cpp
+++ b/src/slic3r/GUI/GUI_Preview.cpp
@@ -1234,7 +1234,11 @@ void Preview::load_print_as_fff(bool keep_z_range)
     }
 
 #if ENABLE_GCODE_VIEWER
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    if (wxGetApp().is_editor() && !has_layers)
+#else
     if (wxGetApp().mainframe->get_mode() != MainFrame::EMode::GCodeViewer && !has_layers)
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 #else
     if (! has_layers)
 #endif // ENABLE_GCODE_VIEWER
diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp
index d9ce44bd6..629766306 100644
--- a/src/slic3r/GUI/GUI_Preview.hpp
+++ b/src/slic3r/GUI/GUI_Preview.hpp
@@ -194,6 +194,9 @@ Preview(wxWindow* parent, Model* model, DynamicPrintConfig* config,
 #if ENABLE_GCODE_VIEWER
     void update_bottom_toolbar();
     void update_moves_slider();
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    void hide_layers_slider();
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 #endif // ENABLE_GCODE_VIEWER
 
 private:
@@ -203,7 +206,9 @@ private:
     void unbind_event_handlers();
 
 #if ENABLE_GCODE_VIEWER
+#if !ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
     void hide_layers_slider();
+#endif // !ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 #else
     void show_hide_ui_elements(const std::string& what);
 
diff --git a/src/slic3r/GUI/KBShortcutsDialog.cpp b/src/slic3r/GUI/KBShortcutsDialog.cpp
index 1eceea22e..632bc48ed 100644
--- a/src/slic3r/GUI/KBShortcutsDialog.cpp
+++ b/src/slic3r/GUI/KBShortcutsDialog.cpp
@@ -95,9 +95,15 @@ void KBShortcutsDialog::fill_shortcuts()
     const std::string& alt = GUI::shortkey_alt_prefix();
 
 #if ENABLE_GCODE_VIEWER
+#if !ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
     bool is_gcode_viewer = wxGetApp().mainframe->get_mode() == MainFrame::EMode::GCodeViewer;
+#endif // !ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    if (wxGetApp().is_editor()) {
+#else
     if (!is_gcode_viewer) {
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 #endif // ENABLE_GCODE_VIEWER
         Shortcuts commands_shortcuts = {
             // File
diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp
index f4d7f03ec..5e3fe4cde 100644
--- a/src/slic3r/GUI/MainFrame.cpp
+++ b/src/slic3r/GUI/MainFrame.cpp
@@ -86,7 +86,6 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
     }
 #endif // ENABLE_GCODE_VIEWER_TASKBAR_ICON
 
-//    SetIcon(wxIcon(Slic3r::var("PrusaSlicer_128px.png"), wxBITMAP_TYPE_PNG));
     // Load the icon either from the exe, or from the ico file.
 #if _WIN32
     {
@@ -96,7 +95,24 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
         SetIcon(wxIcon(szExeFileName, wxBITMAP_TYPE_ICO));
     }
 #else
-    SetIcon(wxIcon(Slic3r::var("PrusaSlicer_128px.png"), wxBITMAP_TYPE_PNG));
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    switch (wxGetApp().get_app_mode())
+    {
+    default:
+    case GUI_App::EAppMode::Editor:
+    {
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+        SetIcon(wxIcon(Slic3r::var("PrusaSlicer_128px.png"), wxBITMAP_TYPE_PNG));
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+        break;
+    }
+    case GUI_App::EAppMode::GCodeViewer:
+    {
+        SetIcon(wxIcon(Slic3r::var("PrusaSlicer-gcodeviewer_128px.png"), wxBITMAP_TYPE_PNG));
+        break;
+    }
+    }
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 #endif // _WIN32
 
 	// initialize status bar
@@ -110,8 +126,15 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
     // initialize tabpanel and menubar
     init_tabpanel();
 #if ENABLE_GCODE_VIEWER
-    init_editor_menubar();
-    init_gcodeviewer_menubar();
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    if (wxGetApp().is_gcode_viewer())
+        init_menubar_as_gcodeviewer();
+    else
+        init_menubar_as_editor();
+#else
+    init_menubar_as_editor();
+    init_menubar_as_gcodeviewer();
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 
 #if _WIN32
     // This is needed on Windows to fake the CTRL+# of the window menu when using the numpad
@@ -142,7 +165,10 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
     sizer->Add(m_main_sizer, 1, wxEXPAND);
     SetSizer(sizer);
     // initialize layout from config
-    update_layout();
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    if (wxGetApp().is_editor())
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+        update_layout();
     sizer->SetSizeHints(this);
     Fit();
 
@@ -294,10 +320,17 @@ void MainFrame::update_layout()
     };
 
 #if ENABLE_GCODE_VIEWER
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    ESettingsLayout layout = wxGetApp().is_gcode_viewer() ? ESettingsLayout::GCodeViewer :
+        (wxGetApp().app_config->get("old_settings_layout_mode") == "1" ? ESettingsLayout::Old :
+            wxGetApp().app_config->get("new_settings_layout_mode") == "1" ? ESettingsLayout::New :
+            wxGetApp().app_config->get("dlg_settings_layout_mode") == "1" ? ESettingsLayout::Dlg : ESettingsLayout::Old);
+#else
     ESettingsLayout layout = (m_mode == EMode::GCodeViewer) ? ESettingsLayout::GCodeViewer :
         (wxGetApp().app_config->get("old_settings_layout_mode") == "1" ? ESettingsLayout::Old :
          wxGetApp().app_config->get("new_settings_layout_mode") == "1" ? ESettingsLayout::New :
          wxGetApp().app_config->get("dlg_settings_layout_mode") == "1" ? ESettingsLayout::Dlg : ESettingsLayout::Old);
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 #else
     ESettingsLayout layout = wxGetApp().app_config->get("old_settings_layout_mode") == "1" ? ESettingsLayout::Old :
         wxGetApp().app_config->get("new_settings_layout_mode") == "1" ? ESettingsLayout::New :
@@ -369,6 +402,12 @@ void MainFrame::update_layout()
     case ESettingsLayout::GCodeViewer:
     {
         m_main_sizer->Add(m_plater, 1, wxEXPAND);
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+        m_plater->set_bed_shape({ { 0.0, 0.0 }, { 200.0, 0.0 }, { 200.0, 200.0 }, { 0.0, 200.0 } }, "", "", true);
+        m_plater->enable_view_toolbar(false);
+        m_plater->get_collapse_toolbar().set_enabled(false);
+        m_plater->collapse_sidebar(true);
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
         m_plater->Show();
         break;
     }
@@ -476,6 +515,7 @@ void MainFrame::shutdown()
 
     if (m_plater != nullptr) {
 #if ENABLE_GCODE_VIEWER
+#if !ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
         // restore sidebar if it was hidden when switching to gcode viewer mode
         if (m_restore_from_gcode_viewer.collapsed_sidebar)
             m_plater->collapse_sidebar(false);
@@ -483,6 +523,7 @@ void MainFrame::shutdown()
         // restore sla printer if it was deselected when switching to gcode viewer mode
         if (m_restore_from_gcode_viewer.sla_technology)
             m_plater->set_printer_technology(ptSLA);
+#endif // !ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 #endif // ENABLE_GCODE_VIEWER
         // Stop the background thread (Windows and Linux).
         // Disconnect from a 3DConnextion driver (OSX).
@@ -584,7 +625,10 @@ void MainFrame::init_tabpanel()
     // or when the preset's "modified" status changes.
     Bind(EVT_TAB_PRESETS_CHANGED, &MainFrame::on_presets_changed, this); // #ys_FIXME_to_delete
 
-    create_preset_tabs();
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    if (wxGetApp().is_editor())
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+        create_preset_tabs();
 
     if (m_plater) {
         // load initial config
@@ -885,7 +929,7 @@ static void add_common_view_menu_items(wxMenu* view_menu, MainFrame* mainFrame,
         "", nullptr, [can_change_view]() { return can_change_view(); }, mainFrame);
 }
 
-void MainFrame::init_editor_menubar()
+void MainFrame::init_menubar_as_editor()
 #else
 void MainFrame::init_menubar()
 #endif // ENABLE_GCODE_VIEWER
@@ -1050,6 +1094,7 @@ void MainFrame::init_menubar()
             [this]() { return true; }, this);
         fileMenu->AppendSeparator();
 #if ENABLE_GCODE_VIEWER
+#if !ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
         append_menu_item(fileMenu, wxID_ANY, _L("&G-code preview"), _L("Switch to G-code preview mode"),
             [this](wxCommandEvent&) {
                 if (m_plater->model().objects.empty() ||
@@ -1057,6 +1102,7 @@ void MainFrame::init_menubar()
                         wxString(SLIC3R_APP_NAME) + " - " + _L("Switch to G-code preview mode"), wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION | wxCENTRE).ShowModal() == wxID_YES)
                     set_mode(EMode::GCodeViewer);
             }, "", nullptr);
+#endif // !ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 #endif // ENABLE_GCODE_VIEWER
         append_menu_item(fileMenu, wxID_ANY, _L("&G-code preview") + dots, _L("Open G-code viewer"),
             [this](wxCommandEvent&) { start_new_gcodeviewer_open_file(this); }, "", nullptr);
@@ -1273,6 +1319,17 @@ void MainFrame::init_menubar()
     // assign menubar to frame after appending items, otherwise special items
     // will not be handled correctly
 #if ENABLE_GCODE_VIEWER
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    m_menubar = new wxMenuBar();
+    m_menubar->Append(fileMenu, _L("&File"));
+    if (editMenu) m_menubar->Append(editMenu, _L("&Edit"));
+    m_menubar->Append(windowMenu, _L("&Window"));
+    if (viewMenu) m_menubar->Append(viewMenu, _L("&View"));
+    // Add additional menus from C++
+    wxGetApp().add_config_menu(m_menubar);
+    m_menubar->Append(helpMenu, _L("&Help"));
+    SetMenuBar(m_menubar);
+#else
     m_editor_menubar = new wxMenuBar();
     m_editor_menubar->Append(fileMenu, _L("&File"));
     if (editMenu) m_editor_menubar->Append(editMenu, _L("&Edit"));
@@ -1282,15 +1339,16 @@ void MainFrame::init_menubar()
     wxGetApp().add_config_menu(m_editor_menubar);
     m_editor_menubar->Append(helpMenu, _L("&Help"));
     SetMenuBar(m_editor_menubar);
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 #else
     auto menubar = new wxMenuBar();
-    menubar->Append(fileMenu, _(L("&File")));
-    if (editMenu) menubar->Append(editMenu, _(L("&Edit")));
-    menubar->Append(windowMenu, _(L("&Window")));
-    if (viewMenu) menubar->Append(viewMenu, _(L("&View")));
+    menubar->Append(fileMenu, _L("&File"));
+    if (editMenu) menubar->Append(editMenu, _L("&Edit"));
+    menubar->Append(windowMenu, _L("&Window"));
+    if (viewMenu) menubar->Append(viewMenu, _L("&View"));
     // Add additional menus from C++
     wxGetApp().add_config_menu(menubar);
-    menubar->Append(helpMenu, _(L("&Help")));
+    menubar->Append(helpMenu, _L("&Help"));
     SetMenuBar(menubar);
 #endif // ENABLE_GCODE_VIEWER
 
@@ -1298,7 +1356,11 @@ void MainFrame::init_menubar()
     // This fixes a bug on Mac OS where the quit command doesn't emit window close events
     // wx bug: https://trac.wxwidgets.org/ticket/18328
 #if ENABLE_GCODE_VIEWER
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    wxMenu* apple_menu = m_menubar->OSXGetAppleMenu();
+#else
     wxMenu* apple_menu = m_editor_menubar->OSXGetAppleMenu();
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 #else
     wxMenu *apple_menu = menubar->OSXGetAppleMenu();
 #endif // ENABLE_GCODE_VIEWER
@@ -1307,18 +1369,14 @@ void MainFrame::init_menubar()
             Close();
         }, wxID_EXIT);
     }
-#endif
+#endif // __APPLE__
 
     if (plater()->printer_technology() == ptSLA)
-#if ENABLE_GCODE_VIEWER
-        update_editor_menubar();
-#else
         update_menubar();
-#endif // ENABLE_GCODE_VIEWER
 }
 
 #if ENABLE_GCODE_VIEWER
-void MainFrame::init_gcodeviewer_menubar()
+void MainFrame::init_menubar_as_gcodeviewer()
 {
     wxMenu* fileMenu = new wxMenu;
     {
@@ -1329,9 +1387,11 @@ void MainFrame::init_gcodeviewer_menubar()
         append_menu_item(fileMenu, wxID_ANY, _L("Export &toolpaths as OBJ") + dots, _L("Export toolpaths as OBJ"),
             [this](wxCommandEvent&) { if (m_plater != nullptr) m_plater->export_toolpaths_to_obj(); }, "export_plater", nullptr,
             [this]() {return can_export_toolpaths(); }, this);
+#if !ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
         fileMenu->AppendSeparator();
         append_menu_item(fileMenu, wxID_ANY, _L("Exit &G-code preview"), _L("Switch to editor mode"),
             [this](wxCommandEvent&) { set_mode(EMode::Editor); });
+#endif // !ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
         fileMenu->AppendSeparator();
         append_menu_item(fileMenu, wxID_EXIT, _L("&Quit"), wxString::Format(_L("Quit %s"), SLIC3R_APP_NAME),
             [this](wxCommandEvent&) { Close(false); });
@@ -1347,13 +1407,37 @@ void MainFrame::init_gcodeviewer_menubar()
     // helpmenu
     auto helpMenu = generate_help_menu();
 
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    m_menubar = new wxMenuBar();
+    m_menubar->Append(fileMenu, _L("&File"));
+    if (viewMenu != nullptr) m_menubar->Append(viewMenu, _L("&View"));
+    m_menubar->Append(helpMenu, _L("&Help"));
+    SetMenuBar(m_menubar);
+#else
     m_gcodeviewer_menubar = new wxMenuBar();
     m_gcodeviewer_menubar->Append(fileMenu, _L("&File"));
-    if ((viewMenu != nullptr))
+    if (viewMenu != nullptr)
         m_gcodeviewer_menubar->Append(viewMenu, _L("&View"));
     m_gcodeviewer_menubar->Append(helpMenu, _L("&Help"));
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+
+#ifdef __APPLE__
+    // This fixes a bug on Mac OS where the quit command doesn't emit window close events
+    // wx bug: https://trac.wxwidgets.org/ticket/18328
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    wxMenu* apple_menu = m_menubar->OSXGetAppleMenu();
+#else
+    wxMenu* apple_menu = m_gcodeviewer_menubar->OSXGetAppleMenu();
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    if (apple_menu != nullptr) {
+        apple_menu->Bind(wxEVT_MENU, [this](wxCommandEvent&) {
+            Close();
+            }, wxID_EXIT);
+    }
+#endif // __APPLE__
 }
 
+#if !ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 void MainFrame::set_mode(EMode mode)
 {
     if (m_mode == mode)
@@ -1419,7 +1503,7 @@ void MainFrame::set_mode(EMode mode)
             TCHAR szExeFileName[MAX_PATH];
             GetModuleFileName(nullptr, szExeFileName, MAX_PATH);
             SetIcon(wxIcon(szExeFileName, wxBITMAP_TYPE_ICO));
-    }
+        }
 #else
         SetIcon(wxIcon(Slic3r::var("PrusaSlicer_128px.png"), wxBITMAP_TYPE_PNG));
 #endif // _WIN32
@@ -1475,11 +1559,11 @@ void MainFrame::set_mode(EMode mode)
 
         m_plater->Thaw();
 
-        SetIcon(wxIcon(Slic3r::var("PrusaSlicerGCodeViewer_128px.png"), wxBITMAP_TYPE_PNG));
+        SetIcon(wxIcon(Slic3r::var("PrusaSlicer-gcodeviewer_128px.png"), wxBITMAP_TYPE_PNG));
 #if ENABLE_GCODE_VIEWER_TASKBAR_ICON
         if (m_taskbar_icon != nullptr) {
             m_taskbar_icon->RemoveIcon();
-            m_taskbar_icon->SetIcon(wxIcon(Slic3r::var("PrusaSlicerGCodeViewer_128px.png"), wxBITMAP_TYPE_PNG), "PrusaSlicer-GCode viewer");
+            m_taskbar_icon->SetIcon(wxIcon(Slic3r::var("PrusaSlicer-gcodeviewer_128px.png"), wxBITMAP_TYPE_PNG), "PrusaSlicer-GCode viewer");
         }
 #endif // ENABLE_GCODE_VIEWER_TASKBAR_ICON
 
@@ -1487,20 +1571,22 @@ void MainFrame::set_mode(EMode mode)
     }
     }
 }
+#endif // !ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 #endif // ENABLE_GCODE_VIEWER
 
-#if ENABLE_GCODE_VIEWER
-void MainFrame::update_editor_menubar()
-#else
 void MainFrame::update_menubar()
-#endif // ENABLE_GCODE_VIEWER
 {
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    if (wxGetApp().is_gcode_viewer())
+        return;
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+
     const bool is_fff = plater()->printer_technology() == ptFFF;
 
-    m_changeable_menu_items[miExport]       ->SetItemLabel((is_fff ? _(L("Export &G-code"))         : _(L("E&xport"))       ) + dots     + "\tCtrl+G");
-    m_changeable_menu_items[miSend]         ->SetItemLabel((is_fff ? _(L("S&end G-code"))           : _(L("S&end to print"))) + dots    + "\tCtrl+Shift+G");
+    m_changeable_menu_items[miExport]       ->SetItemLabel((is_fff ? _L("Export &G-code")         : _L("E&xport"))        + dots    + "\tCtrl+G");
+    m_changeable_menu_items[miSend]         ->SetItemLabel((is_fff ? _L("S&end G-code")           : _L("S&end to print")) + dots    + "\tCtrl+Shift+G");
 
-    m_changeable_menu_items[miMaterialTab]  ->SetItemLabel((is_fff ? _(L("&Filament Settings Tab")) : _(L("Mate&rial Settings Tab")))   + "\tCtrl+3");
+    m_changeable_menu_items[miMaterialTab]  ->SetItemLabel((is_fff ? _L("&Filament Settings Tab") : _L("Mate&rial Settings Tab"))   + "\tCtrl+3");
     m_changeable_menu_items[miMaterialTab]  ->SetBitmap(create_scaled_bitmap(is_fff ? "spool"   : "resin"));
 
     m_changeable_menu_items[miPrinterTab]   ->SetBitmap(create_scaled_bitmap(is_fff ? "printer" : "sla_printer"));
@@ -1983,6 +2069,11 @@ SettingsDialog::SettingsDialog(MainFrame* mainframe)
         wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMINIMIZE_BOX | wxMAXIMIZE_BOX, "settings_dialog"),
     m_main_frame(mainframe)
 {
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    if (wxGetApp().is_gcode_viewer())
+        return;
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+
 #if ENABLE_WX_3_1_3_DPI_CHANGED_EVENT && defined(__WXMSW__)
     // ys_FIXME! temporary workaround for correct font scaling
     // Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts,
@@ -1993,8 +2084,6 @@ SettingsDialog::SettingsDialog(MainFrame* mainframe)
 #endif // ENABLE_WX_3_1_3_DPI_CHANGED_EVENT
     this->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
 
-
-//    SetIcon(wxIcon(Slic3r::var("PrusaSlicer_128px.png"), wxBITMAP_TYPE_PNG));
     // Load the icon either from the exe, or from the ico file.
 #if _WIN32
     {
@@ -2057,6 +2146,11 @@ SettingsDialog::SettingsDialog(MainFrame* mainframe)
 
 void SettingsDialog::on_dpi_changed(const wxRect& suggested_rect)
 {
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    if (wxGetApp().is_gcode_viewer())
+        return;
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+
     const int& em = em_unit();
     const wxSize& size = wxSize(85 * em, 50 * em);
 
diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp
index 7777a053d..867e11e86 100644
--- a/src/slic3r/GUI/MainFrame.hpp
+++ b/src/slic3r/GUI/MainFrame.hpp
@@ -57,7 +57,7 @@ class SettingsDialog : public DPIDialog
     MainFrame*  m_main_frame { nullptr };
 public:
     SettingsDialog(MainFrame* mainframe);
-    ~SettingsDialog() {}
+    ~SettingsDialog() = default;
     void set_tabpanel(wxNotebook* tabpanel) { m_tabpanel = tabpanel; }
 
 protected:
@@ -72,6 +72,9 @@ class MainFrame : public DPIFrame
     wxString    m_qs_last_output_file = wxEmptyString;
     wxString    m_last_config = wxEmptyString;
 #if ENABLE_GCODE_VIEWER
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    wxMenuBar* m_menubar{ nullptr };
+#else
     wxMenuBar* m_editor_menubar{ nullptr };
     wxMenuBar* m_gcodeviewer_menubar{ nullptr };
 
@@ -83,6 +86,7 @@ class MainFrame : public DPIFrame
     };
 
     RestoreFromGCodeViewer m_restore_from_gcode_viewer;
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 #endif // ENABLE_GCODE_VIEWER
 
 #if 0
@@ -146,6 +150,7 @@ class MainFrame : public DPIFrame
     ESettingsLayout m_layout{ ESettingsLayout::Unknown };
 
 #if ENABLE_GCODE_VIEWER
+#if !ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 public:
     enum class EMode : unsigned char
     {
@@ -155,6 +160,7 @@ public:
 
 private:
     EMode m_mode{ EMode::Editor };
+#endif // !ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 #endif // ENABLE_GCODE_VIEWER
 
 protected:
@@ -182,16 +188,17 @@ public:
     void        create_preset_tabs();
     void        add_created_tab(Tab* panel);
 #if ENABLE_GCODE_VIEWER
-    void        init_editor_menubar();
-    void        update_editor_menubar();
-    void        init_gcodeviewer_menubar();
+    void        init_menubar_as_editor();
+    void        init_menubar_as_gcodeviewer();
 
+#if !ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
     EMode       get_mode() const { return m_mode; }
     void        set_mode(EMode mode);
+#endif // !ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 #else
     void        init_menubar();
-    void        update_menubar();
 #endif // ENABLE_GCODE_VIEWER
+    void        update_menubar();
 
     void        update_ui_from_settings();
     bool        is_loaded() const { return m_loaded; }
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index 3a4c31ebd..061084f57 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -1369,41 +1369,52 @@ bool PlaterDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &fi
     this->MSWUpdateDragImageOnLeave();
 #endif // WIN32
 
-    // gcode section
-    for (const auto& filename : filenames) {
-        fs::path path(into_path(filename));
-        if (std::regex_match(path.string(), pattern_gcode_drop))
-            paths.push_back(std::move(path));
-    }
-
-    if (paths.size() > 1) {
-        wxMessageDialog((wxWindow*)plater, _L("You can open only one .gcode file at a time."),
-            wxString(SLIC3R_APP_NAME) + " - " + _L("Drag and drop G-code file"), wxCLOSE | wxICON_WARNING | wxCENTRE).ShowModal();
-        return false;
-    }
-    else if (paths.size() == 1) {
-        if (wxGetApp().mainframe->get_mode() == MainFrame::EMode::GCodeViewer) {
-            plater->load_gcode(from_path(paths.front()));
-            return true;
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    if (wxGetApp().is_gcode_viewer()) {
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+        // gcode section
+        for (const auto& filename : filenames) {
+            fs::path path(into_path(filename));
+            if (std::regex_match(path.string(), pattern_gcode_drop))
+                paths.push_back(std::move(path));
         }
-        else {
-            if (wxMessageDialog((wxWindow*)plater, _L("Do you want to switch to G-code preview ?"),
-                wxString(SLIC3R_APP_NAME) + " - " + _L("Drag and drop G-code file"), wxYES_NO | wxICON_QUESTION | wxYES_DEFAULT | wxCENTRE).ShowModal() == wxID_YES) {
 
-                if (plater->model().objects.empty() ||
-                    wxMessageDialog((wxWindow*)plater, _L("Switching to G-code preview mode will remove all objects, continue?"),
-                        wxString(SLIC3R_APP_NAME) + " - " + _L("Switch to G-code preview mode"), wxYES_NO | wxICON_QUESTION | wxYES_DEFAULT | wxCENTRE).ShowModal() == wxID_YES) {
-                    wxGetApp().mainframe->set_mode(MainFrame::EMode::GCodeViewer);
-                    plater->load_gcode(from_path(paths.front()));
-                    return true;
-                }
-            }
+        if (paths.size() > 1) {
+            wxMessageDialog((wxWindow*)plater, _L("You can open only one .gcode file at a time."),
+                wxString(SLIC3R_APP_NAME) + " - " + _L("Drag and drop G-code file"), wxCLOSE | wxICON_WARNING | wxCENTRE).ShowModal();
             return false;
         }
+        else if (paths.size() == 1) {
+#if !ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+            if (wxGetApp().mainframe->get_mode() == MainFrame::EMode::GCodeViewer) {
+#endif // !ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+                plater->load_gcode(from_path(paths.front()));
+                return true;
+#if !ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+            }
+            else {
+                if (wxMessageDialog((wxWindow*)plater, _L("Do you want to switch to G-code preview ?"),
+                    wxString(SLIC3R_APP_NAME) + " - " + _L("Drag and drop G-code file"), wxYES_NO | wxICON_QUESTION | wxYES_DEFAULT | wxCENTRE).ShowModal() == wxID_YES) {
+
+                    if (plater->model().objects.empty() ||
+                        wxMessageDialog((wxWindow*)plater, _L("Switching to G-code preview mode will remove all objects, continue?"),
+                            wxString(SLIC3R_APP_NAME) + " - " + _L("Switch to G-code preview mode"), wxYES_NO | wxICON_QUESTION | wxYES_DEFAULT | wxCENTRE).ShowModal() == wxID_YES) {
+                        wxGetApp().mainframe->set_mode(MainFrame::EMode::GCodeViewer);
+                        plater->load_gcode(from_path(paths.front()));
+                        return true;
+                    }
+                }
+                return false;
+            }
+#endif // !ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+        }
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+        return false;
     }
+#endif //ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 #endif // ENABLE_GCODE_VIEWER
 
-    // model section
+    // editor section
     for (const auto &filename : filenames) {
         fs::path path(into_path(filename));
         if (std::regex_match(path.string(), pattern_drop))
@@ -1413,6 +1424,7 @@ bool PlaterDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &fi
     }
 
 #if ENABLE_GCODE_VIEWER
+#if !ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
     if (wxGetApp().mainframe->get_mode() == MainFrame::EMode::GCodeViewer) {
         if (wxMessageDialog((wxWindow*)plater, _L("Do you want to exit G-code preview ?"),
             wxString(SLIC3R_APP_NAME) + " - " + _L("Drag and drop model file"), wxYES_NO | wxICON_QUESTION | wxYES_DEFAULT | wxCENTRE).ShowModal() == wxID_YES)
@@ -1420,6 +1432,7 @@ bool PlaterDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &fi
         else
             return false;
     }
+#endif // !ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 #endif // ENABLE_GCODE_VIEWER
 
     wxString snapshot_label;
@@ -1970,7 +1983,13 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
     q->SetDropTarget(new PlaterDropTarget(q));   // if my understanding is right, wxWindow takes the owenership
     q->Layout();
 
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    set_current_panel(wxGetApp().is_editor() ? (wxPanel*)view3D : (wxPanel*)preview);
+    if (wxGetApp().is_gcode_viewer())
+        preview->hide_layers_slider();
+#else
     set_current_panel(view3D);
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 
     // updates camera type from .ini file
     camera.set_type(get_config("use_perspective_camera"));
@@ -1990,33 +2009,38 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
 #endif /* _WIN32 */
 
 	notification_manager = new NotificationManager(this->q);
-	this->q->Bind(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED, [this](EjectDriveNotificationClickedEvent&) { this->q->eject_drive(); });
-	this->q->Bind(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED, [this](ExportGcodeNotificationClickedEvent&) { this->q->export_gcode(true); });
-	this->q->Bind(EVT_PRESET_UPDATE_AVIABLE_CLICKED, [this](PresetUpdateAviableClickedEvent&) {  wxGetApp().get_preset_updater()->on_update_notification_confirm(); });
-
-	this->q->Bind(EVT_REMOVABLE_DRIVE_EJECTED, [this, q](RemovableDriveEjectEvent &evt) {
-		if (evt.data.second) {
-			this->show_action_buttons(this->ready_to_slice);
-			notification_manager->push_notification(format(_L("Unmounting successful. The device %s(%s) can now be safely removed from the computer."),evt.data.first.name, evt.data.first.path),
-				                                    NotificationManager::NotificationLevel::RegularNotification, *q->get_current_canvas3D());
-		} else {
-			notification_manager->push_notification(format(_L("Ejecting of device %s(%s) has failed."), evt.data.first.name, evt.data.first.path),
-				                                    NotificationManager::NotificationLevel::ErrorNotification, *q->get_current_canvas3D());
-		}
-	});
-    this->q->Bind(EVT_REMOVABLE_DRIVES_CHANGED, [this, q](RemovableDrivesChangedEvent &) {
-		this->show_action_buttons(this->ready_to_slice); 
-		if (!this->sidebar->get_eject_shown()) {
-			notification_manager->close_notification_of_type(NotificationType::ExportToRemovableFinished);
-		}
-	});
-    // Start the background thread and register this window as a target for update events.
-    wxGetApp().removable_drive_manager()->init(this->q);
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    if (wxGetApp().is_editor()) {
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+        this->q->Bind(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED, [this](EjectDriveNotificationClickedEvent&) { this->q->eject_drive(); });
+        this->q->Bind(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED, [this](ExportGcodeNotificationClickedEvent&) { this->q->export_gcode(true); });
+        this->q->Bind(EVT_PRESET_UPDATE_AVIABLE_CLICKED, [this](PresetUpdateAviableClickedEvent&) {  wxGetApp().get_preset_updater()->on_update_notification_confirm(); });
+	    this->q->Bind(EVT_REMOVABLE_DRIVE_EJECTED, [this, q](RemovableDriveEjectEvent &evt) {
+		    if (evt.data.second) {
+			    this->show_action_buttons(this->ready_to_slice);
+			    notification_manager->push_notification(format(_L("Unmounting successful. The device %s(%s) can now be safely removed from the computer."),evt.data.first.name, evt.data.first.path),
+				                                        NotificationManager::NotificationLevel::RegularNotification, *q->get_current_canvas3D());
+		    } else {
+			    notification_manager->push_notification(format(_L("Ejecting of device %s(%s) has failed."), evt.data.first.name, evt.data.first.path),
+				                                        NotificationManager::NotificationLevel::ErrorNotification, *q->get_current_canvas3D());
+		    }
+	    });
+        this->q->Bind(EVT_REMOVABLE_DRIVES_CHANGED, [this, q](RemovableDrivesChangedEvent &) {
+		    this->show_action_buttons(this->ready_to_slice); 
+		    if (!this->sidebar->get_eject_shown()) {
+			    notification_manager->close_notification_of_type(NotificationType::ExportToRemovableFinished);
+		    }
+	    });
+        // Start the background thread and register this window as a target for update events.
+        wxGetApp().removable_drive_manager()->init(this->q);
 #ifdef _WIN32
-    // Trigger enumeration of removable media on Win32 notification.
-    this->q->Bind(EVT_VOLUME_ATTACHED, [this](VolumeAttachedEvent &evt) { wxGetApp().removable_drive_manager()->volumes_changed(); });
-    this->q->Bind(EVT_VOLUME_DETACHED, [this](VolumeDetachedEvent &evt) { wxGetApp().removable_drive_manager()->volumes_changed(); });
+        // Trigger enumeration of removable media on Win32 notification.
+        this->q->Bind(EVT_VOLUME_ATTACHED, [this](VolumeAttachedEvent &evt) { wxGetApp().removable_drive_manager()->volumes_changed(); });
+        this->q->Bind(EVT_VOLUME_DETACHED, [this](VolumeDetachedEvent &evt) { wxGetApp().removable_drive_manager()->volumes_changed(); });
 #endif /* _WIN32 */
+#if ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
+    }
+#endif // ENABLE_GCODE_VIEWER_AS_STANDALONE_APPLICATION
 
     // Initialize the Undo / Redo stack with a first snapshot.
     this->take_snapshot(_L("New Project"));
@@ -5629,11 +5653,7 @@ void Plater::set_printer_technology(PrinterTechnology printer_technology)
     p->label_btn_send   = printer_technology == ptFFF ? L("Send G-code")   : L("Send to printer");
 
     if (wxGetApp().mainframe != nullptr)
-#if ENABLE_GCODE_VIEWER
-        wxGetApp().mainframe->update_editor_menubar();
-#else
         wxGetApp().mainframe->update_menubar();
-#endif // ENABLE_GCODE_VIEWER
 
     p->update_main_toolbar_tooltips();