From da5a13a03262e42c56456d262703dc1fd99f0563 Mon Sep 17 00:00:00 2001 From: TheLegendTubaGuy Date: Sat, 16 May 2026 00:12:06 -0500 Subject: [PATCH] Fix DataViewBitmapText assignment --- src/slic3r/GUI/ExtraRenderers.cpp | 5 +- src/slic3r/GUI/ExtraRenderers.hpp | 9 ++ src/slic3r/GUI/GUI_ObjectList.cpp | 109 ++++++++++++++++++++++--- src/slic3r/GUI/GUI_ObjectList.hpp | 7 ++ src/slic3r/GUI/ObjectDataViewModel.cpp | 4 + 5 files changed, 121 insertions(+), 13 deletions(-) diff --git a/src/slic3r/GUI/ExtraRenderers.cpp b/src/slic3r/GUI/ExtraRenderers.cpp index 4c16ce8deb..28837dbdad 100644 --- a/src/slic3r/GUI/ExtraRenderers.cpp +++ b/src/slic3r/GUI/ExtraRenderers.cpp @@ -343,7 +343,10 @@ wxWindow* BitmapChoiceRenderer::CreateEditorCtrl(wxWindow* parent, wxRect labelR bool BitmapChoiceRenderer::GetValueFromEditorCtrl(wxWindow* ctrl, wxVariant& value) { - ::ComboBox*c = static_cast<::ComboBox *>(ctrl); + auto* c = dynamic_cast<::ComboBox*>(ctrl); + if (!c) + return false; + int selection = c->GetSelection(); if (selection < 0) return false; diff --git a/src/slic3r/GUI/ExtraRenderers.hpp b/src/slic3r/GUI/ExtraRenderers.hpp index 18f1f49182..59a1f040ee 100644 --- a/src/slic3r/GUI/ExtraRenderers.hpp +++ b/src/slic3r/GUI/ExtraRenderers.hpp @@ -28,6 +28,15 @@ public: m_bmp(other.m_bmp) { } + DataViewBitmapText& operator=(const DataViewBitmapText &other) + { + if (this != &other) { + m_text = other.m_text; + m_bmp = other.m_bmp; + } + return *this; + } + void SetText(const wxString &text) { m_text = text; } wxString GetText() const { return m_text; } void SetBitmap(const wxBitmap &bmp) { m_bmp = bmp; } diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 3cee3d2058..d0afd8e295 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -435,15 +435,25 @@ void ObjectList::create_objects_ctrl() // column Extruder of the view control: BitmapChoiceRenderer* bmp_choice_renderer = new BitmapChoiceRenderer(); - bmp_choice_renderer->set_can_create_editor_ctrl_function([this]() { - return m_objects_model->GetItemType(GetSelection()) & (itVolume | itLayer | itObject); + const auto get_filament_context_item = [this]() { +#ifdef __WXOSX__ + return m_filament_editor_item.IsOk() ? m_filament_editor_item : GetSelection(); +#else + return GetSelection(); +#endif + }; + bmp_choice_renderer->set_can_create_editor_ctrl_function([this, get_filament_context_item]() { + const wxDataViewItem item = get_filament_context_item(); + return m_objects_model->GetItemType(item) & (itVolume | itLayer | itObject); }); - bmp_choice_renderer->set_default_extruder_idx([this]() { - return m_objects_model->GetDefaultExtruderIdx(GetSelection()); + bmp_choice_renderer->set_default_extruder_idx([this, get_filament_context_item]() { + const wxDataViewItem item = get_filament_context_item(); + return m_objects_model->GetDefaultExtruderIdx(item); }); - bmp_choice_renderer->set_has_default_extruder([this]() { - return m_objects_model->GetVolumeType(GetSelection()) == ModelVolumeType::PARAMETER_MODIFIER || - m_objects_model->GetItemType(GetSelection()) == itLayer; + bmp_choice_renderer->set_has_default_extruder([this, get_filament_context_item]() { + const wxDataViewItem item = get_filament_context_item(); + return m_objects_model->GetVolumeType(item) == ModelVolumeType::PARAMETER_MODIFIER || + m_objects_model->GetItemType(item) == itLayer; }); AppendColumn(new wxDataViewColumn(_L("Fila."), bmp_choice_renderer, colFilament, m_columns_width[colFilament] * em, wxALIGN_CENTER_HORIZONTAL, 0)); @@ -461,11 +471,16 @@ void ObjectList::create_objects_ctrl() wxALIGN_CENTER_HORIZONTAL, 0); - // Open filament editor faster + // On macOS, bypass wxDataViewCtrl::EditItem() for this custom renderer to avoid + // native text editing of wxCustomRendererObject. this->Bind(wxEVT_DATAVIEW_ITEM_ACTIVATED, [this](wxDataViewEvent& event) { if (event.GetColumn() == colFilament) { +#ifdef __WXOSX__ + start_filament_editor(event.GetItem()); +#else // Trigger the editor opening manually this->EditItem(event.GetItem(), GetColumn(colFilament)); +#endif } }); @@ -1082,10 +1097,11 @@ void ObjectList::update_filament_in_config(const wxDataViewItem& item) if (m_prevent_update_filament_in_config) return; + ModelConfig* config = nullptr; const ItemType item_type = m_objects_model->GetItemType(item); if (item_type & itObject) { const int obj_idx = m_objects_model->GetIdByItem(item); - m_config = &(*m_objects)[obj_idx]->config; + config = &(*m_objects)[obj_idx]->config; } else { const int obj_idx = m_objects_model->GetIdByItem(m_objects_model->GetObject(item)); @@ -1094,15 +1110,17 @@ void ObjectList::update_filament_in_config(const wxDataViewItem& item) if (obj_idx < 0 || ui_volume_idx < 0) return; int volume_in3d_idx = m_objects_model->get_real_volume_index_in_3d(obj_idx,ui_volume_idx); - m_config = &(*m_objects)[obj_idx]->volumes[volume_in3d_idx]->config; + config = &(*m_objects)[obj_idx]->volumes[volume_in3d_idx]->config; } else if (item_type & itLayer) - m_config = &get_item_config(item); + config = &get_item_config(item); } - if (!m_config) + if (!config) return; + m_config = config; + take_snapshot("Change Filament"); const int extruder = m_objects_model->GetExtruderNumber(item); @@ -6327,10 +6345,71 @@ void ObjectList::ItemValueChanged(wxDataViewEvent &event) } } +#ifdef __WXOSX__ +bool ObjectList::is_live_model_item(wxDataViewItem item) const +{ + if (!item.IsOk() || !m_objects_model) + return false; + + wxDataViewItemArray all_items; + m_objects_model->GetAllChildren(wxDataViewItem(nullptr), all_items); + for (const wxDataViewItem& live_item : all_items) + if (live_item.GetID() == item.GetID()) + return true; + + return false; +} + +void ObjectList::start_filament_editor(wxDataViewItem item) +{ + if (m_starting_filament_editor || !is_live_model_item(item)) + return; + + const ItemType type = m_objects_model->GetItemType(item); + if (!(type & (itVolume | itLayer | itObject))) + return; + + auto* column = GetColumn(colFilament); + if (!column) + return; + + auto* custom_renderer = dynamic_cast(column->GetRenderer()); + if (!custom_renderer || custom_renderer->GetEditorCtrl()) + return; + + m_starting_filament_editor = true; + m_filament_editor_item = item; + const bool started = custom_renderer->StartEditing(item, GetItemRect(item, column)); + m_filament_editor_item = wxDataViewItem(nullptr); + m_starting_filament_editor = false; + + if (!started) + return; + + SetCustomRendererPtr(custom_renderer); + SetCustomRendererItem(item); +} +#endif // __WXOSX__ + void GUI::ObjectList::OnStartEditing(wxDataViewEvent &event) { auto col = event.GetColumn(); auto item = event.GetItem(); +#ifdef __WXOSX__ + if (col == colFilament) { + if (m_starting_filament_editor) + return; + + event.Veto(); + CallAfter([this, item] { + if (!is_live_model_item(item)) + return; + start_filament_editor(item); + }); + return; + } +#endif // __WXOSX__ + if (col == colName) { ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)item.GetID(); if (node->GetType() & itPlate) { @@ -6398,6 +6477,12 @@ void ObjectList::OnEditingStarted(wxDataViewEvent &event) dynamic_cast(wxGetApp().get_model_tab(vol_idx >= 0))->reset_model_config(); return; } +#ifdef __WXOSX__ + if (col == colFilament) { + start_filament_editor(item); + return; + } +#endif // __WXOSX__ if (col != colFilament && col != colName) return; auto column = GetColumn(col); diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index b97eff05ae..cab78b6adc 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -192,6 +192,13 @@ private: int m_last_selected_column = -1; #endif /* __MSW__ */ +#ifdef __WXOSX__ + bool m_starting_filament_editor = false; + wxDataViewItem m_filament_editor_item { nullptr }; + bool is_live_model_item(wxDataViewItem item) const; + void start_filament_editor(wxDataViewItem item); +#endif // __WXOSX__ + #if 0 SettingsFactory::Bundle m_freq_settings_fff; SettingsFactory::Bundle m_freq_settings_sla; diff --git a/src/slic3r/GUI/ObjectDataViewModel.cpp b/src/slic3r/GUI/ObjectDataViewModel.cpp index ed4ad60f55..7944718e59 100644 --- a/src/slic3r/GUI/ObjectDataViewModel.cpp +++ b/src/slic3r/GUI/ObjectDataViewModel.cpp @@ -332,12 +332,16 @@ bool ObjectDataViewModelNode::SetValue(const wxVariant& variant, unsigned col) m_variable_height_icon << variant; return true; case colName: { + if (variant.GetType() != wxT("DataViewBitmapText")) + return false; DataViewBitmapText data; data << variant; m_bmp = data.GetBitmap(); m_name = data.GetText(); return true; } case colFilament: { + if (variant.GetType() != wxT("DataViewBitmapText")) + return false; DataViewBitmapText data; data << variant; m_extruder_bmp = data.GetBitmap();