diff --git a/src/libslic3r/PrintExport.hpp b/src/libslic3r/PrintExport.hpp
index 1b5efcea1..cdb2cc008 100644
--- a/src/libslic3r/PrintExport.hpp
+++ b/src/libslic3r/PrintExport.hpp
@@ -80,9 +80,8 @@ public:
 // Provokes static_assert in the right way.
 template<class T = void> struct VeryFalse { static const bool value = false; };
 
-// This has to be explicitly implemented in the gui layer or a default zlib
-// based implementation is needed. I don't have time for that and I'm delegating
-// the implementation to the gui layer where the gui toolkit can cover this.
+// This can be explicitly implemented in the gui layer or the default Zipper
+// API in libslic3r with minz.
 template<class Fmt> class LayerWriter {
 public:
 
@@ -91,21 +90,28 @@ public:
                       "No layer writer implementation provided!");
     }
 
+    // Should create a new file within the zip with the given filename. It
+    // should also finish any previous entry.
     void next_entry(const std::string& /*fname*/) {}
 
-    // binary entry
+    // Should create a new file within the archive and write the provided data.
     void binary_entry(const std::string& /*fname*/,
                       const std::uint8_t* buf, size_t len);
 
+    // Get the name of the archive but only the name part without the path or
+    // the extension.
     std::string get_name() { return ""; }
 
+    // Test whether the object can still be used for writing.
     bool is_ok() { return false; }
 
+    // Write some data (text) into the current file (entry) within the archive.
     template<class T> LayerWriter& operator<<(T&& /*arg*/) {
         return *this;
     }
 
-    void close() {}
+    // Flush the current entry into the archive.
+    void finalize() {}
 };
 
 // Implementation for PNG raster output
@@ -267,7 +273,7 @@ public:
                 }
             }
 
