diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 743ac19b4..53066d708 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -58,7 +58,7 @@ ObjectList::ObjectList(wxWindow* parent) : Bind(wxEVT_CHOICE, [this](wxCommandEvent& event) { update_extruder_in_config(event.GetString()); }); GetMainWindow()->Bind(wxEVT_MOTION, [this](wxMouseEvent& event) { - set_tooltip_for_item(event.GetPosition()); + set_tooltip_for_item(/*event.GetPosition()*/get_mouse_position_in_control()); event.Skip(); }); #else @@ -94,17 +94,13 @@ void ObjectList::create_objects_ctrl() // column 0(Icon+Text) of the view control: // And Icon can be consisting of several bitmaps AppendColumn(new wxDataViewColumn(_(L("Name")), new PrusaBitmapTextRenderer(), - 0, 200, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE)); + 0, 250, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE)); // column 1 of the view control: - AppendTextColumn(_(L("Copy")), 1, wxDATAVIEW_CELL_INERT, 45, - wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE); - - // column 2 of the view control: AppendColumn(create_objects_list_extruder_column(4)); - // column 3 of the view control: - AppendBitmapColumn(" ", 3, wxDATAVIEW_CELL_INERT, 25, + // column 2 of the view control: + AppendBitmapColumn(" ", 2, wxDATAVIEW_CELL_INERT, 25, wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE); } @@ -118,7 +114,7 @@ void ObjectList::set_tooltip_for_item(const wxPoint& pt) if (col->GetTitle() == " " && GetSelectedItemsCount()<2) GetMainWindow()->SetToolTip(_(L("Right button click the icon to change the object settings"))); else if (col->GetTitle() == _("Name") && - m_objects_model->GetIcon(item).GetRefData() == m_icon_manifold_warning.GetRefData()) { + m_objects_model->GetBitmap(item).GetRefData() == m_bmp_manifold_warning.GetRefData()) { int obj_idx = m_objects_model->GetIdByItem(item); auto& stats = (*m_objects)[obj_idx]->volumes[0]->mesh.stl.stats; int errors = stats.degenerate_facets + stats.edges_fixed + stats.facets_removed + @@ -178,7 +174,7 @@ wxDataViewColumn* ObjectList::create_objects_list_extruder_column(int extruders_ choices.Add(wxString::Format("%d", i)); wxDataViewChoiceRenderer *c = new wxDataViewChoiceRenderer(choices, wxDATAVIEW_CELL_EDITABLE, wxALIGN_CENTER_HORIZONTAL); - wxDataViewColumn* column = new wxDataViewColumn(_(L("Extruder")), c, 2, 60, wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE); + wxDataViewColumn* column = new wxDataViewColumn(_(L("Extruder")), c, 1, 80, wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE); return column; } @@ -188,17 +184,17 @@ void ObjectList::update_objects_list_extruder_column(int extruders_count) if (wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA) extruders_count = 1; - // delete old 3rd column - DeleteColumn(GetColumn(2)); + // delete old 2nd column + DeleteColumn(GetColumn(1)); // insert new created 3rd column - InsertColumn(2, create_objects_list_extruder_column(extruders_count)); + InsertColumn(1, create_objects_list_extruder_column(extruders_count)); // set show/hide for this column set_extruder_column_hidden(extruders_count <= 1); } void ObjectList::set_extruder_column_hidden(bool hide) { - GetColumn(2)->SetHidden(hide); + GetColumn(1)->SetHidden(hide); } void ObjectList::update_extruder_in_config(const wxString& selection) @@ -214,11 +210,11 @@ void ObjectList::update_extruder_in_config(const wxString& selection) } void ObjectList::init_icons(){ - m_icon_modifiermesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("lambda.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("plugin.png")), wxBITMAP_TYPE_PNG); - m_icon_solidmesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("package.png")), wxBITMAP_TYPE_PNG); + m_bmp_modifiermesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("lambda.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("plugin.png")), wxBITMAP_TYPE_PNG); + m_bmp_solidmesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("package.png")), wxBITMAP_TYPE_PNG); // init icon for manifold warning - m_icon_manifold_warning = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("exclamation_mark_.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("error.png")), wxBITMAP_TYPE_PNG); + m_bmp_manifold_warning = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("exclamation_mark_.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("error.png")), wxBITMAP_TYPE_PNG); // init bitmap for "Split to sub-objects" context menu m_bmp_split = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("split.png")), wxBITMAP_TYPE_PNG); @@ -268,7 +264,7 @@ void ObjectList::context_menu() show_context_menu(); else if (title == _("Name") && pt.x >15 && - m_objects_model->GetIcon(item).GetRefData() == m_icon_manifold_warning.GetRefData()) + m_objects_model->GetBitmap(item).GetRefData() == m_bmp_manifold_warning.GetRefData()) { if (is_windows10()) /*fix_through_netfabb()*/;// #ys_FIXME @@ -283,7 +279,7 @@ void ObjectList::show_context_menu() const auto item = GetSelection(); if (item) { - if (m_objects_model->IsSettingsItem(item)) + if (!(m_objects_model->GetItemType(item) & (itObject | itVolume))) return; const auto menu = m_objects_model->GetParent(item) == wxDataViewItem(0) ? create_add_part_popupmenu() : @@ -313,10 +309,10 @@ void ObjectList::key_event(wxKeyEvent& event) void ObjectList::item_value_change(wxDataViewEvent& event) { - if (event.GetColumn() == 2) + if (event.GetColumn() == 1) { wxVariant variant; - m_objects_model->GetValue(variant, event.GetItem(), 2); + m_objects_model->GetValue(variant, event.GetItem(), 1); #ifdef __WXOSX__ m_selected_extruder = variant.GetString(); #else // --> for Linux @@ -325,14 +321,20 @@ void ObjectList::item_value_change(wxDataViewEvent& event) } } +struct draging_item_data +{ + int obj_idx; + int vol_idx; +}; + void ObjectList::on_begin_drag(wxDataViewEvent &event) { wxDataViewItem item(event.GetItem()); // only allow drags for item, not containers if (multiple_selection() || - m_objects_model->GetParent(item) == wxDataViewItem(0) || - m_objects_model->IsSettingsItem(item) ) { + m_objects_model->GetParent(item) == wxDataViewItem(0) || + m_objects_model->GetItemType(item) != itVolume ) { event.Veto(); return; } @@ -356,7 +358,7 @@ void ObjectList::on_drop_possible(wxDataViewEvent &event) // only allow drags for item or background, not containers if (item.IsOk() && m_objects_model->GetParent(item) == wxDataViewItem(0) || - event.GetDataFormat() != wxDF_UNICODETEXT || m_objects_model->IsSettingsItem(item)) + event.GetDataFormat() != wxDF_UNICODETEXT || m_objects_model->GetItemType(item) != itVolume) event.Veto(); } @@ -366,7 +368,7 @@ void ObjectList::on_drop(wxDataViewEvent &event) // only allow drops for item, not containers if (item.IsOk() && m_objects_model->GetParent(item) == wxDataViewItem(0) || - event.GetDataFormat() != wxDF_UNICODETEXT || m_objects_model->IsSettingsItem(item)) { + event.GetDataFormat() != wxDF_UNICODETEXT || m_objects_model->GetItemType(item) != itVolume) { event.Veto(); return; } @@ -495,7 +497,7 @@ void ObjectList::get_settings_choice(wxMenu *menu, int id, bool is_part) // Add settings item for object const auto item = GetSelection(); if (item) { - const auto settings_item = m_objects_model->HasSettings(item); + const auto settings_item = m_objects_model->GetSettingsItem(item); select_item(settings_item ? settings_item : m_objects_model->AddSettingsChild(item)); #ifndef __WXOSX__ @@ -547,7 +549,7 @@ wxMenu* ObjectList::create_add_part_popupmenu() int i = 0; for (auto& item : menu_items) { auto menu_item = new wxMenuItem(menu, config_id_base + i, _(item)); - menu_item->SetBitmap(i == 0 ? m_icon_solidmesh : m_icon_modifiermesh); + menu_item->SetBitmap(i == 0 ? m_bmp_solidmesh : m_bmp_modifiermesh); if (item == "Add generic") menu_item_add_generic(menu_item, config_id_base + i); menu->Append(menu_item); @@ -666,8 +668,8 @@ void ObjectList::load_subobject(bool is_modifier /*= false*/, bool is_lambda/* = parts_changed(obj_idx); for (int i = 0; i < part_names.size(); ++i) { - const wxDataViewItem sel_item = m_objects_model->AddChild(item, part_names.Item(i), - is_modifier ? m_icon_modifiermesh : m_icon_solidmesh); + const wxDataViewItem sel_item = m_objects_model->AddVolumeChild(item, part_names.Item(i), + is_modifier ? m_bmp_modifiermesh : m_bmp_solidmesh); if (i == part_names.size() - 1) select_item(sel_item); @@ -816,8 +818,8 @@ void ObjectList::load_lambda(const std::string& type_name) m_parts_changed = true; parts_changed(m_selected_object_id); - select_item(m_objects_model->AddChild(GetSelection(), - name, m_icon_modifiermesh)); + select_item(m_objects_model->AddVolumeChild(GetSelection(), + name, m_bmp_modifiermesh)); #ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME selection_changed(); #endif //no __WXOSX__ //__WXMSW__ @@ -830,15 +832,20 @@ void ObjectList::del_subobject_item(wxDataViewItem& item) { if (!item) return; - int obj_idx, vol_idx; - m_objects_model->GetObjectAndVolumeIdsByItem(item, obj_idx, vol_idx); + int obj_idx, idx; + ItemType type; - if (vol_idx == -1) + m_objects_model->GetItemInfo(item, type, obj_idx, idx); + if (type == itUndef) return; - if (vol_idx == -2) + if (type == itSettings) del_settings_from_config(); - else if (!del_subobject_from_object(obj_idx, vol_idx)) + else if (type == itInstanceRoot && obj_idx != -1) + del_instances_from_object(obj_idx); + else if (idx == -1) + return; + else if (!del_subobject_from_object(obj_idx, idx, type)) return; m_objects_model->Delete(item); @@ -859,21 +866,48 @@ void ObjectList::del_settings_from_config() m_config->set_key_value("extruder", new ConfigOptionInt(extruder)); } -bool ObjectList::del_subobject_from_object(const int obj_idx, const int vol_idx) +void ObjectList::del_instances_from_object(const int obj_idx) { - const auto volume = (*m_objects)[obj_idx]->volumes[vol_idx]; + auto instances = (*m_objects)[obj_idx]->instances; + if (instances.size() <= 1) + return; - // if user is deleting the last solid part, throw error - int solid_cnt = 0; - for (auto vol : (*m_objects)[obj_idx]->volumes) - if (vol->is_model_part()) - ++solid_cnt; - if (volume->is_model_part() && solid_cnt == 1) { - Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last solid part from this object."))); - return false; + while ( instances.size()> 1) + instances.pop_back(); + + (*m_objects)[obj_idx]->invalidate_bounding_box(); // ? #ys_FIXME + + m_parts_changed = true; + parts_changed(obj_idx); +} + +bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, const int type) +{ + if (type == itVolume) { + const auto volume = (*m_objects)[obj_idx]->volumes[idx]; + + // if user is deleting the last solid part, throw error + int solid_cnt = 0; + for (auto vol : (*m_objects)[obj_idx]->volumes) + if (vol->is_model_part()) + ++solid_cnt; + if (volume->is_model_part() && solid_cnt == 1) { + Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last solid part from object."))); + return false; + } + + (*m_objects)[obj_idx]->delete_volume(idx); } + else if (type == itInstance) { + if ((*m_objects)[obj_idx]->instances.size() == 1) { + Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last intance from object."))); + return false; + } + (*m_objects)[obj_idx]->delete_instance(idx); + } + else + return false; - (*m_objects)[obj_idx]->delete_volume(vol_idx); m_parts_changed = true; parts_changed(obj_idx); @@ -901,8 +935,8 @@ void ObjectList::split(const bool split_part) m_objects_model->DeleteChildren(parent); for (auto id = 0; id < model_object->volumes.size(); id++) - m_objects_model->AddChild(parent, model_object->volumes[id]->name, - model_object->volumes[id]->is_modifier() ? m_icon_modifiermesh : m_icon_solidmesh, + m_objects_model->AddVolumeChild(parent, model_object->volumes[id]->name, + model_object->volumes[id]->is_modifier() ? m_bmp_modifiermesh : m_bmp_solidmesh, model_object->volumes[id]->config.has("extruder") ? model_object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value : 0, false); @@ -911,8 +945,8 @@ void ObjectList::split(const bool split_part) } else { for (auto id = 0; id < model_object->volumes.size(); id++) - m_objects_model->AddChild(item, model_object->volumes[id]->name, - m_icon_solidmesh, + m_objects_model->AddVolumeChild(item, model_object->volumes[id]->name, + m_bmp_solidmesh, model_object->volumes[id]->config.has("extruder") ? model_object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value : 0, false); @@ -1001,7 +1035,7 @@ void ObjectList::part_selection_changed() m_config = &(*m_objects)[obj_idx]->volumes[volume_id]->config; } } - else { + else if (m_objects_model->GetItemType(item) == itVolume){ og_name = _(L("Part manipulation")); is_part = true; const auto volume_id = m_objects_model->GetVolumeIdByItem(item); @@ -1038,7 +1072,7 @@ void ObjectList::add_object_to_list(size_t obj_idx) { auto model_object = (*m_objects)[obj_idx]; wxString item_name = model_object->name; - auto item = m_objects_model->Add(item_name, model_object->instances.size()); + auto item = m_objects_model->Add(item_name); #if !ENABLE_EXTENDED_SELECTION /*Select*/select_item(item); #endif // !ENABLE_EXTENDED_SELECTION @@ -1049,15 +1083,15 @@ void ObjectList::add_object_to_list(size_t obj_idx) stats.facets_added + stats.facets_reversed + stats.backwards_edges; if (errors > 0) { wxVariant variant; - variant << PrusaDataViewBitmapText(item_name, m_icon_manifold_warning); + variant << PrusaDataViewBitmapText(item_name, m_bmp_manifold_warning); m_objects_model->SetValue(variant, item, 0); } if (model_object->volumes.size() > 1) { for (auto id = 0; id < model_object->volumes.size(); id++) - m_objects_model->AddChild(item, + m_objects_model->AddVolumeChild(item, model_object->volumes[id]->name, - m_icon_solidmesh, + m_bmp_solidmesh, model_object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value, false); Expand(item); @@ -1095,10 +1129,14 @@ void ObjectList::delete_all_objects_from_list() part_selection_changed(); } -void ObjectList::set_object_count(int idx, int count) +void ObjectList::increase_object_instances(const size_t obj_idx, const size_t num) { - m_objects_model->SetValue(wxString::Format("%d", count), idx, 1); - Refresh(); + select_item(m_objects_model->AddInstanceChild(m_objects_model->GetItemById(obj_idx), num)); +} + +void ObjectList::decrease_object_instances(const size_t obj_idx, const size_t num) +{ + select_item(m_objects_model->DeleteLastInstance(m_objects_model->GetItemById(obj_idx), num)); } void ObjectList::unselect_objects() @@ -1198,15 +1236,21 @@ void ObjectList::update_selections_on_canvas() return; } - auto parent = m_objects_model->GetParent(item); - const int obj_idx = m_objects_model->GetIdByItem(parent); - const int vol_idx = m_objects_model->GetVolumeIdByItem(item); - selection.add_volume(obj_idx, vol_idx, as_single_selection); + 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, as_single_selection); + } + else if (m_objects_model->GetItemType(item) == itInstance) { + const int obj_idx = m_objects_model->GetIdByItem(m_objects_model->GetTopParent(item)); + const int inst_idx = m_objects_model->GetInstanceIdByItem(item); + selection.add_instance(obj_idx, inst_idx, as_single_selection); + } }; if (sel_cnt == 1) { wxDataViewItem item = GetSelection(); - if (m_objects_model->IsSettingsItem(item)) + if (m_objects_model->GetItemType(item) & (itSettings|itInstanceRoot)) add_to_selection(m_objects_model->GetParent(item), selection, true); else add_to_selection(item, selection, true); diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 21b4a729f..c56e69670 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -22,9 +22,9 @@ class ObjectList : public wxDataViewCtrl DynamicPrintConfig *m_default_config {nullptr}; - wxBitmap m_icon_modifiermesh; - wxBitmap m_icon_solidmesh; - wxBitmap m_icon_manifold_warning; + wxBitmap m_bmp_modifiermesh; + wxBitmap m_bmp_solidmesh; + wxBitmap m_bmp_manifold_warning; wxBitmap m_bmp_cog; wxBitmap m_bmp_split; @@ -87,7 +87,8 @@ public: void load_lambda(const std::string& type_name); void del_subobject_item(wxDataViewItem& item); void del_settings_from_config(); - bool del_subobject_from_object(const int obj_idx, const int vol_idx); + void del_instances_from_object(const int obj_idx); + bool del_subobject_from_object(const int obj_idx, const int idx, const int type); void split(const bool split_part); bool get_volume_by_item(const bool split_part, const wxDataViewItem& item, ModelVolume*& volume); bool is_splittable_object(const bool split_part); @@ -111,8 +112,10 @@ public: void delete_volume_from_list(const size_t obj_idx, const size_t vol_idx); // Delete all objects from the list void delete_all_objects_from_list(); - // Set count of object on c++ side - void set_object_count(int idx, int count); + // Increase instances count + void increase_object_instances(const size_t obj_idx, const size_t num); + // Decrease instances count + void decrease_object_instances(const size_t obj_idx, const size_t num); // #ys_FIXME_to_delete // Unselect all objects in the list on c++ side diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index 1015e783c..04201b709 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -30,11 +30,11 @@ class Tab; enum QuickSlice { - qsUndef, - qsReslice, - qsSaveAs, - qsExportSVG, - qsExportPNG + qsUndef = 0, + qsReslice = 1, + qsSaveAs = 2, + qsExportSVG = 4, + qsExportPNG = 8 }; struct PresetTab { diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index c58f02f83..051b05598 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1952,7 +1952,7 @@ void Plater::increase(size_t num) float offset = 10.0; for (size_t i = 0; i < num; i++, offset += 10.0) { Vec3d offset_vec = model_instance->get_offset() + Vec3d(offset, offset, 0.0); - auto *new_instance = model_object->add_instance(offset_vec, model_instance->get_scaling_factor(), model_instance->get_rotation()); + model_object->add_instance(offset_vec, model_instance->get_scaling_factor(), model_instance->get_rotation()); #if ENABLE_EXTENDED_SELECTION p->print.get_object(obj_idx)->add_copy(Slic3r::to_2d(offset_vec)); #else @@ -1961,9 +1961,9 @@ void Plater::increase(size_t num) } #if ENABLE_EXTENDED_SELECTION - sidebar().obj_list()->set_object_count(obj_idx, model_object->instances.size()); + sidebar().obj_list()->increase_object_instances(obj_idx, num); #else - sidebar().obj_list()->set_object_count(*obj_idx, model_object->instances.size()); + sidebar().obj_list()->increase_object_instances(*obj_idx, num); #endif // ENABLE_EXTENDED_SELECTION if (p->get_config("autocenter") == "1") { @@ -2001,9 +2001,9 @@ void Plater::decrease(size_t num) #endif // ENABLE_EXTENDED_SELECTION } #if ENABLE_EXTENDED_SELECTION - sidebar().obj_list()->set_object_count(obj_idx, model_object->instances.size()); + sidebar().obj_list()->decrease_object_instances(obj_idx, num); #else - sidebar().obj_list()->set_object_count(*obj_idx, model_object->instances.size()); + sidebar().obj_list()->decrease_object_instances(*obj_idx, num); #endif // ENABLE_EXTENDED_SELECTION } else { @@ -2285,6 +2285,7 @@ void Plater::changed_object_settings(int obj_idx) _3DScene::set_objects_selections(p->canvas3D, selections); #endif // !ENABLE_EXTENDED_SELECTION _3DScene::reload_scene(p->canvas3D, false); + _3DScene::zoom_to_volumes(p->canvas3D); } else { // schedule_background_process(); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 023a6a67d..3b9fe0bd3 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1845,7 +1845,7 @@ void TabPrinter::extruders_count_changed(size_t extruders_count){ if (!wxGetApp().mainframe) return; on_value_change("extruders_count", extruders_count); - wxGetApp().mainframe->m_plater->sidebar().update_objects_list_extruder_column(extruders_count); + wxGetApp().sidebar().update_objects_list_extruder_column(extruders_count); } void TabPrinter::append_option_line(ConfigOptionsGroupShp optgroup, const std::string opt_key) diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 4eaffe49f..4f7f88602 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -376,12 +376,13 @@ void PrusaObjectDataViewModelNode::set_part_action_icon() { Slic3r::GUI::BitmapCache *m_bitmap_cache = nullptr; bool PrusaObjectDataViewModelNode::update_settings_digest(const std::vector<std::string>& categories) { - if (m_type != "settings" || m_opt_categories == categories) + if (m_type != itSettings || m_opt_categories == categories) return false; m_opt_categories = categories; m_name = wxEmptyString; - m_icon = m_empty_icon; +// m_icon = m_empty_icon; + m_bmp = m_empty_bmp; std::map<std::string, wxBitmap>& categories_icon = Slic3r::GUI::wxGetApp().obj_list()->CATEGORY_ICON;//Slic3r::GUI::get_category_icon(); @@ -431,18 +432,7 @@ wxDataViewItem PrusaObjectDataViewModel::Add(const wxString &name) return child; } -wxDataViewItem PrusaObjectDataViewModel::Add(const wxString &name, const int instances_count/*, int scale*/) -{ - auto root = new PrusaObjectDataViewModelNode(name, instances_count); - m_objects.push_back(root); - // notify control - wxDataViewItem child((void*)root); - wxDataViewItem parent((void*)NULL); - ItemAdded(parent, child); - return child; -} - -wxDataViewItem PrusaObjectDataViewModel::AddChild( const wxDataViewItem &parent_item, +wxDataViewItem PrusaObjectDataViewModel::AddVolumeChild(const wxDataViewItem &parent_item, const wxString &name, const wxBitmap& icon, const int extruder/* = 0*/, @@ -453,25 +443,25 @@ wxDataViewItem PrusaObjectDataViewModel::AddChild( const wxDataViewItem &parent_ const wxString extruder_str = extruder == 0 ? "default" : wxString::Format("%d", extruder); - if (create_frst_child && (root->GetChildren().Count() == 0 || - (root->GetChildren().Count() == 1 && root->GetNthChild(0)->m_type == "settings"))) + if (create_frst_child && root->m_volumes_cnt == 0) { - const auto icon_solid_mesh = wxIcon(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG); - const auto node = new PrusaObjectDataViewModelNode(root, root->m_name, icon_solid_mesh, extruder_str, 0); + const auto bmp_solid_mesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG); + const auto node = new PrusaObjectDataViewModelNode(root, root->m_name, bmp_solid_mesh, extruder_str, 0); root->Append(node); // notify control const wxDataViewItem child((void*)node); ItemAdded(parent_item, child); + + root->m_volumes_cnt++; } - const auto volume_id = root->GetChildCount() > 0 && root->GetNthChild(0)->m_type == "settings" ? - root->GetChildCount() - 1 : root->GetChildCount(); - - const auto node = new PrusaObjectDataViewModelNode(root, name, icon, extruder_str, volume_id); + const auto node = new PrusaObjectDataViewModelNode(root, name, icon, extruder_str, root->m_volumes_cnt); root->Append(node); // notify control const wxDataViewItem child((void*)node); - ItemAdded(parent_item, child); + ItemAdded(parent_item, child); + root->m_volumes_cnt++; + return child; } @@ -480,7 +470,7 @@ wxDataViewItem PrusaObjectDataViewModel::AddSettingsChild(const wxDataViewItem & PrusaObjectDataViewModelNode *root = (PrusaObjectDataViewModelNode*)parent_item.GetID(); if (!root) return wxDataViewItem(0); - const auto node = new PrusaObjectDataViewModelNode(root); + const auto node = new PrusaObjectDataViewModelNode(root, itSettings); root->Insert(node, 0); // notify control const wxDataViewItem child((void*)node); @@ -488,6 +478,55 @@ wxDataViewItem PrusaObjectDataViewModel::AddSettingsChild(const wxDataViewItem & return child; } +int get_istances_root_idx(PrusaObjectDataViewModelNode *parent_node) +{ + int inst_root_id = -1; + int stop_search_i = parent_node->GetChildCount(); + if (stop_search_i > 2) stop_search_i = 2; + for (int i = 0; i < stop_search_i; ++i) + if (parent_node->GetNthChild(i)->m_type & itInstanceRoot) { + inst_root_id = i; + break; + } + return inst_root_id; +} + +wxDataViewItem PrusaObjectDataViewModel::AddInstanceChild(const wxDataViewItem &parent_item, size_t num) +{ + PrusaObjectDataViewModelNode *parent_node = (PrusaObjectDataViewModelNode*)parent_item.GetID(); + if (!parent_node) return wxDataViewItem(0); + + // Check and create/get instances root node + const int inst_root_id = get_istances_root_idx(parent_node); + + PrusaObjectDataViewModelNode *inst_root_node = inst_root_id < 0 ? + new PrusaObjectDataViewModelNode(parent_node, itInstanceRoot) : + parent_node->GetNthChild(inst_root_id); + const wxDataViewItem inst_root_item((void*)inst_root_node); + + if (inst_root_id < 0) { + const unsigned insert_pos = parent_node->GetChildCount() == 0 || parent_node->GetNthChild(0)->m_type != itSettings ? 0 : 1; + parent_node->Insert(inst_root_node, insert_pos); + // notify control + ItemAdded(parent_item, inst_root_item); + num++; + } + + // Add instance nodes + PrusaObjectDataViewModelNode *instance_node = nullptr; + size_t counter = 0; + while (counter < num){ + instance_node = new PrusaObjectDataViewModelNode(inst_root_node, itInstance); + inst_root_node->Append(instance_node); + // notify control + const wxDataViewItem instance_item((void*)instance_node); + ItemAdded(inst_root_item, instance_item); + ++counter; + } + + return wxDataViewItem((void*)instance_node); +} + wxDataViewItem PrusaObjectDataViewModel::Delete(const wxDataViewItem &item) { auto ret_item = wxDataViewItem(0); @@ -503,21 +542,45 @@ wxDataViewItem PrusaObjectDataViewModel::Delete(const wxDataViewItem &item) // thus removing the node from it doesn't result in freeing it if (node_parent){ auto id = node_parent->GetChildren().Index(node); - auto v_id = node->GetVolumeId(); + auto idx = node->GetIdx(); node_parent->GetChildren().Remove(node); if (id > 0){ if(id == node_parent->GetChildCount()) id--; ret_item = wxDataViewItem(node_parent->GetChildren().Item(id)); } - //update volume_id value for remaining child-nodes + //update idx value for remaining child-nodes auto children = node_parent->GetChildren(); - for (size_t i = 0; i < node_parent->GetChildCount() && v_id>=0; i++) + for (size_t i = 0; i < node_parent->GetChildCount() && idx>=0; i++) { - auto volume_id = children[i]->GetVolumeId(); - if (volume_id > v_id) - children[i]->SetVolumeId(volume_id-1); + auto cur_idx = children[i]->GetIdx(); + if (cur_idx > idx) + children[i]->SetIdx(cur_idx-1); } + + // if there is last instance item, delete both of it and instance root item + if (node_parent->GetChildCount() == 1 && node_parent->GetNthChild(0)->m_type == itInstance) + { + delete node; + ItemDeleted(parent, item); + + PrusaObjectDataViewModelNode *last_instance_node = node_parent->GetNthChild(0); + node_parent->GetChildren().Remove(last_instance_node); + delete last_instance_node; + ItemDeleted(parent, wxDataViewItem(last_instance_node)); + + PrusaObjectDataViewModelNode *obj_node = node_parent->GetParent(); + obj_node->GetChildren().Remove(node_parent); + delete node_parent; + ret_item = wxDataViewItem(obj_node); + ItemDeleted(ret_item, wxDataViewItem(node_parent)); + +#ifndef __WXGTK__ + if (obj_node->GetChildCount() == 0) + obj_node->m_container = false; +#endif //__WXGTK__ + return ret_item; + } } else { @@ -547,6 +610,54 @@ wxDataViewItem PrusaObjectDataViewModel::Delete(const wxDataViewItem &item) return ret_item; } +wxDataViewItem PrusaObjectDataViewModel::DeleteLastInstance(const wxDataViewItem &parent_item, size_t num) +{ + auto ret_item = wxDataViewItem(0); + PrusaObjectDataViewModelNode *parent_node = (PrusaObjectDataViewModelNode*)parent_item.GetID(); + if (!parent_node) return ret_item; + + const int inst_root_id = get_istances_root_idx(parent_node); + if (inst_root_id < 0) return ret_item; + + wxDataViewItemArray items; + PrusaObjectDataViewModelNode *inst_root_node = parent_node->GetNthChild(inst_root_id); + const wxDataViewItem inst_root_item((void*)inst_root_node); + + const int inst_cnt = inst_root_node->GetChildCount(); + const bool delete_inst_root_item = inst_cnt - num < 2 ? true : false; + + int stop = delete_inst_root_item ? 0 : inst_cnt - num; + for (int i = inst_cnt - 1; i >= stop;--i) { + PrusaObjectDataViewModelNode *last_instance_node = inst_root_node->GetNthChild(i); + inst_root_node->GetChildren().Remove(last_instance_node); + delete last_instance_node; + ItemDeleted(inst_root_item, wxDataViewItem(last_instance_node)); + } + +// for (int i = delete_inst_root_item ? 0 : inst_cnt - num; i < inst_cnt; ++i) +// items.Add(wxDataViewItem(inst_root_node->GetNthChild(i))); +// +// if (delete_inst_root_item) +// inst_root_node->GetChildren().RemoveAt(0, inst_cnt); +// else { +// ret_item = wxDataViewItem(inst_root_node->GetNthChild(inst_cnt - num - 1)); +// inst_root_node->GetChildren().RemoveAt(inst_cnt - num, num); +// } + +// ItemsDeleted(inst_root_item, items); + if (delete_inst_root_item) { + ret_item = parent_item; + parent_node->GetChildren().Remove(inst_root_node); + ItemDeleted(parent_item, inst_root_item); +#ifndef __WXGTK__ + if (parent_node->GetChildCount() == 0) + parent_node->m_container = false; +#endif //__WXGTK__ + } + + return ret_item; +} + void PrusaObjectDataViewModel::DeleteAll() { while (!m_objects.empty()) @@ -606,7 +717,7 @@ wxDataViewItem PrusaObjectDataViewModel::GetItemByVolumeId(int obj_idx, int volu auto parent = m_objects[obj_idx]; if (parent->GetChildCount() == 0 || - (parent->GetChildCount() == 1 && parent->GetNthChild(0)->m_volume_id == -2)) { + (parent->GetChildCount() == 1 && parent->GetNthChild(0)->GetType() & itSettings )) { if (volume_idx == 0) return GetItemById(obj_idx); @@ -615,7 +726,7 @@ wxDataViewItem PrusaObjectDataViewModel::GetItemByVolumeId(int obj_idx, int volu } for (size_t i = 0; i < parent->GetChildCount(); i++) - if (parent->GetNthChild(i)->m_volume_id == volume_idx) + if (parent->GetNthChild(i)->m_idx == volume_idx && parent->GetNthChild(0)->GetType() & itVolume) return wxDataViewItem(parent->GetNthChild(i)); return wxDataViewItem(0); @@ -633,31 +744,49 @@ int PrusaObjectDataViewModel::GetIdByItem(const wxDataViewItem& item) return it - m_objects.begin(); } -int PrusaObjectDataViewModel::GetVolumeIdByItem(const wxDataViewItem& item) +int PrusaObjectDataViewModel::GetIdByItemAndType(const wxDataViewItem& item, const ItemType type) const { wxASSERT(item.IsOk()); PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); - if (!node) // happens if item.IsOk()==false + if (!node || node->m_type != type) return -1; - return node->GetVolumeId(); + return node->GetIdx(); } -void PrusaObjectDataViewModel::GetObjectAndVolumeIdsByItem(const wxDataViewItem& item, int& obj_idx, int& vol_idx) +int PrusaObjectDataViewModel::GetVolumeIdByItem(const wxDataViewItem& item) const +{ + return GetIdByItemAndType(item, itVolume); +} + +int PrusaObjectDataViewModel::GetInstanceIdByItem(const wxDataViewItem& item) const +{ + return GetIdByItemAndType(item, itInstance); +} + +void PrusaObjectDataViewModel::GetItemInfo(const wxDataViewItem& item, ItemType& type, int& obj_idx, int& idx) { wxASSERT(item.IsOk()); - obj_idx = vol_idx = -1; + type = itUndef; PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); - if (!node) return; - vol_idx = node->GetVolumeId(); + if (!node || node->GetIdx() < 0 && node->GetType() != itObject) + return; + + idx = node->GetIdx(); + type = node->GetType(); PrusaObjectDataViewModelNode *parent_node = node->GetParent(); if (!parent_node) return; + if (type == itInstance) + parent_node = node->GetParent()->GetParent(); + if (!parent_node || parent_node->m_type != itObject) { type = itUndef; return; } auto it = find(m_objects.begin(), m_objects.end(), parent_node); if (it != m_objects.end()) obj_idx = it - m_objects.begin(); + else + type = itUndef; } wxString PrusaObjectDataViewModel::GetName(const wxDataViewItem &item) const @@ -669,21 +798,6 @@ wxString PrusaObjectDataViewModel::GetName(const wxDataViewItem &item) const return node->m_name; } -wxString PrusaObjectDataViewModel::GetCopy(const wxDataViewItem &item) const -{ - PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); - if (!node) // happens if item.IsOk()==false - return wxEmptyString; - - return node->m_copy; -} - -wxIcon& PrusaObjectDataViewModel::GetIcon(const wxDataViewItem &item) const -{ - PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); - return node->m_icon; -} - wxBitmap& PrusaObjectDataViewModel::GetBitmap(const wxDataViewItem &item) const { PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); @@ -697,16 +811,13 @@ void PrusaObjectDataViewModel::GetValue(wxVariant &variant, const wxDataViewItem PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); switch (col) { - case 0:{ + case 0: variant << PrusaDataViewBitmapText(node->m_name, node->m_bmp); - break;} - case 1: - variant = node->m_copy; break; - case 2: + case 1: variant = node->m_extruder; break; - case 3: + case 2: variant << node->m_action_icon; break; default: @@ -729,7 +840,7 @@ bool PrusaObjectDataViewModel::SetValue(const wxVariant &variant, const int item return m_objects[item_idx]->SetValue(variant, col); } - +/* wxDataViewItem PrusaObjectDataViewModel::MoveChildUp(const wxDataViewItem &item) { auto ret_item = wxDataViewItem(0); @@ -777,7 +888,7 @@ wxDataViewItem PrusaObjectDataViewModel::MoveChildDown(const wxDataViewItem &ite ret_item = wxDataViewItem(node_parent->GetNthChild(node_parent->GetChildCount()-1)); return ret_item; } - +*/ wxDataViewItem PrusaObjectDataViewModel::ReorganizeChildren(int current_volume_id, int new_volume_id, const wxDataViewItem &parent) { auto ret_item = wxDataViewItem(0); @@ -788,14 +899,14 @@ wxDataViewItem PrusaObjectDataViewModel::ReorganizeChildren(int current_volume_i if (!node_parent) // happens if item.IsOk()==false return ret_item; - const size_t shift = node_parent->GetChildren().Item(0)->m_type == "settings" ? 1 : 0; + const size_t shift = node_parent->GetChildren().Item(0)->m_type == itSettings ? 1 : 0; PrusaObjectDataViewModelNode *deleted_node = node_parent->GetNthChild(current_volume_id+shift); node_parent->GetChildren().Remove(deleted_node); ItemDeleted(parent, wxDataViewItem(deleted_node)); node_parent->Insert(deleted_node, new_volume_id+shift); ItemAdded(parent, wxDataViewItem(deleted_node)); - const auto settings_item = HasSettings(wxDataViewItem(deleted_node)); + const auto settings_item = GetSettingsItem(wxDataViewItem(deleted_node)); if (settings_item) ItemAdded(wxDataViewItem(deleted_node), settings_item); @@ -804,7 +915,7 @@ wxDataViewItem PrusaObjectDataViewModel::ReorganizeChildren(int current_volume_i int id_frst = current_volume_id < new_volume_id ? current_volume_id : new_volume_id; int id_last = current_volume_id > new_volume_id ? current_volume_id : new_volume_id; for (int id = id_frst; id <= id_last; ++id) - children[id+shift]->SetVolumeId(id); + children[id+shift]->SetIdx(id); return wxDataViewItem(node_parent->GetNthChild(new_volume_id+shift)); } @@ -827,12 +938,32 @@ wxDataViewItem PrusaObjectDataViewModel::GetParent(const wxDataViewItem &item) c PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); // objects nodes has no parent too - if (find(m_objects.begin(), m_objects.end(),node) != m_objects.end()) + if (node->m_type == itObject) return wxDataViewItem(0); return wxDataViewItem((void*)node->GetParent()); } +wxDataViewItem PrusaObjectDataViewModel::GetTopParent(const wxDataViewItem &item) const +{ + // the invisible root node has no parent + if (!item.IsOk()) + return wxDataViewItem(0); + + PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); + if (node->m_type == itObject) + return item; + + PrusaObjectDataViewModelNode *parent_node = node->GetParent(); + while (parent_node->m_type != itObject) + { + node = parent_node; + parent_node = node->GetParent(); + } + + return wxDataViewItem((void*)parent_node); +} + bool PrusaObjectDataViewModel::IsContainer(const wxDataViewItem &item) const { // the invisible root node can have children @@ -868,7 +999,15 @@ unsigned int PrusaObjectDataViewModel::GetChildren(const wxDataViewItem &parent, return count; } -wxDataViewItem PrusaObjectDataViewModel::HasSettings(const wxDataViewItem &item) const +ItemType PrusaObjectDataViewModel::GetItemType(const wxDataViewItem &item) const +{ + if (!item.IsOk()) + return itUndef; + PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); + return node->m_type; +} + +wxDataViewItem PrusaObjectDataViewModel::GetSettingsItem(const wxDataViewItem &item) const { if (!item.IsOk()) return wxDataViewItem(0); @@ -877,9 +1016,8 @@ wxDataViewItem PrusaObjectDataViewModel::HasSettings(const wxDataViewItem &item) if (node->GetChildCount() == 0) return wxDataViewItem(0); - auto& children = node->GetChildren(); - if (children[0]->m_type == "settings") - return wxDataViewItem((void*)children[0]);; + if (node->GetNthChild(0)->m_type == itSettings) + return wxDataViewItem((void*)node->GetNthChild(0)); return wxDataViewItem(0); } @@ -889,7 +1027,7 @@ bool PrusaObjectDataViewModel::IsSettingsItem(const wxDataViewItem &item) const if (!item.IsOk()) return false; PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); - return node->m_type == "settings"; + return node->m_type == itSettings; } diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index 07f56e643..f39c38ab5 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -169,7 +169,7 @@ public: void SetText(const wxString &text) { m_text = text; } wxString GetText() const { return m_text; } - void SetBitmap(const wxIcon &icon) { m_bmp = icon; } + void SetBitmap(const wxBitmap &bmp) { m_bmp = bmp; } const wxBitmap &GetBitmap() const { return m_bmp; } bool IsSameAs(const PrusaDataViewBitmapText& other) const { @@ -197,6 +197,15 @@ DECLARE_VARIANT_OBJECT(PrusaDataViewBitmapText) // PrusaObjectDataViewModelNode: a node inside PrusaObjectDataViewModel // ---------------------------------------------------------------------------- +enum ItemType{ + itUndef = 0, + itObject = 1, + itVolume = 2, + itInstanceRoot = 4, + itInstance = 8, + itSettings = 16 +}; + class PrusaObjectDataViewModelNode; WX_DEFINE_ARRAY_PTR(PrusaObjectDataViewModelNode*, MyObjectTreeModelNodePtrArray); @@ -204,16 +213,14 @@ class PrusaObjectDataViewModelNode { PrusaObjectDataViewModelNode* m_parent; MyObjectTreeModelNodePtrArray m_children; - wxIcon m_empty_icon; wxBitmap m_empty_bmp; + size_t m_volumes_cnt = 0; std::vector< std::string > m_opt_categories; public: - PrusaObjectDataViewModelNode(const wxString &name, const int instances_count=1) { + PrusaObjectDataViewModelNode(const wxString &name) { m_parent = NULL; m_name = name; - m_copy = wxString::Format("%d", instances_count); - m_type = "object"; - m_volume_id = -1; + m_type = itObject; #ifdef __WXGTK__ // it's necessary on GTK because of control have to know if this item will be container // in another case you couldn't to add subitem for this item @@ -227,13 +234,12 @@ public: const wxString& sub_obj_name, const wxBitmap& bmp, const wxString& extruder, - const int volume_id=-1) { + const int idx = -1 ) { m_parent = parent; m_name = sub_obj_name; - m_copy = wxEmptyString; m_bmp = bmp; - m_type = "volume"; - m_volume_id = volume_id; + m_type = itVolume; + m_idx = idx; m_extruder = extruder; #ifdef __WXGTK__ // it's necessary on GTK because of control have to know if this item will be container @@ -244,12 +250,22 @@ public: set_part_action_icon(); } - PrusaObjectDataViewModelNode( PrusaObjectDataViewModelNode* parent) : + PrusaObjectDataViewModelNode( PrusaObjectDataViewModelNode* parent, const ItemType type) : m_parent(parent), - m_name("Settings to modified"), - m_copy(wxEmptyString), - m_type("settings"), - m_extruder(wxEmptyString) {} + m_type(type), + m_extruder(wxEmptyString) + { + if (type == itSettings) { + m_name = "Settings to modified"; + } + else if (type == itInstanceRoot) { + m_name = "Instances"; + } + else if (type == itInstance) { + m_idx = parent->GetChildCount(); + m_name = wxString::Format("Instance_%d", m_idx+1); + } + } ~PrusaObjectDataViewModelNode() { @@ -263,11 +279,9 @@ public: } wxString m_name; - wxIcon& m_icon = m_empty_icon; wxBitmap& m_bmp = m_empty_bmp; - wxString m_copy; - std::string m_type; - int m_volume_id = -2; + ItemType m_type; + int m_idx = -1; bool m_container = false; wxString m_extruder = "default"; wxBitmap m_action_icon; @@ -331,12 +345,9 @@ public: m_name = data.GetText(); return true;} case 1: - m_copy = variant.GetString(); - return true; - case 2: m_extruder = variant.GetString(); return true; - case 3: + case 2: m_action_icon << variant; return true; default: @@ -344,28 +355,25 @@ public: } return false; } - void SetIcon(const wxIcon &icon) - { - m_icon = icon; - } void SetBitmap(const wxBitmap &icon) { m_bmp = icon; } - - void SetType(const std::string& type){ - m_type = type; - } - const std::string& GetType(){ - return m_type; + + ItemType GetType() const { + return m_type; + } + + void SetIdx(const int& idx) { + m_idx = idx; + // update name if this node is instance + if (m_type == itInstance) + m_name = wxString::Format("Instance_%d", m_idx + 1); } - void SetVolumeId(const int& volume_id){ - m_volume_id = volume_id; - } - const int& GetVolumeId(){ - return m_volume_id; + int GetIdx() const { + return m_idx; } // use this function only for childrens @@ -373,9 +381,10 @@ public: { // ! Don't overwrite other values because of equality of this values for all children -- m_name = from_node.m_name; - m_icon = from_node.m_icon; - m_volume_id = from_node.m_volume_id; - m_extruder = from_node.m_extruder; + m_bmp = from_node.m_bmp; + m_idx = from_node.m_idx; + m_extruder = from_node.m_extruder; + m_type = from_node.m_type; } bool SwapChildrens(int frst_id, int scnd_id) { @@ -387,8 +396,8 @@ public: PrusaObjectDataViewModelNode new_scnd = *GetNthChild(frst_id); PrusaObjectDataViewModelNode new_frst = *GetNthChild(scnd_id); - new_scnd.m_volume_id = m_children.Item(scnd_id)->m_volume_id; - new_frst.m_volume_id = m_children.Item(frst_id)->m_volume_id; + new_scnd.m_idx = m_children.Item(scnd_id)->m_idx; + new_frst.m_idx = m_children.Item(frst_id)->m_idx; m_children.Item(frst_id)->AssignAllVal(new_frst); m_children.Item(scnd_id)->AssignAllVal(new_scnd); @@ -399,6 +408,8 @@ public: void set_object_action_icon(); void set_part_action_icon(); bool update_settings_digest(const std::vector<std::string>& categories); +private: + friend class PrusaObjectDataViewModel; }; // ---------------------------------------------------------------------------- @@ -413,28 +424,29 @@ public: ~PrusaObjectDataViewModel(); wxDataViewItem Add(const wxString &name); - wxDataViewItem Add(const wxString &name, const int instances_count); - wxDataViewItem AddChild(const wxDataViewItem &parent_item, + wxDataViewItem AddVolumeChild(const wxDataViewItem &parent_item, const wxString &name, const wxBitmap& icon, const int extruder = 0, const bool create_frst_child = true); wxDataViewItem AddSettingsChild(const wxDataViewItem &parent_item); + wxDataViewItem AddInstanceChild(const wxDataViewItem &parent_item, size_t num); wxDataViewItem Delete(const wxDataViewItem &item); + wxDataViewItem DeleteLastInstance(const wxDataViewItem &parent_item, size_t num); void DeleteAll(); void DeleteChildren(wxDataViewItem& parent); wxDataViewItem GetItemById(int obj_idx); wxDataViewItem GetItemByVolumeId(int obj_idx, int volume_idx); int GetIdByItem(const wxDataViewItem& item); - int GetVolumeIdByItem(const wxDataViewItem& item); - void GetObjectAndVolumeIdsByItem(const wxDataViewItem& item, int& obj_idx, int& vol_idx); + int GetIdByItemAndType(const wxDataViewItem& item, const ItemType type) const; + int GetVolumeIdByItem(const wxDataViewItem& item) const; + int GetInstanceIdByItem(const wxDataViewItem& item) const; + void GetItemInfo(const wxDataViewItem& item, ItemType& type, int& obj_idx, int& idx); bool IsEmpty() { return m_objects.empty(); } // helper method for wxLog wxString GetName(const wxDataViewItem &item) const; - wxString GetCopy(const wxDataViewItem &item) const; - wxIcon& GetIcon(const wxDataViewItem &item) const; wxBitmap& GetBitmap(const wxDataViewItem &item) const; // helper methods to change the model @@ -448,8 +460,8 @@ public: const wxDataViewItem &item, unsigned int col) override; bool SetValue(const wxVariant &variant, const int item_idx, unsigned int col); - wxDataViewItem MoveChildUp(const wxDataViewItem &item); - wxDataViewItem MoveChildDown(const wxDataViewItem &item); +// wxDataViewItem MoveChildUp(const wxDataViewItem &item); +// wxDataViewItem MoveChildDown(const wxDataViewItem &item); // For parent move child from cur_volume_id place to new_volume_id // Remaining items will moved up/down accordingly wxDataViewItem ReorganizeChildren(int cur_volume_id, @@ -459,6 +471,8 @@ public: virtual bool IsEnabled(const wxDataViewItem &item, unsigned int col) const override; virtual wxDataViewItem GetParent(const wxDataViewItem &item) const override; + // get object item + wxDataViewItem GetTopParent(const wxDataViewItem &item) const; virtual bool IsContainer(const wxDataViewItem &item) const override; virtual unsigned int GetChildren(const wxDataViewItem &parent, wxDataViewItemArray &array) const override; @@ -467,7 +481,8 @@ public: // In our case it is an item with all columns virtual bool HasContainerColumns(const wxDataViewItem& WXUNUSED(item)) const override { return true; } - wxDataViewItem HasSettings(const wxDataViewItem &item) const; + ItemType GetItemType(const wxDataViewItem &item) const ; + wxDataViewItem GetSettingsItem(const wxDataViewItem &item) const; bool IsSettingsItem(const wxDataViewItem &item) const; void UpdateSettingsDigest(const wxDataViewItem &item, const std::vector<std::string>& categories); };