diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 25e1a5ee5..babb8ed5c 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1003,14 +1003,13 @@ void ObjectList::OnBeginDrag(wxDataViewEvent &event) const bool mult_sel = multiple_selection(); if ((mult_sel && !selected_instances_of_same_object()) || - (!mult_sel && (GetSelection() != item)) || - m_objects_model->GetParent(item) == wxDataViewItem(nullptr) ) { + (!mult_sel && (GetSelection() != item)) ) { event.Veto(); return; } const ItemType& type = m_objects_model->GetItemType(item); - if (!(type & (itVolume | itInstance))) { + if (!(type & (itVolume | itObject | itInstance))) { event.Veto(); return; } @@ -1024,11 +1023,13 @@ void ObjectList::OnBeginDrag(wxDataViewEvent &event) for (auto sel : sels ) sub_obj_idxs.insert(m_objects_model->GetInstanceIdByItem(sel)); } - else + else if (type & itObject) + m_dragged_data.init(m_objects_model->GetIdByItem(item), type); + else m_dragged_data.init(m_objects_model->GetObjectIdByItem(item), - type&itVolume ? m_objects_model->GetVolumeIdByItem(item) : + type&itVolume ? m_objects_model->GetVolumeIdByItem(item) : m_objects_model->GetInstanceIdByItem(item), - type); + type); /* Under MSW or OSX, DnD moves an item to the place of another selected item * But under GTK, DnD moves an item between another two items. @@ -1049,10 +1050,20 @@ void ObjectList::OnBeginDrag(wxDataViewEvent &event) bool ObjectList::can_drop(const wxDataViewItem& item) const { - return (m_dragged_data.type() == itInstance && !item.IsOk()) || - (m_dragged_data.type() == itVolume && item.IsOk() && - m_objects_model->GetItemType(item) == itVolume && - m_dragged_data.obj_idx() == m_objects_model->GetObjectIdByItem(item)); + // move instance(s) or object on "empty place" of ObjectList + if ( (m_dragged_data.type() & (itInstance | itObject)) && !item.IsOk() ) + return true; + + // type of moved item should be the same as a "destination" item + if (!item.IsOk() || !(m_dragged_data.type() & (itVolume|itObject)) || + m_objects_model->GetItemType(item) != m_dragged_data.type() ) + return false; + + // move volumes inside one object only + if (m_dragged_data.type() & itVolume) + return m_dragged_data.obj_idx() == m_objects_model->GetObjectIdByItem(item); + + return true; } void ObjectList::OnDropPossible(wxDataViewEvent &event) @@ -1082,9 +1093,6 @@ void ObjectList::OnDrop(wxDataViewEvent &event) return; } - const int from_volume_id = m_dragged_data.sub_obj_idx(); - int to_volume_id = m_objects_model->GetVolumeIdByItem(item); - // It looks like a fixed in current version of the wxWidgets // #ifdef __WXGTK__ // /* Under GTK, DnD moves an item between another two items. @@ -1096,14 +1104,33 @@ void ObjectList::OnDrop(wxDataViewEvent &event) take_snapshot(_((m_dragged_data.type() == itVolume) ? L("Volumes in Object reordered") : L("Object reordered"))); - auto& volumes = (*m_objects)[m_dragged_data.obj_idx()]->volumes; - auto delta = to_volume_id < from_volume_id ? -1 : 1; - int cnt = 0; - for (int id = from_volume_id; cnt < abs(from_volume_id - to_volume_id); id += delta, cnt++) - std::swap(volumes[id], volumes[id + delta]); + if (m_dragged_data.type() & itVolume) + { + int from_volume_id = m_dragged_data.sub_obj_idx(); + int to_volume_id = m_objects_model->GetVolumeIdByItem(item); + int delta = to_volume_id < from_volume_id ? -1 : 1; - select_item(m_objects_model->ReorganizeChildren(from_volume_id, to_volume_id, - m_objects_model->GetParent(item))); + auto& volumes = (*m_objects)[m_dragged_data.obj_idx()]->volumes; + + int cnt = 0; + for (int id = from_volume_id; cnt < abs(from_volume_id - to_volume_id); id += delta, cnt++) + std::swap(volumes[id], volumes[id + delta]); + + select_item(m_objects_model->ReorganizeChildren(from_volume_id, to_volume_id, m_objects_model->GetParent(item))); + + } + else if (m_dragged_data.type() & itObject) + { + int from_obj_id = m_dragged_data.obj_idx(); + int to_obj_id = item.IsOk() ? m_objects_model->GetIdByItem(item) : ((int)m_objects->size()-1); + int delta = to_obj_id < from_obj_id ? -1 : 1; + + int cnt = 0; + for (int id = from_obj_id; cnt < abs(from_obj_id - to_obj_id); id += delta, cnt++) + std::swap((*m_objects)[id], (*m_objects)[id + delta]); + + select_item(m_objects_model->ReorganizeObjects(from_obj_id, to_obj_id)); + } changed_object(m_dragged_data.obj_idx()); diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index b710d2cd7..a867ca0ec 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -1726,9 +1726,6 @@ wxDataViewItem ObjectDataViewModel::ReorganizeChildren( const int current_volume ItemDeleted(parent, wxDataViewItem(deleted_node)); node_parent->Insert(deleted_node, new_volume_id+shift); ItemAdded(parent, wxDataViewItem(deleted_node)); - const auto settings_item = GetSettingsItem(wxDataViewItem(deleted_node)); - if (settings_item) - ItemAdded(wxDataViewItem(deleted_node), settings_item); //update volume_id value for child-nodes auto children = node_parent->GetChildren(); @@ -1740,6 +1737,21 @@ wxDataViewItem ObjectDataViewModel::ReorganizeChildren( const int current_volume return wxDataViewItem(node_parent->GetNthChild(new_volume_id+shift)); } +wxDataViewItem ObjectDataViewModel::ReorganizeObjects( const int current_id, const int new_id) +{ + if (current_id == new_id) + return wxDataViewItem(nullptr); + + ObjectDataViewModelNode* deleted_node = m_objects[current_id]; + m_objects.erase(m_objects.begin() + current_id); + ItemDeleted(wxDataViewItem(nullptr), wxDataViewItem(deleted_node)); + + m_objects.emplace(m_objects.begin() + new_id, deleted_node); + ItemAdded(wxDataViewItem(nullptr), wxDataViewItem(deleted_node)); + + return wxDataViewItem(deleted_node); +} + bool ObjectDataViewModel::IsEnabled(const wxDataViewItem &item, unsigned int col) const { wxASSERT(item.IsOk()); diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index c3d26c8be..8cd144dc5 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -481,6 +481,7 @@ public: wxDataViewItem ReorganizeChildren( const int cur_volume_id, const int new_volume_id, const wxDataViewItem &parent); + wxDataViewItem ReorganizeObjects( int current_id, int new_id); virtual bool IsEnabled(const wxDataViewItem &item, unsigned int col) const override;