-            writer.close();
+            writer.finalize();
         } catch(std::exception& e) {
             BOOST_LOG_TRIVIAL(error) << e.what();
             // Rethrow the exception
diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp
index 454f5870f..d831908c7 100644
--- a/src/libslic3r/SLAPrint.hpp
+++ b/src/libslic3r/SLAPrint.hpp
@@ -322,18 +322,18 @@ template<> class LayerWriter<SLAminzZipper> {
     Zipper m_zip;
 public:
 
-    inline LayerWriter(const std::string& zipfile_path): m_zip(zipfile_path) {}
+    LayerWriter(const std::string& zipfile_path): m_zip(zipfile_path) {}
 
-    inline void next_entry(const std::string& fname) { m_zip.add_entry(fname); }
+    void next_entry(const std::string& fname) { m_zip.add_entry(fname); }
 
-    inline void binary_entry(const std::string& fname,
+    void binary_entry(const std::string& fname,
                              const std::uint8_t* buf,
                              size_t l)
     {
         m_zip.add_entry(fname, buf, l);
     }
 
-    inline std::string get_name() const {
+    std::string get_name() const {
         return m_zip.get_name();
     }
 
@@ -345,7 +345,11 @@ public:
         return true; // m_zip blows up if something goes wrong...
     }
 
-    inline void close() { m_zip.close(); }
+    // After finalize, no writing to the archive will have an effect. The only
+    // valid operation is to dispose the object calling the destructor which
+    // should close the file. This method can throw and signal potential errors
+    // when flushing the archive. This is why its present.
+    void finalize() { m_zip.finalize(); }
 };
 
 /**
diff --git a/src/libslic3r/Zipper.cpp b/src/libslic3r/Zipper.cpp
index 490805c0d..6b7faaddc 100644
--- a/src/libslic3r/Zipper.cpp
+++ b/src/libslic3r/Zipper.cpp
@@ -111,6 +111,11 @@ public:
     {
         throw std::runtime_error(formatted_errorstr());
     }
+
+    bool is_alive()
+    {
+        return arch.m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
+    }
 };
 
 Zipper::Zipper(const std::string &zipfname, e_compression compression)
@@ -129,11 +134,19 @@ Zipper::Zipper(const std::string &zipfname, e_compression compression)
 
 Zipper::~Zipper()
 {
-    try {
-        close();
-    } catch(...) {
-        BOOST_LOG_TRIVIAL(error) << m_impl->formatted_errorstr();
+    if(m_impl->is_alive()) {
+        // Flush the current entry if not finished yet.
+        try { finish_entry(); } catch(...) {
+            BOOST_LOG_TRIVIAL(error) << m_impl->formatted_errorstr();
+        }
+
+        if(!mz_zip_writer_finalize_archive(&m_impl->arch))
+            BOOST_LOG_TRIVIAL(error) << m_impl->formatted_errorstr();
     }
+
+    // The file should be closed no matter what...
+    if(!mz_zip_writer_end(&m_impl->arch))
+        BOOST_LOG_TRIVIAL(error) << m_impl->formatted_errorstr();
 }
 
 Zipper::Zipper(Zipper &&m):
@@ -152,12 +165,16 @@ Zipper &Zipper::operator=(Zipper &&m) {
 
 void Zipper::add_entry(const std::string &name)
 {
+    if(!m_impl->is_alive()) return;
+
     finish_entry(); // finish previous business
     m_entry = name;
 }
 
 void Zipper::add_entry(const std::string &name, const uint8_t *data, size_t l)
 {
+    if(!m_impl->is_alive()) return;
+
     finish_entry();
     mz_uint cmpr = MZ_NO_COMPRESSION;
     switch (m_compression) {
@@ -175,7 +192,9 @@ void Zipper::add_entry(const std::string &name, const uint8_t *data, size_t l)
 
 void Zipper::finish_entry()
 {
-    if(!m_data.empty() > 0 && !m_entry.empty()) {
+    if(!m_impl->is_alive()) return;
+
+    if(!m_data.empty() && !m_entry.empty()) {
         mz_uint compression = MZ_NO_COMPRESSION;
 
         switch (m_compression) {
@@ -198,12 +217,12 @@ std::string Zipper::get_name() const {
     return boost::filesystem::path(m_impl->m_zipname).stem().string();
 }
 
-void Zipper::close()
+void Zipper::finalize()
 {
     finish_entry();
 
-    if(!mz_zip_writer_finalize_archive(&m_impl->arch)) m_impl->blow_up();
-    if(!mz_zip_writer_end(&m_impl->arch)) m_impl->blow_up();
+    if(m_impl->is_alive()) if(!mz_zip_writer_finalize_archive(&m_impl->arch))
+        m_impl->blow_up();
 }
 
 }
diff --git a/src/libslic3r/Zipper.hpp b/src/libslic3r/Zipper.hpp
index 7319c4ac4..6566dad42 100644
--- a/src/libslic3r/Zipper.hpp
+++ b/src/libslic3r/Zipper.hpp
@@ -47,6 +47,7 @@ public:
     void add_entry(const std::string& name);
 
     /// Add a new binary file entry with an instantly given byte buffer.
+    /// This method throws exactly like finish_entry() does.
     void add_entry(const std::string& name, const std::uint8_t* data, size_t l);
 
     // Writing data to the archive works like with standard streams. The target
@@ -74,12 +75,16 @@ public:
     /// buffer and ones an entry is added, the buffer will bind to the new entry
     /// If the buffer was written, but no entry was added, the buffer will be
     /// cleared after this call.
+    ///
+    /// This method will throw a runtime exception if an error occures. The
+    /// entry will still be open (with the data intact) but the state of the
+    /// file is up to minz after the erroneous write.
     void finish_entry();
 
     /// Gets the name of the archive without the path or extension.
     std::string get_name() const;
 
-    void close();
+    void finalize();
 };
 
 
diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp
index 177f924c7..bdfd2fc26 100644
--- a/src/slic3r/GUI/GUI_App.cpp
+++ b/src/slic3r/GUI/GUI_App.cpp
@@ -649,20 +649,16 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
         }
         case ConfigMenuLanguage:
         {
-            /* Before change application language, let's check unsaved changes
+            /* Before change application language, let's check unsaved changes on 3D-Scene
              * and draw user's attention to the application restarting after a language change
              */
             wxMessageDialog dialog(nullptr,
-                _(L("Application will be restarted after language change, "
-                    "and 3D-Scene will be cleaned.")) + "\n" +
-                _(L("Please, check your changes before.")) + "\n\n" +
-                _(L("Continue anyway?")),
+                _(L("Application will be restarted after language change.")) + "\n" +
+                _(L("3D-Scene will be cleaned.")) + "\n\n" +
+                _(L("Please, check your changes before.")),
                 _(L("Attention!")),
-                wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT);
-            if ( dialog.ShowModal() != wxID_YES)
-                return;
-
-            if (!wxGetApp().check_unsaved_changes())
+                wxICON_QUESTION | wxOK | wxCANCEL);
+            if ( dialog.ShowModal() == wxID_CANCEL)
                 return;
 
             wxArrayString names;
diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp
index 642a9fb55..224bb802e 100644
--- a/src/slic3r/GUI/GUI_ObjectList.cpp
+++ b/src/slic3r/GUI/GUI_ObjectList.cpp
@@ -228,6 +228,21 @@ int ObjectList::get_selected_obj_idx() const
     return -1;
 }
 
