mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-11-02 20:51:23 -07:00 
			
		
		
		
	Merge remote-tracking branch 'origin/ys_dev_native' into dev_native
This commit is contained in:
		
						commit
						80f79451f7
					
				
					 7 changed files with 405 additions and 204 deletions
				
			
		| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue