diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 880d511d7..741dc0801 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1120,7 +1120,8 @@ void ObjectList::append_menu_items_add_volume(wxMenu* menu) wxMenuItem* ObjectList::append_menu_item_split(wxMenu* menu) { return append_menu_item(menu, wxID_ANY, _(L("Split to parts")), "", - [this](wxCommandEvent&) { split(); }, "split_parts_SMALL", menu); + [this](wxCommandEvent&) { split(); }, "split_parts_SMALL", menu, + [this]() { return is_splittable(); }, wxGetApp().plater()); } wxMenuItem* ObjectList::append_menu_item_settings(wxMenu* menu_) @@ -1199,10 +1200,10 @@ wxMenuItem* ObjectList::append_menu_item_change_type(wxMenu* menu) } -wxMenuItem* ObjectList::append_menu_item_instance_to_object(wxMenu* menu) +wxMenuItem* ObjectList::append_menu_item_instance_to_object(wxMenu* menu, wxWindow* parent) { return append_menu_item(menu, wxID_ANY, _(L("Set as a Separated Object")), "", - [this](wxCommandEvent&) { split_instances(); }, "", menu); + [this](wxCommandEvent&) { split_instances(); }, "", menu, [](){return wxGetApp().plater()->can_set_instance_to_object(); }, parent); } void ObjectList::append_menu_items_osx(wxMenu* menu) @@ -1217,8 +1218,10 @@ wxMenuItem* ObjectList::append_menu_item_fix_through_netfabb(wxMenu* menu) { if (!is_windows10()) return nullptr; + Plater* plater = wxGetApp().plater(); wxMenuItem* menu_item = append_menu_item(menu, wxID_ANY, _(L("Fix through the Netfabb")), "", - [this](wxCommandEvent&) { fix_through_netfabb(); }, "", menu); + [this](wxCommandEvent&) { fix_through_netfabb(); }, "", menu, + [plater]() {return plater->can_fix_through_netfabb(); }, plater); menu->AppendSeparator(); return menu_item; @@ -1284,9 +1287,6 @@ void ObjectList::create_object_popupmenu(wxMenu *menu) // rest of a object_menu will be added later in: // - append_menu_items_add_volume() -> for "Add (volumes)" // - append_menu_item_settings() -> for "Add (settings)" - - wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { - evt.Enable(is_splittable()); }, m_menu_item_split->GetId()); } void ObjectList::create_sla_object_popupmenu(wxMenu *menu) @@ -1318,14 +1318,11 @@ void ObjectList::create_part_popupmenu(wxMenu *menu) // rest of a object_sla_menu will be added later in: // - append_menu_item_settings() -> for "Add (settings)" - - wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { - evt.Enable(is_splittable()); }, m_menu_item_split_part->GetId()); } void ObjectList::create_instance_popupmenu(wxMenu*menu) { - m_menu_item_split_instances = append_menu_item_instance_to_object(menu); + m_menu_item_split_instances = append_menu_item_instance_to_object(menu, wxGetApp().plater()); /* New behavior logic: * 1. Split Object to several separated object, if ALL instances are selected diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 1625c2fac..2932d86f9 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -199,7 +199,7 @@ public: wxMenuItem* append_menu_item_split(wxMenu* menu); wxMenuItem* append_menu_item_settings(wxMenu* menu); wxMenuItem* append_menu_item_change_type(wxMenu* menu); - wxMenuItem* append_menu_item_instance_to_object(wxMenu* menu); + wxMenuItem* append_menu_item_instance_to_object(wxMenu* menu, wxWindow* parent); void append_menu_items_osx(wxMenu* menu); wxMenuItem* append_menu_item_fix_through_netfabb(wxMenu* menu); void append_menu_item_export_stl(wxMenu* menu) const ; diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index ba9664ce9..22845df8a 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -341,18 +341,22 @@ void MainFrame::init_menubar() // File menu wxMenu* fileMenu = new wxMenu; { - wxMenuItem* item_open = append_menu_item(fileMenu, wxID_ANY, _(L("&Open Project")) + dots + "\tCtrl+O", _(L("Open a project file")), - [this](wxCommandEvent&) { if (m_plater) m_plater->load_project(); }, menu_icon("open")); - wxMenuItem* item_save = append_menu_item(fileMenu, wxID_ANY, _(L("&Save Project")) + "\tCtrl+S", _(L("Save current project file")), - [this](wxCommandEvent&) { if (m_plater) m_plater->export_3mf(into_path(m_plater->get_project_filename())); }, menu_icon("save")); - wxMenuItem* item_save_as = append_menu_item(fileMenu, wxID_ANY, _(L("Save Project &as")) + dots + "\tCtrl+Alt+S", _(L("Save current project file as")), - [this](wxCommandEvent&) { if (m_plater) m_plater->export_3mf(); }, menu_icon("save")); + append_menu_item(fileMenu, wxID_ANY, _(L("&Open Project")) + dots + "\tCtrl+O", _(L("Open a project file")), + [this](wxCommandEvent&) { if (m_plater) m_plater->load_project(); }, menu_icon("open"), nullptr, + [this](){return m_plater != nullptr; }, this); + append_menu_item(fileMenu, wxID_ANY, _(L("&Save Project")) + "\tCtrl+S", _(L("Save current project file")), + [this](wxCommandEvent&) { if (m_plater) m_plater->export_3mf(into_path(m_plater->get_project_filename())); }, menu_icon("save"), nullptr, + [this](){return m_plater != nullptr && can_save(); }, this); + append_menu_item(fileMenu, wxID_ANY, _(L("Save Project &as")) + dots + "\tCtrl+Alt+S", _(L("Save current project file as")), + [this](wxCommandEvent&) { if (m_plater) m_plater->export_3mf(); }, menu_icon("save"), nullptr, + [this](){return m_plater != nullptr && can_save(); }, this); fileMenu->AppendSeparator(); wxMenu* import_menu = new wxMenu(); - wxMenuItem* item_import_model = append_menu_item(import_menu, wxID_ANY, _(L("Import STL/OBJ/AM&F/3MF")) + dots + "\tCtrl+I", _(L("Load a model")), - [this](wxCommandEvent&) { if (m_plater) m_plater->add_model(); }, menu_icon("import_plater")); + append_menu_item(import_menu, wxID_ANY, _(L("Import STL/OBJ/AM&F/3MF")) + dots + "\tCtrl+I", _(L("Load a model")), + [this](wxCommandEvent&) { if (m_plater) m_plater->add_model(); }, menu_icon("import_plater"), nullptr, + [this](){return m_plater != nullptr; }, this); import_menu->AppendSeparator(); append_menu_item(import_menu, wxID_ANY, _(L("Import &Config")) + dots + "\tCtrl+L", _(L("Load exported configuration file")), [this](wxCommandEvent&) { load_config_file(); }, menu_icon("import_config")); @@ -365,15 +369,19 @@ void MainFrame::init_menubar() wxMenu* export_menu = new wxMenu(); wxMenuItem* item_export_gcode = append_menu_item(export_menu, wxID_ANY, _(L("Export &G-code")) + dots +"\tCtrl+G", _(L("Export current plate as G-code")), - [this](wxCommandEvent&) { if (m_plater) m_plater->export_gcode(); }, menu_icon("export_gcode")); + [this](wxCommandEvent&) { if (m_plater) m_plater->export_gcode(); }, menu_icon("export_gcode"), nullptr, + [this](){return can_export_gcode(); }, this); m_changeable_menu_items.push_back(item_export_gcode); export_menu->AppendSeparator(); - wxMenuItem* item_export_stl = append_menu_item(export_menu, wxID_ANY, _(L("Export plate as &STL")) + dots, _(L("Export current plate as STL")), - [this](wxCommandEvent&) { if (m_plater) m_plater->export_stl(); }, menu_icon("export_plater")); - wxMenuItem* item_export_stl_sla = append_menu_item(export_menu, wxID_ANY, _(L("Export plate as STL including supports")) + dots, _(L("Export current plate as STL including supports")), - [this](wxCommandEvent&) { if (m_plater) m_plater->export_stl(true); }, menu_icon("export_plater")); - wxMenuItem* item_export_amf = append_menu_item(export_menu, wxID_ANY, _(L("Export plate as &AMF")) + dots, _(L("Export current plate as AMF")), - [this](wxCommandEvent&) { if (m_plater) m_plater->export_amf(); }, menu_icon("export_plater")); + append_menu_item(export_menu, wxID_ANY, _(L("Export plate as &STL")) + dots, _(L("Export current plate as STL")), + [this](wxCommandEvent&) { if (m_plater) m_plater->export_stl(); }, menu_icon("export_plater"), nullptr, + [this](){return can_export_model(); }, this); + append_menu_item(export_menu, wxID_ANY, _(L("Export plate as STL including supports")) + dots, _(L("Export current plate as STL including supports")), + [this](wxCommandEvent&) { if (m_plater) m_plater->export_stl(true); }, menu_icon("export_plater"), nullptr, + [this](){return can_export_supports(); }, this); + append_menu_item(export_menu, wxID_ANY, _(L("Export plate as &AMF")) + dots, _(L("Export current plate as AMF")), + [this](wxCommandEvent&) { if (m_plater) m_plater->export_amf(); }, menu_icon("export_plater"), nullptr, + [this](){return can_export_model(); }, this); export_menu->AppendSeparator(); append_menu_item(export_menu, wxID_ANY, _(L("Export &Config")) +dots +"\tCtrl+E", _(L("Export current configuration to file")), [this](wxCommandEvent&) { export_config(); }, menu_icon("export_config")); @@ -413,16 +421,6 @@ void MainFrame::init_menubar() fileMenu->AppendSeparator(); append_menu_item(fileMenu, wxID_EXIT, _(L("&Quit")), wxString::Format(_(L("Quit %s")), SLIC3R_APP_NAME), [this](wxCommandEvent&) { Close(false); }); - - Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(m_plater != nullptr); }, item_open->GetId()); - Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable((m_plater != nullptr) && can_save()); }, item_save->GetId()); - Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable((m_plater != nullptr) && can_save()); }, item_save_as->GetId()); - Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(m_plater != nullptr); }, item_import_model->GetId()); - Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_export_gcode()); }, item_export_gcode->GetId()); - Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_export_model()); }, item_export_stl->GetId()); - Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_export_supports()); }, item_export_stl_sla->GetId()); - Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_export_model()); }, item_export_amf->GetId()); - Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_slice()); }, m_menu_item_reslice_now->GetId()); } #ifdef _MSC_VER @@ -446,26 +444,25 @@ void MainFrame::init_menubar() #else wxString hotkey_delete = "Del"; #endif - wxMenuItem* item_select_all = append_menu_item(editMenu, wxID_ANY, _(L("&Select all")) + sep + GUI::shortkey_ctrl_prefix() + sep_space + "A", _(L("Selects all objects")), - [this](wxCommandEvent&) { if (m_plater != nullptr) m_plater->select_all(); }, ""); + append_menu_item(editMenu, wxID_ANY, _(L("&Select all")) + sep + GUI::shortkey_ctrl_prefix() + sep_space + "A", + _(L("Selects all objects")), [this](wxCommandEvent&) { if (m_plater != nullptr) m_plater->select_all(); }, + "", nullptr, [this](){return can_select(); }, this); editMenu->AppendSeparator(); - wxMenuItem* item_delete_sel = append_menu_item(editMenu, wxID_ANY, _(L("&Delete selected")) + sep + hotkey_delete, _(L("Deletes the current selection")), - [this](wxCommandEvent&) { m_plater->remove_selected(); }, menu_icon("remove_menu")); - wxMenuItem* item_delete_all = append_menu_item(editMenu, wxID_ANY, _(L("Delete &all")) + sep + GUI::shortkey_ctrl_prefix() + sep_space + hotkey_delete, _(L("Deletes all objects")), - [this](wxCommandEvent&) { m_plater->reset_with_confirm(); }, menu_icon("delete_all_menu")); + append_menu_item(editMenu, wxID_ANY, _(L("&Delete selected")) + sep + hotkey_delete, + _(L("Deletes the current selection")),[this](wxCommandEvent&) { m_plater->remove_selected(); }, + menu_icon("remove_menu"), nullptr, [this](){return can_delete(); }, this); + append_menu_item(editMenu, wxID_ANY, _(L("Delete &all")) + sep + GUI::shortkey_ctrl_prefix() + sep_space + hotkey_delete, + _(L("Deletes all objects")), [this](wxCommandEvent&) { m_plater->reset_with_confirm(); }, + menu_icon("delete_all_menu"), nullptr, [this](){return can_delete_all(); }, this); editMenu->AppendSeparator(); - wxMenuItem* item_copy = append_menu_item(editMenu, wxID_ANY, _(L("&Copy")) + sep + GUI::shortkey_ctrl_prefix() + sep_space + "C", _(L("Copy selection to clipboard")), - [this](wxCommandEvent&) { m_plater->copy_selection_to_clipboard(); }, menu_icon("copy_menu")); - wxMenuItem* item_paste = append_menu_item(editMenu, wxID_ANY, _(L("&Paste")) + sep + GUI::shortkey_ctrl_prefix() + sep_space + "V", _(L("Paste clipboard")), - [this](wxCommandEvent&) { m_plater->paste_from_clipboard(); }, menu_icon("paste_menu")); - - Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_select()); }, item_select_all->GetId()); - Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete()); }, item_delete_sel->GetId()); - Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete_all()); }, item_delete_all->GetId()); - Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(m_plater->can_copy()); }, item_copy->GetId()); - Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(m_plater->can_paste()); }, item_paste->GetId()); + append_menu_item(editMenu, wxID_ANY, _(L("&Copy")) + sep + GUI::shortkey_ctrl_prefix() + sep_space + "C", + _(L("Copy selection to clipboard")), [this](wxCommandEvent&) { m_plater->copy_selection_to_clipboard(); }, + menu_icon("copy_menu"), nullptr, [this](){return m_plater->can_copy(); }, this); + append_menu_item(editMenu, wxID_ANY, _(L("&Paste")) + sep + GUI::shortkey_ctrl_prefix() + sep_space + "V", + _(L("Paste clipboard")), [this](wxCommandEvent&) { m_plater->paste_from_clipboard(); }, + menu_icon("paste_menu"), nullptr, [this](){return m_plater->can_paste(); }, this); } // Window menu @@ -489,13 +486,12 @@ void MainFrame::init_menubar() [this, tab_offset](wxCommandEvent&) { select_tab(tab_offset + 2); }, menu_icon("printer")); if (m_plater) { windowMenu->AppendSeparator(); - wxMenuItem* item_3d = append_menu_item(windowMenu, wxID_HIGHEST + 5, _(L("3&D")) + "\tCtrl+5", _(L("Show the 3D editing view")), - [this](wxCommandEvent&) { m_plater->select_view_3D("3D"); }, menu_icon("editor_menu")); - wxMenuItem* item_preview = append_menu_item(windowMenu, wxID_HIGHEST + 6, _(L("Pre&view")) + "\tCtrl+6", _(L("Show the 3D slices preview")), - [this](wxCommandEvent&) { m_plater->select_view_3D("Preview"); }, menu_icon("preview_menu")); - - Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_change_view()); }, item_3d->GetId()); - Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_change_view()); }, item_preview->GetId()); + append_menu_item(windowMenu, wxID_HIGHEST + 5, _(L("3&D")) + "\tCtrl+5", _(L("Show the 3D editing view")), + [this](wxCommandEvent&) { m_plater->select_view_3D("3D"); }, menu_icon("editor_menu"), nullptr, + [this](){return can_change_view(); }, this); + append_menu_item(windowMenu, wxID_HIGHEST + 6, _(L("Pre&view")) + "\tCtrl+6", _(L("Show the 3D slices preview")), + [this](wxCommandEvent&) { m_plater->select_view_3D("Preview"); }, menu_icon("preview_menu"), nullptr, + [this](){return can_change_view(); }, this); } #if _WIN32 @@ -521,24 +517,23 @@ void MainFrame::init_menubar() if (m_plater) { viewMenu = new wxMenu(); // The camera control accelerators are captured by GLCanvas3D::on_char(). - wxMenuItem* item_iso = append_menu_item(viewMenu, wxID_ANY, _(L("Iso")) + sep + "&0", _(L("Iso View")), [this](wxCommandEvent&) { select_view("iso"); }); + append_menu_item(viewMenu, wxID_ANY, _(L("Iso")) + sep + "&0", _(L("Iso View")),[this](wxCommandEvent&) { select_view("iso"); }, + "", nullptr, [this](){return can_change_view(); }, this); viewMenu->AppendSeparator(); //TRN To be shown in the main menu View->Top - wxMenuItem* item_top = append_menu_item(viewMenu, wxID_ANY, _(L("Top")) + sep + "&1", _(L("Top View")), [this](wxCommandEvent&) { select_view("top"); }); + append_menu_item(viewMenu, wxID_ANY, _(L("Top")) + sep + "&1", _(L("Top View")), [this](wxCommandEvent&) { select_view("top"); }, + "", nullptr, [this](){return can_change_view(); }, this); //TRN To be shown in the main menu View->Bottom - wxMenuItem* item_bottom = append_menu_item(viewMenu, wxID_ANY, _(L("Bottom")) + sep + "&2", _(L("Bottom View")), [this](wxCommandEvent&) { select_view("bottom"); }); - wxMenuItem* item_front = append_menu_item(viewMenu, wxID_ANY, _(L("Front")) + sep + "&3", _(L("Front View")), [this](wxCommandEvent&) { select_view("front"); }); - wxMenuItem* item_rear = append_menu_item(viewMenu, wxID_ANY, _(L("Rear")) + sep + "&4", _(L("Rear View")), [this](wxCommandEvent&) { select_view("rear"); }); - wxMenuItem* item_left = append_menu_item(viewMenu, wxID_ANY, _(L("Left")) + sep + "&5", _(L("Left View")), [this](wxCommandEvent&) { select_view("left"); }); - wxMenuItem* item_right = append_menu_item(viewMenu, wxID_ANY, _(L("Right")) + sep + "&6", _(L("Right View")), [this](wxCommandEvent&) { select_view("right"); }); - - Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_change_view()); }, item_iso->GetId()); - Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_change_view()); }, item_top->GetId()); - Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_change_view()); }, item_bottom->GetId()); - Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_change_view()); }, item_front->GetId()); - Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_change_view()); }, item_rear->GetId()); - Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_change_view()); }, item_left->GetId()); - Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_change_view()); }, item_right->GetId()); + append_menu_item(viewMenu, wxID_ANY, _(L("Bottom")) + sep + "&2", _(L("Bottom View")), [this](wxCommandEvent&) { select_view("bottom"); }, + "", nullptr, [this](){return can_change_view(); }, this); + append_menu_item(viewMenu, wxID_ANY, _(L("Front")) + sep + "&3", _(L("Front View")), [this](wxCommandEvent&) { select_view("front"); }, + "", nullptr, [this](){return can_change_view(); }, this); + append_menu_item(viewMenu, wxID_ANY, _(L("Rear")) + sep + "&4", _(L("Rear View")), [this](wxCommandEvent&) { select_view("rear"); }, + "", nullptr, [this](){return can_change_view(); }, this); + append_menu_item(viewMenu, wxID_ANY, _(L("Left")) + sep + "&5", _(L("Left View")), [this](wxCommandEvent&) { select_view("left"); }, + "", nullptr, [this](){return can_change_view(); }, this); + append_menu_item(viewMenu, wxID_ANY, _(L("Right")) + sep + "&6", _(L("Right View")), [this](wxCommandEvent&) { select_view("right"); }, + "", nullptr, [this](){return can_change_view(); }, this); } // Help menu diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 404456cf0..be0988567 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1336,6 +1336,8 @@ struct Plater::priv bool can_arrange() const; bool can_layers_editing() const; bool can_fix_through_netfabb() const; + bool can_set_instance_to_object() const; + bool can_mirror() const; void msw_rescale_object_menu(); @@ -1347,10 +1349,8 @@ private: bool complit_init_part_menu(); void init_view_toolbar(); - bool can_set_instance_to_object() const; bool can_split() const; bool layers_height_allowed() const; - bool can_mirror() const; void update_fff_scene(); void update_sla_scene(); @@ -2928,39 +2928,31 @@ void Plater::priv::msw_rescale_object_menu() bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/) { - wxMenuItem* item_delete = nullptr; if (is_part) { - item_delete = append_menu_item(menu, wxID_ANY, _(L("Delete")) + "\tDel", _(L("Remove the selected object")), - [this](wxCommandEvent&) { q->remove_selected(); }, "delete"); + append_menu_item(menu, wxID_ANY, _(L("Delete")) + "\tDel", _(L("Remove the selected object")), + [this](wxCommandEvent&) { q->remove_selected(); }, "delete", nullptr, [this]() { return can_delete(); }, q); sidebar->obj_list()->append_menu_item_export_stl(menu); } else { wxMenuItem* item_increase = append_menu_item(menu, wxID_ANY, _(L("Increase copies")) + "\t+", _(L("Place one more copy of the selected object")), - [this](wxCommandEvent&) { q->increase_instances(); }, "add_copies"); + [this](wxCommandEvent&) { q->increase_instances(); }, "add_copies", nullptr, [this]() { return can_increase_instances(); }, q); wxMenuItem* item_decrease = append_menu_item(menu, wxID_ANY, _(L("Decrease copies")) + "\t-", _(L("Remove one copy of the selected object")), - [this](wxCommandEvent&) { q->decrease_instances(); }, "remove_copies"); + [this](wxCommandEvent&) { q->decrease_instances(); }, "remove_copies", nullptr, [this]() { return can_decrease_instances(); }, q); wxMenuItem* item_set_number_of_copies = append_menu_item(menu, wxID_ANY, _(L("Set number of copies")) + dots, _(L("Change the number of copies of the selected object")), - [this](wxCommandEvent&) { q->set_number_of_copies(); }, "number_of_copies"); + [this](wxCommandEvent&) { q->set_number_of_copies(); }, "number_of_copies", nullptr, [this]() { return can_increase_instances(); }, q); + items_increase.push_back(item_increase); items_decrease.push_back(item_decrease); items_set_number_of_copies.push_back(item_set_number_of_copies); // Delete menu was moved to be after +/- instace to make it more difficult to be selected by mistake. - item_delete = append_menu_item(menu, wxID_ANY, _(L("Delete")) + "\tDel", _(L("Remove the selected object")), - [this](wxCommandEvent&) { q->remove_selected(); }, "delete"); + append_menu_item(menu, wxID_ANY, _(L("Delete")) + "\tDel", _(L("Remove the selected object")), + [this](wxCommandEvent&) { q->remove_selected(); }, "delete", nullptr, [this]() { return can_delete(); }, q); menu->AppendSeparator(); - wxMenuItem* item_instance_to_object = sidebar->obj_list()->append_menu_item_instance_to_object(menu); - - if (q != nullptr) - { - q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_increase_instances()); }, item_increase->GetId()); - q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_decrease_instances()); }, item_decrease->GetId()); - q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_increase_instances()); }, item_set_number_of_copies->GetId()); - q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_set_instance_to_object()); }, item_instance_to_object->GetId()); - } + sidebar->obj_list()->append_menu_item_instance_to_object(menu, q); menu->AppendSeparator(); append_menu_item(menu, wxID_ANY, _(L("Reload from Disk")), _(L("Reload the selected file from Disk")), @@ -2972,7 +2964,7 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/ menu->AppendSeparator(); } - wxMenuItem* item_fix_through_netfabb = sidebar->obj_list()->append_menu_item_fix_through_netfabb(menu); + sidebar->obj_list()->append_menu_item_fix_through_netfabb(menu); wxMenu* mirror_menu = new wxMenu(); if (mirror_menu == nullptr) @@ -2985,16 +2977,8 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/ append_menu_item(mirror_menu, wxID_ANY, _(L("Along Z axis")), _(L("Mirror the selected object along the Z axis")), [this](wxCommandEvent&) { mirror(Z); }, "mark_Z", menu); - wxMenuItem* item_mirror = append_submenu(menu, mirror_menu, wxID_ANY, _(L("Mirror")), _(L("Mirror the selected object"))); - - // ui updates needs to be bound to the parent panel - if (q != nullptr) - { - q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_mirror()); }, item_mirror->GetId()); - q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete()); }, item_delete->GetId()); - if (item_fix_through_netfabb) - q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_fix_through_netfabb()); }, item_fix_through_netfabb->GetId()); - } + append_submenu(menu, mirror_menu, wxID_ANY, _(L("Mirror")), _(L("Mirror the selected object")), "", + [this]() { return can_mirror(); }, q); return true; } @@ -3005,30 +2989,24 @@ bool Plater::priv::complit_init_object_menu() if (split_menu == nullptr) return false; - wxMenuItem* item_split_objects = append_menu_item(split_menu, wxID_ANY, _(L("To objects")), _(L("Split the selected object into individual objects")), - [this](wxCommandEvent&) { split_object(); }, "split_object_SMALL", &object_menu); - wxMenuItem* item_split_volumes = append_menu_item(split_menu, wxID_ANY, _(L("To parts")), _(L("Split the selected object into individual sub-parts")), - [this](wxCommandEvent&) { split_volume(); }, "split_parts_SMALL", &object_menu); + append_menu_item(split_menu, wxID_ANY, _(L("To objects")), _(L("Split the selected object into individual objects")), + [this](wxCommandEvent&) { split_object(); }, "split_object_SMALL", &object_menu, [this]() { return can_split(); }, q); + append_menu_item(split_menu, wxID_ANY, _(L("To parts")), _(L("Split the selected object into individual sub-parts")), + [this](wxCommandEvent&) { split_volume(); }, "split_parts_SMALL", &object_menu, [this]() { return can_split(); }, q); - wxMenuItem* item_split = append_submenu(&object_menu, split_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object"))/*, "shape_ungroup.png"*/); + append_submenu(&object_menu, split_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object")), "", + [this]() { return can_split() && wxGetApp().get_mode() > comSimple; }, q); object_menu.AppendSeparator(); // "Add (volumes)" popupmenu will be added later in append_menu_items_add_volume() - // ui updates needs to be binded to the parent panel - if (q != nullptr) - { - q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split()); }, item_split->GetId()); - q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split()); }, item_split_objects->GetId()); - q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split() && wxGetApp().get_mode() > comSimple); }, item_split_volumes->GetId()); - } return true; } bool Plater::priv::complit_init_sla_object_menu() { - wxMenuItem* item_split = append_menu_item(&sla_object_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object into individual objects")), - [this](wxCommandEvent&) { split_object(); }, "split_object_SMALL"); + append_menu_item(&sla_object_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object into individual objects")), + [this](wxCommandEvent&) { split_object(); }, "split_object_SMALL", nullptr, [this]() { return can_split(); }, q); sla_object_menu.AppendSeparator(); @@ -3036,31 +3014,19 @@ bool Plater::priv::complit_init_sla_object_menu() append_menu_item(&sla_object_menu, wxID_ANY, _(L("Optimize orientation")), _(L("Optimize the rotation of the object for better print results.")), [this](wxCommandEvent&) { sla_optimize_rotation(); }); - // ui updates needs to be binded to the parent panel - if (q != nullptr) - { - q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split()); }, item_split->GetId()); - } - return true; } bool Plater::priv::complit_init_part_menu() { - wxMenuItem* item_split = append_menu_item(&part_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object into individual sub-parts")), - [this](wxCommandEvent&) { split_volume(); }, "split_parts_SMALL"); + append_menu_item(&part_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object into individual sub-parts")), + [this](wxCommandEvent&) { split_volume(); }, "split_parts_SMALL", nullptr, [this]() { return can_split(); }, q); part_menu.AppendSeparator(); auto obj_list = sidebar->obj_list(); obj_list->append_menu_item_change_type(&part_menu); - // ui updates needs to be binded to the parent panel - if (q != nullptr) - { - q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split()); }, item_split->GetId()); - } - return true; } @@ -3965,6 +3931,8 @@ bool Plater::can_delete() const { return p->can_delete(); } bool Plater::can_delete_all() const { return p->can_delete_all(); } bool Plater::can_increase_instances() const { return p->can_increase_instances(); } bool Plater::can_decrease_instances() const { return p->can_decrease_instances(); } +bool Plater::can_set_instance_to_object() const { return p->can_set_instance_to_object(); } +bool Plater::can_fix_through_netfabb() const { return p->can_fix_through_netfabb(); } bool Plater::can_split_to_objects() const { return p->can_split_to_objects(); } bool Plater::can_split_to_volumes() const { return p->can_split_to_volumes(); } bool Plater::can_arrange() const { return p->can_arrange(); } diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index e4327f433..3e7003686 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -200,6 +200,8 @@ public: bool can_delete_all() const; bool can_increase_instances() const; bool can_decrease_instances() const; + bool can_set_instance_to_object() const; + bool can_fix_through_netfabb() const; bool can_split_to_objects() const; bool can_split_to_volumes() const; bool can_arrange() const; diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 3a36ef9c3..049f81ac4 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -25,8 +25,9 @@ using Slic3r::GUI::from_u8; wxDEFINE_EVENT(wxCUSTOMEVT_TICKSCHANGED, wxEvent); wxDEFINE_EVENT(wxCUSTOMEVT_LAST_VOLUME_IS_DELETED, wxCommandEvent); -#ifdef __WXMSW__ +#ifndef __WXGTK__// msw_menuitem_bitmaps is used for MSW and OSX static std::map msw_menuitem_bitmaps; +#ifdef __WXMSW__ void msw_rescale_menu(wxMenu* menu) { struct update_icons { @@ -47,9 +48,29 @@ void msw_rescale_menu(wxMenu* menu) update_icons::run(item); } #endif /* __WXMSW__ */ +#endif /* no __WXGTK__ */ + +void enable_menu_item(wxUpdateUIEvent& evt, std::function const cb_condition, wxMenuItem* item) +{ + const bool enable = cb_condition(); + evt.Enable(enable); + +#ifdef __WXOSX__ + const auto it = msw_menuitem_bitmaps.find(item->GetId()); + if (it != msw_menuitem_bitmaps.end()) + { + const wxBitmap& item_icon = create_scaled_bitmap(nullptr, it->second); + if (item_icon.IsOk()) { + double g = 0.6; + item->SetBitmap(enable ? item_icon : item_icon.ConvertToImage().ConvertToGreyscale(g, g, g)); + } + } +#endif // __WXOSX__ +} wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description, - std::function cb, const wxBitmap& icon, wxEvtHandler* event_handler) + std::function cb, const wxBitmap& icon, wxEvtHandler* event_handler, + std::function const cb_condition, wxWindow* parent) { if (id == wxID_ANY) id = wxNewId(); @@ -67,25 +88,33 @@ wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const #endif // __WXMSW__ menu->Bind(wxEVT_MENU, cb, id); + if (parent) { + parent->Bind(wxEVT_UPDATE_UI, [cb_condition, item](wxUpdateUIEvent& evt) { + enable_menu_item(evt, cb_condition, item); }, id); + } + return item; } wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description, - std::function cb, const std::string& icon, wxEvtHandler* event_handler) + std::function cb, const std::string& icon, wxEvtHandler* event_handler, + std::function const cb_condition, wxWindow* parent) { if (id == wxID_ANY) id = wxNewId(); const wxBitmap& bmp = !icon.empty() ? create_scaled_bitmap(nullptr, icon) : wxNullBitmap; // FIXME: pass window ptr -#ifdef __WXMSW__ +//#ifdef __WXMSW__ +#ifndef __WXGTK__ if (bmp.IsOk()) msw_menuitem_bitmaps[id] = icon; #endif /* __WXMSW__ */ - return append_menu_item(menu, id, string, description, cb, bmp, event_handler); + return append_menu_item(menu, id, string, description, cb, bmp, event_handler, cb_condition, parent); } -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, + std::function const cb_condition, wxWindow* parent) { if (id == wxID_ANY) id = wxNewId(); @@ -93,7 +122,8 @@ wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxStrin wxMenuItem* item = new wxMenuItem(menu, id, string, description); if (!icon.empty()) { item->SetBitmap(create_scaled_bitmap(nullptr, icon)); // FIXME: pass window ptr -#ifdef __WXMSW__ +//#ifdef __WXMSW__ +#ifndef __WXGTK__ msw_menuitem_bitmaps[id] = icon; #endif /* __WXMSW__ */ } @@ -101,6 +131,11 @@ wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxStrin item->SetSubMenu(sub_menu); menu->Append(item); + if (parent) { + parent->Bind(wxEVT_UPDATE_UI, [cb_condition, item](wxUpdateUIEvent& evt) { + enable_menu_item(evt, cb_condition, item); }, id); + } + return item; } diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index 2b47cd77e..2eb1d1832 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -27,12 +27,15 @@ inline void msw_rescale_menu(wxMenu* /* menu */) {} #endif /* __WXMSW__ */ wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description, - std::function cb, const wxBitmap& icon, wxEvtHandler* event_handler = nullptr); + std::function cb, const wxBitmap& icon, wxEvtHandler* event_handler = nullptr, + std::function const cb_condition = []() { return true;}, wxWindow* parent = nullptr); wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description, - std::function cb, const std::string& icon = "", wxEvtHandler* event_handler = nullptr); + std::function cb, const std::string& icon = "", wxEvtHandler* event_handler = nullptr, + std::function const cb_condition = []() { return true; }, wxWindow* parent = nullptr); wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxString& string, const wxString& description, - const std::string& icon = ""); + const std::string& icon = "", + std::function const cb_condition = []() { return true; }, wxWindow* parent = nullptr); wxMenuItem* append_menu_radio_item(wxMenu* menu, int id, const wxString& string, const wxString& description, std::function cb, wxEvtHandler* event_handler);