+DynamicPrintConfig& ObjectList::get_item_config(const wxDataViewItem& item) const 
+{
+    assert(item);
+    const ItemType type = m_objects_model->GetItemType(item);
+
+    const int obj_idx = type & itObject ? m_objects_model->GetIdByItem(item) :
+        m_objects_model->GetIdByItem(m_objects_model->GetTopParent(item));
+
+    const int vol_idx = type & itVolume ? m_objects_model->GetVolumeIdByItem(item) : -1;
+
+    assert(obj_idx >= 0 || ((type & itVolume) && vol_idx >=0));
+    return type & itObject|itInstance ? (*m_objects)[obj_idx]->config :
+        (*m_objects)[obj_idx]->volumes[vol_idx]->config;
+}
+
 wxDataViewColumn* ObjectList::create_objects_list_extruder_column(int extruders_count)
 {
     wxArrayString choices;
@@ -910,8 +925,10 @@ wxMenuItem* ObjectList::append_menu_item_split(wxMenu* menu)
 wxMenuItem* ObjectList::append_menu_item_settings(wxMenu* menu_) 
 {
     PrusaMenu* menu = dynamic_cast<PrusaMenu*>(menu_);
+
+    const wxString menu_name = _(L("Add settings"));
     // Delete old items from settings popupmenu
-    auto settings_id = menu->FindItem(_("Add settings"));
+    auto settings_id = menu->FindItem(menu_name);
     if (settings_id != wxNOT_FOUND)
         menu->Destroy(settings_id);
 
@@ -966,14 +983,10 @@ wxMenuItem* ObjectList::append_menu_item_settings(wxMenu* menu_)
     menu->m_separator_scnd = menu->AppendSeparator();
 
     // Add full settings list
-    auto  menu_item = new wxMenuItem(menu, wxID_ANY, _(L("Add settings")));
+    auto  menu_item = new wxMenuItem(menu, wxID_ANY, menu_name);
     menu_item->SetBitmap(m_bmp_cog);
 
-//     const auto sel_vol = get_selected_model_volume();
-//     if (sel_vol && sel_vol->type() >= ModelVolumeType::SUPPORT_ENFORCER)
-//         menu_item->Enable(false);
-//     else
-        menu_item->SetSubMenu(create_settings_popupmenu(menu));
+    menu_item->SetSubMenu(create_settings_popupmenu(menu));
 
     return menu->Append(menu_item);
 }
@@ -1018,6 +1031,37 @@ void ObjectList::append_menu_item_export_stl(wxMenu* menu) const
     menu->AppendSeparator();
 }
 
