diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 00b074f7d2..cb031a8d0f 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -64,12 +64,6 @@ ObjectList::ObjectList(wxWindow* parent) : init_icons(); - // create popup menus for object and part - create_object_popupmenu(&m_menu_object); - create_part_popupmenu(&m_menu_part); - create_sla_object_popupmenu(&m_menu_sla_object); - create_instance_popupmenu(&m_menu_instance); - // describe control behavior Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this](wxEvent& event) { selection_changed(); @@ -141,6 +135,15 @@ void ObjectList::create_objects_ctrl() wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE); } +void ObjectList::create_popup_menus() +{ + // create popup menus for object and part + create_object_popupmenu(&m_menu_object); + create_part_popupmenu(&m_menu_part); + create_sla_object_popupmenu(&m_menu_sla_object); + create_instance_popupmenu(&m_menu_instance); +} + void ObjectList::set_tooltip_for_item(const wxPoint& pt) { wxDataViewItem item; @@ -310,7 +313,7 @@ void ObjectList::update_extruder_in_config(const wxDataViewItem& item) wxGetApp().plater()->update(); } -void ObjectList::update_name_in_model(const wxDataViewItem& item) +void ObjectList::update_name_in_model(const wxDataViewItem& item) const { const int obj_idx = m_objects_model->GetObjectIdByItem(item); if (obj_idx < 0) return; @@ -421,9 +424,6 @@ void ObjectList::show_context_menu() if (multiple_selection() && selected_instances_of_same_object()) { wxGetApp().plater()->PopupMenu(&m_menu_instance); - - wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { - evt.Enable(can_split_instances()); }, m_menu_item_split_instances->GetId()); return; } @@ -442,12 +442,6 @@ void ObjectList::show_context_menu() append_menu_item_settings(menu); wxGetApp().plater()->PopupMenu(menu); - - wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { - evt.Enable(is_splittable()); }, m_menu_item_split->GetId()); - - wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { - evt.Enable(is_splittable()); }, m_menu_item_split_part->GetId()); } } @@ -964,8 +958,18 @@ wxMenuItem* ObjectList::append_menu_item_instance_to_object(wxMenu* menu) [this](wxCommandEvent&) { split_instances(); }, "", menu); } +wxMenuItem* ObjectList::append_menu_item_rename(wxMenu* menu) +{ + return append_menu_item(menu, wxID_ANY, _(L("Rename")), "", + [this](wxCommandEvent&) { rename_item(); }, "", menu); +} + void ObjectList::create_object_popupmenu(wxMenu *menu) { +#ifdef __WXOSX__ + append_menu_item_rename(menu); +#endif // __WXOSX__ + // Split object to parts m_menu_item_split = append_menu_item_split(menu); menu->AppendSeparator(); @@ -973,6 +977,9 @@ 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) @@ -983,6 +990,10 @@ void ObjectList::create_sla_object_popupmenu(wxMenu *menu) void ObjectList::create_part_popupmenu(wxMenu *menu) { +#ifdef __WXOSX__ + append_menu_item_rename(menu); +#endif // __WXOSX__ + m_menu_item_split_part = append_menu_item_split(menu); // Append change part type @@ -991,11 +1002,17 @@ 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); + + wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { + evt.Enable(can_split_instances()); }, m_menu_item_split_instances->GetId()); } wxMenu* ObjectList::create_settings_popupmenu(wxMenu *parent_menu) @@ -2052,6 +2069,48 @@ void ObjectList::split_instances() instances_to_separated_object(obj_idx, inst_idxs); } +void ObjectList::rename_item() +{ + const wxDataViewItem item = GetSelection(); + if (!item || !(m_objects_model->GetItemType(item) & (itVolume | itObject))) + return ; + + const wxString new_name = wxGetTextFromUser(_(L("Enter new name"))+":", _(L("Renaming")), + m_objects_model->GetName(item), this); + + bool is_unusable_symbol = false; + std::string chosen_name = Slic3r::normalize_utf8_nfc(new_name.ToUTF8()); + const char* unusable_symbols = "<>:/\\|?*\""; + for (size_t i = 0; i < std::strlen(unusable_symbols); i++) { + if (chosen_name.find_first_of(unusable_symbols[i]) != std::string::npos) { + is_unusable_symbol = true; + } + } + + if (is_unusable_symbol) { + show_error(this, _(L("The supplied name is not valid;")) + "\n" + + _(L("the following characters are not allowed:")) + " <>:/\\|?*\""); + return; + } + + // The icon can't be edited so get its old value and reuse it. + wxVariant valueOld; + m_objects_model->GetValue(valueOld, item, 0); + + PrusaDataViewBitmapText bmpText; + bmpText << valueOld; + + // But replace the text with the value entered by user. + bmpText.SetText(new_name); + + wxVariant value; + value << bmpText; + m_objects_model->SetValue(value, item, 0); + m_objects_model->ItemChanged(item); + + update_name_in_model(item); +} + void ObjectList::ItemValueChanged(wxDataViewEvent &event) { if (event.GetColumn() == 0) diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 93a3ba60f1..86e2167ddc 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -153,6 +153,7 @@ public: void create_objects_ctrl(); + void create_popup_menus(); wxDataViewColumn* create_objects_list_extruder_column(int extruders_count); void update_objects_list_extruder_column(int extruders_count); // show/hide "Extruder" column for Objects List @@ -160,7 +161,7 @@ public: // update extruder in current config void update_extruder_in_config(const wxDataViewItem& item); // update changed name in the object model - void update_name_in_model(const wxDataViewItem& item); + void update_name_in_model(const wxDataViewItem& item) const; void update_extruder_values_for_items(const int max_extruder); void init_icons(); @@ -181,6 +182,7 @@ public: 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_rename(wxMenu* menu); void create_object_popupmenu(wxMenu *menu); void create_sla_object_popupmenu(wxMenu*menu); void create_part_popupmenu(wxMenu*menu); @@ -262,6 +264,7 @@ public: void instances_to_separated_object(const int obj_idx, const std::set& inst_idx); void split_instances(); + void rename_item(); private: void OnChar(wxKeyEvent& event); diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 51f1c5f197..947dd59bdf 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -22,6 +22,7 @@ #include "AppConfig.hpp" #include "PrintHostDialogs.hpp" #include "wxExtensions.hpp" +#include "GUI_ObjectList.hpp" #include "I18N.hpp" #include @@ -132,6 +133,8 @@ void MainFrame::init_tabpanel() wxGetApp().plater_ = m_plater; m_tabpanel->AddPage(m_plater, _(L("Plater"))); + wxGetApp().obj_list()->create_popup_menus(); + // The following event is emited by Tab implementation on config value change. Bind(EVT_TAB_VALUE_CHANGED, &MainFrame::on_value_changed, this); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 42e404106a..e559be64fd 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1717,6 +1717,8 @@ void Plater::priv::reset() object_list_changed(); update(); + // The hiding of the slicing results, if shown, is not taken care by the background process, so we do it here + this->sidebar->show_sliced_info_sizer(false); auto& config = wxGetApp().preset_bundle->project_config; config.option("colorprint_heights")->values.clear();