+void ObjectList::append_menu_item_change_extruder(wxMenu* menu) const
+{
+    const wxString name = _(L("Change extruder"));
+    // Delete old menu item
+    const int item_id = menu->FindItem(name);
+    if (item_id != wxNOT_FOUND)
+        menu->Destroy(item_id);
+
+    const int extruders_cnt = extruders_count();
+    const wxDataViewItem item = GetSelection();
+    if (item && extruders_cnt > 1)
+    {
+        DynamicPrintConfig& config = get_item_config(item);
+
+        const int initial_extruder = !config.has("extruder") ? 0 :
+                                      config.option<ConfigOptionInt>("extruder")->value;
+
+        wxMenu* extruder_selection_menu = new wxMenu();
+
+        for (int i = 0; i <= extruders_cnt; i++)
+        {
+            const wxString& item_name = i == 0 ? _(L("Default")) : wxString::Format("%d", i);
+
+            append_menu_radio_item(extruder_selection_menu, wxID_ANY, item_name, "",
+                [this, i](wxCommandEvent&) { set_extruder_for_selected_items(i); }, menu)->Check(i == initial_extruder);
+        }
+
+        menu->AppendSubMenu(extruder_selection_menu, name, _(L("Select new extruder for the object/part")));
+    }
+}
+
 void ObjectList::create_object_popupmenu(wxMenu *menu)
 {
 #ifdef __WXOSX__  
@@ -1989,7 +2033,7 @@ void ObjectList::update_selections_on_canvas()
         return;
     }
 
-    auto add_to_selection = [this](const wxDataViewItem& item, Selection& selection, bool as_single_selection)
+    auto add_to_selection = [this](const wxDataViewItem& item, Selection& selection, int instance_idx, bool as_single_selection)
     {
         if (m_objects_model->GetParent(item) == wxDataViewItem(0)) {
             selection.add_object(m_objects_model->GetIdByItem(item), as_single_selection);
@@ -1999,7 +2043,7 @@ void ObjectList::update_selections_on_canvas()
         if (m_objects_model->GetItemType(item) == itVolume) {
             const int obj_idx = m_objects_model->GetIdByItem(m_objects_model->GetParent(item));
             const int vol_idx = m_objects_model->GetVolumeIdByItem(item);
-            selection.add_volume(obj_idx, vol_idx, 0, as_single_selection);
+            selection.add_volume(obj_idx, vol_idx, std::max(instance_idx, 0), as_single_selection);
         }
         else if (m_objects_model->GetItemType(item) == itInstance) {
             const int obj_idx = m_objects_model->GetIdByItem(m_objects_model->GetTopParent(item));
@@ -2011,10 +2055,10 @@ void ObjectList::update_selections_on_canvas()
     if (sel_cnt == 1) {
         wxDataViewItem item = GetSelection();
         if (m_objects_model->GetItemType(item) & (itSettings|itInstanceRoot))
-            add_to_selection(m_objects_model->GetParent(item), selection, true);
+            add_to_selection(m_objects_model->GetParent(item), selection, -1, true);
         else
-            add_to_selection(item, selection, true);
-            
+            add_to_selection(item, selection, -1, true);
+
         wxGetApp().plater()->canvas3D()->update_gizmos_on_off_state();
         return;
     }
@@ -2022,9 +2066,11 @@ void ObjectList::update_selections_on_canvas()
     wxDataViewItemArray sels;
     GetSelections(sels);
 
+    // stores current instance idx before to clear the selection
+    int instance_idx = selection.get_instance_idx();
     selection.clear();
     for (auto item: sels)
-        add_to_selection(item, selection, false);
+        add_to_selection(item, selection, instance_idx, false);
 
     wxGetApp().plater()->canvas3D()->update_gizmos_on_off_state();
 }
@@ -2425,15 +2471,7 @@ void ObjectList::set_extruder_for_selected_items(const int extruder) const
 
     for (const wxDataViewItem& item : sels)
     {
-        const ItemType type = m_objects_model->GetItemType(item);
-
-        const int obj_idx = type & itObject ? m_objects_model->GetIdByItem(item) :
-                            m_objects_model->GetIdByItem(m_objects_model->GetTopParent(item));
-
-        const int vol_idx = type & itVolume ? m_objects_model->GetVolumeIdByItem(item) : -1;
-
-        DynamicPrintConfig& config = type & itObject ? (*m_objects)[obj_idx]->config : 
-                                     (*m_objects)[obj_idx]->volumes[vol_idx]->config;
+        DynamicPrintConfig& config = get_item_config(item);
         
         if (config.has("extruder")) {
             if (extruder == 0)
@@ -2446,7 +2484,16 @@ void ObjectList::set_extruder_for_selected_items(const int extruder) const
 
         const wxString extruder_str = extruder == 0 ? wxString ("default") : 
                                       wxString::Format("%d", config.option<ConfigOptionInt>("extruder")->value);
-        m_objects_model->SetValue(extruder_str, item, 1);
+
+        auto const type = m_objects_model->GetItemType(item);
+
+        /* We can change extruder for Object/Volume only.
+         * So, if Instance is selected, get its Object item and change it
+         */
+        m_objects_model->SetValue(extruder_str, type & itInstance ? m_objects_model->GetTopParent(item) : item, 1);
+
+        const int obj_idx = type & itObject ? m_objects_model->GetIdByItem(item) :
+                            m_objects_model->GetIdByItem(m_objects_model->GetTopParent(item));
 
         wxGetApp().plater()->canvas3D()->ensure_on_bed(obj_idx);
     }
diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp
index e0df8dd40..4ddc6ea71 100644
--- a/src/slic3r/GUI/GUI_ObjectList.hpp
+++ b/src/slic3r/GUI/GUI_ObjectList.hpp
@@ -187,6 +187,7 @@ public:
     void                append_menu_items_osx(wxMenu* menu);
     void                append_menu_item_fix_through_netfabb(wxMenu* menu);
     void                append_menu_item_export_stl(wxMenu* menu) const ;
+    void                append_menu_item_change_extruder(wxMenu* menu) const;
     void                create_object_popupmenu(wxMenu *menu);
     void                create_sla_object_popupmenu(wxMenu*menu);
     void                create_part_popupmenu(wxMenu*menu);
@@ -213,12 +214,13 @@ public:
     wxPoint             get_mouse_position_in_control();
     wxBoxSizer*         get_sizer() {return  m_sizer;}
     int                 get_selected_obj_idx() const;
+    DynamicPrintConfig& get_item_config(const wxDataViewItem& item) const;
     bool                is_parts_changed() const { return m_parts_changed; }
     bool                is_part_settings_changed() const { return m_part_settings_changed; }
     void                part_settings_changed();
 
-    void                 parts_changed(int obj_idx);
-    void                 part_selection_changed();
+    void                parts_changed(int obj_idx);
+    void                part_selection_changed();
 
     // Add object to the list
     void add_object_to_list(size_t obj_idx);
diff --git a/src/slic3r/GUI/MsgDialog.cpp b/src/slic3r/GUI/MsgDialog.cpp
index 961888455..cc2b9c842 100644
--- a/src/slic3r/GUI/MsgDialog.cpp
+++ b/src/slic3r/GUI/MsgDialog.cpp
@@ -28,7 +28,7 @@ MsgDialog::MsgDialog(wxWindow *parent, const wxString &title, const wxString &he
 {}
 
 MsgDialog::MsgDialog(wxWindow *parent, const wxString &title, const wxString &headline, wxBitmap bitmap, wxWindowID button_id) :
-	wxDialog(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxRESIZE_BORDER),
+wxDialog(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER),
 	boldfont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)),
 	content_sizer(new wxBoxSizer(wxVERTICAL)),
 	btn_sizer(new wxBoxSizer(wxHORIZONTAL))
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index fa4587ca6..c92c22c50 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -427,7 +427,7 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent, const int label_width) :
 
     option = m_og->get_option("fill_density");
     option.opt.label = L("Infill");
-    option.opt.width = 5 * wxGetApp().em_unit();
+    option.opt.width = 6 * wxGetApp().em_unit();
     option.opt.sidetext = "     ";
     line.append_option(option);
 
@@ -2624,29 +2624,35 @@ void Plater::priv::on_right_click(Vec2dEvent& evt)
 
     sidebar->obj_list()->append_menu_item_settings(menu);
 
-    /* Remove/Prepend "increase/decrease instances" menu items according to the view mode.
-     * Suppress to show those items for a Simple mode
-     */
-    const MenuIdentifier id = printer_technology == ptSLA ? miObjectSLA : miObjectFFF;
-    if (wxGetApp().get_mode() == comSimple) {
-        if (menu->FindItem(_(L("Increase copies"))) != wxNOT_FOUND)
-        {
-            /* Detach an items from the menu, but don't delete them 
-             * so that they can be added back later
-             * (after switching to the Advanced/Expert mode)
-             */
-            menu->Remove(items_increase[id]);
-            menu->Remove(items_decrease[id]);
-            menu->Remove(items_set_number_of_copies[id]);
+    if (printer_technology != ptSLA)
+        sidebar->obj_list()->append_menu_item_change_extruder(menu);
+
+    if (menu != &part_menu)
+    {
+        /* Remove/Prepend "increase/decrease instances" menu items according to the view mode.
+         * Suppress to show those items for a Simple mode
+         */
+        const MenuIdentifier id = printer_technology == ptSLA ? miObjectSLA : miObjectFFF;
+        if (wxGetApp().get_mode() == comSimple) {
+            if (menu->FindItem(_(L("Increase copies"))) != wxNOT_FOUND)
+            {
+                /* Detach an items from the menu, but don't delete them
+                 * so that they can be added back later
+                 * (after switching to the Advanced/Expert mode)
+                 */
+                menu->Remove(items_increase[id]);
+                menu->Remove(items_decrease[id]);
+                menu->Remove(items_set_number_of_copies[id]);
+            }
         }
-    }
-    else {
-        if (menu->FindItem(_(L("Increase copies"))) == wxNOT_FOUND)
-        {
-            // Prepend items to the menu, if those aren't not there
-            menu->Prepend(items_set_number_of_copies[id]);
-            menu->Prepend(items_decrease[id]);
-            menu->Prepend(items_increase[id]);
+        else {
+            if (menu->FindItem(_(L("Increase copies"))) == wxNOT_FOUND)
+            {
+                // Prepend items to the menu, if those aren't not there
+                menu->Prepend(items_set_number_of_copies[id]);
+                menu->Prepend(items_decrease[id]);
+                menu->Prepend(items_increase[id]);
+            }
         }
     }
 
diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp
index dee18ad43..55544f28e 100644
--- a/src/slic3r/GUI/wxExtensions.cpp
+++ b/src/slic3r/GUI/wxExtensions.cpp
@@ -61,6 +61,24 @@ wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxStrin
     return item;
 }
 
+wxMenuItem* append_menu_radio_item(wxMenu* menu, int id, const wxString& string, const wxString& description,
+    std::function<void(wxCommandEvent& event)> cb, wxEvtHandler* event_handler)
+{
+    if (id == wxID_ANY)
+        id = wxNewId();
+
+    wxMenuItem* item = menu->AppendRadioItem(id, string, description);
+
+#ifdef __WXMSW__
+    if (event_handler != nullptr && event_handler != menu)
+        event_handler->Bind(wxEVT_MENU, cb, id);
+    else
+#endif // __WXMSW__
+        menu->Bind(wxEVT_MENU, cb, id);
+
+    return item;
+}
+
 const unsigned int wxCheckListBoxComboPopup::DefaultWidth = 200;
 const unsigned int wxCheckListBoxComboPopup::DefaultHeight = 200;
 const unsigned int wxCheckListBoxComboPopup::DefaultItemHeight = 18;
diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp
index a15bee256..27da67deb 100644
--- a/src/slic3r/GUI/wxExtensions.hpp
+++ b/src/slic3r/GUI/wxExtensions.hpp
@@ -25,7 +25,11 @@ wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const
 wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description,
     std::function<void(wxCommandEvent& event)> cb, const std::string& icon = "", wxEvtHandler* event_handler = nullptr);
 
-wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxString& string, const wxString& description, const std::string& icon = "");
+wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxString& string, const wxString& description, 
+    const std::string& icon = "");
+
+wxMenuItem* append_menu_radio_item(wxMenu* menu, int id, const wxString& string, const wxString& description, 
+    std::function<void(wxCommandEvent& event)> cb, wxEvtHandler* event_handler);
 
 wxBitmap create_scaled_bitmap(const std::string& bmp_name);